Improved discovery mechanism #323

Does not rely solely on mac addresses anymore. Should help when
mac address randomization is used.
master
cpfeiffer 2016-06-28 00:35:50 +02:00
parent 76a44ad3a4
commit 7613b62dab
4 changed files with 79 additions and 2 deletions

View File

@ -1,9 +1,39 @@
package nodomain.freeyourgadget.gadgetbridge.devices;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(AbstractDeviceCoordinator.class);
public boolean allowFetchActivityData(GBDevice device) {
return device.isInitialized() && !device.isBusy() && supportsActivityDataFetching();
}
public boolean isHealthWearable(BluetoothDevice device) {
BluetoothClass bluetoothClass = device.getBluetoothClass();
if (bluetoothClass == null) {
LOG.warn("unable to determine bluetooth device class of " + device);
return false;
}
if (bluetoothClass.getMajorDeviceClass() == BluetoothClass.Device.Major.WEARABLE
|| bluetoothClass.getMajorDeviceClass() == BluetoothClass.Device.Major.UNCATEGORIZED) {
int deviceClasses =
BluetoothClass.Device.HEALTH_BLOOD_PRESSURE
| BluetoothClass.Device.HEALTH_DATA_DISPLAY
| BluetoothClass.Device.HEALTH_PULSE_RATE
| BluetoothClass.Device.HEALTH_WEIGHING
| BluetoothClass.Device.HEALTH_UNCATEGORIZED
| BluetoothClass.Device.HEALTH_PULSE_OXIMETER
| BluetoothClass.Device.HEALTH_GLUCOSE;
return (bluetoothClass.getDeviceClass() & deviceClasses) != 0;
}
return false;
}
}

View File

@ -24,6 +24,7 @@ public final class MiBandConst {
public static final String ORIGIN_K9MAIL = "k9mail";
public static final String ORIGIN_PEBBLEMSG = "pebblemsg";
public static final String ORIGIN_GENERIC = "generic";
public static final String MI_GENERAL_NAME_PREFIX = "MI";
public static final String MI_1 = "1";
public static final String MI_1A = "1A";
public static final String MI_1S = "1S";

View File

@ -32,8 +32,22 @@ public class MiBandCoordinator extends AbstractDeviceCoordinator {
@Override
public boolean supports(GBDeviceCandidate candidate) {
String macAddress = candidate.getMacAddress().toUpperCase();
return macAddress.startsWith(MiBandService.MAC_ADDRESS_FILTER_1_1A)
|| macAddress.startsWith(MiBandService.MAC_ADDRESS_FILTER_1S);
if (macAddress.startsWith(MiBandService.MAC_ADDRESS_FILTER_1_1A)
|| macAddress.startsWith(MiBandService.MAC_ADDRESS_FILTER_1S)) {
return true;
}
if (candidate.supportsService(MiBandService.UUID_SERVICE_MIBAND_SERVICE)) {
return true;
}
// and a heuristic
try {
if (isHealthWearable(candidate.getDevice())) {
return candidate.getName().toUpperCase().startsWith(MiBandConst.MI_GENERAL_NAME_PREFIX.toUpperCase());
}
} catch (Exception ex) {
LOG.error("unable to check device support", ex);
}
return false;
}
@Override

View File

@ -2,8 +2,14 @@ package nodomain.freeyourgadget.gadgetbridge.impl;
import android.bluetooth.BluetoothDevice;
import android.os.Parcel;
import android.os.ParcelUuid;
import android.os.Parcelable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
@ -14,6 +20,8 @@ import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
* support this candidate, will the candidate be promoted to a GBDevice.
*/
public class GBDeviceCandidate implements Parcelable {
private static final Logger LOG = LoggerFactory.getLogger(GBDeviceCandidate.class);
private final BluetoothDevice device;
private final short rssi;
private DeviceType deviceType = DeviceType.UNKNOWN;
@ -40,6 +48,10 @@ public class GBDeviceCandidate implements Parcelable {
dest.writeString(deviceType.name());
}
public BluetoothDevice getDevice() {
return device;
}
public DeviceType getDeviceType() {
return deviceType;
}
@ -48,6 +60,21 @@ public class GBDeviceCandidate implements Parcelable {
return device != null ? device.getAddress() : GBApplication.getContext().getString(R.string._unknown_);
}
public boolean supportsService(UUID aService) {
ParcelUuid[] uuids = device.getUuids();
if (uuids == null) {
LOG.warn("no cached services available for " + this);
return false;
}
for (ParcelUuid uuid : uuids) {
if (uuid != null && aService.equals(uuid.getUuid())) {
return true;
}
}
return false;
}
public String getName() {
String name = null;
if (device != null) {
@ -85,4 +112,9 @@ public class GBDeviceCandidate implements Parcelable {
public int hashCode() {
return device.getAddress().hashCode() ^ 37;
}
@Override
public String toString() {
return getName() + ": " + getMacAddress();
}
}