diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/AbstractBTLEDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/AbstractBTLEDeviceSupport.java index b65a6d5e5..9764dfe7c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/AbstractBTLEDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/AbstractBTLEDeviceSupport.java @@ -2,6 +2,7 @@ package nodomain.freeyourgadget.gadgetbridge.btle; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattService; import org.slf4j.Logger; @@ -173,6 +174,14 @@ public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport im BluetoothGattCharacteristic characteristic, int status) { } + @Override + public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { + } + + @Override + public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { + } + @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/BtLEQueue.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/BtLEQueue.java index e131f5dc6..eba0cbf90 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/BtLEQueue.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/BtLEQueue.java @@ -5,6 +5,7 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothProfile; import android.content.Context; @@ -69,11 +70,10 @@ public final class BtLEQueue { // Run all actions of the transaction until one doesn't succeed for (BtLEAction action : transaction.getActions()) { mWaitCharacteristic = action.getCharacteristic(); - boolean waitForResult = action.expectsResult(); - if (waitForResult) { - mWaitForActionResultLatch = new CountDownLatch(1); - } + mWaitForActionResultLatch = new CountDownLatch(1); if (action.run(mBluetoothGatt)) { + // check again, maybe due to some condition, action did not need to write, so we can't wait + boolean waitForResult = action.expectsResult(); if (waitForResult) { mWaitForActionResultLatch.await(); mWaitForActionResultLatch = null; @@ -278,6 +278,7 @@ public final class BtLEQueue { @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { + LOG.debug("characteristic write: " + characteristic.getUuid()); if (!checkCorrectGattInstance(gatt, "characteristic write")) { return; } @@ -296,6 +297,7 @@ public final class BtLEQueue { public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { + LOG.debug("characteristic read: " + characteristic.getUuid()); if (!checkCorrectGattInstance(gatt, "characteristic read")) { return; } @@ -308,9 +310,40 @@ public final class BtLEQueue { checkWaitingCharacteristic(characteristic, status); } + @Override + public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { + LOG.debug("descriptor read: " + descriptor.getUuid()); + if (!checkCorrectGattInstance(gatt, "descriptor read")) { + return; + } + if (status != BluetoothGatt.GATT_SUCCESS) { + LOG.error("Reading descriptor " + descriptor.getUuid() + " failed: " + status); + } + if (mExternalGattCallback != null) { + mExternalGattCallback.onDescriptorRead(gatt, descriptor, status); + } + checkWaitingCharacteristic(descriptor.getCharacteristic(), status); + } + + @Override + public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { + LOG.debug("descriptor write: " + descriptor.getUuid()); + if (!checkCorrectGattInstance(gatt, "descriptor write")) { + return; + } + if (status != BluetoothGatt.GATT_SUCCESS) { + LOG.error("Writing descriptor " + descriptor.getUuid() + " failed: " + status); + } + if (mExternalGattCallback != null) { + mExternalGattCallback.onDescriptorWrite(gatt, descriptor, status); + } + checkWaitingCharacteristic(descriptor.getCharacteristic(), status); + } + @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + LOG.debug("characteristic changed: " + characteristic.getUuid()); if (!checkCorrectGattInstance(gatt, "characteristic changed")) { return; } @@ -325,6 +358,7 @@ public final class BtLEQueue { @Override public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { + LOG.debug("remote rssi: " + rssi); if (!checkCorrectGattInstance(gatt, "remote rssi")) { return; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/GattCallback.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/GattCallback.java index 90561270a..6bc005737 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/GattCallback.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/btle/GattCallback.java @@ -19,6 +19,7 @@ package nodomain.freeyourgadget.gadgetbridge.btle; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; /** * Callback interface handling gatt events. @@ -66,23 +67,23 @@ public interface GattCallback { void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic); -// /** -// * @see BluetoothGattCallback#onDescriptorRead(BluetoothGatt, BluetoothGattDescriptor, int) -// * @param gatt -// * @param descriptor -// * @param status -// */ -// public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, -// int status); -// -// /** -// * @see BluetoothGattCallback#onDescriptorWrite(BluetoothGatt, BluetoothGattDescriptor, int) -// * @param gatt -// * @param descriptor -// * @param status -// */ -// public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, -// int status); + /** + * @see BluetoothGattCallback#onDescriptorRead(BluetoothGatt, BluetoothGattDescriptor, int) + * @param gatt + * @param descriptor + * @param status + */ + public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, + int status); + + /** + * @see BluetoothGattCallback#onDescriptorWrite(BluetoothGatt, BluetoothGattDescriptor, int) + * @param gatt + * @param descriptor + * @param status + */ + public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, + int status); // // /** // * @see BluetoothGattCallback#onReliableWriteCompleted(BluetoothGatt, int) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandNotifyAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandNotifyAction.java index 486718fe1..508d4c40a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandNotifyAction.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandNotifyAction.java @@ -23,6 +23,7 @@ import nodomain.freeyourgadget.gadgetbridge.miband.MiBandService; 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); @@ -32,24 +33,34 @@ public class MiBandNotifyAction extends NotifyAction { public boolean run(BluetoothGatt gatt) { boolean result = super.run(gatt); if (result) { - BluetoothGattDescriptor sleepDescriptor = getCharacteristic().getDescriptor(MiBandService.UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION); - if (sleepDescriptor != null) { + BluetoothGattDescriptor notifyDescriptor = getCharacteristic().getDescriptor(MiBandService.UUID_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION); + if (notifyDescriptor != null) { int properties = getCharacteristic().getProperties(); if ((properties & 0x10) > 0) { - LOG.info("properties & 0x10 > 0"); - sleepDescriptor.setValue(enableFlag ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); - result = gatt.writeDescriptor(sleepDescriptor); + LOG.debug("properties & 0x10 > 0"); + notifyDescriptor.setValue(enableFlag ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); + result = gatt.writeDescriptor(notifyDescriptor); } else if ((properties & 0x20) > 0){ - LOG.info("properties & 0x20 > 0"); - sleepDescriptor.setValue(enableFlag ? BluetoothGattDescriptor.ENABLE_INDICATION_VALUE : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); - result = gatt.writeDescriptor(sleepDescriptor); + LOG.debug("properties & 0x20 > 0"); + 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/miband/MiBandSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java index 7bf967dc9..b3929df48 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/miband/MiBandSupport.java @@ -2,6 +2,7 @@ package nodomain.freeyourgadget.gadgetbridge.miband; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; import android.content.SharedPreferences; import android.preference.PreferenceManager; @@ -50,7 +51,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { @Override protected TransactionBuilder initializeDevice(TransactionBuilder builder) { - pair(builder).sendUserInfo(builder).setCurrentTime(builder).requestBatteryInfo(builder).enableNotifications(builder, true); + pair(builder).sendUserInfo(builder).enableNotifications(builder, true).setCurrentTime(builder).requestBatteryInfo(builder); return builder; } @@ -59,7 +60,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { private MiBandSupport enableNotifications(TransactionBuilder builder, boolean enable) { builder.notify(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_NOTIFICATION), enable) .notify(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_REALTIME_STEPS), enable) - .notify(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_ACTIVITY_DATA),enable) + .notify(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_ACTIVITY_DATA), enable) .notify(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_BATTERY), enable) .notify(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_SENSOR_DATA), enable); @@ -362,7 +363,6 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - LOG.info("Notification characteristic changed: " + characteristic.getUuid()); super.onCharacteristicChanged(gatt, characteristic); UUID characteristicUUID = characteristic.getUuid(); @@ -370,6 +370,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { handleActivityData(characteristic.getValue(), BluetoothGatt.GATT_SUCCESS); } } + @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {