From fe11e6d306d5d3548d99cc085b22764ca239cc57 Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Fri, 7 Aug 2015 16:59:52 +0200 Subject: [PATCH] Some BTLE cleanup: - the BASE_UUID is shared between all BTLE devices, not miband specific. So are the UUID DESCRIPTORS. Hence these have been moved to AbstractBTLEDeviceSupport - the gatt-characteristic-property-constants used previously in MiBandNotifyAction are also general, and exposed by the gatt subsystem, hence the specific action has been dropped moving the logic to the NotifyAction class - the logic for checking the gatt-characteristic-property-constants has been extended also to the ReadAction and WriteAction class, this way we won't try to read (or write) a characteristic that isn't readable (or writeable) --- .../devices/miband/MiBandNotifyAction.java | 64 ------------------- .../devices/miband/MiBandService.java | 8 +-- .../miband/MiBandTransactionBuilder.java | 2 +- .../btle/AbstractBTLEDeviceSupport.java | 7 +- .../service/btle/actions/NotifyAction.java | 33 +++++++++- .../service/btle/actions/ReadAction.java | 6 +- .../service/btle/actions/WriteAction.java | 7 +- 7 files changed, 50 insertions(+), 77 deletions(-) delete mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandNotifyAction.java diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandNotifyAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandNotifyAction.java deleted file mode 100644 index 0eb9a628d..000000000 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandNotifyAction.java +++ /dev/null @@ -1,64 +0,0 @@ -package nodomain.freeyourgadget.gadgetbridge.devices.miband; - -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCallback; -import android.bluetooth.BluetoothGattCharacteristic; -import android.bluetooth.BluetoothGattDescriptor; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.NotifyAction; -import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; - -/** - * Enables or disables notifications for a given GATT characteristic. - * The result will be made available asynchronously through the - * {@link BluetoothGattCallback}. - *

- * This class is Mi Band specific. - */ -public class MiBandNotifyAction extends NotifyAction { - - private static final Logger LOG = LoggerFactory.getLogger(TransactionBuilder.class); - private boolean hasWrittenDescriptor = true; - - public MiBandNotifyAction(BluetoothGattCharacteristic characteristic, boolean enable) { - super(characteristic, enable); - } - - @Override - public boolean run(BluetoothGatt gatt) { - boolean result = super.run(gatt); - if (result) { - BluetoothGattDescriptor notifyDescriptor = getCharacteristic().getDescriptor(MiBandService.UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION); - if (notifyDescriptor != null) { - int properties = getCharacteristic().getProperties(); - if ((properties & 0x10) > 0) { - LOG.debug("use NOTIFICATION"); - notifyDescriptor.setValue(enableFlag ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); - result = gatt.writeDescriptor(notifyDescriptor); - } else if ((properties & 0x20) > 0) { - LOG.debug("use INDICATION"); - notifyDescriptor.setValue(enableFlag ? BluetoothGattDescriptor.ENABLE_INDICATION_VALUE : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); - result = gatt.writeDescriptor(notifyDescriptor); - hasWrittenDescriptor = true; - } else { - hasWrittenDescriptor = false; - } - } else { - LOG.warn("sleep descriptor null"); - hasWrittenDescriptor = false; - } - } else { - hasWrittenDescriptor = false; - LOG.error("Unable to enable notification for " + getCharacteristic().getUuid()); - } - return result; - } - - @Override - public boolean expectsResult() { - return hasWrittenDescriptor; - } -} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandService.java index f6f5e456f..9addf457d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandService.java @@ -4,13 +4,13 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; +import static nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport.BASE_UUID; + public class MiBandService { public static final String MAC_ADDRESS_FILTER = "88:0F:10"; - public static final String BASE_UUID = "0000%s-0000-1000-8000-00805f9b34fb"; - public static final UUID UUID_SERVICE_MIBAND_SERVICE = UUID.fromString(String.format(BASE_UUID, "FEE0")); public static final UUID UUID_CHARACTERISTIC_DEVICE_INFO = UUID.fromString(String.format(BASE_UUID, "FF01")); @@ -53,10 +53,6 @@ public class MiBandService { public static final String UUID_SERVICE_WEIGHT_SERVICE = "00001530-0000-3512-2118-0009af100700"; - public static final UUID UUID_DESCRIPTOR_CHARACTERISTIC_USER_CONFIGURATION = UUID.fromString(String.format(BASE_UUID, "2901")); - - public static final UUID UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION = UUID.fromString(String.format(BASE_UUID, "2902")); - public static final byte ALIAS_LEN = 0xa; /*NOTIFICATIONS: usually received on the UUID_CHARACTERISTIC_NOTIFICATION characteristic */ diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandTransactionBuilder.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandTransactionBuilder.java index 5c385a6c2..d5787e63a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandTransactionBuilder.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandTransactionBuilder.java @@ -17,6 +17,6 @@ public class MiBandTransactionBuilder extends TransactionBuilder { @Override protected NotifyAction createNotifyAction(BluetoothGattCharacteristic characteristic, boolean enable) { - return new MiBandNotifyAction(characteristic, enable); + return new NotifyAction(characteristic, enable); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEDeviceSupport.java index b3b095c51..2f7757a73 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEDeviceSupport.java @@ -20,7 +20,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.AbstractDeviceSupport; /** * Abstract base class for all devices connected through Bluetooth Low Energy (LE) aka * Bluetooth Smart. - * + *

* The connection to the device and all communication is made with a generic {@link BtLEQueue}. * Messages to the device are encoded as {@link BtLEAction actions} that are grouped with a * {@link Transaction} and sent via {@link BtLEQueue}. @@ -35,6 +35,11 @@ public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport im private HashMap mAvailableCharacteristics; private Set mSupportedServices = new HashSet<>(4); + public static final String BASE_UUID = "0000%s-0000-1000-8000-00805f9b34fb"; //this is common for all BTLE devices. see http://stackoverflow.com/questions/18699251/finding-out-android-bluetooth-le-gatt-profiles + public static final UUID UUID_DESCRIPTOR_CHARACTERISTIC_USER_CONFIGURATION = UUID.fromString(String.format(BASE_UUID, "2901")); + public static final UUID UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION = UUID.fromString(String.format(BASE_UUID, "2902")); + + @Override public boolean connect() { if (mQueue == null) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/NotifyAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/NotifyAction.java index b2f4ebeae..6e5995d33 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/NotifyAction.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/NotifyAction.java @@ -3,6 +3,7 @@ package nodomain.freeyourgadget.gadgetbridge.service.btle.actions; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,6 +11,8 @@ import org.slf4j.LoggerFactory; import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import static nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport.UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION; + /** * Enables or disables notifications for a given GATT characteristic. * The result will be made available asynchronously through the @@ -19,6 +22,7 @@ public class NotifyAction extends BtLEAction { private static final Logger LOG = LoggerFactory.getLogger(TransactionBuilder.class); protected final boolean enableFlag; + private boolean hasWrittenDescriptor = true; public NotifyAction(BluetoothGattCharacteristic characteristic, boolean enable) { super(characteristic); @@ -27,11 +31,36 @@ public class NotifyAction extends BtLEAction { @Override public boolean run(BluetoothGatt gatt) { - return gatt.setCharacteristicNotification(getCharacteristic(), enableFlag); + boolean result = gatt.setCharacteristicNotification(getCharacteristic(), enableFlag); + if (result) { + BluetoothGattDescriptor notifyDescriptor = getCharacteristic().getDescriptor(UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION); + if (notifyDescriptor != null) { + int properties = getCharacteristic().getProperties(); + if ((properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) { + LOG.debug("use NOTIFICATION"); + notifyDescriptor.setValue(enableFlag ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); + result = gatt.writeDescriptor(notifyDescriptor); + } else if ((properties & BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0) { + LOG.debug("use INDICATION"); + notifyDescriptor.setValue(enableFlag ? BluetoothGattDescriptor.ENABLE_INDICATION_VALUE : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); + result = gatt.writeDescriptor(notifyDescriptor); + hasWrittenDescriptor = true; + } else { + hasWrittenDescriptor = false; + } + } else { + LOG.warn("sleep descriptor null"); + hasWrittenDescriptor = false; + } + } else { + hasWrittenDescriptor = false; + LOG.error("Unable to enable notification for " + getCharacteristic().getUuid()); + } + return result; } @Override public boolean expectsResult() { - return false; + return hasWrittenDescriptor; } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/ReadAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/ReadAction.java index fbc00bbee..36c6d07bd 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/ReadAction.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/ReadAction.java @@ -19,7 +19,11 @@ public class ReadAction extends BtLEAction { @Override public boolean run(BluetoothGatt gatt) { - return gatt.readCharacteristic(getCharacteristic()); + int properties = getCharacteristic().getProperties(); + if ((properties & BluetoothGattCharacteristic.PROPERTY_READ) > 0) { + return gatt.readCharacteristic(getCharacteristic()); + } + return false; } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/WriteAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/WriteAction.java index 9c72759ce..de05414b9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/WriteAction.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/WriteAction.java @@ -22,8 +22,11 @@ public class WriteAction extends BtLEAction { @Override public boolean run(BluetoothGatt gatt) { - if (getCharacteristic().setValue(value)) { - return gatt.writeCharacteristic(getCharacteristic()); + int properties = getCharacteristic().getProperties(); + if ((properties & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) { + if (getCharacteristic().setValue(value)) { + return gatt.writeCharacteristic(getCharacteristic()); + } } return false; }