mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2025-01-11 01:21:56 +01:00
Some more improvements to discovery
- pass service uuids to GBDeviceCandaidate so that DeviceCoordinators can detect devices by their services. Note: they should not rely on service uuids being available
This commit is contained in:
parent
b9ff2cd468
commit
2f7eb9ef23
@ -8,6 +8,7 @@ import android.bluetooth.BluetoothDevice;
|
|||||||
import android.bluetooth.BluetoothManager;
|
import android.bluetooth.BluetoothManager;
|
||||||
import android.bluetooth.le.ScanCallback;
|
import android.bluetooth.le.ScanCallback;
|
||||||
import android.bluetooth.le.ScanFilter;
|
import android.bluetooth.le.ScanFilter;
|
||||||
|
import android.bluetooth.le.ScanRecord;
|
||||||
import android.bluetooth.le.ScanResult;
|
import android.bluetooth.le.ScanResult;
|
||||||
import android.bluetooth.le.ScanSettings;
|
import android.bluetooth.le.ScanSettings;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
@ -42,6 +43,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
|
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
|
|
||||||
@ -95,6 +97,14 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC
|
|||||||
handleDeviceFound(device, rssi);
|
handleDeviceFound(device, rssi);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case BluetoothDevice.ACTION_UUID: {
|
||||||
|
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||||
|
short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, GBDevice.RSSI_UNKNOWN);
|
||||||
|
Parcelable[] uuids = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
|
||||||
|
ParcelUuid[] uuids2 = AndroidUtils.toParcelUUids(uuids);
|
||||||
|
handleDeviceFound(device, rssi, uuids2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case BluetoothDevice.ACTION_BOND_STATE_CHANGED: {
|
case BluetoothDevice.ACTION_BOND_STATE_CHANGED: {
|
||||||
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||||
if (device != null && device.getAddress().equals(bondingAddress)) {
|
if (device != null && device.getAddress().equals(bondingAddress)) {
|
||||||
@ -131,10 +141,18 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC
|
|||||||
public void onScanResult(int callbackType, ScanResult result) {
|
public void onScanResult(int callbackType, ScanResult result) {
|
||||||
super.onScanResult(callbackType, result);
|
super.onScanResult(callbackType, result);
|
||||||
try {
|
try {
|
||||||
|
ScanRecord scanRecord = result.getScanRecord();
|
||||||
|
ParcelUuid[] uuids = null;
|
||||||
|
if (scanRecord != null) {
|
||||||
|
//logMessageContent(scanRecord.getBytes());
|
||||||
|
List<ParcelUuid> serviceUuids = scanRecord.getServiceUuids();
|
||||||
|
if (serviceUuids != null) {
|
||||||
|
uuids = serviceUuids.toArray(new ParcelUuid[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
LOG.warn(result.getDevice().getName() + ": " +
|
LOG.warn(result.getDevice().getName() + ": " +
|
||||||
((result.getScanRecord() != null) ? result.getScanRecord().getBytes().length : -1));
|
((scanRecord != null) ? scanRecord.getBytes().length : -1));
|
||||||
//logMessageContent(result.getScanRecord().getBytes());
|
handleDeviceFound(result.getDevice(), (short) result.getRssi(), uuids);
|
||||||
handleDeviceFound(result.getDevice(), (short) result.getRssi());
|
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
LOG.warn("Error handling scan result", e);
|
LOG.warn("Error handling scan result", e);
|
||||||
}
|
}
|
||||||
@ -199,6 +217,7 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC
|
|||||||
|
|
||||||
IntentFilter bluetoothIntents = new IntentFilter();
|
IntentFilter bluetoothIntents = new IntentFilter();
|
||||||
bluetoothIntents.addAction(BluetoothDevice.ACTION_FOUND);
|
bluetoothIntents.addAction(BluetoothDevice.ACTION_FOUND);
|
||||||
|
bluetoothIntents.addAction(BluetoothDevice.ACTION_UUID);
|
||||||
bluetoothIntents.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
|
bluetoothIntents.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
|
||||||
bluetoothIntents.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
|
bluetoothIntents.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
|
||||||
bluetoothIntents.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
|
bluetoothIntents.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
|
||||||
@ -247,9 +266,20 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleDeviceFound(BluetoothDevice device, short rssi) {
|
private void handleDeviceFound(BluetoothDevice device, short rssi) {
|
||||||
|
ParcelUuid[] uuids = device.getUuids();
|
||||||
|
if (uuids == null) {
|
||||||
|
if (device.fetchUuidsWithSdp()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDeviceFound(device, rssi, uuids);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void handleDeviceFound(BluetoothDevice device, short rssi, ParcelUuid[] uuids) {
|
||||||
LOG.debug("found device: " + device.getName() + ", " + device.getAddress());
|
LOG.debug("found device: " + device.getName() + ", " + device.getAddress());
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
ParcelUuid[] uuids = device.getUuids();
|
|
||||||
if (uuids != null && uuids.length > 0) {
|
if (uuids != null && uuids.length > 0) {
|
||||||
for (ParcelUuid uuid : uuids) {
|
for (ParcelUuid uuid : uuids) {
|
||||||
LOG.debug(" supports uuid: " + uuid.toString());
|
LOG.debug(" supports uuid: " + uuid.toString());
|
||||||
@ -260,7 +290,7 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC
|
|||||||
return; // ignore already bonded devices
|
return; // ignore already bonded devices
|
||||||
}
|
}
|
||||||
|
|
||||||
GBDeviceCandidate candidate = new GBDeviceCandidate(device, rssi);
|
GBDeviceCandidate candidate = new GBDeviceCandidate(device, rssi, uuids);
|
||||||
DeviceType deviceType = DeviceHelper.getInstance().getSupportedType(candidate);
|
DeviceType deviceType = DeviceHelper.getInstance().getSupportedType(candidate);
|
||||||
if (deviceType.isSupported()) {
|
if (deviceType.isSupported()) {
|
||||||
candidate.setDeviceType(deviceType);
|
candidate.setDeviceType(deviceType);
|
||||||
|
@ -40,8 +40,13 @@ public class MiBand2Coordinator extends MiBandCoordinator {
|
|||||||
return Collections.singletonList(filter);
|
return Collections.singletonList(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
|
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
|
||||||
|
if (candidate.supportsService(MiBand2Service.UUID_SERVICE_MIBAND2_SERVICE)) {
|
||||||
|
return DeviceType.MIBAND2;
|
||||||
|
}
|
||||||
|
|
||||||
// and a heuristic for now
|
// and a heuristic for now
|
||||||
try {
|
try {
|
||||||
BluetoothDevice device = candidate.getDevice();
|
BluetoothDevice device = candidate.getDevice();
|
||||||
|
@ -49,6 +49,7 @@ public class MiBandCoordinator extends AbstractDeviceCoordinator {
|
|||||||
return Collections.singletonList(filter);
|
return Collections.singletonList(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
|
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
|
||||||
String macAddress = candidate.getMacAddress().toUpperCase();
|
String macAddress = candidate.getMacAddress().toUpperCase();
|
||||||
|
@ -5,17 +5,22 @@ import android.os.Parcel;
|
|||||||
import android.os.ParcelUuid;
|
import android.os.ParcelUuid;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
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;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A device candidate is a Bluetooth device that is not yet managed by
|
* A device candidate is a Bluetooth device that is not yet managed by
|
||||||
@ -27,21 +32,25 @@ public class GBDeviceCandidate implements Parcelable {
|
|||||||
|
|
||||||
private final BluetoothDevice device;
|
private final BluetoothDevice device;
|
||||||
private final short rssi;
|
private final short rssi;
|
||||||
|
private final ParcelUuid[] serviceUuds;
|
||||||
private DeviceType deviceType = DeviceType.UNKNOWN;
|
private DeviceType deviceType = DeviceType.UNKNOWN;
|
||||||
|
|
||||||
public GBDeviceCandidate(BluetoothDevice device, short rssi) {
|
public GBDeviceCandidate(BluetoothDevice device, short rssi, ParcelUuid[] serviceUuds) {
|
||||||
this.device = device;
|
this.device = device;
|
||||||
this.rssi = rssi;
|
this.rssi = rssi;
|
||||||
|
this.serviceUuds = mergeServiceUuids(serviceUuds, device.getUuids());
|
||||||
}
|
}
|
||||||
|
|
||||||
private GBDeviceCandidate(Parcel in) {
|
private GBDeviceCandidate(Parcel in) {
|
||||||
device = in.readParcelable(getClass().getClassLoader());
|
device = in.readParcelable(getClass().getClassLoader());
|
||||||
rssi = (short) in.readInt();
|
|
||||||
deviceType = DeviceType.valueOf(in.readString());
|
|
||||||
|
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
throw new IllegalStateException("Unable to read state from Parcel");
|
throw new IllegalStateException("Unable to read state from Parcel");
|
||||||
}
|
}
|
||||||
|
rssi = (short) in.readInt();
|
||||||
|
deviceType = DeviceType.valueOf(in.readString());
|
||||||
|
|
||||||
|
ParcelUuid[] uuids = AndroidUtils.toParcelUUids(in.readParcelableArray(getClass().getClassLoader()));
|
||||||
|
serviceUuds = mergeServiceUuids(uuids, device.getUuids());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -49,8 +58,21 @@ public class GBDeviceCandidate implements Parcelable {
|
|||||||
dest.writeParcelable(device, 0);
|
dest.writeParcelable(device, 0);
|
||||||
dest.writeInt(rssi);
|
dest.writeInt(rssi);
|
||||||
dest.writeString(deviceType.name());
|
dest.writeString(deviceType.name());
|
||||||
|
dest.writeArray(serviceUuds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final Creator<GBDeviceCandidate> CREATOR = new Creator<GBDeviceCandidate>() {
|
||||||
|
@Override
|
||||||
|
public GBDeviceCandidate createFromParcel(Parcel in) {
|
||||||
|
return new GBDeviceCandidate(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GBDeviceCandidate[] newArray(int size) {
|
||||||
|
return new GBDeviceCandidate[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public BluetoothDevice getDevice() {
|
public BluetoothDevice getDevice() {
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
@ -67,9 +89,25 @@ 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_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ParcelUuid[] mergeServiceUuids(ParcelUuid[] serviceUuds, ParcelUuid[] deviceUuids) {
|
||||||
|
Set<ParcelUuid> uuids = new HashSet<>();
|
||||||
|
if (serviceUuds != null) {
|
||||||
|
uuids.addAll(Arrays.asList(serviceUuds));
|
||||||
|
}
|
||||||
|
if (deviceUuids != null) {
|
||||||
|
uuids.addAll(Arrays.asList(deviceUuids));
|
||||||
|
}
|
||||||
|
return uuids.toArray(new ParcelUuid[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public ParcelUuid[] getServiceUuids() {
|
||||||
|
return serviceUuds;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean supportsService(UUID aService) {
|
public boolean supportsService(UUID aService) {
|
||||||
ParcelUuid[] uuids = device.getUuids();
|
ParcelUuid[] uuids = getServiceUuids();
|
||||||
if (uuids == null) {
|
if (uuids.length == 0) {
|
||||||
LOG.warn("no cached services available for " + this);
|
LOG.warn("no cached services available for " + this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.util;
|
||||||
|
|
||||||
|
import android.os.ParcelUuid;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
public class AndroidUtils {
|
||||||
|
public static ParcelUuid[] toParcelUUids(Parcelable[] uuids) {
|
||||||
|
if (uuids == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ParcelUuid[] uuids2 = new ParcelUuid[uuids.length];
|
||||||
|
System.arraycopy(uuids, 0, uuids2, 0, uuids.length);
|
||||||
|
return uuids2;
|
||||||
|
}
|
||||||
|
}
|
@ -120,7 +120,7 @@ public class DeviceHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public GBDevice toSupportedDevice(BluetoothDevice device) {
|
public GBDevice toSupportedDevice(BluetoothDevice device) {
|
||||||
GBDeviceCandidate candidate = new GBDeviceCandidate(device, GBDevice.RSSI_UNKNOWN);
|
GBDeviceCandidate candidate = new GBDeviceCandidate(device, GBDevice.RSSI_UNKNOWN, device.getUuids());
|
||||||
|
|
||||||
for (DeviceCoordinator coordinator : getAllCoordinators()) {
|
for (DeviceCoordinator coordinator : getAllCoordinators()) {
|
||||||
if (coordinator.supports(candidate)) {
|
if (coordinator.supports(candidate)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user