From be21af0c7458875adb042ac8bd53879acc3d99f8 Mon Sep 17 00:00:00 2001 From: Peter Rosenberg Date: Sun, 3 Jan 2021 13:29:04 +0100 Subject: [PATCH 01/15] [bluetooth] Add BluetoothDevice.isNotifying() Signed-off-by: Peter Rosenberg --- .../bluetooth/bluegiga/BlueGigaBluetoothDevice.java | 6 ++++++ .../bluez/internal/BlueZBluetoothDevice.java | 13 +++++++++++++ .../openhab/binding/bluetooth/BluetoothDevice.java | 10 ++++++++++ .../binding/bluetooth/DelegateBluetoothDevice.java | 6 ++++++ .../binding/bluetooth/MockBluetoothDevice.java | 5 +++++ 5 files changed, 40 insertions(+) diff --git a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java index c2cb969e8fe4e..21af625982020 100644 --- a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java @@ -288,6 +288,12 @@ public boolean disableNotifications(BluetoothCharacteristic characteristic) { return true; } + @Override + public boolean isNotifying(BluetoothCharacteristic characteristic) { + // TODO will be implemented in a followup PR + return false; + } + @Override public boolean enableNotifications(BluetoothDescriptor descriptor) { // TODO will be implemented in a followup PR diff --git a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java index f4d78ab591e64..3cb8ef63babda 100644 --- a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java @@ -57,6 +57,7 @@ * * @author Kai Kreuzer - Initial contribution and API * @author Benjamin Lafois - Replaced tinyB with bluezDbus + * @author Peter Rosenberg - Improve notifications * */ @NonNullByDefault @@ -438,6 +439,18 @@ public boolean readCharacteristic(BluetoothCharacteristic characteristic) { return true; } + @Override + public boolean isNotifying(BluetoothCharacteristic characteristic) { + BluetoothGattCharacteristic c = getDBusBlueZCharacteristicByUUID(characteristic.getUuid().toString()); + if (c != null) { + Boolean isNotifying = c.isNotifying(); + return Objects.requireNonNullElse(isNotifying, false); + } else { + logger.warn("Characteristic '{}' is missing on device '{}'.", characteristic.getUuid(), address); + return false; + } + } + @Override public boolean disableNotifications(BluetoothCharacteristic characteristic) { BluetoothGattCharacteristic c = getDBusBlueZCharacteristicByUUID(characteristic.getUuid().toString()); diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDevice.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDevice.java index f9dfde0862b5d..e90d7ff2bdd44 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDevice.java @@ -28,6 +28,7 @@ * @author Chris Jackson - Initial contribution * @author Kai Kreuzer - Refactored class to use Integer instead of int, fixed bugs, diverse improvements * @author Connor Petty - Made most of the methods abstract + * @author Peter Rosenberg - Improve notifications */ @NonNullByDefault public abstract class BluetoothDevice { @@ -249,6 +250,15 @@ public BluetoothAdapter getAdapter() { */ public abstract boolean writeCharacteristic(BluetoothCharacteristic characteristic); + /** + * Returns if notification is enabled for the given characteristic. + * + * @param characteristic the {@link BluetoothCharacteristic} to disable notifications for. + * @return true if notification is enabled, false if notification is disabled, characteristic missing on device or + * notification not supported. + */ + public abstract boolean isNotifying(BluetoothCharacteristic characteristic); + /** * Enables notifications for a characteristic. Only a single read or write operation can be requested at once. * Attempting to perform an operation when one is already in progress will result in subsequent calls returning diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/DelegateBluetoothDevice.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/DelegateBluetoothDevice.java index bb4c37029bf1b..074d9a8f39e7e 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/DelegateBluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/DelegateBluetoothDevice.java @@ -112,6 +112,12 @@ public boolean writeCharacteristic(BluetoothCharacteristic characteristic) { return delegate != null && delegate.writeCharacteristic(characteristic); } + @Override + public boolean isNotifying(BluetoothCharacteristic characteristic) { + BluetoothDevice delegate = getDelegate(); + return delegate != null ? delegate.isNotifying(characteristic) : false; + } + @Override public boolean enableNotifications(BluetoothCharacteristic characteristic) { BluetoothDevice delegate = getDelegate(); diff --git a/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/MockBluetoothDevice.java b/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/MockBluetoothDevice.java index d5170cd071df5..892362f86c1d2 100644 --- a/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/MockBluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/MockBluetoothDevice.java @@ -102,6 +102,11 @@ public boolean enableNotifications(BluetoothCharacteristic characteristic) { return false; } + @Override + public boolean isNotifying(BluetoothCharacteristic characteristic) { + return false; + } + @Override public boolean disableNotifications(BluetoothCharacteristic characteristic) { return false; From 0a4b9ce2eada8bdee29475e119bf7c92089263fb Mon Sep 17 00:00:00 2001 From: Peter Rosenberg Date: Sun, 3 Jan 2021 15:19:34 +0100 Subject: [PATCH 02/15] [bluetooth] Improve Characteristic properties support Signed-off-by: Peter Rosenberg --- .../bluetooth/BluetoothCharacteristic.java | 16 +++ .../CharacteristicPropertiesTest.java | 101 ++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/CharacteristicPropertiesTest.java diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java index 0a014ecb36e93..90131a44ab23c 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java @@ -31,6 +31,7 @@ * * @author Chris Jackson - Initial contribution * @author Kai Kreuzer - Cleaned up code + * @author Peter Rosenberg - Improve properties support */ public class BluetoothCharacteristic { public static final int FORMAT_UINT8 = 0x11; @@ -142,6 +143,10 @@ public int getInstanceId() { return instance; } + public void setProperties(int properties) { + this.properties = properties; + } + /** * Returns the properties of this characteristic. * @@ -152,6 +157,17 @@ public int getProperties() { return properties; } + /** + * Returns if the given characteristics property is enabled or not. + * + * @param property one of the Constants BluetoothCharacteristic.PROPERTY_XX + * @return true if this characteristic has the given property enabled, false if properties not set or + * the given property is not enabled. + */ + public boolean hasPropertyEnabled(int property) { + return (properties & property) != 0; + } + /** * Returns the permissions for this characteristic. */ diff --git a/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/CharacteristicPropertiesTest.java b/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/CharacteristicPropertiesTest.java new file mode 100644 index 0000000000000..3d40537f6d550 --- /dev/null +++ b/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/CharacteristicPropertiesTest.java @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bluetooth; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.UUID; + +import org.junit.jupiter.api.Test; + +/** + * Tests {@link BluetoothCharacteristic}. + * + * @author Peter Rosenberg - Initial contribution + */ +public class CharacteristicPropertiesTest { + private BluetoothCharacteristic characteristic = new BluetoothCharacteristic(UUID.randomUUID(), 0); + + @Test + public void testAllSupportedProperties() { + // given + // when + int properties = 0; + properties |= BluetoothCharacteristic.PROPERTY_BROADCAST; + properties |= BluetoothCharacteristic.PROPERTY_READ; + properties |= BluetoothCharacteristic.PROPERTY_WRITE_NO_RESPONSE; + properties |= BluetoothCharacteristic.PROPERTY_WRITE; + properties |= BluetoothCharacteristic.PROPERTY_NOTIFY; + properties |= BluetoothCharacteristic.PROPERTY_INDICATE; + characteristic.setProperties(properties); + + // then + assertTrue(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_BROADCAST), "Broastcast not set"); + assertTrue(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_READ), "Read not set"); + assertTrue(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_WRITE_NO_RESPONSE), + "Write not response not set"); + assertTrue(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_WRITE), "Write not set"); + assertTrue(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_NOTIFY), "Notify not set"); + assertTrue(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_INDICATE), "Indicate not set"); + assertFalse(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_SIGNED_WRITE), + "Signed write set"); + assertFalse(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_EXTENDED_PROPS), + "Extended props set"); + } + + @Test + public void testNoProperties() { + // given + // when + int properties = 0; + characteristic.setProperties(properties); + + // then + assertFalse(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_BROADCAST), + "Broastcast not set"); + assertFalse(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_READ), "Read not set"); + assertFalse(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_WRITE_NO_RESPONSE), + "Write not response not set"); + assertFalse(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_WRITE), "Write not set"); + assertFalse(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_NOTIFY), "Notify not set"); + assertFalse(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_INDICATE), "Indicate not set"); + assertFalse(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_SIGNED_WRITE), + "Signed write set"); + assertFalse(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_EXTENDED_PROPS), + "Extended props set"); + } + + @Test + public void testSomeSupportedProperties() { + // given + // when + int properties = 0; + properties |= BluetoothCharacteristic.PROPERTY_READ; + properties |= BluetoothCharacteristic.PROPERTY_NOTIFY; + characteristic.setProperties(properties); + + // then + assertFalse(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_BROADCAST), + "Broastcast not set"); + assertTrue(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_READ), "Read not set"); + assertFalse(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_WRITE_NO_RESPONSE), + "Write not response not set"); + assertFalse(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_WRITE), "Write not set"); + assertTrue(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_NOTIFY), "Notify not set"); + assertFalse(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_INDICATE), "Indicate not set"); + assertFalse(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_SIGNED_WRITE), + "Signed write set"); + assertFalse(characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_EXTENDED_PROPS), + "Extended props set"); + } +} From 98c576a5a90b33bd6adc2295ee7ec2b668d276c8 Mon Sep 17 00:00:00 2001 From: Peter Rosenberg Date: Sun, 3 Jan 2021 15:20:04 +0100 Subject: [PATCH 03/15] [bluez] Improve Characteristic properties support Signed-off-by: Peter Rosenberg --- .../bluez/internal/BlueZBluetoothDevice.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java index 3cb8ef63babda..fb82b479fb9a1 100644 --- a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java @@ -57,7 +57,7 @@ * * @author Kai Kreuzer - Initial contribution and API * @author Benjamin Lafois - Replaced tinyB with bluezDbus - * @author Peter Rosenberg - Improve notifications + * @author Peter Rosenberg - Improve notifications and properties support * */ @NonNullByDefault @@ -400,6 +400,7 @@ public boolean discoverServices() { for (BluetoothGattCharacteristic dBusBlueZCharacteristic : dBusBlueZService.getGattCharacteristics()) { BluetoothCharacteristic characteristic = new BluetoothCharacteristic( UUID.fromString(dBusBlueZCharacteristic.getUuid()), 0); + convertCharacteristicProperties(dBusBlueZCharacteristic, characteristic); for (BluetoothGattDescriptor dBusBlueZDescriptor : dBusBlueZCharacteristic.getGattDescriptors()) { BluetoothDescriptor descriptor = new BluetoothDescriptor(characteristic, @@ -415,6 +416,35 @@ public boolean discoverServices() { return true; } + private void convertCharacteristicProperties(BluetoothGattCharacteristic dBusBlueZCharacteristic, BluetoothCharacteristic characteristic) { + int properties = 0; + + for (String property : dBusBlueZCharacteristic.getFlags()) { + switch (property) { + case "broadcast": + properties |= BluetoothCharacteristic.PROPERTY_BROADCAST; + break; + case "read": + properties |= BluetoothCharacteristic.PROPERTY_READ; + break; + case "write-without-response": + properties |= BluetoothCharacteristic.PROPERTY_WRITE_NO_RESPONSE; + break; + case "write": + properties |= BluetoothCharacteristic.PROPERTY_WRITE; + break; + case "notify": + properties |= BluetoothCharacteristic.PROPERTY_NOTIFY; + break; + case "indicate": + properties |= BluetoothCharacteristic.PROPERTY_INDICATE; + break; + } + } + + characteristic.setProperties(properties); + } + @Override public boolean readCharacteristic(BluetoothCharacteristic characteristic) { BluetoothGattCharacteristic c = getDBusBlueZCharacteristicByUUID(characteristic.getUuid().toString()); From 9ed8febd6047102dd1225e5b74c28137c0ab1c7f Mon Sep 17 00:00:00 2001 From: Peter Rosenberg Date: Sun, 3 Jan 2021 15:32:48 +0100 Subject: [PATCH 04/15] [bluetooth] Add BluetoothDevice.canNotify() Signed-off-by: Peter Rosenberg --- .../bluetooth/BluetoothCharacteristic.java | 6 ++++++ .../binding/bluetooth/BluetoothDevice.java | 17 ++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java index 90131a44ab23c..875ae46394117 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java @@ -143,6 +143,12 @@ public int getInstanceId() { return instance; } + /** + * Set the raw properties. The individual properties are represented as bits inside + * of this int value. + * + * @param properties of this Characteristic + */ public void setProperties(int properties) { this.properties = properties; } diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDevice.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDevice.java index e90d7ff2bdd44..51d7223df8c69 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDevice.java @@ -250,12 +250,23 @@ public BluetoothAdapter getAdapter() { */ public abstract boolean writeCharacteristic(BluetoothCharacteristic characteristic); + /** + * Returns if notifications can be enabled on the given characteristics. + * + * @param characteristic the {@link BluetoothCharacteristic} to check if notifications can be enabled. + * @return true if notifications can be enabled, false if notifications are not supported, characteristic is missing + * on device or notifications are not supported. + */ + public boolean canNotify(BluetoothCharacteristic characteristic) { + return characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_NOTIFY); + } + /** * Returns if notification is enabled for the given characteristic. * - * @param characteristic the {@link BluetoothCharacteristic} to disable notifications for. - * @return true if notification is enabled, false if notification is disabled, characteristic missing on device or - * notification not supported. + * @param characteristic the {@link BluetoothCharacteristic} to check if notifications are enabled. + * @return true if notification is enabled, false if notification is disabled, characteristic is missing on device + * or notifications are not supported. */ public abstract boolean isNotifying(BluetoothCharacteristic characteristic); From ffc8992bdcee0349a60dcbb597ad314c8fd2f6a3 Mon Sep 17 00:00:00 2001 From: Peter Rosenberg Date: Sun, 3 Jan 2021 15:49:50 +0100 Subject: [PATCH 05/15] [bluez] Also catch DBusExecutionException on read value Signed-off-by: Peter Rosenberg --- .../binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java index fb82b479fb9a1..f073830500573 100644 --- a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java @@ -459,7 +459,8 @@ public boolean readCharacteristic(BluetoothCharacteristic characteristic) { characteristic.setValue(value); notifyListeners(BluetoothEventType.CHARACTERISTIC_READ_COMPLETE, characteristic, BluetoothCompletionStatus.SUCCESS); - } catch (DBusException e) { + } catch (DBusException | DBusExecutionException e) { + // DBusExecutionException is thrown if the value cannot be read logger.debug("Exception occurred when trying to read characteristic '{}': {}", characteristic.getUuid(), e.getMessage()); notifyListeners(BluetoothEventType.CHARACTERISTIC_READ_COMPLETE, characteristic, From 1e26b0b80dddf66293117baca3c4b61995a278ab Mon Sep 17 00:00:00 2001 From: Peter Rosenberg Date: Sun, 3 Jan 2021 15:46:20 +0100 Subject: [PATCH 06/15] [bluetooth.generic] Activate notifications for linked channels where characteristics are able to notify Signed-off-by: Peter Rosenberg --- .../bluez/internal/BlueZBluetoothDevice.java | 3 +- .../internal/GenericBluetoothHandler.java | 58 ++++++++++++++----- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java index f073830500573..c2ddc31f3d992 100644 --- a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java @@ -416,7 +416,8 @@ public boolean discoverServices() { return true; } - private void convertCharacteristicProperties(BluetoothGattCharacteristic dBusBlueZCharacteristic, BluetoothCharacteristic characteristic) { + private void convertCharacteristicProperties(BluetoothGattCharacteristic dBusBlueZCharacteristic, + BluetoothCharacteristic characteristic) { int properties = 0; for (String property : dBusBlueZCharacteristic.getFlags()) { diff --git a/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java b/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java index 5717b08210729..929755650f157 100644 --- a/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java +++ b/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java @@ -58,6 +58,7 @@ * channels based off of a bluetooth device's GATT characteristics. * * @author Connor Petty - Initial contribution + * @author Peter Rosenberg - Use notifications * */ @NonNullByDefault @@ -84,20 +85,51 @@ public void initialize() { readCharacteristicJob = scheduler.scheduleWithFixedDelay(() -> { if (device.getConnectionState() == ConnectionState.CONNECTED) { if (resolved) { - for (CharacteristicHandler charHandler : charHandlers.values()) { - if (charHandler.canRead()) { - device.readCharacteristic(charHandler.characteristic); - try { - // TODO the ideal solution would be to use locks/conditions and timeouts - // between this code and `onCharacteristicReadComplete` but - // that would overcomplicate the code a bit and I plan - // on implementing a better more generalized solution later - Thread.sleep(50); - } catch (InterruptedException e) { - return; + // go through all characteristics of all services + this.device.getServices().forEach((service) -> { + service.getCharacteristics().forEach((characteristic) -> { + CharacteristicHandler charHandler; + if (device.canNotify(characteristic)) { + // If notifications can be enabled, we create the CharacteristicHandler + // if it not exists so that we can register notifications. + charHandler = charHandlers.computeIfAbsent(characteristic, CharacteristicHandler::new); + } else { + // Otherwise we let it being created by getCharacteristicHandler() and do + // nothing here if it is not created yet. + charHandler = charHandlers.get(characteristic); } - } - } + + if (charHandler != null) { + // Only read the value manually if notification is not on. + // Also read it the first time before we activate notifications below. + if (!device.isNotifying(characteristic) && charHandler.canRead()) { + device.readCharacteristic(characteristic); + try { + // TODO the ideal solution would be to use locks/conditions and timeouts + // between this code and `onCharacteristicReadComplete` but + // that would overcomplicate the code a bit and I plan + // on implementing a better more generalized solution later + Thread.sleep(50); + } catch (InterruptedException e) { + return; + } + } + if (device.canNotify(characteristic)) { + ChannelUID channelUID = charHandler.getChannelUID(null); + // Enabled/Disable notifications dependent on if the channel is linked. + if (isLinked(channelUID)) { + if (!device.isNotifying(characteristic)) { + device.enableNotifications(characteristic); + } + } else { + if (device.isNotifying(characteristic)) { + device.disableNotifications(characteristic); + } + } + } + } + }); + }); } else { // if we are connected and still haven't been able to resolve the services, try disconnecting and // then connecting again From 09259943a9be6bc3778b23926ae74ec8432d9750 Mon Sep 17 00:00:00 2001 From: Peter Rosenberg Date: Wed, 10 Feb 2021 19:15:44 +0100 Subject: [PATCH 07/15] [bluez] Adjust javadoc Signed-off-by: Peter Rosenberg --- .../bluetooth/bluez/internal/BlueZBluetoothDevice.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java index c2ddc31f3d992..509f21fa429a1 100644 --- a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/internal/BlueZBluetoothDevice.java @@ -416,6 +416,12 @@ public boolean discoverServices() { return true; } + /** + * Convert the flags of BluetoothGattCharacteristic to the int bitset used by BluetoothCharacteristic. + * + * @param dBusBlueZCharacteristic source characteristic to read the flags from + * @param characteristic destination characteristic to write to properties to + */ private void convertCharacteristicProperties(BluetoothGattCharacteristic dBusBlueZCharacteristic, BluetoothCharacteristic characteristic) { int properties = 0; From c2d759a75bb65d09a00587440f268d52b3cb6fd1 Mon Sep 17 00:00:00 2001 From: Peter Rosenberg Date: Sun, 14 Feb 2021 08:20:03 +0100 Subject: [PATCH 08/15] [bluegiga] Add BluetoothDevice.isNotifying() support Signed-off-by: Peter Rosenberg --- .../binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java index 21af625982020..4e92bbb6be953 100644 --- a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java @@ -290,8 +290,8 @@ public boolean disableNotifications(BluetoothCharacteristic characteristic) { @Override public boolean isNotifying(BluetoothCharacteristic characteristic) { - // TODO will be implemented in a followup PR - return false; + BlueGigaBluetoothCharacteristic ch = (BlueGigaBluetoothCharacteristic) characteristic; + return ch.isNotificationEnabled(); } @Override From 159b683fd4b760b2377fcf3b66a5bf76ebcf4c6d Mon Sep 17 00:00:00 2001 From: Peter Rosenberg Date: Sun, 14 Feb 2021 08:38:51 +0100 Subject: [PATCH 09/15] [bluegiga] Fix notification enabled check Signed-off-by: Peter Rosenberg --- .../binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java index 4e92bbb6be953..2c37168a8b36d 100644 --- a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java @@ -241,12 +241,12 @@ public boolean enableNotifications(BluetoothCharacteristic characteristic) { @Override public boolean disableNotifications(BluetoothCharacteristic characteristic) { if (connection == -1) { - logger.debug("Cannot enable notifications, device not connected {}", this); + logger.debug("Cannot disable notifications, device not connected {}", this); return false; } BlueGigaBluetoothCharacteristic ch = (BlueGigaBluetoothCharacteristic) characteristic; - if (ch.isNotificationEnabled()) { + if (!ch.isNotificationEnabled()) { return true; } From 26a9007bebead2076af6bb62ef17c6bc6029a8a1 Mon Sep 17 00:00:00 2001 From: Peter Rosenberg Date: Sun, 14 Feb 2021 09:18:28 +0100 Subject: [PATCH 10/15] [bluetooth] move canNotify() to Characteristic Signed-off-by: Peter Rosenberg --- .../generic/internal/GenericBluetoothHandler.java | 4 ++-- .../binding/bluetooth/BluetoothCharacteristic.java | 10 ++++++++++ .../openhab/binding/bluetooth/BluetoothDevice.java | 11 ----------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java b/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java index 929755650f157..12bc36353bc8d 100644 --- a/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java +++ b/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java @@ -89,7 +89,7 @@ public void initialize() { this.device.getServices().forEach((service) -> { service.getCharacteristics().forEach((characteristic) -> { CharacteristicHandler charHandler; - if (device.canNotify(characteristic)) { + if (characteristic.canNotify()) { // If notifications can be enabled, we create the CharacteristicHandler // if it not exists so that we can register notifications. charHandler = charHandlers.computeIfAbsent(characteristic, CharacteristicHandler::new); @@ -114,7 +114,7 @@ public void initialize() { return; } } - if (device.canNotify(characteristic)) { + if (characteristic.canNotify()) { ChannelUID channelUID = charHandler.getChannelUID(null); // Enabled/Disable notifications dependent on if the channel is linked. if (isLinked(channelUID)) { diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java index 875ae46394117..aa4afc74e9562 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java @@ -174,6 +174,16 @@ public boolean hasPropertyEnabled(int property) { return (properties & property) != 0; } + /** + * Returns if notifications can be enabled on this characteristic. + * + * @return true if notifications can be enabled, false if notifications are not supported, characteristic is missing + * on device or notifications are not supported. + */ + public boolean canNotify() { + return hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_NOTIFY); + } + /** * Returns the permissions for this characteristic. */ diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDevice.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDevice.java index 51d7223df8c69..ba1186829f12b 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDevice.java @@ -250,17 +250,6 @@ public BluetoothAdapter getAdapter() { */ public abstract boolean writeCharacteristic(BluetoothCharacteristic characteristic); - /** - * Returns if notifications can be enabled on the given characteristics. - * - * @param characteristic the {@link BluetoothCharacteristic} to check if notifications can be enabled. - * @return true if notifications can be enabled, false if notifications are not supported, characteristic is missing - * on device or notifications are not supported. - */ - public boolean canNotify(BluetoothCharacteristic characteristic) { - return characteristic.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_NOTIFY); - } - /** * Returns if notification is enabled for the given characteristic. * From 64897c0e16cdabf1a04560899cf56d9614b56415 Mon Sep 17 00:00:00 2001 From: Peter Rosenberg Date: Sun, 14 Feb 2021 19:20:51 +0100 Subject: [PATCH 11/15] [bluegiga] rename notificationEnabled to notifying Signed-off-by: Peter Rosenberg --- .../bluegiga/BlueGigaBluetoothCharacteristic.java | 10 +++++----- .../bluetooth/bluegiga/BlueGigaBluetoothDevice.java | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothCharacteristic.java b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothCharacteristic.java index afa8ba4843b83..43206c9b1c37f 100644 --- a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothCharacteristic.java +++ b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothCharacteristic.java @@ -27,7 +27,7 @@ */ public class BlueGigaBluetoothCharacteristic extends BluetoothCharacteristic { - private boolean notificationEnabled; + private boolean notifying; public BlueGigaBluetoothCharacteristic(int handle) { super(null, handle); @@ -45,11 +45,11 @@ public void setUUID(UUID uuid) { this.uuid = uuid; } - public boolean isNotificationEnabled() { - return notificationEnabled; + public boolean isNotifying() { + return notifying; } - public void setNotificationEnabled(boolean enable) { - this.notificationEnabled = enable; + public void setNotifying(boolean enable) { + this.notifying = enable; } } diff --git a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java index 2c37168a8b36d..ccff259a0b878 100644 --- a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java @@ -196,7 +196,7 @@ public boolean enableNotifications(BluetoothCharacteristic characteristic) { } BlueGigaBluetoothCharacteristic ch = (BlueGigaBluetoothCharacteristic) characteristic; - if (ch.isNotificationEnabled()) { + if (ch.isNotifying()) { return true; } @@ -246,7 +246,7 @@ public boolean disableNotifications(BluetoothCharacteristic characteristic) { } BlueGigaBluetoothCharacteristic ch = (BlueGigaBluetoothCharacteristic) characteristic; - if (!ch.isNotificationEnabled()) { + if (!ch.isNotifying()) { return true; } @@ -291,7 +291,7 @@ public boolean disableNotifications(BluetoothCharacteristic characteristic) { @Override public boolean isNotifying(BluetoothCharacteristic characteristic) { BlueGigaBluetoothCharacteristic ch = (BlueGigaBluetoothCharacteristic) characteristic; - return ch.isNotificationEnabled(); + return ch.isNotifying(); } @Override @@ -619,7 +619,7 @@ private void handleProcedureCompletedEvent(BlueGigaProcedureCompletedEvent event if (!success) { logger.debug("write to descriptor failed"); } - ((BlueGigaBluetoothCharacteristic) procedureCharacteristic).setNotificationEnabled(success); + ((BlueGigaBluetoothCharacteristic) procedureCharacteristic).setNotifying(success); procedureProgress = BlueGigaProcedure.NONE; procedureCharacteristic = null; break; @@ -628,7 +628,7 @@ private void handleProcedureCompletedEvent(BlueGigaProcedureCompletedEvent event if (!success) { logger.debug("write to descriptor failed"); } - ((BlueGigaBluetoothCharacteristic) procedureCharacteristic).setNotificationEnabled(!success); + ((BlueGigaBluetoothCharacteristic) procedureCharacteristic).setNotifying(!success); procedureProgress = BlueGigaProcedure.NONE; procedureCharacteristic = null; break; @@ -662,7 +662,7 @@ private void handleDisconnectedEvent(BlueGigaDisconnectedEvent event) { } for (BlueGigaBluetoothCharacteristic ch : handleToCharacteristic.values()) { - ch.setNotificationEnabled(false); + ch.setNotifying(false); } cancelTimer(procedureTimer); From e1124612ccad7cf14d8543879c19212cb43b71d5 Mon Sep 17 00:00:00 2001 From: Peter Rosenberg Date: Mon, 15 Feb 2021 19:26:51 +0100 Subject: [PATCH 12/15] [bluetooth.generic] use handlerToChannels to subscribe to notifications Signed-off-by: Peter Rosenberg --- .../internal/GenericBluetoothHandler.java | 68 ++++++++----------- 1 file changed, 28 insertions(+), 40 deletions(-) diff --git a/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java b/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java index 12bc36353bc8d..4f593144a3d47 100644 --- a/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java +++ b/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java @@ -69,6 +69,7 @@ public class GenericBluetoothHandler extends ConnectedBluetoothHandler { private final Map channelHandlers = new ConcurrentHashMap<>(); private final BluetoothGattParser gattParser = BluetoothGattParserFactory.getDefault(); private final CharacteristicChannelTypeProvider channelTypeProvider; + private final Map> handlerToChannels = new ConcurrentHashMap<>(); private @Nullable ScheduledFuture readCharacteristicJob = null; @@ -85,50 +86,34 @@ public void initialize() { readCharacteristicJob = scheduler.scheduleWithFixedDelay(() -> { if (device.getConnectionState() == ConnectionState.CONNECTED) { if (resolved) { - // go through all characteristics of all services - this.device.getServices().forEach((service) -> { - service.getCharacteristics().forEach((characteristic) -> { - CharacteristicHandler charHandler; - if (characteristic.canNotify()) { - // If notifications can be enabled, we create the CharacteristicHandler - // if it not exists so that we can register notifications. - charHandler = charHandlers.computeIfAbsent(characteristic, CharacteristicHandler::new); - } else { - // Otherwise we let it being created by getCharacteristicHandler() and do - // nothing here if it is not created yet. - charHandler = charHandlers.get(characteristic); + handlerToChannels.forEach((charHandler, channelUids) -> { + // Only read the value manually if notification is not on. + // Also read it the first time before we activate notifications below. + if (!device.isNotifying(charHandler.characteristic) && charHandler.canRead()) { + device.readCharacteristic(charHandler.characteristic); + try { + // TODO the ideal solution would be to use locks/conditions and timeouts + // Kbetween this code and `onCharacteristicReadComplete` but + // that would overcomplicate the code a bit and I plan + // on implementing a better more generalized solution later + Thread.sleep(50); + } catch (InterruptedException e) { + return; } - - if (charHandler != null) { - // Only read the value manually if notification is not on. - // Also read it the first time before we activate notifications below. - if (!device.isNotifying(characteristic) && charHandler.canRead()) { - device.readCharacteristic(characteristic); - try { - // TODO the ideal solution would be to use locks/conditions and timeouts - // between this code and `onCharacteristicReadComplete` but - // that would overcomplicate the code a bit and I plan - // on implementing a better more generalized solution later - Thread.sleep(50); - } catch (InterruptedException e) { - return; - } + } + if (charHandler.characteristic.canNotify()) { + ChannelUID channelUID = charHandler.getChannelUID(null); + // Enabled/Disable notifications dependent on if the channel is linked. + if (isLinked(channelUID)) { + if (!device.isNotifying(charHandler.characteristic)) { + device.enableNotifications(charHandler.characteristic); } - if (characteristic.canNotify()) { - ChannelUID channelUID = charHandler.getChannelUID(null); - // Enabled/Disable notifications dependent on if the channel is linked. - if (isLinked(channelUID)) { - if (!device.isNotifying(characteristic)) { - device.enableNotifications(characteristic); - } - } else { - if (device.isNotifying(characteristic)) { - device.disableNotifications(characteristic); - } - } + } else { + if (device.isNotifying(charHandler.characteristic)) { + device.disableNotifications(charHandler.characteristic); } } - }); + } }); } else { // if we are connected and still haven't been able to resolve the services, try disconnecting and @@ -149,6 +134,7 @@ public void dispose() { charHandlers.clear(); channelHandlers.clear(); + handlerToChannels.clear(); } @Override @@ -193,9 +179,11 @@ private void updateThingChannels() { logger.trace("{} processing characteristic {}", address, characteristic.getUuid()); CharacteristicHandler handler = getCharacteristicHandler(characteristic); List chans = handler.buildChannels(); + List chanUids = chans.stream().map(Channel::getUID).collect(Collectors.toList()); for (Channel channel : chans) { channelHandlers.put(channel.getUID(), handler); } + handlerToChannels.put(handler, chanUids); return chans.stream(); })// .collect(Collectors.toList()); From 3fbac6fc2500ad68d8c3a02178164e2e3f75b826 Mon Sep 17 00:00:00 2001 From: Peter Rosenberg Date: Mon, 15 Feb 2021 20:15:17 +0100 Subject: [PATCH 13/15] [bluetooth.generic] implement TODOs of canRead()/canWrite() Signed-off-by: Peter Rosenberg --- .../internal/GenericBluetoothHandler.java | 6 ++---- .../bluetooth/BluetoothCharacteristic.java | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java b/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java index 4f593144a3d47..bd950fd23c245 100644 --- a/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java +++ b/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java @@ -361,8 +361,7 @@ public boolean canRead() { if (gattParser.isKnownCharacteristic(charUUID)) { return gattParser.isValidForRead(charUUID); } - // TODO: need to evaluate this from characteristic properties, but such properties aren't support yet - return true; + return characteristic.canRead(); } public boolean canWrite() { @@ -370,8 +369,7 @@ public boolean canWrite() { if (gattParser.isKnownCharacteristic(charUUID)) { return gattParser.isValidForWrite(charUUID); } - // TODO: need to evaluate this from characteristic properties, but such properties aren't support yet - return true; + return characteristic.canWrite(); } private boolean isAdvanced() { diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java index aa4afc74e9562..dd591acc723f6 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java @@ -184,6 +184,25 @@ public boolean canNotify() { return hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_NOTIFY); } + /** + * Returns if the value can be read on this characteristic. + * + * @return true if the value can be read, false otherwise. + */ + public boolean canRead() { + return hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_READ); + } + + /** + * Returns if the value can be written on this characteristic. + * + * @return true if the value can be written with of without a response, false otherwise. + */ + public boolean canWrite() { + return hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_WRITE) + || hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_WRITE_NO_RESPONSE); + } + /** * Returns the permissions for this characteristic. */ From c372f6fd49f59a44d068136fc39e2fe58f468344 Mon Sep 17 00:00:00 2001 From: Peter Rosenberg Date: Mon, 15 Feb 2021 20:18:50 +0100 Subject: [PATCH 14/15] [bluetooth.generic] optimize ChannelUID Signed-off-by: Peter Rosenberg --- .../bluetooth/generic/internal/GenericBluetoothHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java b/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java index bd950fd23c245..0e2a83d0925de 100644 --- a/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java +++ b/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java @@ -180,8 +180,8 @@ private void updateThingChannels() { CharacteristicHandler handler = getCharacteristicHandler(characteristic); List chans = handler.buildChannels(); List chanUids = chans.stream().map(Channel::getUID).collect(Collectors.toList()); - for (Channel channel : chans) { - channelHandlers.put(channel.getUID(), handler); + for (ChannelUID channel : chanUids) { + channelHandlers.put(channel, handler); } handlerToChannels.put(handler, chanUids); return chans.stream(); From e89f593a19229db4a4617aa64695d0044d897f6c Mon Sep 17 00:00:00 2001 From: Peter Rosenberg Date: Mon, 15 Feb 2021 20:28:11 +0100 Subject: [PATCH 15/15] [bluetooth.generic] use channelUids for link check Signed-off-by: Peter Rosenberg --- .../bluetooth/generic/internal/GenericBluetoothHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java b/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java index 0e2a83d0925de..633170f4284e4 100644 --- a/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java +++ b/bundles/org.openhab.binding.bluetooth.generic/src/main/java/org/openhab/binding/bluetooth/generic/internal/GenericBluetoothHandler.java @@ -102,9 +102,9 @@ public void initialize() { } } if (charHandler.characteristic.canNotify()) { - ChannelUID channelUID = charHandler.getChannelUID(null); // Enabled/Disable notifications dependent on if the channel is linked. - if (isLinked(channelUID)) { + // TODO check why isLinked() is true for not linked channels + if (channelUids.stream().anyMatch(this::isLinked)) { if (!device.isNotifying(charHandler.characteristic)) { device.enableNotifications(charHandler.characteristic); }