From a5a923a752974fabec92143268b8bac4013f3da9 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Wed, 22 Feb 2023 02:23:11 +0100 Subject: [PATCH] Added `BluetoothDeviceNewDataEvent`. These events handle the case where a Bluetooth device only publishes new service data without advertising any additional updated properties. --- platypush/message/event/bluetooth/__init__.py | 7 +++++ platypush/plugins/bluetooth/ble/__init__.py | 29 +++++++++++++++---- platypush/plugins/bluetooth/ble/manifest.yaml | 1 + 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/platypush/message/event/bluetooth/__init__.py b/platypush/message/event/bluetooth/__init__.py index df9439fbf..5109c06ad 100644 --- a/platypush/message/event/bluetooth/__init__.py +++ b/platypush/message/event/bluetooth/__init__.py @@ -97,6 +97,13 @@ class BluetoothDeviceEvent(BluetoothWithPortEvent): ) +class BluetoothDeviceNewDataEvent(BluetoothDeviceEvent): + """ + Event triggered when a Bluetooth device publishes new manufacturer/service + data. + """ + + class BluetoothDeviceFoundEvent(BluetoothDeviceEvent): """ Event triggered when a Bluetooth device is discovered during a scan. diff --git a/platypush/plugins/bluetooth/ble/__init__.py b/platypush/plugins/bluetooth/ble/__init__.py index 2dd95ee93..014996779 100644 --- a/platypush/plugins/bluetooth/ble/__init__.py +++ b/platypush/plugins/bluetooth/ble/__init__.py @@ -30,6 +30,7 @@ from platypush.message.event.bluetooth import ( BluetoothDeviceDisconnectedEvent, BluetoothDeviceFoundEvent, BluetoothDeviceLostEvent, + BluetoothDeviceNewDataEvent, BluetoothDevicePairedEvent, BluetoothDeviceSignalUpdateEvent, BluetoothDeviceTrustedEvent, @@ -51,6 +52,13 @@ class BluetoothBlePlugin(AsyncRunnablePlugin, EntityManager): """ Plugin to interact with BLE (Bluetooth Low-Energy) devices. + This plugin uses `_Bleak_ `_ to interact + with the Bluetooth stack and `_Theengs_ `_ + to map the services exposed by the devices into native entities. + + The full list of devices natively supported can be found + `here `_. + Note that the support for Bluetooth low-energy devices requires a Bluetooth adapter compatible with the Bluetooth 5.0 specification or higher. @@ -67,6 +75,7 @@ class BluetoothBlePlugin(AsyncRunnablePlugin, EntityManager): * :class:`platypush.message.event.bluetooth.BluetoothDeviceDisconnectedEvent` * :class:`platypush.message.event.bluetooth.BluetoothDeviceFoundEvent` * :class:`platypush.message.event.bluetooth.BluetoothDeviceLostEvent` + * :class:`platypush.message.event.bluetooth.BluetoothDeviceNewDataEvent` * :class:`platypush.message.event.bluetooth.BluetoothDevicePairedEvent` * :class:`platypush.message.event.bluetooth.BluetoothDeviceTrustedEvent` * :class:`platypush.message.event.bluetooth.BluetoothDeviceUnblockedEvent` @@ -183,10 +192,11 @@ class BluetoothBlePlugin(AsyncRunnablePlugin, EntityManager): """ event_types: List[Type[BluetoothDeviceEvent]] = [] - existing_entity = self._entities.get(device.address) entity = device_to_entity(device, data) + existing_entity = self._entities.get(device.address) + existing_device = self._devices.get(device.address) - if existing_entity: + if existing_entity and existing_device: if existing_entity.paired != entity.paired: event_types.append( BluetoothDevicePairedEvent @@ -222,6 +232,15 @@ class BluetoothBlePlugin(AsyncRunnablePlugin, EntityManager): or existing_entity.tx_power != entity.tx_power ): event_types.append(BluetoothDeviceSignalUpdateEvent) + + if ( + existing_device.metadata.get('manufacturer_data', {}) + != device.metadata.get('manufacturer_data', {}) + ) or ( + existing_device.details.get('props', {}).get('ServiceData', {}) + != device.details.get('props', {}).get('ServiceData', {}) + ): + event_types.append(BluetoothDeviceNewDataEvent) else: event_types.append(BluetoothDeviceFoundEvent) @@ -235,10 +254,10 @@ class BluetoothBlePlugin(AsyncRunnablePlugin, EntityManager): self._post_event(event_type, device) self._device_last_updated_at[device.address] = time() - for child in entity.children: - child.parent = entity + for child in entity.children: + child.parent = entity - self.publish_entities([entity]) + self.publish_entities([entity]) def _has_changed(self, entity: BluetoothDevice) -> bool: existing_entity = self._entities.get(entity.id or entity.external_id) diff --git a/platypush/plugins/bluetooth/ble/manifest.yaml b/platypush/plugins/bluetooth/ble/manifest.yaml index e1ada8305..35de98b33 100644 --- a/platypush/plugins/bluetooth/ble/manifest.yaml +++ b/platypush/plugins/bluetooth/ble/manifest.yaml @@ -5,6 +5,7 @@ manifest: platypush.message.event.bluetooth.BluetoothDeviceDisconnectedEvent: platypush.message.event.bluetooth.BluetoothDeviceFoundEvent: platypush.message.event.bluetooth.BluetoothDeviceLostEvent: + platypush.message.event.bluetooth.BluetoothDeviceNewDataEvent: platypush.message.event.bluetooth.BluetoothDevicePairedEvent: platypush.message.event.bluetooth.BluetoothDeviceTrustedEvent: platypush.message.event.bluetooth.BluetoothDeviceUnblockedEvent: