mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-24 10:56:50 +01:00
Improved discovery mechanism #323
Does not rely solely on mac addresses anymore. Should help when mac address randomization is used.
This commit is contained in:
parent
76a44ad3a4
commit
7613b62dab
@ -1,9 +1,39 @@
|
|||||||
package nodomain.freeyourgadget.gadgetbridge.devices;
|
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;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
|
|
||||||
public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
|
public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(AbstractDeviceCoordinator.class);
|
||||||
|
|
||||||
public boolean allowFetchActivityData(GBDevice device) {
|
public boolean allowFetchActivityData(GBDevice device) {
|
||||||
return device.isInitialized() && !device.isBusy() && supportsActivityDataFetching();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ public final class MiBandConst {
|
|||||||
public static final String ORIGIN_K9MAIL = "k9mail";
|
public static final String ORIGIN_K9MAIL = "k9mail";
|
||||||
public static final String ORIGIN_PEBBLEMSG = "pebblemsg";
|
public static final String ORIGIN_PEBBLEMSG = "pebblemsg";
|
||||||
public static final String ORIGIN_GENERIC = "generic";
|
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_1 = "1";
|
||||||
public static final String MI_1A = "1A";
|
public static final String MI_1A = "1A";
|
||||||
public static final String MI_1S = "1S";
|
public static final String MI_1S = "1S";
|
||||||
|
@ -32,8 +32,22 @@ public class MiBandCoordinator extends AbstractDeviceCoordinator {
|
|||||||
@Override
|
@Override
|
||||||
public boolean supports(GBDeviceCandidate candidate) {
|
public boolean supports(GBDeviceCandidate candidate) {
|
||||||
String macAddress = candidate.getMacAddress().toUpperCase();
|
String macAddress = candidate.getMacAddress().toUpperCase();
|
||||||
return macAddress.startsWith(MiBandService.MAC_ADDRESS_FILTER_1_1A)
|
if (macAddress.startsWith(MiBandService.MAC_ADDRESS_FILTER_1_1A)
|
||||||
|| macAddress.startsWith(MiBandService.MAC_ADDRESS_FILTER_1S);
|
|| 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
|
@Override
|
||||||
|
@ -2,8 +2,14 @@ package nodomain.freeyourgadget.gadgetbridge.impl;
|
|||||||
|
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
|
import android.os.ParcelUuid;
|
||||||
import android.os.Parcelable;
|
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.GBApplication;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
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.
|
* support this candidate, will the candidate be promoted to a GBDevice.
|
||||||
*/
|
*/
|
||||||
public class GBDeviceCandidate implements Parcelable {
|
public class GBDeviceCandidate implements Parcelable {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(GBDeviceCandidate.class);
|
||||||
|
|
||||||
private final BluetoothDevice device;
|
private final BluetoothDevice device;
|
||||||
private final short rssi;
|
private final short rssi;
|
||||||
private DeviceType deviceType = DeviceType.UNKNOWN;
|
private DeviceType deviceType = DeviceType.UNKNOWN;
|
||||||
@ -40,6 +48,10 @@ public class GBDeviceCandidate implements Parcelable {
|
|||||||
dest.writeString(deviceType.name());
|
dest.writeString(deviceType.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BluetoothDevice getDevice() {
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
public DeviceType getDeviceType() {
|
public DeviceType getDeviceType() {
|
||||||
return deviceType;
|
return deviceType;
|
||||||
}
|
}
|
||||||
@ -48,6 +60,21 @@ public class GBDeviceCandidate implements Parcelable {
|
|||||||
return device != null ? device.getAddress() : GBApplication.getContext().getString(R.string._unknown_);
|
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() {
|
public String getName() {
|
||||||
String name = null;
|
String name = null;
|
||||||
if (device != null) {
|
if (device != null) {
|
||||||
@ -85,4 +112,9 @@ public class GBDeviceCandidate implements Parcelable {
|
|||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return device.getAddress().hashCode() ^ 37;
|
return device.getAddress().hashCode() ^ 37;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getName() + ": " + getMacAddress();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user