From dc60e8db7549d44b668cb6487ee912b98d9c8336 Mon Sep 17 00:00:00 2001 From: Matthias Granberry Date: Mon, 18 Apr 2016 10:25:03 -0500 Subject: [PATCH] Character indications on connection as well. --- .../polidea/rxandroidble/RxBleConnection.java | 15 ++++++++ .../connection/RxBleConnectionImpl.java | 38 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/rxandroidble/src/main/java/com/polidea/rxandroidble/RxBleConnection.java b/rxandroidble/src/main/java/com/polidea/rxandroidble/RxBleConnection.java index 440050830..211fea70e 100644 --- a/rxandroidble/src/main/java/com/polidea/rxandroidble/RxBleConnection.java +++ b/rxandroidble/src/main/java/com/polidea/rxandroidble/RxBleConnection.java @@ -72,6 +72,21 @@ public String toString() { */ Observable> setupNotification(@NonNull UUID characteristicUuid); + /** + * Setup characteristic indication in order to receive callbacks when given characteristic has been changed. Returned observable will + * emit Observable once the indication setup has been completed. It is possible to setup more observables for the same + * characteristic and the lifecycle of the indication will be shared among them. + *

+ * Indication is automatically unregistered once this observable is unsubscribed. + * + * @param characteristicUuid Characteristic UUID for indication setup. + * @return Observable emitting another observable when the indication setup is complete. + * @throws BleCharacteristicNotFoundException if characteristic with given UUID hasn't been found. + * @throws BleCannotSetCharacteristicNotificationException if setup process indication setup process fail. This may be an internal + * reason or lack of permissions. + */ + Observable> setupIndication(@NonNull UUID characteristicUuid); + /** * Convenience method for characteristic retrieval. First step is service discovery which is followed by service/characteristic * traversal. This is an alias to: diff --git a/rxandroidble/src/main/java/com/polidea/rxandroidble/internal/connection/RxBleConnectionImpl.java b/rxandroidble/src/main/java/com/polidea/rxandroidble/internal/connection/RxBleConnectionImpl.java index 1fc4fa88c..20057eca5 100644 --- a/rxandroidble/src/main/java/com/polidea/rxandroidble/internal/connection/RxBleConnectionImpl.java +++ b/rxandroidble/src/main/java/com/polidea/rxandroidble/internal/connection/RxBleConnectionImpl.java @@ -27,6 +27,7 @@ import rx.Observable; import static android.bluetooth.BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE; +import static android.bluetooth.BluetoothGattDescriptor.ENABLE_INDICATION_VALUE; import static android.bluetooth.BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE; import static rx.Observable.create; import static rx.Observable.error; @@ -94,12 +95,37 @@ public Observable> setupNotification(@NonNull UUID characteri } } + @Override + public Observable> setupIndication(@NonNull UUID characteristicUuid) { + synchronized (notificationObservableMap) { + final Observable> availableObservable = notificationObservableMap.get(characteristicUuid); + + if (availableObservable != null) { + return availableObservable; + } + + final Observable> newObservable = createCharacteristicIndicationObservable(characteristicUuid) + .doOnUnsubscribe(() -> dismissCharacteristicNotification(characteristicUuid)) + .map(notificationDescriptorData -> observeOnCharacteristicChangeCallbacks(characteristicUuid)) + .replay(1) + .refCount(); + notificationObservableMap.put(characteristicUuid, newObservable); + return newObservable; + } + } + private Observable createCharacteristicNotificationObservable(UUID characteristicUuid) { return getClientConfigurationDescriptor(characteristicUuid) .flatMap(descriptor -> setupCharacteristicNotification(descriptor, true)) .flatMap(ObservableUtil::justOnNext); } + private Observable createCharacteristicIndicationObservable(UUID characteristicUuid) { + return getClientConfigurationDescriptor(characteristicUuid) + .flatMap(descriptor -> setupCharacteristicIndication(descriptor, true)) + .flatMap(ObservableUtil::justOnNext); + } + private void dismissCharacteristicNotification(UUID characteristicUuid) { synchronized (notificationObservableMap) { @@ -134,6 +160,18 @@ private Observable setupCharacteristicNotification(BluetoothGattDescript } } + @NonNull + private Observable setupCharacteristicIndication(BluetoothGattDescriptor bluetoothGattDescriptor, boolean enabled) { + final BluetoothGattCharacteristic characteristic = bluetoothGattDescriptor.getCharacteristic(); + + if (bluetoothGatt.setCharacteristicNotification(characteristic, enabled)) { + return writeDescriptor(bluetoothGattDescriptor, enabled ? ENABLE_INDICATION_VALUE : DISABLE_NOTIFICATION_VALUE) + .onErrorResumeNext(throwable -> error(new BleCannotSetCharacteristicNotificationException(characteristic))); + } else { + return error(new BleCannotSetCharacteristicNotificationException(characteristic)); + } + } + @NonNull private Observable getClientConfigurationDescriptor(UUID characteristicUuid) { return getCharacteristic(characteristicUuid)