From 41ac8c860b5250979dcfd5c5d2c2aa8465aeefdc Mon Sep 17 00:00:00 2001 From: SuperFashi Date: Wed, 1 Jul 2020 22:35:59 -0400 Subject: [PATCH 1/8] Fix when characteristic updates value faster than asyncio schedule --- bleak/backends/corebluetooth/PeripheralDelegate.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bleak/backends/corebluetooth/PeripheralDelegate.py b/bleak/backends/corebluetooth/PeripheralDelegate.py index 0f5aad4b..a6d1135b 100644 --- a/bleak/backends/corebluetooth/PeripheralDelegate.py +++ b/bleak/backends/corebluetooth/PeripheralDelegate.py @@ -290,7 +290,7 @@ def peripheral_didDiscoverDescriptorsForCharacteristic_error_( @objc.python_method def did_update_value_for_characteristic( - self, peripheral: CBPeripheral, characteristic: CBCharacteristic, error: NSError + self, peripheral: CBPeripheral, characteristic: CBCharacteristic, value: bytes, error: NSError ): cUUID = characteristic.UUID().UUIDString() if error is not None: @@ -300,7 +300,7 @@ def did_update_value_for_characteristic( notify_callback = self._characteristic_notify_callbacks.get(cUUID) if notify_callback: - notify_callback(cUUID, characteristic.value()) + notify_callback(cUUID, value) logger.debug("Read characteristic value") event = self._characteristic_read_events.get(cUUID) @@ -318,6 +318,7 @@ def peripheral_didUpdateValueForCharacteristic_error_( self.did_update_value_for_characteristic, peripheral, characteristic, + characteristic.value(), error, ) From a845d80087f6e09b7b301b444192ee60709a78a9 Mon Sep 17 00:00:00 2001 From: Henrik Blidh Date: Thu, 2 Jul 2020 23:06:02 +0200 Subject: [PATCH 2/8] Tiny mod and Changelog for changes in #240. Evaluated need for descriptor changes related to #240, but since no notifications are present on descriptors, there is no need for improved value handling. Fixes #240 --- CHANGELOG.rst | 8 ++++++++ bleak/backends/corebluetooth/PeripheralDelegate.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 1ec65873..98c41a11 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,6 +7,14 @@ All notable changes to this project will be documented in this file. The format is based on `Keep a Changelog `_, and this project adheres to `Semantic Versioning `_. +`Unreleased`_ +------------- + +Fixed +~~~~~ + +* Fix when characteristic updates value faster than asyncio schedule (#240 & #241) + `0.7.0`_ (2020-06-30) --------------------- diff --git a/bleak/backends/corebluetooth/PeripheralDelegate.py b/bleak/backends/corebluetooth/PeripheralDelegate.py index a6d1135b..30a8857a 100644 --- a/bleak/backends/corebluetooth/PeripheralDelegate.py +++ b/bleak/backends/corebluetooth/PeripheralDelegate.py @@ -329,7 +329,7 @@ def did_update_value_for_descriptor( dUUID = descriptor.UUID().UUIDString() if error is not None: raise BleakError( - "Failed to read characteristic {}: {}".format(dUUID, error) + "Failed to read descriptor {}: {}".format(dUUID, error) ) logger.debug("Read descriptor value") From d78d78d23cf72c63514cb234cf62ef9e916ddf9c Mon Sep 17 00:00:00 2001 From: Henrik Blidh Date: Thu, 2 Jul 2020 23:13:28 +0200 Subject: [PATCH 3/8] Improved error handling on BlueZ backend. Fixes #238 --- CHANGELOG.rst | 5 +++++ bleak/backends/bluezdbus/client.py | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 98c41a11..a34d6fd7 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -10,6 +10,11 @@ and this project adheres to `Semantic Versioning Date: Thu, 2 Jul 2020 17:15:17 -0400 Subject: [PATCH 4/8] add CHANGELOG.rst to sdist --- MANIFEST.in | 1 + 1 file changed, 1 insertion(+) diff --git a/MANIFEST.in b/MANIFEST.in index 4aded436..e8fdfa35 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,5 @@ include AUTHORS.rst +include CHANGELOG.rst include CONTRIBUTING.rst include HISTORY.rst include LICENSE From 0793c522182c01153630e13f97a4fc56c99283e8 Mon Sep 17 00:00:00 2001 From: Henrik Blidh Date: Thu, 2 Jul 2020 23:30:11 +0200 Subject: [PATCH 5/8] Improved documentation regarding scanning filter. Relates to #230 --- CHANGELOG.rst | 1 + MANIFEST.in | 1 - docs/scanning.rst | 33 ++++++++++++++++++++++++++------- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a34d6fd7..95f68a3a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,7 @@ Changed ~~~~~~~ * Improved, more explantory error on BlueZ backend when ``BleakClient`` cannot find the desired device. (#238) +* Better-than-nothing documentation about scanning filters added (#230). Fixed ~~~~~ diff --git a/MANIFEST.in b/MANIFEST.in index e8fdfa35..907b8232 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,7 +1,6 @@ include AUTHORS.rst include CHANGELOG.rst include CONTRIBUTING.rst -include HISTORY.rst include LICENSE include README.rst diff --git a/docs/scanning.rst b/docs/scanning.rst index 3210cee0..c4950064 100644 --- a/docs/scanning.rst +++ b/docs/scanning.rst @@ -35,9 +35,8 @@ the manufacturer of the device respectively. BleakScanner ------------ -A new scanning class is being implemented, and is ready to be used for the .NET backend, -and partly for the macOS backend as well. -It can be used in a fashion similar to the old ``discover`` method, using its class method: +A new scanning class has being implemented. It can be used in a fashion similar to the +old ``discover`` method, using its class method: .. code-block:: python @@ -52,7 +51,7 @@ It can be used in a fashion similar to the old ``discover`` method, using its cl loop = asyncio.get_event_loop() loop.run_until_complete(run()) -But it can also be used as a separate object, either in a synchronous context manager way: +But it can also be used as a separate object, either in a asynchronous context manager way: .. code-block:: python @@ -94,14 +93,14 @@ or separately, calling ``start`` and ``stop`` methods on the scanner manually: loop.run_until_complete(run()) In the manual mode, it is possible to add an own callback that you want to call upon each -scanner detection, as can be seen above. There is also possibilities of adding scanning filters, -but these differ so widely between implementations, so these details are recorded there instead. +scanner detection, as can be seen above. There are also possibilities of adding scanning filters, +which differ widely between OS backend implementations, so the instructions merit careful reading. Scanning Filters ---------------- There are some scanning filters that can be applied, that will reduce your scanning -results prior to them getting to bleak. These are pretty quite backend specific, but +results prior to them getting to bleak. These are quite backend specific, but they are generally used like this: - On the `discover` method, send in keyword arguments according to what is @@ -112,3 +111,23 @@ they are generally used like this: Scanning filters are currently implemented in Windows and BlueZ backends, but not yet in the macOS backend. + +Scanning filter examples in .NET backend +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To be written. In the meantime, check docstrings +`here `_ +and check out issue `#230 `_. + + +Scanning filter examples in BlueZ backend +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To be written. In the meantime, check +`docstrings `_. + + +Scanning filter examples in Core Bluetooth backend +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To be implemented. Exists in a draft in `PR #209 `_. From e0ee18f44f03e4225542891ede430bf9e823030e Mon Sep 17 00:00:00 2001 From: Henrik Blidh Date: Thu, 2 Jul 2020 23:41:23 +0200 Subject: [PATCH 6/8] Ran Black on code. --- CHANGELOG.rst | 1 + bleak/backends/bluezdbus/characteristic.py | 6 +- bleak/backends/bluezdbus/client.py | 53 +- bleak/backends/bluezdbus/descriptor.py | 8 +- bleak/backends/characteristic.py | 4 +- bleak/backends/client.py | 20 +- .../corebluetooth/CentralManagerDelegate.py | 32 +- .../corebluetooth/PeripheralDelegate.py | 43 +- .../backends/corebluetooth/characteristic.py | 9 +- bleak/backends/corebluetooth/client.py | 44 +- bleak/backends/corebluetooth/descriptor.py | 4 +- bleak/backends/corebluetooth/device.py | 1 - bleak/backends/corebluetooth/discovery.py | 2 +- bleak/backends/corebluetooth/scanner.py | 17 +- bleak/backends/corebluetooth/service.py | 2 +- bleak/backends/corebluetooth/utils.py | 2 +- bleak/backends/descriptor.py | 93 +- bleak/backends/device.py | 8 +- bleak/backends/dotnet/characteristic.py | 8 +- bleak/backends/dotnet/client.py | 26 +- bleak/backends/dotnet/descriptor.py | 4 +- bleak/backends/dotnet/discovery.py | 27 +- bleak/backends/dotnet/service.py | 4 +- bleak/backends/service.py | 18 +- bleak/uuids.py | 934 +++++++++--------- examples/disconnect_callback.py | 4 +- examples/enable_notifications.py | 4 +- examples/sensortag.py | 4 +- examples/service_explorer.py | 6 +- examples/two_devices.py | 13 +- tests/test_imports.py | 3 +- 31 files changed, 803 insertions(+), 601 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 95f68a3a..e84d7673 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,6 +15,7 @@ Changed * Improved, more explantory error on BlueZ backend when ``BleakClient`` cannot find the desired device. (#238) * Better-than-nothing documentation about scanning filters added (#230). +* Ran black on code which was forgotten in 0.7.0. Large diffs due to that. Fixed ~~~~~ diff --git a/bleak/backends/bluezdbus/characteristic.py b/bleak/backends/bluezdbus/characteristic.py index 614f5e03..4ed42b49 100644 --- a/bleak/backends/bluezdbus/characteristic.py +++ b/bleak/backends/bluezdbus/characteristic.py @@ -26,7 +26,7 @@ # "authorize" } -_handle_regex = re.compile('/char([0-9a-fA-F]*)') +_handle_regex = re.compile("/char([0-9a-fA-F]*)") class BleakGATTCharacteristicBlueZDBus(BleakGATTCharacteristic): @@ -92,7 +92,9 @@ def get_descriptor( if isinstance(specifier, int): return next(filter(lambda x: x.handle == specifier, self.descriptors)) else: - return next(filter(lambda x: x.uuid == str(specifier), self.descriptors)) + return next( + filter(lambda x: x.uuid == str(specifier), self.descriptors) + ) except StopIteration: return None diff --git a/bleak/backends/bluezdbus/client.py b/bleak/backends/bluezdbus/client.py index b786f174..017b8421 100644 --- a/bleak/backends/bluezdbus/client.py +++ b/bleak/backends/bluezdbus/client.py @@ -112,7 +112,9 @@ async def connect(self, **kwargs) -> bool: # is done in the `get_device_object_path` method. Try to get it from # BlueZ instead. # Otherwise, use the old fallback and hope for the best. - bluez_devices = list(filter(lambda d: d.address.lower() == self.address.lower(), discovered)) + bluez_devices = list( + filter(lambda d: d.address.lower() == self.address.lower(), discovered) + ) if bluez_devices: self._device_path = bluez_devices[0].details["path"] else: @@ -152,8 +154,12 @@ def _services_resolved_callback(message): except RemoteError as e: await self._cleanup_all() if 'Method "Connect" with signature "" on interface' in str(e): - raise BleakError("Device with address {0} could not be found. " - "Try increasing `timeout` value or moving the device closer.".format(self.address)) + raise BleakError( + "Device with address {0} could not be found. " + "Try increasing `timeout` value or moving the device closer.".format( + self.address + ) + ) else: raise BleakError(str(e)) @@ -350,7 +356,12 @@ async def get_services(self) -> BleakGATTServiceCollection: ) ) self.services.add_descriptor( - BleakGATTDescriptorBlueZDBus(desc, object_path, _characteristic[0].uuid, int(_characteristic[0].handle)) + BleakGATTDescriptorBlueZDBus( + desc, + object_path, + _characteristic[0].uuid, + int(_characteristic[0].handle), + ) ) self._services_resolved = True @@ -358,7 +369,11 @@ async def get_services(self) -> BleakGATTServiceCollection: # IO methods - async def read_gatt_char(self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], **kwargs) -> bytearray: + async def read_gatt_char( + self, + char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], + **kwargs + ) -> bytearray: """Perform read operation on the specified GATT characteristic. Args: @@ -408,7 +423,9 @@ async def read_gatt_char(self, char_specifier: Union[BleakGATTCharacteristic, in return value raise BleakError( - "Characteristic with UUID {0} could not be found!".format(char_specifier) + "Characteristic with UUID {0} could not be found!".format( + char_specifier + ) ) value = bytearray( @@ -462,7 +479,10 @@ async def read_gatt_descriptor(self, handle: int, **kwargs) -> bytearray: return value async def write_gatt_char( - self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], data: bytearray, response: bool = False + self, + char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], + data: bytearray, + response: bool = False, ) -> None: """Perform a write operation on the specified GATT characteristic. @@ -495,7 +515,8 @@ async def write_gatt_char( and "write-without-response" not in characteristic.properties ): raise BleakError( - "Characteristic %s does not support write operations!" % str(characteristic.uuid) + "Characteristic %s does not support write operations!" + % str(characteristic.uuid) ) if not response and "write-without-response" not in characteristic.properties: response = True @@ -617,10 +638,14 @@ def callback(sender, data): ): raise BleakError( "Notifications on Battery Level Char ({0}) is not " - "possible in BlueZ >= 5.48. Use regular read instead.".format(char_specifier) + "possible in BlueZ >= 5.48. Use regular read instead.".format( + char_specifier + ) ) raise BleakError( - "Characteristic with UUID {0} could not be found!".format(char_specifier) + "Characteristic with UUID {0} could not be found!".format( + char_specifier + ) ) await self._bus.callRemote( characteristic.path, @@ -647,7 +672,9 @@ def callback(sender, data): self._subscriptions.append(characteristic.handle) - async def stop_notify(self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID]) -> None: + async def stop_notify( + self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID] + ) -> None: """Deactivate notification/indication on a specified characteristic. Args: @@ -678,7 +705,9 @@ async def stop_notify(self, char_specifier: Union[BleakGATTCharacteristic, int, # DBUS introspection method for characteristics. - async def get_all_for_characteristic(self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID]) -> dict: + async def get_all_for_characteristic( + self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID] + ) -> dict: """Get all properties for a characteristic. This method should generally not be needed by end user, since it is a DBus specific method. diff --git a/bleak/backends/bluezdbus/descriptor.py b/bleak/backends/bluezdbus/descriptor.py index 5a7d09f7..20bc0cb3 100644 --- a/bleak/backends/bluezdbus/descriptor.py +++ b/bleak/backends/bluezdbus/descriptor.py @@ -4,7 +4,13 @@ class BleakGATTDescriptorBlueZDBus(BleakGATTDescriptor): """GATT Descriptor implementation for BlueZ DBus backend""" - def __init__(self, obj: dict, object_path: str, characteristic_uuid: str, characteristic_handle: int): + def __init__( + self, + obj: dict, + object_path: str, + characteristic_uuid: str, + characteristic_handle: int, + ): super(BleakGATTDescriptorBlueZDBus, self).__init__(obj) self.__path = object_path self.__characteristic_uuid = characteristic_uuid diff --git a/bleak/backends/characteristic.py b/bleak/backends/characteristic.py index 64078606..fb3c81c5 100644 --- a/bleak/backends/characteristic.py +++ b/bleak/backends/characteristic.py @@ -74,7 +74,9 @@ def descriptors(self) -> List: raise NotImplementedError() @abc.abstractmethod - def get_descriptor(self, specifier: Union[int, str, UUID]) -> Union[BleakGATTDescriptor, None]: + def get_descriptor( + self, specifier: Union[int, str, UUID] + ) -> Union[BleakGATTDescriptor, None]: """Get a descriptor by handle (int) or UUID (str or uuid.UUID)""" raise NotImplementedError() diff --git a/bleak/backends/client.py b/bleak/backends/client.py index 83fb7c8d..cd339eee 100644 --- a/bleak/backends/client.py +++ b/bleak/backends/client.py @@ -123,7 +123,11 @@ async def get_services(self) -> BleakGATTServiceCollection: # I/O methods @abc.abstractmethod - async def read_gatt_char(self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], **kwargs) -> bytearray: + async def read_gatt_char( + self, + char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], + **kwargs + ) -> bytearray: """Perform read operation on the specified GATT characteristic. Args: @@ -152,7 +156,10 @@ async def read_gatt_descriptor(self, handle: int, **kwargs) -> bytearray: @abc.abstractmethod async def write_gatt_char( - self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], data: bytearray, response: bool = False + self, + char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], + data: bytearray, + response: bool = False, ) -> None: """Perform a write operation on the specified GATT characteristic. @@ -179,7 +186,10 @@ async def write_gatt_descriptor(self, handle: int, data: bytearray) -> None: @abc.abstractmethod async def start_notify( - self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], callback: Callable[[str, Any], Any], **kwargs + self, + char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], + callback: Callable[[str, Any], Any], + **kwargs ) -> None: """Activate notifications/indications on a characteristic. @@ -202,7 +212,9 @@ def callback(sender, data): raise NotImplementedError() @abc.abstractmethod - async def stop_notify(self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID]) -> None: + async def stop_notify( + self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID] + ) -> None: """Deactivate notification/indication on a specified characteristic. Args: diff --git a/bleak/backends/corebluetooth/CentralManagerDelegate.py b/bleak/backends/corebluetooth/CentralManagerDelegate.py index add08e12..c09615b6 100644 --- a/bleak/backends/corebluetooth/CentralManagerDelegate.py +++ b/bleak/backends/corebluetooth/CentralManagerDelegate.py @@ -41,7 +41,7 @@ CBCentralManagerDelegate = objc.protocolNamed("CBCentralManagerDelegate") -_mac_version = list(map(int, platform.mac_ver()[0].split('.'))) +_mac_version = list(map(int, platform.mac_ver()[0].split("."))) _IS_PRE_10_13 = _mac_version[0] == 10 and _mac_version[1] < 13 @@ -189,8 +189,7 @@ def did_update_state(self, centralManager): def centralManagerDidUpdateState_(self, centralManager): logger.debug("centralManagerDidUpdateState_") self.event_loop.call_soon_threadsafe( - self.did_update_state, - centralManager, + self.did_update_state, centralManager, ) @objc.python_method @@ -231,8 +230,11 @@ def did_discover_peripheral( if callback: callback(peripheral, advertisementData, RSSI) - logger.debug("Discovered device {}: {} @ RSSI: {} (kCBAdvData {})".format( - uuid_string, device.name, RSSI, advertisementData.keys())) + logger.debug( + "Discovered device {}: {} @ RSSI: {} (kCBAdvData {})".format( + uuid_string, device.name, RSSI, advertisementData.keys() + ) + ) def centralManager_didDiscoverPeripheral_advertisementData_RSSI_( self, @@ -243,11 +245,7 @@ def centralManager_didDiscoverPeripheral_advertisementData_RSSI_( ): logger.debug("centralManager_didDiscoverPeripheral_advertisementData_RSSI_") self.event_loop.call_soon_threadsafe( - self.did_discover_peripheral, - central, - peripheral, - advertisementData, - RSSI, + self.did_discover_peripheral, central, peripheral, advertisementData, RSSI, ) @objc.python_method @@ -264,9 +262,7 @@ def did_connect_peripheral(self, central, peripheral): def centralManager_didConnectPeripheral_(self, central, peripheral): logger.debug("centralManager_didConnectPeripheral_") self.event_loop.call_soon_threadsafe( - self.did_connect_peripheral, - central, - peripheral, + self.did_connect_peripheral, central, peripheral, ) @objc.python_method @@ -285,10 +281,7 @@ def centralManager_didFailToConnectPeripheral_error_( ): logger.debug("centralManager_didFailToConnectPeripheral_error_") self.event_loop.call_soon_threadsafe( - self.did_fail_to_connect_peripheral, - centralManager, - peripheral, - error, + self.did_fail_to_connect_peripheral, centralManager, peripheral, error, ) @objc.python_method @@ -306,10 +299,7 @@ def centralManager_didDisconnectPeripheral_error_( ): logger.debug("centralManager_didDisconnectPeripheral_error_") self.event_loop.call_soon_threadsafe( - self.did_disconnect_peripheral, - central, - peripheral, - error, + self.did_disconnect_peripheral, central, peripheral, error, ) diff --git a/bleak/backends/corebluetooth/PeripheralDelegate.py b/bleak/backends/corebluetooth/PeripheralDelegate.py index 30a8857a..f1921180 100644 --- a/bleak/backends/corebluetooth/PeripheralDelegate.py +++ b/bleak/backends/corebluetooth/PeripheralDelegate.py @@ -20,7 +20,10 @@ NSData, NSError, ) -from CoreBluetooth import CBCharacteristicWriteWithResponse, CBCharacteristicWriteWithoutResponse +from CoreBluetooth import ( + CBCharacteristicWriteWithResponse, + CBCharacteristicWriteWithoutResponse, +) from bleak.exc import BleakError @@ -211,9 +214,7 @@ async def stopNotify_(self, characteristic: CBCharacteristic) -> bool: # Protocol Functions @objc.python_method - def did_discover_services( - self, peripheral: CBPeripheral, error: NSError - ) -> None: + def did_discover_services(self, peripheral: CBPeripheral, error: NSError) -> None: if error is not None: raise BleakError("Failed to discover services {}".format(error)) @@ -225,9 +226,7 @@ def peripheral_didDiscoverServices_( ) -> None: logger.debug("peripheral_didDiscoverServices_") self._event_loop.call_soon_threadsafe( - self.did_discover_services, - peripheral, - error, + self.did_discover_services, peripheral, error, ) @objc.python_method @@ -252,10 +251,7 @@ def peripheral_didDiscoverCharacteristicsForService_error_( ): logger.debug("peripheral_didDiscoverCharacteristicsForService_error_") self._event_loop.call_soon_threadsafe( - self.did_discover_characteristics_for_service, - peripheral, - service, - error, + self.did_discover_characteristics_for_service, peripheral, service, error, ) @objc.python_method @@ -290,7 +286,11 @@ def peripheral_didDiscoverDescriptorsForCharacteristic_error_( @objc.python_method def did_update_value_for_characteristic( - self, peripheral: CBPeripheral, characteristic: CBCharacteristic, value: bytes, error: NSError + self, + peripheral: CBPeripheral, + characteristic: CBCharacteristic, + value: bytes, + error: NSError, ): cUUID = characteristic.UUID().UUIDString() if error is not None: @@ -328,9 +328,7 @@ def did_update_value_for_descriptor( ): dUUID = descriptor.UUID().UUIDString() if error is not None: - raise BleakError( - "Failed to read descriptor {}: {}".format(dUUID, error) - ) + raise BleakError("Failed to read descriptor {}: {}".format(dUUID, error)) logger.debug("Read descriptor value") event = self._descriptor_read_events.get(dUUID) @@ -344,10 +342,7 @@ def peripheral_didUpdateValueForDescriptor_error_( ): logger.debug("peripheral_didUpdateValueForDescriptor_error_") self._event_loop.call_soon_threadsafe( - self.did_update_value_for_descriptor, - peripheral, - descriptor, - error, + self.did_update_value_for_descriptor, peripheral, descriptor, error, ) @objc.python_method @@ -373,10 +368,7 @@ def peripheral_didWriteValueForCharacteristic_error_( ): logger.debug("peripheral_didWriteValueForCharacteristic_error_") self._event_loop.call_soon_threadsafe( - self.did_write_value_for_characteristic, - peripheral, - characteristic, - error, + self.did_write_value_for_characteristic, peripheral, characteristic, error, ) @objc.python_method @@ -399,10 +391,7 @@ def peripheral_didWriteValueForDescriptor_error_( ): logger.debug("peripheral_didWriteValueForDescriptor_error_") self._event_loop.call_soon_threadsafe( - self.did_write_value_for_descriptor, - peripheral, - descriptor, - error, + self.did_write_value_for_descriptor, peripheral, descriptor, error, ) @objc.python_method diff --git a/bleak/backends/corebluetooth/characteristic.py b/bleak/backends/corebluetooth/characteristic.py index 22bd72fc..f4b954cc 100644 --- a/bleak/backends/corebluetooth/characteristic.py +++ b/bleak/backends/corebluetooth/characteristic.py @@ -14,6 +14,7 @@ from bleak.backends.descriptor import BleakGATTDescriptor from bleak.backends.corebluetooth.utils import cb_uuid_to_str + class CBChacteristicProperties(Enum): BROADCAST = 0x1 READ = 0x2 @@ -103,13 +104,17 @@ def descriptors(self) -> List[BleakGATTDescriptorCoreBluetooth]: """List of descriptors for this service""" return self.__descriptors - def get_descriptor(self, specifier) -> Union[BleakGATTDescriptorCoreBluetooth, None]: + def get_descriptor( + self, specifier + ) -> Union[BleakGATTDescriptorCoreBluetooth, None]: """Get a descriptor by handle (int) or UUID (str or uuid.UUID)""" try: if isinstance(specifier, int): return next(filter(lambda x: x.handle == specifier, self.descriptors)) else: - return next(filter(lambda x: x.uuid == str(specifier), self.descriptors)) + return next( + filter(lambda x: x.uuid == str(specifier), self.descriptors) + ) except StopIteration: return None diff --git a/bleak/backends/corebluetooth/client.py b/bleak/backends/corebluetooth/client.py index 4c314812..05ee42ec 100644 --- a/bleak/backends/corebluetooth/client.py +++ b/bleak/backends/corebluetooth/client.py @@ -10,11 +10,14 @@ from typing import Callable, Any, Union from Foundation import NSData, CBUUID -from CoreBluetooth import CBCharacteristicWriteWithResponse, CBCharacteristicWriteWithoutResponse +from CoreBluetooth import ( + CBCharacteristicWriteWithResponse, + CBCharacteristicWriteWithoutResponse, +) from bleak.backends.client import BaseBleakClient from bleak.backends.corebluetooth.characteristic import ( - BleakGATTCharacteristicCoreBluetooth + BleakGATTCharacteristicCoreBluetooth, ) from bleak.backends.corebluetooth.descriptor import BleakGATTDescriptorCoreBluetooth from bleak.backends.corebluetooth.discovery import discover @@ -131,9 +134,7 @@ async def get_services(self) -> BleakGATTServiceCollection: logger.debug("Retrieving services...") manager = self._device_info.manager().delegate() - services = ( - await manager.connected_peripheral_delegate.discoverServices() - ) + services = await manager.connected_peripheral_delegate.discoverServices() for service in services: serviceUUID = service.UUID().UUIDString() @@ -161,14 +162,21 @@ async def get_services(self) -> BleakGATTServiceCollection: for descriptor in descriptors: self.services.add_descriptor( BleakGATTDescriptorCoreBluetooth( - descriptor, characteristic.UUID().UUIDString(), int(characteristic.handle()) + descriptor, + characteristic.UUID().UUIDString(), + int(characteristic.handle()), ) ) self._services_resolved = True self._services = services return self.services - async def read_gatt_char(self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], use_cached=False, **kwargs) -> bytearray: + async def read_gatt_char( + self, + char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], + use_cached=False, + **kwargs + ) -> bytearray: """Perform read operation on the specified GATT characteristic. Args: @@ -230,7 +238,10 @@ async def read_gatt_descriptor( return value async def write_gatt_char( - self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], data: bytearray, response: bool = False + self, + char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], + data: bytearray, + response: bool = False, ) -> None: """Perform a write operation of the specified GATT characteristic. @@ -255,10 +266,14 @@ async def write_gatt_char( success = await manager.connected_peripheral_delegate.writeCharacteristic_value_type_( characteristic.obj, value, - CBCharacteristicWriteWithResponse if response else CBCharacteristicWriteWithoutResponse + CBCharacteristicWriteWithResponse + if response + else CBCharacteristicWriteWithoutResponse, ) if success: - logger.debug("Write Characteristic {0} : {1}".format(characteristic.uuid, data)) + logger.debug( + "Write Characteristic {0} : {1}".format(characteristic.uuid, data) + ) else: raise BleakError( "Could not write value {0} to characteristic {1}: {2}".format( @@ -294,7 +309,10 @@ async def write_gatt_descriptor(self, handle: int, data: bytearray) -> None: ) async def start_notify( - self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], callback: Callable[[str, Any], Any], **kwargs + self, + char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], + callback: Callable[[str, Any], Any], + **kwargs ) -> None: """Activate notifications/indications on a characteristic. @@ -333,7 +351,9 @@ def callback(sender, data): ) ) - async def stop_notify(self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID]) -> None: + async def stop_notify( + self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID] + ) -> None: """Deactivate notification/indication on a specified characteristic. Args: diff --git a/bleak/backends/corebluetooth/descriptor.py b/bleak/backends/corebluetooth/descriptor.py index de33e0b5..1ef5138a 100644 --- a/bleak/backends/corebluetooth/descriptor.py +++ b/bleak/backends/corebluetooth/descriptor.py @@ -12,7 +12,9 @@ class BleakGATTDescriptorCoreBluetooth(BleakGATTDescriptor): """GATT Descriptor implementation for CoreBluetooth backend""" - def __init__(self, obj: CBDescriptor, characteristic_uuid: str, characteristic_handle: int): + def __init__( + self, obj: CBDescriptor, characteristic_uuid: str, characteristic_handle: int + ): super(BleakGATTDescriptorCoreBluetooth, self).__init__(obj) self.obj = obj self.__characteristic_uuid = characteristic_uuid diff --git a/bleak/backends/corebluetooth/device.py b/bleak/backends/corebluetooth/device.py index 7aadafd4..453c437b 100644 --- a/bleak/backends/corebluetooth/device.py +++ b/bleak/backends/corebluetooth/device.py @@ -110,4 +110,3 @@ def __str__(self): # TODO: Evaluate how to interpret the value of the company identifier... return "{0}: {1} ({2})".format(self.address, mf, value) return "{0}: {1}".format(self.address, self.name) - diff --git a/bleak/backends/corebluetooth/discovery.py b/bleak/backends/corebluetooth/discovery.py index 3d80a444..5853c3c6 100644 --- a/bleak/backends/corebluetooth/discovery.py +++ b/bleak/backends/corebluetooth/discovery.py @@ -15,6 +15,7 @@ from bleak.backends.device import BLEDevice from bleak.exc import BleakError + async def discover( timeout: float = 5.0, loop: AbstractEventLoop = None, **kwargs ) -> List[BLEDevice]: @@ -44,4 +45,3 @@ async def discover( devices = manager.devices return list(devices.values()) - diff --git a/bleak/backends/corebluetooth/scanner.py b/bleak/backends/corebluetooth/scanner.py index 64383771..abee7bb3 100644 --- a/bleak/backends/corebluetooth/scanner.py +++ b/bleak/backends/corebluetooth/scanner.py @@ -34,6 +34,7 @@ class BleakScannerCoreBluetooth(BaseBleakScanner): ``stopScan_`` method. """ + def __init__(self, loop: AbstractEventLoop = None, **kwargs): super(BleakScannerCoreBluetooth, self).__init__(loop, **kwargs) self._callback = None @@ -70,7 +71,9 @@ async def stop(self): logger.warning("stopScan method could not be called: {0}".format(e)) async def set_scanning_filter(self, **kwargs): - raise NotImplementedError("Need to evaluate which macOS versions to support first...") + raise NotImplementedError( + "Need to evaluate which macOS versions to support first..." + ) async def get_discovered_devices(self) -> List[BLEDevice]: found = [] @@ -84,7 +87,9 @@ async def get_discovered_devices(self) -> List[BLEDevice]: details = peripheral advertisementData = self._identifiers[peripheral.identifier()] - manufacturer_binary_data = advertisementData.get("kCBAdvDataManufacturerData") + manufacturer_binary_data = advertisementData.get( + "kCBAdvDataManufacturerData" + ) manufacturer_data = {} if manufacturer_binary_data: manufacturer_id = int.from_bytes( @@ -101,7 +106,11 @@ async def get_discovered_devices(self) -> List[BLEDevice]: found.append( BLEDevice( - address, name, details, uuids=uuids, manufacturer_data=manufacturer_data + address, + name, + details, + uuids=uuids, + manufacturer_data=manufacturer_data, ) ) @@ -119,5 +128,3 @@ def is_scanning(self): return self._manager.isScanning_ except: return None - - diff --git a/bleak/backends/corebluetooth/service.py b/bleak/backends/corebluetooth/service.py index 6e6ef4d5..231c230c 100644 --- a/bleak/backends/corebluetooth/service.py +++ b/bleak/backends/corebluetooth/service.py @@ -3,7 +3,7 @@ from Foundation import CBService, CBUUID from bleak.backends.corebluetooth.characteristic import ( - BleakGATTCharacteristicCoreBluetooth + BleakGATTCharacteristicCoreBluetooth, ) from bleak.backends.service import BleakGATTService diff --git a/bleak/backends/corebluetooth/utils.py b/bleak/backends/corebluetooth/utils.py index bb1c92b4..53bc7303 100644 --- a/bleak/backends/corebluetooth/utils.py +++ b/bleak/backends/corebluetooth/utils.py @@ -3,7 +3,7 @@ def cb_uuid_to_str(_uuid: str) -> str: if len(_uuid) == 4: - return '0000{0}-0000-1000-8000-00805f9b34fb'.format(_uuid.lower()) + return "0000{0}-0000-1000-8000-00805f9b34fb".format(_uuid.lower()) # TODO: Evaluate if this is a necessary method... # elif _is_uuid_16bit_compatible(_uuid): # return _uuid[4:8].lower() diff --git a/bleak/backends/descriptor.py b/bleak/backends/descriptor.py index b8e4c707..5c7d3f4d 100644 --- a/bleak/backends/descriptor.py +++ b/bleak/backends/descriptor.py @@ -8,7 +8,98 @@ import abc from typing import Any -_descriptor_descriptions = {'00002905-0000-1000-8000-00805f9b34fb': ['Characteristic Aggregate Format', 'org.bluetooth.descriptor.gatt.characteristic_aggregate_format', '0x2905', 'GSS'], '00002900-0000-1000-8000-00805f9b34fb': ['Characteristic Extended Properties', 'org.bluetooth.descriptor.gatt.characteristic_extended_properties', '0x2900', 'GSS'], '00002904-0000-1000-8000-00805f9b34fb': ['Characteristic Presentation Format', 'org.bluetooth.descriptor.gatt.characteristic_presentation_format', '0x2904', 'GSS'], '00002901-0000-1000-8000-00805f9b34fb': ['Characteristic User Description', 'org.bluetooth.descriptor.gatt.characteristic_user_description', '0x2901', 'GSS'], '00002902-0000-1000-8000-00805f9b34fb': ['Client Characteristic Configuration', 'org.bluetooth.descriptor.gatt.client_characteristic_configuration', '0x2902', 'GSS'], '0000290B-0000-1000-8000-00805f9b34fb': ['Environmental Sensing Configuration', 'org.bluetooth.descriptor.es_configuration', '0x290B', 'GSS'], '0000290C-0000-1000-8000-00805f9b34fb': ['Environmental Sensing Measurement', 'org.bluetooth.descriptor.es_measurement', '0x290C', 'GSS'], '0000290D-0000-1000-8000-00805f9b34fb': ['Environmental Sensing Trigger Setting', 'org.bluetooth.descriptor.es_trigger_setting', '0x290D', 'GSS'], '00002907-0000-1000-8000-00805f9b34fb': ['External Report Reference', 'org.bluetooth.descriptor.external_report_reference', '0x2907', 'GSS'], '00002909-0000-1000-8000-00805f9b34fb': ['Number of Digitals', 'org.bluetooth.descriptor.number_of_digitals', '0x2909', 'GSS'], '00002908-0000-1000-8000-00805f9b34fb': ['Report Reference', 'org.bluetooth.descriptor.report_reference', '0x2908', 'GSS'], '00002903-0000-1000-8000-00805f9b34fb': ['Server Characteristic Configuration', 'org.bluetooth.descriptor.gatt.server_characteristic_configuration', '0x2903', 'GSS'], '0000290E-0000-1000-8000-00805f9b34fb': ['Time Trigger Setting', 'org.bluetooth.descriptor.time_trigger_setting', '0x290E', 'GSS'], '00002906-0000-1000-8000-00805f9b34fb': ['Valid Range', 'org.bluetooth.descriptor.valid_range', '0x2906', 'GSS'], '0000290A-0000-1000-8000-00805f9b34fb': ['Value Trigger Setting', 'org.bluetooth.descriptor.value_trigger_setting', '0x290A', 'GSS']} +_descriptor_descriptions = { + "00002905-0000-1000-8000-00805f9b34fb": [ + "Characteristic Aggregate Format", + "org.bluetooth.descriptor.gatt.characteristic_aggregate_format", + "0x2905", + "GSS", + ], + "00002900-0000-1000-8000-00805f9b34fb": [ + "Characteristic Extended Properties", + "org.bluetooth.descriptor.gatt.characteristic_extended_properties", + "0x2900", + "GSS", + ], + "00002904-0000-1000-8000-00805f9b34fb": [ + "Characteristic Presentation Format", + "org.bluetooth.descriptor.gatt.characteristic_presentation_format", + "0x2904", + "GSS", + ], + "00002901-0000-1000-8000-00805f9b34fb": [ + "Characteristic User Description", + "org.bluetooth.descriptor.gatt.characteristic_user_description", + "0x2901", + "GSS", + ], + "00002902-0000-1000-8000-00805f9b34fb": [ + "Client Characteristic Configuration", + "org.bluetooth.descriptor.gatt.client_characteristic_configuration", + "0x2902", + "GSS", + ], + "0000290B-0000-1000-8000-00805f9b34fb": [ + "Environmental Sensing Configuration", + "org.bluetooth.descriptor.es_configuration", + "0x290B", + "GSS", + ], + "0000290C-0000-1000-8000-00805f9b34fb": [ + "Environmental Sensing Measurement", + "org.bluetooth.descriptor.es_measurement", + "0x290C", + "GSS", + ], + "0000290D-0000-1000-8000-00805f9b34fb": [ + "Environmental Sensing Trigger Setting", + "org.bluetooth.descriptor.es_trigger_setting", + "0x290D", + "GSS", + ], + "00002907-0000-1000-8000-00805f9b34fb": [ + "External Report Reference", + "org.bluetooth.descriptor.external_report_reference", + "0x2907", + "GSS", + ], + "00002909-0000-1000-8000-00805f9b34fb": [ + "Number of Digitals", + "org.bluetooth.descriptor.number_of_digitals", + "0x2909", + "GSS", + ], + "00002908-0000-1000-8000-00805f9b34fb": [ + "Report Reference", + "org.bluetooth.descriptor.report_reference", + "0x2908", + "GSS", + ], + "00002903-0000-1000-8000-00805f9b34fb": [ + "Server Characteristic Configuration", + "org.bluetooth.descriptor.gatt.server_characteristic_configuration", + "0x2903", + "GSS", + ], + "0000290E-0000-1000-8000-00805f9b34fb": [ + "Time Trigger Setting", + "org.bluetooth.descriptor.time_trigger_setting", + "0x290E", + "GSS", + ], + "00002906-0000-1000-8000-00805f9b34fb": [ + "Valid Range", + "org.bluetooth.descriptor.valid_range", + "0x2906", + "GSS", + ], + "0000290A-0000-1000-8000-00805f9b34fb": [ + "Value Trigger Setting", + "org.bluetooth.descriptor.value_trigger_setting", + "0x290A", + "GSS", + ], +} class BleakGATTDescriptor(abc.ABC): diff --git a/bleak/backends/device.py b/bleak/backends/device.py index 4d90fa80..a1dc94a0 100644 --- a/bleak/backends/device.py +++ b/bleak/backends/device.py @@ -37,7 +37,9 @@ def rssi(self): elif hasattr(self.details, "RawSignalStrengthInDBm"): rssi = self.details.RawSignalStrengthInDBm elif hasattr(self.details, "Properties"): - rssi = {p.Key: p.Value for p in self.details.Properties}['System.Devices.Aep.SignalStrength'] + rssi = {p.Key: p.Value for p in self.details.Properties}[ + "System.Devices.Aep.SignalStrength" + ] else: rssi = None return int(rssi) if rssi is not None else None @@ -47,9 +49,9 @@ def __str__(self): if "manufacturer_data" in self.metadata: ks = list(self.metadata["manufacturer_data"].keys()) if len(ks): - mf = MANUFACTURERS.get(ks[0], MANUFACTURERS.get(0xffff)) + mf = MANUFACTURERS.get(ks[0], MANUFACTURERS.get(0xFFFF)) value = self.metadata["manufacturer_data"].get( - ks[0], MANUFACTURERS.get(0xffff) + ks[0], MANUFACTURERS.get(0xFFFF) ) # TODO: Evaluate how to interpret the value of the company identifier... return "{0}: {1} ({2})".format(self.address, mf, value) diff --git a/bleak/backends/dotnet/characteristic.py b/bleak/backends/dotnet/characteristic.py index fc662366..4c828f9c 100644 --- a/bleak/backends/dotnet/characteristic.py +++ b/bleak/backends/dotnet/characteristic.py @@ -84,13 +84,17 @@ def descriptors(self) -> List[BleakGATTDescriptorDotNet]: """List of descriptors for this service""" return self.__descriptors - def get_descriptor(self, specifier: Union[int, str, UUID]) -> Union[BleakGATTDescriptorDotNet, None]: + def get_descriptor( + self, specifier: Union[int, str, UUID] + ) -> Union[BleakGATTDescriptorDotNet, None]: """Get a descriptor by handle (int) or UUID (str or uuid.UUID)""" try: if isinstance(specifier, int): return next(filter(lambda x: x.handle == specifier, self.descriptors)) else: - return next(filter(lambda x: x.uuid == str(specifier), self.descriptors)) + return next( + filter(lambda x: x.uuid == str(specifier), self.descriptors) + ) except StopIteration: return None diff --git a/bleak/backends/dotnet/client.py b/bleak/backends/dotnet/client.py index edef7380..513b380f 100644 --- a/bleak/backends/dotnet/client.py +++ b/bleak/backends/dotnet/client.py @@ -322,7 +322,9 @@ async def get_services(self) -> BleakGATTServiceCollection: for descriptor in list(descriptors_result.Descriptors): self.services.add_descriptor( BleakGATTDescriptorDotNet( - descriptor, characteristic.Uuid.ToString(), int(characteristic.AttributeHandle) + descriptor, + characteristic.Uuid.ToString(), + int(characteristic.AttributeHandle), ) ) @@ -332,7 +334,10 @@ async def get_services(self) -> BleakGATTServiceCollection: # I/O methods async def read_gatt_char( - self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], use_cached=False, **kwargs + self, + char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], + use_cached=False, + **kwargs ) -> bytearray: """Perform read operation on the specified GATT characteristic. @@ -370,7 +375,9 @@ async def read_gatt_char( output = Array.CreateInstance(Byte, reader.UnconsumedBufferLength) reader.ReadBytes(output) value = bytearray(output) - logger.debug("Read Characteristic {0} : {1}".format(characteristic.uuid, value)) + logger.debug( + "Read Characteristic {0} : {1}".format(characteristic.uuid, value) + ) else: if read_result.Status == GattCommunicationStatus.ProtocolError: raise BleakDotNetTaskError( @@ -444,7 +451,10 @@ async def read_gatt_descriptor( return value async def write_gatt_char( - self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], data: bytearray, response: bool = False + self, + char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID], + data: bytearray, + response: bool = False, ) -> None: """Perform a write operation of the specified GATT characteristic. @@ -480,7 +490,9 @@ async def write_gatt_char( loop=self.loop, ) if write_result.Status == GattCommunicationStatus.Success: - logger.debug("Write Characteristic {0} : {1}".format(characteristic.uuid, data)) + logger.debug( + "Write Characteristic {0} : {1}".format(characteristic.uuid, data) + ) else: if write_result.Status == GattCommunicationStatus.ProtocolError: raise BleakError( @@ -652,7 +664,9 @@ async def _start_notify( return GattCommunicationStatus.AccessDenied return status - async def stop_notify(self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID]) -> None: + async def stop_notify( + self, char_specifier: Union[BleakGATTCharacteristic, int, str, uuid.UUID] + ) -> None: """Deactivate notification/indication on a specified characteristic. Args: diff --git a/bleak/backends/dotnet/descriptor.py b/bleak/backends/dotnet/descriptor.py index 27a16f2a..d92d5bc5 100644 --- a/bleak/backends/dotnet/descriptor.py +++ b/bleak/backends/dotnet/descriptor.py @@ -7,7 +7,9 @@ class BleakGATTDescriptorDotNet(BleakGATTDescriptor): """GATT Descriptor implementation for .NET backend""" - def __init__(self, obj: GattDescriptor, characteristic_uuid: str, characteristic_handle: int): + def __init__( + self, obj: GattDescriptor, characteristic_uuid: str, characteristic_handle: int + ): super(BleakGATTDescriptorDotNet, self).__init__(obj) self.obj = obj self.__characteristic_uuid = characteristic_uuid diff --git a/bleak/backends/dotnet/discovery.py b/bleak/backends/dotnet/discovery.py index 59b11484..e74d0678 100644 --- a/bleak/backends/dotnet/discovery.py +++ b/bleak/backends/dotnet/discovery.py @@ -18,8 +18,11 @@ from System import Array, Byte from Windows.Devices import Enumeration -from Windows.Devices.Bluetooth.Advertisement import \ - BluetoothLEAdvertisementWatcher, BluetoothLEScanningMode, BluetoothLEAdvertisementType +from Windows.Devices.Bluetooth.Advertisement import ( + BluetoothLEAdvertisementWatcher, + BluetoothLEScanningMode, + BluetoothLEAdvertisementType, +) from Windows.Storage.Streams import DataReader, IBuffer logger = logging.getLogger(__name__) @@ -127,13 +130,7 @@ def AdvertisementWatcher_Stopped(sender, e): if not local_name and d.BluetoothAddress in scan_responses: local_name = scan_responses[d.BluetoothAddress].Advertisement.LocalName found.append( - BLEDevice( - bdaddr, - local_name, - d, - uuids=uuids, - manufacturer_data=data, - ) + BLEDevice(bdaddr, local_name, d, uuids=uuids, manufacturer_data=data,) ) return found @@ -171,7 +168,9 @@ async def discover_by_enumeration( "System.Devices.Aep.SignalStrength", ] ) - aqs_all_bluetooth_le_devices = '(System.Devices.Aep.ProtocolId:="' '{bb7bb05e-5972-42b5-94fc-76eaa7084d49}")' + aqs_all_bluetooth_le_devices = ( + '(System.Devices.Aep.ProtocolId:="' '{bb7bb05e-5972-42b5-94fc-76eaa7084d49}")' + ) watcher = Enumeration.DeviceInformation.CreateWatcher( aqs_all_bluetooth_le_devices, requested_properties, @@ -251,7 +250,13 @@ def DeviceWatcher_Stopped(sender, obj): for d in devices.values(): properties = {p.Key: p.Value for p in d.Properties} found.append( - BLEDevice(properties["System.Devices.Aep.DeviceAddress"], d.Name, d, uuids=[], manufacturer_data=b'') + BLEDevice( + properties["System.Devices.Aep.DeviceAddress"], + d.Name, + d, + uuids=[], + manufacturer_data=b"", + ) ) return found diff --git a/bleak/backends/dotnet/service.py b/bleak/backends/dotnet/service.py index 2f56ebe2..e1f6e333 100644 --- a/bleak/backends/dotnet/service.py +++ b/bleak/backends/dotnet/service.py @@ -25,7 +25,9 @@ def characteristics(self) -> List[BleakGATTCharacteristicDotNet]: """List of characteristics for this service""" return self.__characteristics - def get_characteristic(self, _uuid: Union[str, UUID]) -> Union[BleakGATTCharacteristicDotNet, None]: + def get_characteristic( + self, _uuid: Union[str, UUID] + ) -> Union[BleakGATTCharacteristicDotNet, None]: """Get a characteristic by UUID""" try: return next(filter(lambda x: x.uuid == str(_uuid), self.characteristics)) diff --git a/bleak/backends/service.py b/bleak/backends/service.py index 26d7d80b..79c678aa 100644 --- a/bleak/backends/service.py +++ b/bleak/backends/service.py @@ -51,7 +51,9 @@ def add_characteristic(self, characteristic: BleakGATTCharacteristic): raise NotImplementedError() @abc.abstractmethod - def get_characteristic(self, _uuid: Union[str, UUID]) -> Union[BleakGATTCharacteristic, None]: + def get_characteristic( + self, _uuid: Union[str, UUID] + ) -> Union[BleakGATTCharacteristic, None]: """Get a characteristic by UUID""" raise NotImplementedError() @@ -122,15 +124,23 @@ def add_characteristic(self, characteristic: BleakGATTCharacteristic): "This characteristic is already present in this BleakGATTServiceCollection!" ) - def get_characteristic(self, specifier: Union[int, str, UUID]) -> BleakGATTCharacteristic: + def get_characteristic( + self, specifier: Union[int, str, UUID] + ) -> BleakGATTCharacteristic: """Get a characteristic by handle (int) or UUID (str or uuid.UUID)""" if isinstance(specifier, int): return self.characteristics.get(specifier, None) else: # Assume uuid usage. - x = list(filter(lambda x: x.uuid == str(specifier), self.characteristics.values())) + x = list( + filter( + lambda x: x.uuid == str(specifier), self.characteristics.values() + ) + ) if len(x) > 1: - raise BleakError("Multiple Characteristics with this UUID, refer to your desired characteristic by the `handle` attribute instead.") + raise BleakError( + "Multiple Characteristics with this UUID, refer to your desired characteristic by the `handle` attribute instead." + ) else: return x[0] if x else None diff --git a/bleak/uuids.py b/bleak/uuids.py index fb0ceadf..ef9fc62a 100644 --- a/bleak/uuids.py +++ b/bleak/uuids.py @@ -6,7 +6,7 @@ 0x0005: "TCS-BIN", 0x0007: "ATT", 0x0008: "OBEX", - 0x000f: "BNEP", + 0x000F: "BNEP", 0x0010: "UPNP", 0x0011: "HIDP", 0x0012: "Hardcopy Control Channel", @@ -14,9 +14,9 @@ 0x0016: "Hardcopy Notification", 0x0017: "AVCTP", 0x0019: "AVDTP", - 0x001b: "CMTP", - 0x001e: "MCAP Control Channel", - 0x001f: "MCAP Data Channel", + 0x001B: "CMTP", + 0x001E: "MCAP Control Channel", + 0x001F: "MCAP Data Channel", 0x0100: "L2CAP", # 0x0101 to 0x0fff undefined */ 0x1000: "Service Discovery Server Service Class", @@ -32,12 +32,12 @@ 0x1107: "IrMC Sync Command", 0x1108: "Headset", 0x1109: "Cordless Telephony", - 0x110a: "Audio Source", - 0x110b: "Audio Sink", - 0x110c: "A/V Remote Control Target", - 0x110d: "Advanced Audio Distribution", - 0x110e: "A/V Remote Control", - 0x110f: "A/V Remote Control Controller", + 0x110A: "Audio Source", + 0x110B: "Audio Sink", + 0x110C: "A/V Remote Control Target", + 0x110D: "Advanced Audio Distribution", + 0x110E: "A/V Remote Control", + 0x110F: "A/V Remote Control Controller", 0x1110: "Intercom", 0x1111: "Fax", 0x1112: "Headset AG", @@ -48,12 +48,12 @@ 0x1117: "GN", 0x1118: "Direct Printing", 0x1119: "Reference Printing", - 0x111a: "Basic Imaging Profile", - 0x111b: "Imaging Responder", - 0x111c: "Imaging Automatic Archive", - 0x111d: "Imaging Referenced Objects", - 0x111e: "Handsfree", - 0x111f: "Handsfree Audio Gateway", + 0x111A: "Basic Imaging Profile", + 0x111B: "Imaging Responder", + 0x111C: "Imaging Automatic Archive", + 0x111D: "Imaging Referenced Objects", + 0x111E: "Handsfree", + 0x111F: "Handsfree Audio Gateway", 0x1120: "Direct Printing Refrence Objects Service", 0x1121: "Reflected UI", 0x1122: "Basic Printing", @@ -64,9 +64,9 @@ 0x1127: "HCR Scan", 0x1128: "Common ISDN Access", # 0x1129 and 0x112a undefined */ - 0x112d: "SIM Access", - 0x112e: "Phonebook Access Client", - 0x112f: "Phonebook Access Server", + 0x112D: "SIM Access", + 0x112E: "Phonebook Access Client", + 0x112F: "Phonebook Access Server", 0x1130: "Phonebook Access", 0x1131: "Headset HS", 0x1132: "Message Access Server", @@ -77,8 +77,8 @@ 0x1137: "3D Display", 0x1138: "3D Glasses", 0x1139: "3D Synchronization", - 0x113a: "MPS Profile", - 0x113b: "MPS Service", + 0x113A: "MPS Profile", + 0x113B: "MPS Service", # 0x113c to 0x11ff undefined */ 0x1200: "PnP Information", 0x1201: "Generic Networking", @@ -108,11 +108,11 @@ 0x1807: "Next DST Change Service", 0x1808: "Glucose", 0x1809: "Health Thermometer", - 0x180a: "Device Information", + 0x180A: "Device Information", # 0x180b and 0x180c undefined */ - 0x180d: "Heart Rate", - 0x180e: "Phone Alert Status Service", - 0x180f: "Battery Service", + 0x180D: "Heart Rate", + 0x180E: "Phone Alert Status Service", + 0x180F: "Battery Service", 0x1810: "Blood Pressure", 0x1811: "Alert Notification Service", 0x1812: "Human Interface Device", @@ -123,12 +123,12 @@ # 0x1817 undefined */ 0x1818: "Cycling Power", 0x1819: "Location and Navigation", - 0x181a: "Environmental Sensing", - 0x181b: "Body Composition", - 0x181c: "User Data", - 0x181d: "Weight Scale", - 0x181e: "Bond Management", - 0x181f: "Continuous Glucose Monitoring", + 0x181A: "Environmental Sensing", + 0x181B: "Body Composition", + 0x181C: "User Data", + 0x181D: "Weight Scale", + 0x181E: "Bond Management", + 0x181F: "Continuous Glucose Monitoring", 0x1820: "Internet Protocol Support", 0x1821: "Indoor Positioning", 0x1822: "Pulse Oximeter", @@ -154,454 +154,454 @@ 0x2907: "External Report Reference", 0x2908: "Report Reference", 0x2909: "Number of Digitals", - 0x290a: "Value Trigger Setting", - 0x290b: "Environmental Sensing Configuration", - 0x290c: "Environmental Sensing Measurement", - 0x290d: "Environmental Sensing Trigger Setting", - 0x290e: "Time Trigger Setting", + 0x290A: "Value Trigger Setting", + 0x290B: "Environmental Sensing Configuration", + 0x290C: "Environmental Sensing Measurement", + 0x290D: "Environmental Sensing Trigger Setting", + 0x290E: "Time Trigger Setting", # 0x290f to 0x29ff undefined */ - 0x2a00: "Device Name", - 0x2a01: "Appearance", - 0x2a02: "Peripheral Privacy Flag", - 0x2a03: "Reconnection Address", - 0x2a04: "Peripheral Preferred Connection Parameters", - 0x2a05: "Service Changed", - 0x2a06: "Alert Level", - 0x2a07: "Tx Power Level", - 0x2a08: "Date Time", - 0x2a09: "Day of Week", - 0x2a0a: "Day Date Time", + 0x2A00: "Device Name", + 0x2A01: "Appearance", + 0x2A02: "Peripheral Privacy Flag", + 0x2A03: "Reconnection Address", + 0x2A04: "Peripheral Preferred Connection Parameters", + 0x2A05: "Service Changed", + 0x2A06: "Alert Level", + 0x2A07: "Tx Power Level", + 0x2A08: "Date Time", + 0x2A09: "Day of Week", + 0x2A0A: "Day Date Time", # 0x2a0b undefined */ - 0x2a0c: "Exact Time 256", - 0x2a0d: "DST Offset", - 0x2a0e: "Time Zone", - 0x2a0f: "Local Time Information", + 0x2A0C: "Exact Time 256", + 0x2A0D: "DST Offset", + 0x2A0E: "Time Zone", + 0x2A0F: "Local Time Information", # 0x2a10 undefined */ - 0x2a11: "Time with DST", - 0x2a12: "Time Accuracy", - 0x2a13: "Time Source", - 0x2a14: "Reference Time Information", + 0x2A11: "Time with DST", + 0x2A12: "Time Accuracy", + 0x2A13: "Time Source", + 0x2A14: "Reference Time Information", # 0x2a15 undefined */ - 0x2a16: "Time Update Control Point", - 0x2a17: "Time Update State", - 0x2a18: "Glucose Measurement", - 0x2a19: "Battery Level", + 0x2A16: "Time Update Control Point", + 0x2A17: "Time Update State", + 0x2A18: "Glucose Measurement", + 0x2A19: "Battery Level", # 0x2a1a and 0x2a1b undefined */ - 0x2a1c: "Temperature Measurement", - 0x2a1d: "Temperature Type", - 0x2a1e: "Intermediate Temperature", + 0x2A1C: "Temperature Measurement", + 0x2A1D: "Temperature Type", + 0x2A1E: "Intermediate Temperature", # 0x2a1f and 0x2a20 undefined */ - 0x2a21: "Measurement Interval", - 0x2a22: "Boot Keyboard Input Report", - 0x2a23: "System ID", - 0x2a24: "Model Number String", - 0x2a25: "Serial Number String", - 0x2a26: "Firmware Revision String", - 0x2a27: "Hardware Revision String", - 0x2a28: "Software Revision String", - 0x2a29: "Manufacturer Name String", - 0x2a2a: "IEEE 11073-20601 Regulatory Cert. Data List", - 0x2a2b: "Current Time", - 0x2a2c: "Magnetic Declination", + 0x2A21: "Measurement Interval", + 0x2A22: "Boot Keyboard Input Report", + 0x2A23: "System ID", + 0x2A24: "Model Number String", + 0x2A25: "Serial Number String", + 0x2A26: "Firmware Revision String", + 0x2A27: "Hardware Revision String", + 0x2A28: "Software Revision String", + 0x2A29: "Manufacturer Name String", + 0x2A2A: "IEEE 11073-20601 Regulatory Cert. Data List", + 0x2A2B: "Current Time", + 0x2A2C: "Magnetic Declination", # 0x2a2d to 0x2a30 undefined */ - 0x2a31: "Scan Refresh", - 0x2a32: "Boot Keyboard Output Report", - 0x2a33: "Boot Mouse Input Report", - 0x2a34: "Glucose Measurement Context", - 0x2a35: "Blood Pressure Measurement", - 0x2a36: "Intermediate Cuff Pressure", - 0x2a37: "Heart Rate Measurement", - 0x2a38: "Body Sensor Location", - 0x2a39: "Heart Rate Control Point", + 0x2A31: "Scan Refresh", + 0x2A32: "Boot Keyboard Output Report", + 0x2A33: "Boot Mouse Input Report", + 0x2A34: "Glucose Measurement Context", + 0x2A35: "Blood Pressure Measurement", + 0x2A36: "Intermediate Cuff Pressure", + 0x2A37: "Heart Rate Measurement", + 0x2A38: "Body Sensor Location", + 0x2A39: "Heart Rate Control Point", # 0x2a3a to 0x2a3e undefined */ - 0x2a3f: "Alert Status", - 0x2a40: "Ringer Control Point", - 0x2a41: "Ringer Setting", - 0x2a42: "Alert Category ID Bit Mask", - 0x2a43: "Alert Category ID", - 0x2a44: "Alert Notification Control Point", - 0x2a45: "Unread Alert Status", - 0x2a46: "New Alert", - 0x2a47: "Supported New Alert Category", - 0x2a48: "Supported Unread Alert Category", - 0x2a49: "Blood Pressure Feature", - 0x2a4a: "HID Information", - 0x2a4b: "Report Map", - 0x2a4c: "HID Control Point", - 0x2a4d: "Report", - 0x2a4e: "Protocol Mode", - 0x2a4f: "Scan Interval Window", - 0x2a50: "PnP ID", - 0x2a51: "Glucose Feature", - 0x2a52: "Record Access Control Point", - 0x2a53: "RSC Measurement", - 0x2a54: "RSC Feature", - 0x2a55: "SC Control Point", - 0x2a56: "Digital", + 0x2A3F: "Alert Status", + 0x2A40: "Ringer Control Point", + 0x2A41: "Ringer Setting", + 0x2A42: "Alert Category ID Bit Mask", + 0x2A43: "Alert Category ID", + 0x2A44: "Alert Notification Control Point", + 0x2A45: "Unread Alert Status", + 0x2A46: "New Alert", + 0x2A47: "Supported New Alert Category", + 0x2A48: "Supported Unread Alert Category", + 0x2A49: "Blood Pressure Feature", + 0x2A4A: "HID Information", + 0x2A4B: "Report Map", + 0x2A4C: "HID Control Point", + 0x2A4D: "Report", + 0x2A4E: "Protocol Mode", + 0x2A4F: "Scan Interval Window", + 0x2A50: "PnP ID", + 0x2A51: "Glucose Feature", + 0x2A52: "Record Access Control Point", + 0x2A53: "RSC Measurement", + 0x2A54: "RSC Feature", + 0x2A55: "SC Control Point", + 0x2A56: "Digital", # 0x2a57 undefined */ - 0x2a58: "Analog", + 0x2A58: "Analog", # 0x2a59 undefined */ - 0x2a5a: "Aggregate", - 0x2a5b: "CSC Measurement", - 0x2a5c: "CSC Feature", - 0x2a5d: "Sensor Location", + 0x2A5A: "Aggregate", + 0x2A5B: "CSC Measurement", + 0x2A5C: "CSC Feature", + 0x2A5D: "Sensor Location", # 0x2a5e to 0x2a62 undefined */ - 0x2a63: "Cycling Power Measurement", - 0x2a64: "Cycling Power Vector", - 0x2a65: "Cycling Power Feature", - 0x2a66: "Cycling Power Control Point", - 0x2a67: "Location and Speed", - 0x2a68: "Navigation", - 0x2a69: "Position Quality", - 0x2a6a: "LN Feature", - 0x2a6b: "LN Control Point", - 0x2a6c: "Elevation", - 0x2a6d: "Pressure", - 0x2a6e: "Temperature", - 0x2a6f: "Humidity", - 0x2a70: "True Wind Speed", - 0x2a71: "True Wind Direction", - 0x2a72: "Apparent Wind Speed", - 0x2a73: "Apparent Wind Direction", - 0x2a74: "Gust Factor", - 0x2a75: "Pollen Concentration", - 0x2a76: "UV Index", - 0x2a77: "Irradiance", - 0x2a78: "Rainfall", - 0x2a79: "Wind Chill", - 0x2a7a: "Heat Index", - 0x2a7b: "Dew Point", - 0x2a7c: "Trend", - 0x2a7d: "Descriptor Value Changed", - 0x2a7e: "Aerobic Heart Rate Lower Limit", - 0x2a7f: "Aerobic Threshold", - 0x2a80: "Age", - 0x2a81: "Anaerobic Heart Rate Lower Limit", - 0x2a82: "Anaerobic Heart Rate Upper Limit", - 0x2a83: "Anaerobic Threshold", - 0x2a84: "Aerobic Heart Rate Upper Limit", - 0x2a85: "Date of Birth", - 0x2a86: "Date of Threshold Assessment", - 0x2a87: "Email Address", - 0x2a88: "Fat Burn Heart Rate Lower Limit", - 0x2a89: "Fat Burn Heart Rate Upper Limit", - 0x2a8a: "First Name", - 0x2a8b: "Five Zone Heart Rate Limits", - 0x2a8c: "Gender", - 0x2a8d: "Heart Rate Max", - 0x2a8e: "Height", - 0x2a8f: "Hip Circumference", - 0x2a90: "Last Name", - 0x2a91: "Maximum Recommended Heart Rate", - 0x2a92: "Resting Heart Rate", - 0x2a93: "Sport Type for Aerobic/Anaerobic Thresholds", - 0x2a94: "Three Zone Heart Rate Limits", - 0x2a95: "Two Zone Heart Rate Limit", - 0x2a96: "VO2 Max", - 0x2a97: "Waist Circumference", - 0x2a98: "Weight", - 0x2a99: "Database Change Increment", - 0x2a9a: "User Index", - 0x2a9b: "Body Composition Feature", - 0x2a9c: "Body Composition Measurement", - 0x2a9d: "Weight Measurement", - 0x2a9e: "Weight Scale Feature", - 0x2a9f: "User Control Point", - 0x2aa0: "Magnetic Flux Density - 2D", - 0x2aa1: "Magnetic Flux Density - 3D", - 0x2aa2: "Language", - 0x2aa3: "Barometric Pressure Trend", - 0x2aa4: "Bond Management Control Point", - 0x2aa5: "Bond Management Feature", - 0x2aa6: "Central Address Resolution", - 0x2aa7: "CGM Measurement", - 0x2aa8: "CGM Feature", - 0x2aa9: "CGM Status", - 0x2aaa: "CGM Session Start Time", - 0x2aab: "CGM Session Run Time", - 0x2aac: "CGM Specific Ops Control Point", - 0x2aad: "Indoor Positioning Configuration", - 0x2aae: "Latitude", - 0x2aaf: "Longitude", - 0x2ab0: "Local North Coordinate", - 0x2ab1: "Local East Coordinate", - 0x2ab2: "Floor Number", - 0x2ab3: "Altitude", - 0x2ab4: "Uncertainty", - 0x2ab5: "Location Name", - 0x2ab6: "URI", - 0x2ab7: "HTTP Headers", - 0x2ab8: "HTTP Status Code", - 0x2ab9: "HTTP Entity Body", - 0x2aba: "HTTP Control Point", - 0x2abb: "HTTPS Security", - 0x2abc: "TDS Control Point", - 0x2abd: "OTS Feature", - 0x2abe: "Object Name", - 0x2abf: "Object Type", - 0x2ac0: "Object Size", - 0x2ac1: "Object First-Created", - 0x2ac2: "Object Last-Modified", - 0x2ac3: "Object ID", - 0x2ac4: "Object Properties", - 0x2ac5: "Object Action Control Point", - 0x2ac6: "Object List Control Point", - 0x2ac7: "Object List Filter", - 0x2ac8: "Object Changed", - 0x2ac9: "Resolvable Private Address Only", + 0x2A63: "Cycling Power Measurement", + 0x2A64: "Cycling Power Vector", + 0x2A65: "Cycling Power Feature", + 0x2A66: "Cycling Power Control Point", + 0x2A67: "Location and Speed", + 0x2A68: "Navigation", + 0x2A69: "Position Quality", + 0x2A6A: "LN Feature", + 0x2A6B: "LN Control Point", + 0x2A6C: "Elevation", + 0x2A6D: "Pressure", + 0x2A6E: "Temperature", + 0x2A6F: "Humidity", + 0x2A70: "True Wind Speed", + 0x2A71: "True Wind Direction", + 0x2A72: "Apparent Wind Speed", + 0x2A73: "Apparent Wind Direction", + 0x2A74: "Gust Factor", + 0x2A75: "Pollen Concentration", + 0x2A76: "UV Index", + 0x2A77: "Irradiance", + 0x2A78: "Rainfall", + 0x2A79: "Wind Chill", + 0x2A7A: "Heat Index", + 0x2A7B: "Dew Point", + 0x2A7C: "Trend", + 0x2A7D: "Descriptor Value Changed", + 0x2A7E: "Aerobic Heart Rate Lower Limit", + 0x2A7F: "Aerobic Threshold", + 0x2A80: "Age", + 0x2A81: "Anaerobic Heart Rate Lower Limit", + 0x2A82: "Anaerobic Heart Rate Upper Limit", + 0x2A83: "Anaerobic Threshold", + 0x2A84: "Aerobic Heart Rate Upper Limit", + 0x2A85: "Date of Birth", + 0x2A86: "Date of Threshold Assessment", + 0x2A87: "Email Address", + 0x2A88: "Fat Burn Heart Rate Lower Limit", + 0x2A89: "Fat Burn Heart Rate Upper Limit", + 0x2A8A: "First Name", + 0x2A8B: "Five Zone Heart Rate Limits", + 0x2A8C: "Gender", + 0x2A8D: "Heart Rate Max", + 0x2A8E: "Height", + 0x2A8F: "Hip Circumference", + 0x2A90: "Last Name", + 0x2A91: "Maximum Recommended Heart Rate", + 0x2A92: "Resting Heart Rate", + 0x2A93: "Sport Type for Aerobic/Anaerobic Thresholds", + 0x2A94: "Three Zone Heart Rate Limits", + 0x2A95: "Two Zone Heart Rate Limit", + 0x2A96: "VO2 Max", + 0x2A97: "Waist Circumference", + 0x2A98: "Weight", + 0x2A99: "Database Change Increment", + 0x2A9A: "User Index", + 0x2A9B: "Body Composition Feature", + 0x2A9C: "Body Composition Measurement", + 0x2A9D: "Weight Measurement", + 0x2A9E: "Weight Scale Feature", + 0x2A9F: "User Control Point", + 0x2AA0: "Magnetic Flux Density - 2D", + 0x2AA1: "Magnetic Flux Density - 3D", + 0x2AA2: "Language", + 0x2AA3: "Barometric Pressure Trend", + 0x2AA4: "Bond Management Control Point", + 0x2AA5: "Bond Management Feature", + 0x2AA6: "Central Address Resolution", + 0x2AA7: "CGM Measurement", + 0x2AA8: "CGM Feature", + 0x2AA9: "CGM Status", + 0x2AAA: "CGM Session Start Time", + 0x2AAB: "CGM Session Run Time", + 0x2AAC: "CGM Specific Ops Control Point", + 0x2AAD: "Indoor Positioning Configuration", + 0x2AAE: "Latitude", + 0x2AAF: "Longitude", + 0x2AB0: "Local North Coordinate", + 0x2AB1: "Local East Coordinate", + 0x2AB2: "Floor Number", + 0x2AB3: "Altitude", + 0x2AB4: "Uncertainty", + 0x2AB5: "Location Name", + 0x2AB6: "URI", + 0x2AB7: "HTTP Headers", + 0x2AB8: "HTTP Status Code", + 0x2AB9: "HTTP Entity Body", + 0x2ABA: "HTTP Control Point", + 0x2ABB: "HTTPS Security", + 0x2ABC: "TDS Control Point", + 0x2ABD: "OTS Feature", + 0x2ABE: "Object Name", + 0x2ABF: "Object Type", + 0x2AC0: "Object Size", + 0x2AC1: "Object First-Created", + 0x2AC2: "Object Last-Modified", + 0x2AC3: "Object ID", + 0x2AC4: "Object Properties", + 0x2AC5: "Object Action Control Point", + 0x2AC6: "Object List Control Point", + 0x2AC7: "Object List Filter", + 0x2AC8: "Object Changed", + 0x2AC9: "Resolvable Private Address Only", # 0x2aca and 0x2acb undefined */ - 0x2acc: "Fitness Machine Feature", - 0x2acd: "Treadmill Data", - 0x2ace: "Cross Trainer Data", - 0x2acf: "Step Climber Data", - 0x2ad0: "Stair Climber Data", - 0x2ad1: "Rower Data", - 0x2ad2: "Indoor Bike Data", - 0x2ad3: "Training Status", - 0x2ad4: "Supported Speed Range", - 0x2ad5: "Supported Inclination Range", - 0x2ad6: "Supported Resistance Level Range", - 0x2ad7: "Supported Heart Rate Range", - 0x2ad8: "Supported Power Range", - 0x2ad9: "Fitness Machine Control Point", - 0x2ada: "Fitness Machine Status", - 0x2adb: "Mesh Provisioning Data In", - 0x2adc: "Mesh Provisioning Data Out", - 0x2add: "Mesh Proxy Data In", - 0x2ade: "Mesh Proxy Data Out", + 0x2ACC: "Fitness Machine Feature", + 0x2ACD: "Treadmill Data", + 0x2ACE: "Cross Trainer Data", + 0x2ACF: "Step Climber Data", + 0x2AD0: "Stair Climber Data", + 0x2AD1: "Rower Data", + 0x2AD2: "Indoor Bike Data", + 0x2AD3: "Training Status", + 0x2AD4: "Supported Speed Range", + 0x2AD5: "Supported Inclination Range", + 0x2AD6: "Supported Resistance Level Range", + 0x2AD7: "Supported Heart Rate Range", + 0x2AD8: "Supported Power Range", + 0x2AD9: "Fitness Machine Control Point", + 0x2ADA: "Fitness Machine Status", + 0x2ADB: "Mesh Provisioning Data In", + 0x2ADC: "Mesh Provisioning Data Out", + 0x2ADD: "Mesh Proxy Data In", + 0x2ADE: "Mesh Proxy Data Out", # vendor defined */ - 0xfeff: "GN Netcom", - 0xfefe: "GN ReSound A/S", - 0xfefd: "Gimbal: Inc.", - 0xfefc: "Gimbal: Inc.", - 0xfefb: "Stollmann E+V GmbH", - 0xfefa: "PayPal: Inc.", - 0xfef9: "PayPal: Inc.", - 0xfef8: "Aplix Corporation", - 0xfef7: "Aplix Corporation", - 0xfef6: "Wicentric: Inc.", - 0xfef5: "Dialog Semiconductor GmbH", - 0xfef4: "Google", - 0xfef3: "Google", - 0xfef2: "CSR", - 0xfef1: "CSR", - 0xfef0: "Intel", - 0xfeef: "Polar Electro Oy", - 0xfeee: "Polar Electro Oy", - 0xfeed: "Tile: Inc.", - 0xfeec: "Tile: Inc.", - 0xfeeb: "Swirl Networks: Inc.", - 0xfeea: "Swirl Networks: Inc.", - 0xfee9: "Quintic Corp.", - 0xfee8: "Quintic Corp.", - 0xfee7: "Tencent Holdings Limited", - 0xfee6: "Seed Labs: Inc.", - 0xfee5: "Nordic Semiconductor ASA", - 0xfee4: "Nordic Semiconductor ASA", - 0xfee3: "Anki: Inc.", - 0xfee2: "Anki: Inc.", - 0xfee1: "Anhui Huami Information Technology Co.", - 0xfee0: "Anhui Huami Information Technology Co.", - 0xfedf: "Design SHIFT", - 0xfede: "Coin: Inc.", - 0xfedd: "Jawbone", - 0xfedc: "Jawbone", - 0xfedb: "Perka: Inc.", - 0xfeda: "ISSC Technologies Corporation", - 0xfed9: "Pebble Technology Corporation", - 0xfed8: "Google", - 0xfed7: "Broadcom Corporation", - 0xfed6: "Broadcom Corporation", - 0xfed5: "Plantronics Inc.", - 0xfed4: "Apple: Inc.", - 0xfed3: "Apple: Inc.", - 0xfed2: "Apple: Inc.", - 0xfed1: "Apple: Inc.", - 0xfed0: "Apple: Inc.", - 0xfecf: "Apple: Inc.", - 0xfece: "Apple: Inc.", - 0xfecd: "Apple: Inc.", - 0xfecc: "Apple: Inc.", - 0xfecb: "Apple: Inc.", - 0xfeca: "Apple: Inc.", - 0xfec9: "Apple: Inc.", - 0xfec8: "Apple: Inc.", - 0xfec7: "Apple: Inc.", - 0xfec6: "Kocomojo: LLC", - 0xfec5: "Realtek Semiconductor Corp.", - 0xfec4: "PLUS Location Systems", - 0xfec3: "360fly: Inc.", - 0xfec2: "Blue Spark Technologies: Inc.", - 0xfec1: "KDDI Corporation", - 0xfec0: "KDDI Corporation", - 0xfebf: "Nod: Inc.", - 0xfebe: "Bose Corporation", - 0xfebd: "Clover Network: Inc.", - 0xfebc: "Dexcom: Inc.", - 0xfebb: "adafruit industries", - 0xfeba: "Tencent Holdings Limited", - 0xfeb9: "LG Electronics", - 0xfeb8: "Facebook: Inc.", - 0xfeb7: "Facebook: Inc.", - 0xfeb6: "Vencer Co: Ltd", - 0xfeb5: "WiSilica Inc.", - 0xfeb4: "WiSilica Inc.", - 0xfeb3: "Taobao", - 0xfeb2: "Microsoft Corporation", - 0xfeb1: "Electronics Tomorrow Limited", - 0xfeb0: "Nest Labs Inc.", - 0xfeaf: "Nest Labs Inc.", - 0xfeae: "Nokia Corporation", - 0xfead: "Nokia Corporation", - 0xfeac: "Nokia Corporation", - 0xfeab: "Nokia Corporation", - 0xfeaa: "Google", - 0xfea9: "Savant Systems LLC", - 0xfea8: "Savant Systems LLC", - 0xfea7: "UTC Fire and Security", - 0xfea6: "GoPro: Inc.", - 0xfea5: "GoPro: Inc.", - 0xfea4: "Paxton Access Ltd", - 0xfea3: "ITT Industries", - 0xfea2: "Intrepid Control Systems: Inc.", - 0xfea1: "Intrepid Control Systems: Inc.", - 0xfea0: "Google", - 0xfe9f: "Google", - 0xfe9e: "Dialog Semiconductor B.V.", - 0xfe9d: "Mobiquity Networks Inc", - 0xfe9c: "GSI Laboratories: Inc.", - 0xfe9b: "Samsara Networks: Inc", - 0xfe9a: "Estimote", - 0xfe99: "Currant: Inc.", - 0xfe98: "Currant: Inc.", - 0xfe97: "Tesla Motor Inc.", - 0xfe96: "Tesla Motor Inc.", - 0xfe95: "Xiaomi Inc.", - 0xfe94: "OttoQ Inc.", - 0xfe93: "OttoQ Inc.", - 0xfe92: "Jarden Safety & Security", - 0xfe91: "Shanghai Imilab Technology Co.,Ltd", - 0xfe90: "JUMA", - 0xfe8f: "CSR", - 0xfe8e: "ARM Ltd", - 0xfe8d: "Interaxon Inc.", - 0xfe8c: "TRON Forum", - 0xfe8b: "Apple: Inc.", - 0xfe8a: "Apple: Inc.", - 0xfe89: "B&O Play A/S", - 0xfe88: "SALTO SYSTEMS S.L.", - 0xfe87: "Qingdao Yeelink Information Technology Co.: Ltd. ( 青岛亿联客信息技术有限公司 )", - 0xfe86: "HUAWEI Technologies Co.: Ltd. ( 华为技术有限公司 )", - 0xfe85: "RF Digital Corp", - 0xfe84: "RF Digital Corp", - 0xfe83: "Blue Bite", - 0xfe82: "Medtronic Inc.", - 0xfe81: "Medtronic Inc.", - 0xfe80: "Doppler Lab", - 0xfe7f: "Doppler Lab", - 0xfe7e: "Awear Solutions Ltd", - 0xfe7d: "Aterica Health Inc.", - 0xfe7c: "Stollmann E+V GmbH", - 0xfe7b: "Orion Labs: Inc.", - 0xfe7a: "Bragi GmbH", - 0xfe79: "Zebra Technologies", - 0xfe78: "Hewlett-Packard Company", - 0xfe77: "Hewlett-Packard Company", - 0xfe76: "TangoMe", - 0xfe75: "TangoMe", - 0xfe74: "unwire", - 0xfe73: "St. Jude Medical: Inc.", - 0xfe72: "St. Jude Medical: Inc.", - 0xfe71: "Plume Design Inc", - 0xfe70: "Beijing Jingdong Century Trading Co.: Ltd.", - 0xfe6f: "LINE Corporation", - 0xfe6e: "The University of Tokyo", - 0xfe6d: "The University of Tokyo", - 0xfe6c: "TASER International: Inc.", - 0xfe6b: "TASER International: Inc.", - 0xfe6a: "Kontakt Micro-Location Sp. z o.o.", - 0xfe69: "Qualcomm Life Inc", - 0xfe68: "Qualcomm Life Inc", - 0xfe67: "Lab Sensor Solutions", - 0xfe66: "Intel Corporation", - 0xfe65: "CHIPOLO d.o.o.", - 0xfe64: "Siemens AG", - 0xfe63: "Connected Yard: Inc.", - 0xfe62: "Indagem Tech LLC", - 0xfe61: "Logitech International SA", - 0xfe60: "Lierda Science & Technology Group Co.: Ltd.", - 0xfe5F: "Eyefi: Inc.", - 0xfe5E: "Plastc Corporation", - 0xfe5D: "Grundfos A/S", - 0xfe5C: "million hunters GmbH", - 0xfe5B: "GT-tronics HK Ltd", - 0xfe5A: "Chronologics Corporation", - 0xfe59: "Nordic Semiconductor ASA", - 0xfe58: "Nordic Semiconductor ASA", - 0xfe57: "Dotted Labs", - 0xfe56: "Google Inc.", - 0xfe55: "Google Inc.", - 0xfe54: "Motiv: Inc.", - 0xfe53: "3M", - 0xfe52: "SetPoint Medical", - 0xfe51: "SRAM", - 0xfe50: "Google Inc.", - 0xfe4F: "Molekule: Inc.", - 0xfe4E: "NTT docomo", - 0xfe4D: "Casambi Technologies Oy", - 0xfe4C: "Volkswagen AG", - 0xfe4B: "Koninklijke Philips N.V.", - 0xfe4A: "OMRON HEALTHCARE Co.: Ltd.", - 0xfe49: "SenionLab AB", - 0xfe48: "General Motors", - 0xfe47: "General Motors", - 0xfe46: "B&O Play A/S", - 0xfe45: "Snapchat Inc", - 0xfe44: "SK Telecom", - 0xfe43: "Andreas Stihl AG & Co. KG", - 0xfe42: "Nets A/S", - 0xfe41: "Inugo Systems Limited", - 0xfe40: "Inugo Systems Limited", - 0xfe3F: "Friday Labs Limited", - 0xfe3E: "BD Medical", - 0xfe3D: "BD Medical", - 0xfe3C: "Alibaba", - 0xfe3B: "Dolby Laboratories", - 0xfe3A: "TTS Tooltechnic Systems AG & Co. KG", - 0xfe39: "TTS Tooltechnic Systems AG & Co. KG", - 0xfe38: "Spaceek LTD", - 0xfe37: "Spaceek LTD", - 0xfe36: "HUAWEI Technologies Co.: Ltd", - 0xfe35: "HUAWEI Technologies Co.: Ltd", - 0xfe34: "SmallLoop LLC", - 0xfe33: "CHIPOLO d.o.o.", - 0xfe32: "Pro-Mark: Inc.", - 0xfe31: "Volkswagen AG", - 0xfe30: "Volkswagen AG", - 0xfe2F: "CRESCO Wireless: Inc", - 0xfe2E: "ERi,Inc.", - 0xfe2D: "SMART INNOVATION Co.,Ltd", - 0xfe2C: "Google Inc.", - 0xfe2B: "ITT Industries", - 0xfe2A: "DaisyWorks: Inc.", - 0xfe29: "Gibson Innovations", - 0xfe28: "Ayla Network", - 0xfe27: "Google Inc.", - 0xfe26: "Google Inc.", - 0xfe25: "Apple: Inc.", - 0xfe24: "August Home Inc", - 0xfe23: "Zoll Medical Corporation", - 0xfe22: "Zoll Medical Corporation", - 0xfe21: "Bose Corporation", - 0xfe20: "Emerson", - 0xfe1F: "Garmin International: Inc.", - 0xfe1E: "Smart Innovations Co.: Ltd", - 0xfe1D: "Illuminati Instrument Corporation", - 0xfe1C: "NetMedia: Inc.", + 0xFEFF: "GN Netcom", + 0xFEFE: "GN ReSound A/S", + 0xFEFD: "Gimbal: Inc.", + 0xFEFC: "Gimbal: Inc.", + 0xFEFB: "Stollmann E+V GmbH", + 0xFEFA: "PayPal: Inc.", + 0xFEF9: "PayPal: Inc.", + 0xFEF8: "Aplix Corporation", + 0xFEF7: "Aplix Corporation", + 0xFEF6: "Wicentric: Inc.", + 0xFEF5: "Dialog Semiconductor GmbH", + 0xFEF4: "Google", + 0xFEF3: "Google", + 0xFEF2: "CSR", + 0xFEF1: "CSR", + 0xFEF0: "Intel", + 0xFEEF: "Polar Electro Oy", + 0xFEEE: "Polar Electro Oy", + 0xFEED: "Tile: Inc.", + 0xFEEC: "Tile: Inc.", + 0xFEEB: "Swirl Networks: Inc.", + 0xFEEA: "Swirl Networks: Inc.", + 0xFEE9: "Quintic Corp.", + 0xFEE8: "Quintic Corp.", + 0xFEE7: "Tencent Holdings Limited", + 0xFEE6: "Seed Labs: Inc.", + 0xFEE5: "Nordic Semiconductor ASA", + 0xFEE4: "Nordic Semiconductor ASA", + 0xFEE3: "Anki: Inc.", + 0xFEE2: "Anki: Inc.", + 0xFEE1: "Anhui Huami Information Technology Co.", + 0xFEE0: "Anhui Huami Information Technology Co.", + 0xFEDF: "Design SHIFT", + 0xFEDE: "Coin: Inc.", + 0xFEDD: "Jawbone", + 0xFEDC: "Jawbone", + 0xFEDB: "Perka: Inc.", + 0xFEDA: "ISSC Technologies Corporation", + 0xFED9: "Pebble Technology Corporation", + 0xFED8: "Google", + 0xFED7: "Broadcom Corporation", + 0xFED6: "Broadcom Corporation", + 0xFED5: "Plantronics Inc.", + 0xFED4: "Apple: Inc.", + 0xFED3: "Apple: Inc.", + 0xFED2: "Apple: Inc.", + 0xFED1: "Apple: Inc.", + 0xFED0: "Apple: Inc.", + 0xFECF: "Apple: Inc.", + 0xFECE: "Apple: Inc.", + 0xFECD: "Apple: Inc.", + 0xFECC: "Apple: Inc.", + 0xFECB: "Apple: Inc.", + 0xFECA: "Apple: Inc.", + 0xFEC9: "Apple: Inc.", + 0xFEC8: "Apple: Inc.", + 0xFEC7: "Apple: Inc.", + 0xFEC6: "Kocomojo: LLC", + 0xFEC5: "Realtek Semiconductor Corp.", + 0xFEC4: "PLUS Location Systems", + 0xFEC3: "360fly: Inc.", + 0xFEC2: "Blue Spark Technologies: Inc.", + 0xFEC1: "KDDI Corporation", + 0xFEC0: "KDDI Corporation", + 0xFEBF: "Nod: Inc.", + 0xFEBE: "Bose Corporation", + 0xFEBD: "Clover Network: Inc.", + 0xFEBC: "Dexcom: Inc.", + 0xFEBB: "adafruit industries", + 0xFEBA: "Tencent Holdings Limited", + 0xFEB9: "LG Electronics", + 0xFEB8: "Facebook: Inc.", + 0xFEB7: "Facebook: Inc.", + 0xFEB6: "Vencer Co: Ltd", + 0xFEB5: "WiSilica Inc.", + 0xFEB4: "WiSilica Inc.", + 0xFEB3: "Taobao", + 0xFEB2: "Microsoft Corporation", + 0xFEB1: "Electronics Tomorrow Limited", + 0xFEB0: "Nest Labs Inc.", + 0xFEAF: "Nest Labs Inc.", + 0xFEAE: "Nokia Corporation", + 0xFEAD: "Nokia Corporation", + 0xFEAC: "Nokia Corporation", + 0xFEAB: "Nokia Corporation", + 0xFEAA: "Google", + 0xFEA9: "Savant Systems LLC", + 0xFEA8: "Savant Systems LLC", + 0xFEA7: "UTC Fire and Security", + 0xFEA6: "GoPro: Inc.", + 0xFEA5: "GoPro: Inc.", + 0xFEA4: "Paxton Access Ltd", + 0xFEA3: "ITT Industries", + 0xFEA2: "Intrepid Control Systems: Inc.", + 0xFEA1: "Intrepid Control Systems: Inc.", + 0xFEA0: "Google", + 0xFE9F: "Google", + 0xFE9E: "Dialog Semiconductor B.V.", + 0xFE9D: "Mobiquity Networks Inc", + 0xFE9C: "GSI Laboratories: Inc.", + 0xFE9B: "Samsara Networks: Inc", + 0xFE9A: "Estimote", + 0xFE99: "Currant: Inc.", + 0xFE98: "Currant: Inc.", + 0xFE97: "Tesla Motor Inc.", + 0xFE96: "Tesla Motor Inc.", + 0xFE95: "Xiaomi Inc.", + 0xFE94: "OttoQ Inc.", + 0xFE93: "OttoQ Inc.", + 0xFE92: "Jarden Safety & Security", + 0xFE91: "Shanghai Imilab Technology Co.,Ltd", + 0xFE90: "JUMA", + 0xFE8F: "CSR", + 0xFE8E: "ARM Ltd", + 0xFE8D: "Interaxon Inc.", + 0xFE8C: "TRON Forum", + 0xFE8B: "Apple: Inc.", + 0xFE8A: "Apple: Inc.", + 0xFE89: "B&O Play A/S", + 0xFE88: "SALTO SYSTEMS S.L.", + 0xFE87: "Qingdao Yeelink Information Technology Co.: Ltd. ( 青岛亿联客信息技术有限公司 )", + 0xFE86: "HUAWEI Technologies Co.: Ltd. ( 华为技术有限公司 )", + 0xFE85: "RF Digital Corp", + 0xFE84: "RF Digital Corp", + 0xFE83: "Blue Bite", + 0xFE82: "Medtronic Inc.", + 0xFE81: "Medtronic Inc.", + 0xFE80: "Doppler Lab", + 0xFE7F: "Doppler Lab", + 0xFE7E: "Awear Solutions Ltd", + 0xFE7D: "Aterica Health Inc.", + 0xFE7C: "Stollmann E+V GmbH", + 0xFE7B: "Orion Labs: Inc.", + 0xFE7A: "Bragi GmbH", + 0xFE79: "Zebra Technologies", + 0xFE78: "Hewlett-Packard Company", + 0xFE77: "Hewlett-Packard Company", + 0xFE76: "TangoMe", + 0xFE75: "TangoMe", + 0xFE74: "unwire", + 0xFE73: "St. Jude Medical: Inc.", + 0xFE72: "St. Jude Medical: Inc.", + 0xFE71: "Plume Design Inc", + 0xFE70: "Beijing Jingdong Century Trading Co.: Ltd.", + 0xFE6F: "LINE Corporation", + 0xFE6E: "The University of Tokyo", + 0xFE6D: "The University of Tokyo", + 0xFE6C: "TASER International: Inc.", + 0xFE6B: "TASER International: Inc.", + 0xFE6A: "Kontakt Micro-Location Sp. z o.o.", + 0xFE69: "Qualcomm Life Inc", + 0xFE68: "Qualcomm Life Inc", + 0xFE67: "Lab Sensor Solutions", + 0xFE66: "Intel Corporation", + 0xFE65: "CHIPOLO d.o.o.", + 0xFE64: "Siemens AG", + 0xFE63: "Connected Yard: Inc.", + 0xFE62: "Indagem Tech LLC", + 0xFE61: "Logitech International SA", + 0xFE60: "Lierda Science & Technology Group Co.: Ltd.", + 0xFE5F: "Eyefi: Inc.", + 0xFE5E: "Plastc Corporation", + 0xFE5D: "Grundfos A/S", + 0xFE5C: "million hunters GmbH", + 0xFE5B: "GT-tronics HK Ltd", + 0xFE5A: "Chronologics Corporation", + 0xFE59: "Nordic Semiconductor ASA", + 0xFE58: "Nordic Semiconductor ASA", + 0xFE57: "Dotted Labs", + 0xFE56: "Google Inc.", + 0xFE55: "Google Inc.", + 0xFE54: "Motiv: Inc.", + 0xFE53: "3M", + 0xFE52: "SetPoint Medical", + 0xFE51: "SRAM", + 0xFE50: "Google Inc.", + 0xFE4F: "Molekule: Inc.", + 0xFE4E: "NTT docomo", + 0xFE4D: "Casambi Technologies Oy", + 0xFE4C: "Volkswagen AG", + 0xFE4B: "Koninklijke Philips N.V.", + 0xFE4A: "OMRON HEALTHCARE Co.: Ltd.", + 0xFE49: "SenionLab AB", + 0xFE48: "General Motors", + 0xFE47: "General Motors", + 0xFE46: "B&O Play A/S", + 0xFE45: "Snapchat Inc", + 0xFE44: "SK Telecom", + 0xFE43: "Andreas Stihl AG & Co. KG", + 0xFE42: "Nets A/S", + 0xFE41: "Inugo Systems Limited", + 0xFE40: "Inugo Systems Limited", + 0xFE3F: "Friday Labs Limited", + 0xFE3E: "BD Medical", + 0xFE3D: "BD Medical", + 0xFE3C: "Alibaba", + 0xFE3B: "Dolby Laboratories", + 0xFE3A: "TTS Tooltechnic Systems AG & Co. KG", + 0xFE39: "TTS Tooltechnic Systems AG & Co. KG", + 0xFE38: "Spaceek LTD", + 0xFE37: "Spaceek LTD", + 0xFE36: "HUAWEI Technologies Co.: Ltd", + 0xFE35: "HUAWEI Technologies Co.: Ltd", + 0xFE34: "SmallLoop LLC", + 0xFE33: "CHIPOLO d.o.o.", + 0xFE32: "Pro-Mark: Inc.", + 0xFE31: "Volkswagen AG", + 0xFE30: "Volkswagen AG", + 0xFE2F: "CRESCO Wireless: Inc", + 0xFE2E: "ERi,Inc.", + 0xFE2D: "SMART INNOVATION Co.,Ltd", + 0xFE2C: "Google Inc.", + 0xFE2B: "ITT Industries", + 0xFE2A: "DaisyWorks: Inc.", + 0xFE29: "Gibson Innovations", + 0xFE28: "Ayla Network", + 0xFE27: "Google Inc.", + 0xFE26: "Google Inc.", + 0xFE25: "Apple: Inc.", + 0xFE24: "August Home Inc", + 0xFE23: "Zoll Medical Corporation", + 0xFE22: "Zoll Medical Corporation", + 0xFE21: "Bose Corporation", + 0xFE20: "Emerson", + 0xFE1F: "Garmin International: Inc.", + 0xFE1E: "Smart Innovations Co.: Ltd", + 0xFE1D: "Illuminati Instrument Corporation", + 0xFE1C: "NetMedia: Inc.", # SDO defined */ - 0xfffc: "AirFuel Alliance", - 0xfffe: "Alliance for Wireless Power (A4WP)", - 0xfffd: "Fast IDentity Online Alliance (FIDO)", + 0xFFFC: "AirFuel Alliance", + 0xFFFE: "Alliance for Wireless Power (A4WP)", + 0xFFFD: "Fast IDentity Online Alliance (FIDO)", } uuid128_dict = { @@ -661,8 +661,8 @@ def uuidstr_to_str(uuid_): if not s and uuid_.endswith("-0000-1000-8000-00805f9b34fb"): s = "Vendor specific" v = int(uuid_[:8], 16) - if (v & 0xffff0000) == 0x0000: - s = uuid16_dict.get(v & 0x0000ffff, s) + if (v & 0xFFFF0000) == 0x0000: + s = uuid16_dict.get(v & 0x0000FFFF, s) if not s: return "Unknown" diff --git a/examples/disconnect_callback.py b/examples/disconnect_callback.py index c21fd1d3..1344fa3d 100644 --- a/examples/disconnect_callback.py +++ b/examples/disconnect_callback.py @@ -25,7 +25,9 @@ def disconnect_callback(client, future): print("Sleeping until device disconnects according to BlueZ...") await disconnected_event.wait() print("Connected: {0}".format(await client.is_connected())) - await asyncio.sleep(0.5) # Sleep a bit longer to allow _cleanup to remove all BlueZ notifications nicely... + await asyncio.sleep( + 0.5 + ) # Sleep a bit longer to allow _cleanup to remove all BlueZ notifications nicely... mac_addr = "24:71:89:cc:09:05" diff --git a/examples/enable_notifications.py b/examples/enable_notifications.py index c1f6c0c7..8316899a 100644 --- a/examples/enable_notifications.py +++ b/examples/enable_notifications.py @@ -17,9 +17,7 @@ from bleak import _logger as logger -CHARACTERISTIC_UUID = ( - "f000aa65-0451-4000-b000-000000000000" -) # <--- Change to the characteristic you want to enable notifications from. +CHARACTERISTIC_UUID = "f000aa65-0451-4000-b000-000000000000" # <--- Change to the characteristic you want to enable notifications from. def notification_handler(sender, data): diff --git a/examples/sensortag.py b/examples/sensortag.py index c5821a60..8a88219a 100644 --- a/examples/sensortag.py +++ b/examples/sensortag.py @@ -87,7 +87,7 @@ BATTERY_LEVEL_UUID = "0000{0:x}-0000-1000-8000-00805f9b34fb".format( uuid16_dict.get("Battery Level") ) -KEY_PRESS_UUID = "0000{0:x}-0000-1000-8000-00805f9b34fb".format(0xffe1) +KEY_PRESS_UUID = "0000{0:x}-0000-1000-8000-00805f9b34fb".format(0xFFE1) # I/O test points on SensorTag. IO_DATA_CHAR_UUID = "f000aa65-0451-4000-b000-000000000000" IO_CONFIG_CHAR_UUID = "f000aa66-0451-4000-b000-000000000000" @@ -142,7 +142,7 @@ async def run(address, loop, debug=False): def keypress_handler(sender, data): print("{0}: {1}".format(sender, data)) - write_value = bytearray([0xa0]) + write_value = bytearray([0xA0]) value = await client.read_gatt_char(IO_DATA_CHAR_UUID) print("I/O Data Pre-Write Value: {0}".format(value)) diff --git a/examples/service_explorer.py b/examples/service_explorer.py index 5b7bbe6d..4e6f650c 100644 --- a/examples/service_explorer.py +++ b/examples/service_explorer.py @@ -42,7 +42,11 @@ async def run(address, loop, debug=False): value = None log.info( "\t[Characteristic] {0}: (Handle: {1}) ({2}) | Name: {3}, Value: {4} ".format( - char.uuid, char.handle, ",".join(char.properties), char.description, value + char.uuid, + char.handle, + ",".join(char.properties), + char.description, + value, ) ) for descriptor in char.descriptors: diff --git a/examples/two_devices.py b/examples/two_devices.py index 2db89273..928a0bf8 100644 --- a/examples/two_devices.py +++ b/examples/two_devices.py @@ -4,21 +4,21 @@ temperatureUUID = "45366e80-cf3a-11e1-9ab4-0002a5d5c51b" ecgUUID = "46366e80-cf3a-11e1-9ab4-0002a5d5c51b" -notify_uuid = "0000{0:x}-0000-1000-8000-00805f9b34fb".format(0xffe1) +notify_uuid = "0000{0:x}-0000-1000-8000-00805f9b34fb".format(0xFFE1) def callback(sender, data): print(sender, data) + def run(addresses): loop = asyncio.get_event_loop() - tasks = asyncio.gather( - *(connect_to_device(address, loop) for address in addresses) - ) + tasks = asyncio.gather(*(connect_to_device(address, loop) for address in addresses)) loop.run_until_complete(tasks) + async def connect_to_device(address, loop): print("starting", address, "loop") async with BleakClient(address, loop=loop, timeout=5.0) as client: @@ -33,5 +33,8 @@ async def connect_to_device(address, loop): print("disconnect from", address) + if __name__ == "__main__": - run(["B9EA5233-37EF-4DD6-87A8-2A875E821C46", "F0CBEBD3-299B-4139-A9FC-44618C720157" ]) + run( + ["B9EA5233-37EF-4DD6-87A8-2A875E821C46", "F0CBEBD3-299B-4139-A9FC-44618C720157"] + ) diff --git a/tests/test_imports.py b/tests/test_imports.py index c21b230b..3563249c 100644 --- a/tests/test_imports.py +++ b/tests/test_imports.py @@ -13,7 +13,8 @@ @pytest.mark.skipif( - condition=_IS_AZURE_PIPELINES and (platform.system().lower() in ("linux", "darwin")), + condition=_IS_AZURE_PIPELINES + and (platform.system().lower() in ("linux", "darwin")), reason="""Cannot run on Azure Pipelines with Ubuntu 16.04 or macOS installed.""", ) From 48cd8c157e56bc9753892d18d5a52e11405e684f Mon Sep 17 00:00:00 2001 From: Henrik Blidh Date: Thu, 2 Jul 2020 23:44:24 +0200 Subject: [PATCH 7/8] Version bump and CHANGELOG update --- CHANGELOG.rst | 9 +++++---- bleak/__version__.py | 2 +- setup.cfg | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e84d7673..6e7551fb 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,13 +7,13 @@ All notable changes to this project will be documented in this file. The format is based on `Keep a Changelog `_, and this project adheres to `Semantic Versioning `_. -`Unreleased`_ -------------- +`0.7.1`_ (2020-07-02) +--------------------- Changed ~~~~~~~ -* Improved, more explantory error on BlueZ backend when ``BleakClient`` cannot find the desired device. (#238) +* Improved, more explantory error on BlueZ backend when ``BleakClient`` cannot find the desired device when trying to connect. (#238) * Better-than-nothing documentation about scanning filters added (#230). * Ran black on code which was forgotten in 0.7.0. Large diffs due to that. @@ -246,7 +246,8 @@ Fixed * Bleak created. -.. _Unreleased: https://github.com/hbldh/bleak/compare/v0.7.0...develop +.. _Unreleased: https://github.com/hbldh/bleak/compare/v0.7.1...develop +.. _0.7.1: https://github.com/hbldh/bleak/compare/v0.7.1...v0.7.0 .. _0.7.0: https://github.com/hbldh/bleak/compare/v0.7.0...v0.6.4 .. _0.6.4: https://github.com/hbldh/bleak/compare/v0.6.3...v0.6.4 .. _0.6.3: https://github.com/hbldh/bleak/compare/v0.6.2...v0.6.3 diff --git a/bleak/__version__.py b/bleak/__version__.py index e0abfd00..caddb08a 100644 --- a/bleak/__version__.py +++ b/bleak/__version__.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- -__version__ = "0.7.0" +__version__ = "0.7.1" diff --git a/setup.cfg b/setup.cfg index 26077cd0..0d061a64 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.7.0 +current_version = 0.7.1 commit = False tag = False From 85be832fa6a561c50ecc206b5c8ce6a96eafc000 Mon Sep 17 00:00:00 2001 From: Henrik Blidh Date: Thu, 2 Jul 2020 23:49:33 +0200 Subject: [PATCH 8/8] Github Action update --- .github/workflows/build_and_test.yml | 2 -- CHANGELOG.rst | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index f6597e2f..bc4bac3c 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -15,8 +15,6 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] python-version: [3.5, 3.6, 3.7, 3.8] exclude: - - os: windows-latest - python-version: 3.8 - os: macos-latest python-version: 3.5 steps: diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6e7551fb..2cfa9c30 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -16,6 +16,7 @@ Changed * Improved, more explantory error on BlueZ backend when ``BleakClient`` cannot find the desired device when trying to connect. (#238) * Better-than-nothing documentation about scanning filters added (#230). * Ran black on code which was forgotten in 0.7.0. Large diffs due to that. +* Re-adding Python 3.8 CI "tests" on Windows again. Fixed ~~~~~