[bluetooth] Add support for service data (#10278)
Signed-off-by: Peter Rosenberg <prosenb.dev@gmail.com>
This commit is contained in:
@@ -28,7 +28,9 @@ import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.bluetooth.BluetoothBindingConstants;
|
||||
import org.openhab.binding.bluetooth.BluetoothCharacteristic;
|
||||
import org.openhab.binding.bluetooth.BluetoothDevice.ConnectionState;
|
||||
import org.openhab.binding.bluetooth.BluetoothService;
|
||||
import org.openhab.binding.bluetooth.ConnectedBluetoothHandler;
|
||||
import org.openhab.binding.bluetooth.notification.BluetoothScanNotification;
|
||||
import org.openhab.bluetooth.gattparser.BluetoothGattParser;
|
||||
import org.openhab.bluetooth.gattparser.BluetoothGattParserFactory;
|
||||
import org.openhab.bluetooth.gattparser.FieldHolder;
|
||||
@@ -57,7 +59,7 @@ import org.slf4j.LoggerFactory;
|
||||
* channels based off of a bluetooth device's GATT characteristics.
|
||||
*
|
||||
* @author Connor Petty - Initial contribution
|
||||
* @author Peter Rosenberg - Use notifications
|
||||
* @author Peter Rosenberg - Use notifications, add support for ServiceData
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@@ -159,6 +161,71 @@ public class GenericBluetoothHandler extends ConnectedBluetoothHandler {
|
||||
getCharacteristicHandler(characteristic).handleCharacteristicUpdate(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScanRecordReceived(BluetoothScanNotification scanNotification) {
|
||||
super.onScanRecordReceived(scanNotification);
|
||||
|
||||
handleServiceData(scanNotification);
|
||||
}
|
||||
|
||||
/**
|
||||
* Service data is specified in the "Core Specification Supplement"
|
||||
* https://www.bluetooth.com/specifications/specs/
|
||||
* 1.11 SERVICE DATA
|
||||
* <p>
|
||||
* Broadcast configuration to configure what to advertise in service data
|
||||
* is specified in "Core Specification 5.3"
|
||||
* https://www.bluetooth.com/specifications/specs/
|
||||
* Part G: GENERIC ATTRIBUTE PROFILE (GATT): 2.7 CONFIGURED BROADCAST
|
||||
*
|
||||
* This method extracts ServiceData, finds the Service and the Characteristic it belongs
|
||||
* to and notifies a value change.
|
||||
*
|
||||
* @param scanNotification to get serviceData from
|
||||
*/
|
||||
private void handleServiceData(BluetoothScanNotification scanNotification) {
|
||||
Map<String, byte[]> serviceData = scanNotification.getServiceData();
|
||||
if (serviceData != null) {
|
||||
for (String uuidStr : serviceData.keySet()) {
|
||||
@Nullable
|
||||
BluetoothService service = device.getServices(UUID.fromString(uuidStr));
|
||||
if (service == null) {
|
||||
logger.warn("Service with UUID {} not found on {}, ignored.", uuidStr,
|
||||
scanNotification.getAddress());
|
||||
} else {
|
||||
// The ServiceData contains the UUID of the Service but no identifier of the
|
||||
// Characteristic the data belongs to.
|
||||
// Check which Characteristic within this service has the `Broadcast` property set
|
||||
// and select this one as the Characteristic to assign the data to.
|
||||
List<BluetoothCharacteristic> broadcastCharacteristics = service.getCharacteristics().stream()
|
||||
.filter((characteristic) -> characteristic
|
||||
.hasPropertyEnabled(BluetoothCharacteristic.PROPERTY_BROADCAST))
|
||||
.collect(Collectors.toUnmodifiableList());
|
||||
|
||||
if (broadcastCharacteristics.size() == 0) {
|
||||
logger.info(
|
||||
"No Characteristic of service with UUID {} on {} has the broadcast property set, ignored.",
|
||||
uuidStr, scanNotification.getAddress());
|
||||
} else if (broadcastCharacteristics.size() > 1) {
|
||||
logger.warn(
|
||||
"Multiple Characteristics of service with UUID {} on {} have the broadcast property set what is not supported, ignored.",
|
||||
uuidStr, scanNotification.getAddress());
|
||||
} else {
|
||||
BluetoothCharacteristic broadcastCharacteristic = broadcastCharacteristics.get(0);
|
||||
|
||||
byte[] value = serviceData.get(uuidStr);
|
||||
if (value != null) {
|
||||
onCharacteristicUpdate(broadcastCharacteristic, value);
|
||||
} else {
|
||||
logger.warn("Service Data for Service with UUID {} on {} is null, ignored.", uuidStr,
|
||||
scanNotification.getAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateThingChannels() {
|
||||
List<Channel> channels = device.getServices().stream()//
|
||||
.flatMap(service -> service.getCharacteristics().stream())//
|
||||
|
||||
Reference in New Issue
Block a user