From 5072ab691bef32353ca88d3d75928e6c3d304a6e Mon Sep 17 00:00:00 2001 From: Henrik Blidh Date: Thu, 1 Aug 2019 23:42:34 +0200 Subject: [PATCH] Ran black on code. --- bleak/__init__.py | 8 +- bleak/backends/bluezdbus/client.py | 66 +++++---- bleak/backends/bluezdbus/discovery.py | 60 +++++--- bleak/backends/client.py | 2 +- .../corebluetooth/CentralManagerDelegate.py | 92 +++++++++---- .../corebluetooth/PeripheralDelegate.py | 128 +++++++++++++----- bleak/backends/corebluetooth/__init__.py | 14 +- .../backends/corebluetooth/characteristic.py | 1 + bleak/backends/corebluetooth/client.py | 97 +++++++++---- bleak/backends/corebluetooth/corebleak.py | 10 +- bleak/backends/corebluetooth/discovery.py | 40 ++++-- bleak/backends/corebluetooth/service.py | 10 +- bleak/backends/dotnet/client.py | 2 +- bleak/backends/dotnet/discovery.py | 10 +- examples/enable_notifications.py | 4 +- examples/sensortag.py | 6 +- examples/service_explorer.py | 8 +- 17 files changed, 380 insertions(+), 178 deletions(-) diff --git a/bleak/__init__.py b/bleak/__init__.py index 87647281..95137db1 100644 --- a/bleak/__init__.py +++ b/bleak/__init__.py @@ -3,7 +3,7 @@ """Top-level package for bleak.""" __author__ = """Henrik Blidh""" -__email__ = "henrik.blidh@nedomkull.com" +__email__ = "henrik.blidh@gmail.com" import re import os @@ -48,13 +48,15 @@ BleakClientBlueZDBus as BleakClient ) # noqa elif platform.system() == "Darwin": - # TODO: Check if macOS version has Core Bluetooth, raise error otherwise. from Foundation import NSClassFromString + if NSClassFromString("CBPeripheral") is None: raise BleakError("Bleak requires the CoreBluetooth Framework") from bleak.backends.corebluetooth.discovery import discover - from bleak.backends.corebluetooth.client import BleakClientCoreBluetooth as BleakClient + from bleak.backends.corebluetooth.client import ( + BleakClientCoreBluetooth as BleakClient + ) elif platform.system() == "Windows": # Requires Windows 10 Creators update at least, i.e. Window 10.0.16299 diff --git a/bleak/backends/bluezdbus/client.py b/bleak/backends/bluezdbus/client.py index ffdc215f..a13a6e83 100644 --- a/bleak/backends/bluezdbus/client.py +++ b/bleak/backends/bluezdbus/client.py @@ -55,7 +55,7 @@ def __init__(self, address, loop=None, **kwargs): # Connectivity methods def set_disconnected_callback( - self, callback: Callable[[BaseBleakClient], None], **kwargs + self, callback: Callable[[BaseBleakClient], None], **kwargs ) -> None: """Set the disconnected callback. The callback will be called on DBus PropChanged event with @@ -81,7 +81,9 @@ async def connect(self, **kwargs) -> bool: # A Discover must have been run before connecting to any devices. Do a quick one here # to ensure that it has been done. - await discover(timeout=kwargs.get('timeout', 0.1), device=self.device, loop=self.loop) + await discover( + timeout=kwargs.get("timeout", 0.1), device=self.device, loop=self.loop + ) # Create system bus self._bus = await txdbus_connect(reactor, busAddress="system").asFuture( @@ -141,7 +143,8 @@ async def _cleanup(self) -> None: await self._bus.delMatch(rule_id).asFuture(self.loop) await asyncio.gather( - *(self.stop_notify(_uuid) for _uuid in self._subscriptions)) + *(self.stop_notify(_uuid) for _uuid in self._subscriptions) + ) async def disconnect(self) -> bool: """Disconnect from the specified GATT server. @@ -225,13 +228,9 @@ async def get_services(self) -> BleakGATTServiceCollection: _descs.append([desc, object_path]) for char, object_path in _chars: - _service = list( - filter(lambda x: x.path == char["Service"], self.services) - ) + _service = list(filter(lambda x: x.path == char["Service"], self.services)) self.services.add_characteristic( - BleakGATTCharacteristicBlueZDBus( - char, object_path, _service[0].uuid - ) + BleakGATTCharacteristicBlueZDBus(char, object_path, _service[0].uuid) ) self._char_path_to_uuid[object_path] = char.get("UUID") @@ -243,9 +242,7 @@ async def get_services(self) -> BleakGATTServiceCollection: ) ) self.services.add_descriptor( - BleakGATTDescriptorBlueZDBus( - desc, object_path, _characteristic[0].uuid - ) + BleakGATTDescriptorBlueZDBus(desc, object_path, _characteristic[0].uuid) ) self._services_resolved = True @@ -349,14 +346,26 @@ async def write_gatt_char( """ characteristic = self.services.get_characteristic(str(_uuid)) - if ("write" not in characteristic.properties and "write-without-response" not in characteristic.properties): - raise BleakError("Characteristic %s does not support write operations!" % str(_uuid)) + if ( + "write" not in characteristic.properties + and "write-without-response" not in characteristic.properties + ): + raise BleakError( + "Characteristic %s does not support write operations!" % str(_uuid) + ) if not response and "write-without-response" not in characteristic.properties: response = True # Force response here, since the device only supports that. - if response and "write" not in characteristic.properties and "write-without-response" in characteristic.properties: + if ( + response + and "write" not in characteristic.properties + and "write-without-response" in characteristic.properties + ): response = False - logger.warning("Characteristic %s does not support Write with response. Trying without..." % str(_uuid)) + logger.warning( + "Characteristic %s does not support Write with response. Trying without..." + % str(_uuid) + ) if response or (self._bluez_version[0] == 5 and self._bluez_version[1] > 50): # TODO: Add OnValueUpdated handler for response=True? @@ -551,10 +560,11 @@ def _properties_changed_callback(self, message): """ - logger.debug('DBUS: path: {}, domain: {}, body: {}' - .format(message.path, - message.body[0], - message.body[1])) + logger.debug( + "DBUS: path: {}, domain: {}, body: {}".format( + message.path, message.body[0], message.body[1] + ) + ) if message.body[0] == defs.GATT_CHARACTERISTIC_INTERFACE: if message.path in self._notification_callbacks: @@ -567,20 +577,24 @@ def _properties_changed_callback(self, message): message.path, message.body[1] ) elif message.body[0] == defs.DEVICE_INTERFACE: - device_path = '/org/bluez/%s/dev_%s' % (self.device, - self.address.replace(':', '_')) + device_path = "/org/bluez/%s/dev_%s" % ( + self.device, + self.address.replace(":", "_"), + ) if message.path == device_path: message_body_map = message.body[1] - if 'Connected' in message_body_map and \ - not message_body_map['Connected']: - logger.debug("Device {} disconnected." - .format(self.address)) + if ( + "Connected" in message_body_map + and not message_body_map["Connected"] + ): + logger.debug("Device {} disconnected.".format(self.address)) self.loop.create_task(self._cleanup()) if self._disconnected_callback is not None: self._disconnected_callback(self) + def _data_notification_wrapper(func, char_map): @wraps(func) def args_parser(sender, data): diff --git a/bleak/backends/bluezdbus/discovery.py b/bleak/backends/bluezdbus/discovery.py index 6ff99e02..0f3642bb 100644 --- a/bleak/backends/bluezdbus/discovery.py +++ b/bleak/backends/bluezdbus/discovery.py @@ -101,7 +101,10 @@ def parse_msg(message): devices[msg_path] = ( {**devices[msg_path], **changed} if msg_path in devices else changed ) - elif message.member == "InterfacesRemoved" and message.body[1][0] == defs.BATTERY_INTERFACE: + elif ( + message.member == "InterfacesRemoved" + and message.body[1][0] == defs.BATTERY_INTERFACE + ): logger.info( "{0}, {1} ({2}): {3}".format( message.member, message.interface, message.path, message.body @@ -125,21 +128,27 @@ def parse_msg(message): bus = await client.connect(reactor, "system").asFuture(loop) # Add signal listeners - rules.append(await bus.addMatch( - parse_msg, - interface="org.freedesktop.DBus.ObjectManager", - member="InterfacesAdded", - ).asFuture(loop)) - rules.append(await bus.addMatch( - parse_msg, - interface="org.freedesktop.DBus.ObjectManager", - member="InterfacesRemoved", - ).asFuture(loop)) - rules.append(await bus.addMatch( - parse_msg, - interface="org.freedesktop.DBus.Properties", - member="PropertiesChanged", - ).asFuture(loop)) + rules.append( + await bus.addMatch( + parse_msg, + interface="org.freedesktop.DBus.ObjectManager", + member="InterfacesAdded", + ).asFuture(loop) + ) + rules.append( + await bus.addMatch( + parse_msg, + interface="org.freedesktop.DBus.ObjectManager", + member="InterfacesRemoved", + ).asFuture(loop) + ) + rules.append( + await bus.addMatch( + parse_msg, + interface="org.freedesktop.DBus.Properties", + member="PropertiesChanged", + ).asFuture(loop) + ) # Find the HCI device to use for scanning and get cached device properties objects = await bus.callRemote( @@ -162,7 +171,7 @@ def parse_msg(message): interface="org.bluez.Adapter1", destination="org.bluez", signature="a{sv}", - body=[{"Transport": "le"}] + body=[{"Transport": "le"}], ).asFuture(loop) await bus.callRemote( adapter_path, @@ -193,13 +202,22 @@ def parse_msg(message): discovered_devices = [] for path, props in devices.items(): if not props: - logger.debug("Disregarding %s since no properties could be obtained." % path) + logger.debug( + "Disregarding %s since no properties could be obtained." % path + ) continue name, address, _, path = _device_info(path, props) uuids = props.get("UUIDs", []) - manufacturer_data = props.get('ManufacturerData', {}) - discovered_devices.append(BLEDevice(address, name, {"path": path, "props": props}, uuids=uuids, - manufacturer_data=manufacturer_data)) + manufacturer_data = props.get("ManufacturerData", {}) + discovered_devices.append( + BLEDevice( + address, + name, + {"path": path, "props": props}, + uuids=uuids, + manufacturer_data=manufacturer_data, + ) + ) for rule in rules: await bus.delMatch(rule).asFuture(loop) diff --git a/bleak/backends/client.py b/bleak/backends/client.py index 8d428b83..9587e609 100644 --- a/bleak/backends/client.py +++ b/bleak/backends/client.py @@ -48,7 +48,7 @@ async def __aexit__(self, exc_type, exc_val, exc_tb): @abc.abstractmethod async def set_disconnected_callback( - self, callback: Callable[['BaseBleakClient'], None], **kwargs + self, callback: Callable[["BaseBleakClient"], None], **kwargs ) -> None: """Set the disconnect callback. The callback will only be called on unsolicited disconnect event. diff --git a/bleak/backends/corebluetooth/CentralManagerDelegate.py b/bleak/backends/corebluetooth/CentralManagerDelegate.py index f8f06155..36bb327b 100644 --- a/bleak/backends/corebluetooth/CentralManagerDelegate.py +++ b/bleak/backends/corebluetooth/CentralManagerDelegate.py @@ -12,29 +12,34 @@ from typing import List import objc -from Foundation import NSObject, \ - CBCentralManager, \ - CBPeripheral, \ - CBUUID, \ - NSArray, \ - NSDictionary, \ - NSNumber, \ - NSError +from Foundation import ( + NSObject, + CBCentralManager, + CBPeripheral, + CBUUID, + NSArray, + NSDictionary, + NSNumber, + NSError, +) from bleak.backends.corebluetooth.PeripheralDelegate import PeripheralDelegate # logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger(__name__) -CBCentralManagerDelegate = objc.protocolNamed('CBCentralManagerDelegate') +CBCentralManagerDelegate = objc.protocolNamed("CBCentralManagerDelegate") + class CMDConnectionState(Enum): DISCONNECTED = 0 PENDING = 1 CONNECTED = 2 + class CentralManagerDelegate(NSObject): """macOS conforming python class for managing the CentralManger for BLE""" + ___pyobjc_protocols__ = [CBCentralManagerDelegate] def init(self): @@ -44,7 +49,9 @@ def init(self): if self is None: return None - self.central_manager = CBCentralManager.alloc().initWithDelegate_queue_(self, None) + self.central_manager = CBCentralManager.alloc().initWithDelegate_queue_( + self, None + ) self.connected_peripheral_delegate = None self.connected_peripheral = None @@ -64,7 +71,9 @@ def init(self): def compliant(self): """Determins whether the class adheres to the CBCentralManagerDelegate protocol""" - return CentralManagerDelegate.pyobjc_classMethods.conformsToProtocol_(CBCentralManagerDelegate) + return CentralManagerDelegate.pyobjc_classMethods.conformsToProtocol_( + CBCentralManagerDelegate + ) @property def enabled(self): @@ -89,15 +98,19 @@ async def scanForPeripherals_(self, scan_options) -> List[CBPeripheral]: scan_options = { service_uuids, timeout } """ service_uuids = [] - if 'service_uuids' in scan_options: - service_uuids_str = scan_options['service_uuids'] - service_uuids = NSArray.alloc().initWithArray_(list(map(string2uuid, service_uuids_str))) + if "service_uuids" in scan_options: + service_uuids_str = scan_options["service_uuids"] + service_uuids = NSArray.alloc().initWithArray_( + list(map(string2uuid, service_uuids_str)) + ) timeout = None - if 'timeout' in scan_options: - timeout = scan_options['timeout'] + if "timeout" in scan_options: + timeout = scan_options["timeout"] - self.central_manager.scanForPeripheralsWithServices_options_(service_uuids, None) + self.central_manager.scanForPeripheralsWithServices_options_( + service_uuids, None + ) if timeout is None or type(timeout) not in (int, float): return @@ -145,33 +158,52 @@ def centralManagerDidUpdateState_(self, centralManager): self.ready = True - - def centralManager_didDiscoverPeripheral_advertisementData_RSSI_(self, - central: CBCentralManager, - peripheral: CBPeripheral, - advertisementData: NSDictionary, - RSSI: NSNumber): + def centralManager_didDiscoverPeripheral_advertisementData_RSSI_( + self, + central: CBCentralManager, + peripheral: CBPeripheral, + advertisementData: NSDictionary, + RSSI: NSNumber, + ): uuid_string = peripheral.identifier().UUIDString() - if uuid_string not in list(map(lambda x: x.identifier().UUIDString(), self.peripheral_list)): + if uuid_string not in list( + map(lambda x: x.identifier().UUIDString(), self.peripheral_list) + ): self.peripheral_list.append(peripheral) self.advertisement_data_list.append(advertisementData) - logger.debug("Discovered device {}: {} @ RSSI: {}".format(uuid_string, peripheral.name() or 'Unknown', RSSI)) + logger.debug( + "Discovered device {}: {} @ RSSI: {}".format( + uuid_string, peripheral.name() or "Unknown", RSSI + ) + ) def centralManager_didConnectPeripheral_(self, central, peripheral): - logger.debug("Successfully connected to device uuid {}".format(peripheral.identifier().UUIDString())) + logger.debug( + "Successfully connected to device uuid {}".format( + peripheral.identifier().UUIDString() + ) + ) peripheralDelegate = PeripheralDelegate.alloc().initWithPeripheral_(peripheral) self.connected_peripheral_delegate = peripheralDelegate self._connection_state = CMDConnectionState.CONNECTED - def centralManager_didFailToConnectPeripheral_error_(self, centralManager: CBCentralManager, peripheral: CBPeripheral, error: NSError): - logger.debug("Failed to connect to device uuid {}".format(peripheral.identifier().UUIDString())) + def centralManager_didFailToConnectPeripheral_error_( + self, centralManager: CBCentralManager, peripheral: CBPeripheral, error: NSError + ): + logger.debug( + "Failed to connect to device uuid {}".format( + peripheral.identifier().UUIDString() + ) + ) self._connection_state = CMDConnectionState.DISCONNECTED - def centralManager_didDisconnectPeripheral_error_(self, central: CBCentralManager, peripheral: CBPeripheral, error: NSError): + def centralManager_didDisconnectPeripheral_error_( + self, central: CBCentralManager, peripheral: CBPeripheral, error: NSError + ): logger.debug("Peripheral Device disconnected!") self._connection_state = CMDConnectionState.DISCONNECTED + def string2uuid(uuid_str: str) -> CBUUID: """Convert a string to a uuid""" return CBUUID.UUIDWithString_(uuid_str) - diff --git a/bleak/backends/corebluetooth/PeripheralDelegate.py b/bleak/backends/corebluetooth/PeripheralDelegate.py index 2b048a15..8056e4c8 100644 --- a/bleak/backends/corebluetooth/PeripheralDelegate.py +++ b/bleak/backends/corebluetooth/PeripheralDelegate.py @@ -11,24 +11,27 @@ from typing import Callable, Any import objc -from Foundation import NSObject, \ - CBPeripheral, \ - CBService, \ - CBCharacteristic, \ - CBDescriptor, \ - NSData, \ - NSError +from Foundation import ( + NSObject, + CBPeripheral, + CBService, + CBCharacteristic, + CBDescriptor, + NSData, + NSError, +) from bleak.exc import BleakError # logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger(__name__) -CBPeripheralDelegate = objc.protocolNamed('CBPeripheralDelegate') +CBPeripheralDelegate = objc.protocolNamed("CBPeripheralDelegate") class PeripheralDelegate(NSObject): """macOS conforming python class for managing the PeripheralDelegate for BLE""" + ___pyobjc_protocols__ = [CBPeripheralDelegate] def initWithPeripheral_(self, peripheral: CBPeripheral): @@ -63,10 +66,12 @@ def initWithPeripheral_(self, peripheral: CBPeripheral): def compliant(self): """Determins whether the class adheres to the CBCentralManagerDelegate protocol""" - return PeripheralDelegate.pyobjc_classMethods.conformsToProtocol_(CBPeripheralDelegate) + return PeripheralDelegate.pyobjc_classMethods.conformsToProtocol_( + CBPeripheralDelegate + ) async def discoverServices(self, use_cached=True) -> [CBService]: - if self._services_discovered and ( use_cached is True ): + if self._services_discovered and (use_cached is True): return self.peripheral.services() self.peripheral.discoverServices_(None) @@ -76,7 +81,9 @@ async def discoverServices(self, use_cached=True) -> [CBService]: return self.peripheral.services() - async def discoverCharacteristics_(self, service: CBService, use_cached=True) -> [CBCharacteristic]: + async def discoverCharacteristics_( + self, service: CBService, use_cached=True + ) -> [CBCharacteristic]: if service.characteristics() is not None and use_cached is True: return service.characteristics() @@ -90,10 +97,12 @@ async def discoverCharacteristics_(self, service: CBService, use_cached=True) -> return service.characteristics() - async def discoverDescriptors_(self, characteristic: CBCharacteristic, use_cached=True) -> [CBDescriptor]: + async def discoverDescriptors_( + self, characteristic: CBCharacteristic, use_cached=True + ) -> [CBDescriptor]: if characteristic.descriptors() is not None and use_cached is True: return characteristic.descriptors() - + cUUID = characteristic.UUID().UUIDString() self._characteristic_descriptor_log[cUUID] = False @@ -104,7 +113,9 @@ async def discoverDescriptors_(self, characteristic: CBCharacteristic, use_cache return characteristic.descriptors() - async def readCharacteristic_(self, characteristic: CBCharacteristic, use_cached=True) -> NSData: + async def readCharacteristic_( + self, characteristic: CBCharacteristic, use_cached=True + ) -> NSData: if characteristic.value() is not None and use_cached is True: return characteristic.value() @@ -118,7 +129,9 @@ async def readCharacteristic_(self, characteristic: CBCharacteristic, use_cached return characteristic.value() - async def readDescriptor_(self, descriptor: CBDescriptor, use_cached=True) -> NSData: + async def readDescriptor_( + self, descriptor: CBDescriptor, use_cached=True + ) -> NSData: if descriptor.value() is not None and use_cached is True: return descriptor.value() @@ -132,8 +145,10 @@ async def readDescriptor_(self, descriptor: CBDescriptor, use_cached=True) -> NS return descriptor.value() - async def writeCharacteristic_value_(self, characteristic: CBCharacteristic, value: NSData) -> bool: - + async def writeCharacteristic_value_( + self, characteristic: CBCharacteristic, value: NSData + ) -> bool: + cUUID = characteristic.UUID().UUIDString() self._characteristic_write_log[cUUID] = False @@ -144,7 +159,9 @@ async def writeCharacteristic_value_(self, characteristic: CBCharacteristic, val return True - async def writeDescriptor_value_(self, descriptor: CBDescriptor, value: NSData) -> bool: + async def writeDescriptor_value_( + self, descriptor: CBDescriptor, value: NSData + ) -> bool: dUUID = descriptor.UUID().UUIDString() self._descriptor_write_log[dUUID] = False @@ -155,11 +172,13 @@ async def writeDescriptor_value_(self, descriptor: CBDescriptor, value: NSData) return True - async def startNotify_cb_(self, characteristic: CBCharacteristic, callback: Callable[[str, Any], Any] ) -> bool: + async def startNotify_cb_( + self, characteristic: CBCharacteristic, callback: Callable[[str, Any], Any] + ) -> bool: cUUID = characteristic.UUID().UUIDString() self._characteristic_notify_log[cUUID] = False self._characteristic_notify_callbacks[cUUID] = callback - + self.peripheral.setNotifyValue_forCharacteristic_(True, characteristic) while not self._characteristic_notify_log[cUUID]: @@ -181,57 +200,88 @@ async def stopNotify_(self, characteristic: CBCharacteristic) -> bool: return True # Protocol Functions - def peripheral_didDiscoverServices_(self, peripheral: CBPeripheral, error: NSError) -> None: + def peripheral_didDiscoverServices_( + self, peripheral: CBPeripheral, error: NSError + ) -> None: if error is not None: raise BleakError("Failed to discover services {}".format(error)) logger.debug("Services discovered") self._services_discovered = True - def peripheral_didDiscoverCharacteristicsForService_error_(self, peripheral: CBPeripheral, service:CBService, error: NSError): + def peripheral_didDiscoverCharacteristicsForService_error_( + self, peripheral: CBPeripheral, service: CBService, error: NSError + ): serviceUUID = service.UUID().UUIDString() if error is not None: - raise BleakError("Failed to discover services for service {}: {}".format(serviceUUID, error)) + raise BleakError( + "Failed to discover services for service {}: {}".format( + serviceUUID, error + ) + ) logger.debug("Characteristics discovered") self._service_characteristic_discovered_log[serviceUUID] = True - def peripheral_didDiscoverDescriptorsForCharacteristic_error_(self, peripheral: CBPeripheral, characteristic: CBCharacteristic, error: NSError): + def peripheral_didDiscoverDescriptorsForCharacteristic_error_( + self, peripheral: CBPeripheral, characteristic: CBCharacteristic, error: NSError + ): cUUID = characteristic.UUID().UUIDString() if error is not None: - raise BleakError("Failed to discover descriptors for characteristic {}: {}".format(cUUID, error)) + raise BleakError( + "Failed to discover descriptors for characteristic {}: {}".format( + cUUID, error + ) + ) logger.debug("Descriptor discovered {}".format(cUUID)) self._characteristic_descriptor_log[cUUID] = True - def peripheral_didUpdateValueForCharacteristic_error_(self, peripheral: CBPeripheral, characteristic: CBCharacteristic, error: NSError): + def peripheral_didUpdateValueForCharacteristic_error_( + self, peripheral: CBPeripheral, characteristic: CBCharacteristic, error: NSError + ): cUUID = characteristic.UUID().UUIDString() if error is not None: - raise BleakError("Failed to read characteristic {}: {}".format(cUUID, error)) - - if cUUID in self._characteristic_notify_status and self._characteristic_notify_status[cUUID]: + raise BleakError( + "Failed to read characteristic {}: {}".format(cUUID, error) + ) + + if ( + cUUID in self._characteristic_notify_status + and self._characteristic_notify_status[cUUID] + ): self._characteristic_notify_callbacks[cUUID](cUUID, characteristic.value()) logger.debug("Read characteristic value") self._characteristic_value_log[cUUID] = True - def peripheral_didUpdateValueForDescriptor_error_(self, peripheral: CBPeripheral, descriptor: CBDescriptor, error: NSError): + def peripheral_didUpdateValueForDescriptor_error_( + self, peripheral: CBPeripheral, descriptor: CBDescriptor, error: NSError + ): dUUID = descriptor.UUID().UUIDString() if error is not None: - raise BleakError("Failed to read characteristic {}: {}".format(dUUID, error)) + raise BleakError( + "Failed to read characteristic {}: {}".format(dUUID, error) + ) logger.debug("Read descriptor value") self._descriptor_value_log[dUUID] = True - def peripheral_didWriteValueForCharacteristic_error_(self, peripheral: CBPeripheral, characteristic: CBCharacteristic, error: NSError): + def peripheral_didWriteValueForCharacteristic_error_( + self, peripheral: CBPeripheral, characteristic: CBCharacteristic, error: NSError + ): cUUID = characteristic.UUID().UUIDString() if error is not None: - raise BleakError("Failed to write characteristic {}: {}".format(cUUID, error)) + raise BleakError( + "Failed to write characteristic {}: {}".format(cUUID, error) + ) logger.debug("Write Characteristic Value") self._characteristic_write_log[cUUID] = True - def peripheral_didWriteValueForDescriptor_error_(self, peripheral: CBPeripheral, descriptor: CBDescriptor, error: NSError): + def peripheral_didWriteValueForDescriptor_error_( + self, peripheral: CBPeripheral, descriptor: CBDescriptor, error: NSError + ): dUUID = descriptor.UUID().UUIDString() if error is not None: raise BleakError("Failed to write descriptor {}: {}".format(dUUID, error)) @@ -239,10 +289,16 @@ def peripheral_didWriteValueForDescriptor_error_(self, peripheral: CBPeripheral, logger.debug("Write Descriptor Value") self._descriptor_write_log[dUUID] = True - def peripheral_didUpdateNotificationStateForCharacteristic_error_(self, peripheral: CBPeripheral, characteristic: CBCharacteristic, error: NSError): + def peripheral_didUpdateNotificationStateForCharacteristic_error_( + self, peripheral: CBPeripheral, characteristic: CBCharacteristic, error: NSError + ): cUUID = characteristic.UUID().UUIDString() if error is not None: - raise BleakError("Failed to update the notification status for characteristic {}: {}".format(cUUID, error)) + raise BleakError( + "Failed to update the notification status for characteristic {}: {}".format( + cUUID, error + ) + ) logger.debug("Character Notify Update") self._characteristic_notify_log[cUUID] = True diff --git a/bleak/backends/corebluetooth/__init__.py b/bleak/backends/corebluetooth/__init__.py index 03e0ac0c..f83dff4a 100644 --- a/bleak/backends/corebluetooth/__init__.py +++ b/bleak/backends/corebluetooth/__init__.py @@ -12,9 +12,10 @@ from .CentralManagerDelegate import CentralManagerDelegate # async def discover(device="hci0", timeout=5.0): - # raise NotImplementedError("CoreBluetooth discover not implemented yet.") +# raise NotImplementedError("CoreBluetooth discover not implemented yet.") -class Application(): + +class Application: """ This is a temporary application class responsible for running the NSRunLoop so that events within CoreBluetooth are appropriately handled @@ -29,7 +30,7 @@ def __init__(self): self.main_loop.create_task(self._central_manager_delegate_ready()) self.nsrunloop = NSRunLoop.currentRunLoop() - + self.central_manager_delegate = CentralManagerDelegate.alloc().init() def __del__(self): @@ -37,13 +38,16 @@ def __del__(self): async def _handle_nsrunloop(self): while not self.ns_run_loop_done: - time_interval = NSDate.alloc().initWithTimeIntervalSinceNow_(self.ns_run_loop_interval) + time_interval = NSDate.alloc().initWithTimeIntervalSinceNow_( + self.ns_run_loop_interval + ) self.nsrunloop.runMode_beforeDate_(NSDefaultRunLoopMode, time_interval) await asyncio.sleep(0) async def _central_manager_delegate_ready(self): await self.central_manager_delegate.is_ready() + # Restructure this later: Global isn't the prettiest way of doing this... -global CBAPP +global CBAPP CBAPP = Application() diff --git a/bleak/backends/corebluetooth/characteristic.py b/bleak/backends/corebluetooth/characteristic.py index 1133f0a4..5b04cb94 100644 --- a/bleak/backends/corebluetooth/characteristic.py +++ b/bleak/backends/corebluetooth/characteristic.py @@ -26,6 +26,7 @@ class CBChacteristicProperties(Enum): NOTIFY_ENCRYPTION_REQUIRED = 0x100 INDICATE_ENCRYPTION_REQUIRED = 0x200 + _GattCharacteristicsPropertiesEnum = { None: ("None", "The characteristic doesn’t have any properties that apply"), 1: ("Broadcast".lower(), "The characteristic supports broadcasting"), diff --git a/bleak/backends/corebluetooth/client.py b/bleak/backends/corebluetooth/client.py index 88be1c0e..cb46d153 100644 --- a/bleak/backends/corebluetooth/client.py +++ b/bleak/backends/corebluetooth/client.py @@ -12,7 +12,9 @@ from bleak.backends.client import BaseBleakClient from bleak.backends.corebluetooth import CBAPP as cbapp -from bleak.backends.corebluetooth.characteristic import BleakGATTCharacteristicCoreBluetooth +from bleak.backends.corebluetooth.characteristic import ( + BleakGATTCharacteristicCoreBluetooth +) from bleak.backends.corebluetooth.descriptor import BleakGATTDescriptorCoreBluetooth from bleak.backends.corebluetooth.discovery import discover from bleak.backends.corebluetooth.service import BleakGATTServiceCoreBluetooth @@ -21,6 +23,7 @@ logger = logging.getLogger(__name__) + class BleakClientCoreBluetooth(BaseBleakClient): """CoreBluetooth class interface for BleakClient""" @@ -45,13 +48,17 @@ async def connect(self, **kwargs) -> bool: Boolean representing connection status. """ - devices = await discover(timeout=kwargs.get('timeout', 5.0), loop=self.loop) - sought_device = list(filter(lambda x: x.address.upper() == self.address.upper(), devices)) + devices = await discover(timeout=kwargs.get("timeout", 5.0), loop=self.loop) + sought_device = list( + filter(lambda x: x.address.upper() == self.address.upper(), devices) + ) if len(sought_device): self._device_info = sought_device[0].details else: - raise BleakError("Device with address {} was not found".format(self.address)) + raise BleakError( + "Device with address {} was not found".format(self.address) + ) logger.debug("Connecting to BLE device @ {}".format(self.address)) @@ -82,27 +89,39 @@ async def get_services(self) -> BleakGATTServiceCollection: return self._services logger.debug("Retrieving services...") - services = await cbapp.central_manager_delegate.connected_peripheral_delegate.discoverServices() + services = ( + await cbapp.central_manager_delegate.connected_peripheral_delegate.discoverServices() + ) for service in services: serviceUUID = service.UUID().UUIDString() - logger.debug("Retrieving characteristics for service {}".format(serviceUUID)) - characteristics = await cbapp.central_manager_delegate.connected_peripheral_delegate.discoverCharacteristics_(service) + logger.debug( + "Retrieving characteristics for service {}".format(serviceUUID) + ) + characteristics = await cbapp.central_manager_delegate.connected_peripheral_delegate.discoverCharacteristics_( + service + ) self.services.add_service(BleakGATTServiceCoreBluetooth(service)) for characteristic in characteristics: cUUID = characteristic.UUID().UUIDString() - logger.debug("Retrieving descriptors for characteristic {}".format(cUUID)) - descriptors = await cbapp.central_manager_delegate.connected_peripheral_delegate.discoverDescriptors_(characteristic) + logger.debug( + "Retrieving descriptors for characteristic {}".format(cUUID) + ) + descriptors = await cbapp.central_manager_delegate.connected_peripheral_delegate.discoverDescriptors_( + characteristic + ) - self.services.add_characteristic(BleakGATTCharacteristicCoreBluetooth(characteristic)) + self.services.add_characteristic( + BleakGATTCharacteristicCoreBluetooth(characteristic) + ) for descriptor in descriptors: self.services.add_descriptor( - BleakGATTDescriptorCoreBluetooth( - descriptor, characteristic.UUID().UUIDString() - ) - ) + BleakGATTDescriptorCoreBluetooth( + descriptor, characteristic.UUID().UUIDString() + ) + ) self._services_resolved = True return self.services @@ -123,12 +142,16 @@ async def read_gatt_char(self, _uuid: str, use_cached=False, **kwargs) -> bytear if not characteristic: raise BleakError("Characteristic {} was not found!".format(_uuid)) - output = await cbapp.central_manager_delegate.connected_peripheral_delegate.readCharacteristic_(characteristic.obj, use_cached=use_cached) + output = await cbapp.central_manager_delegate.connected_peripheral_delegate.readCharacteristic_( + characteristic.obj, use_cached=use_cached + ) value = bytearray(output) logger.debug("Read Characteristic {0} : {1}".format(_uuid, value)) return value - async def read_gatt_descriptor(self, handle: int, use_cached=False, **kwargs) -> bytearray: + async def read_gatt_descriptor( + self, handle: int, use_cached=False, **kwargs + ) -> bytearray: """Perform read operation on the specified GATT descriptor. Args: @@ -143,15 +166,21 @@ async def read_gatt_descriptor(self, handle: int, use_cached=False, **kwargs) -> if not descriptor: raise BleakError("Descriptor {} was not found!".format(handle)) - output = await cbapp.central_manager_delegate.connected_peripheral_delegate.readDescriptor_(descriptor.obj, use_cached=use_cached) - if isinstance(output, str): # Sometimes a `pyobjc_unicode`or `__NSCFString` is returned and they can be used as regular Python strings. - value = bytearray(output.encode('utf-8')) + output = await cbapp.central_manager_delegate.connected_peripheral_delegate.readDescriptor_( + descriptor.obj, use_cached=use_cached + ) + if isinstance( + output, str + ): # Sometimes a `pyobjc_unicode`or `__NSCFString` is returned and they can be used as regular Python strings. + value = bytearray(output.encode("utf-8")) else: # _NSInlineData value = bytearray(output) # value.getBytes_length_(None, len(value)) logger.debug("Read Descriptor {0} : {1}".format(handle, value)) return value - async def write_gatt_char(self, _uuid: str, data: bytearray, response: bool = False) -> None: + async def write_gatt_char( + self, _uuid: str, data: bytearray, response: bool = False + ) -> None: """Perform a write operation of the specified GATT characteristic. Args: @@ -166,7 +195,9 @@ async def write_gatt_char(self, _uuid: str, data: bytearray, response: bool = Fa raise BleakError("Characteristic {} was not found!".format(_uuid)) value = NSData.alloc().initWithBytes_length_(data, len(data)) - success = await cbapp.central_manager_delegate.connected_peripheral_delegate.writeCharacteristic_value_(characteristic.obj, value) + success = await cbapp.central_manager_delegate.connected_peripheral_delegate.writeCharacteristic_value_( + characteristic.obj, value + ) if success: logger.debug("Write Characteristic {0} : {1}".format(_uuid, data)) else: @@ -189,7 +220,9 @@ async def write_gatt_descriptor(self, handle: int, data: bytearray) -> None: raise BleakError("Descriptor {} was not found!".format(handle)) value = NSData.alloc().initWithBytes_length_(data, len(data)) - success = await cbapp.central_manager_delegate.connected_peripheral_delegate.writeDescriptor_value_(descriptor.obj, value) + success = await cbapp.central_manager_delegate.connected_peripheral_delegate.writeDescriptor_value_( + descriptor.obj, value + ) if success: logger.debug("Write Descriptor {0} : {1}".format(handle, data)) else: @@ -199,7 +232,9 @@ async def write_gatt_descriptor(self, handle: int, data: bytearray) -> None: ) ) - async def start_notify(self, _uuid: str, callback: Callable[[str, Any], Any], **kwargs) -> None: + async def start_notify( + self, _uuid: str, callback: Callable[[str, Any], Any], **kwargs + ) -> None: """Activate notifications/indications on a characteristic. Callbacks must accept two inputs. The first will be a uuid string @@ -221,10 +256,14 @@ def callback(sender, data): if not characteristic: raise BleakError("Characteristic {} not found!".format(_uuid)) - success = await cbapp.central_manager_delegate.connected_peripheral_delegate.startNotify_cb_(characteristic.obj, callback) + success = await cbapp.central_manager_delegate.connected_peripheral_delegate.startNotify_cb_( + characteristic.obj, callback + ) if not success: raise BleakError( - "Could not start notify on {0}: {1}".format(characteristic.uuid, success) + "Could not start notify on {0}: {1}".format( + characteristic.uuid, success + ) ) async def stop_notify(self, _uuid: str) -> None: @@ -243,7 +282,9 @@ async def stop_notify(self, _uuid: str) -> None: if not characteristic: raise BleakError("Characteristic {} not found!".format(_uuid)) - success = await cbapp.central_manager_delegate.connected_peripheral_delegate.stopNotify_(characteristic.obj) + success = await cbapp.central_manager_delegate.connected_peripheral_delegate.stopNotify_( + characteristic.obj + ) if not success: raise BleakError( "Could not stop notify on {0}: {1}".format(characteristic.uuid, success) @@ -269,11 +310,11 @@ async def convert_uuid_to_int(self, _uuid: str) -> int: UUID_cb = CBUUID.alloc().initWithString_(_uuid) UUID_data = UUID_cb.data() UUID_bytes = UUID_data.getBytes_length_(None, len(UUID_data)) - UUID_int = int.from_bytes(UUID_bytes, byteorder='big') + UUID_int = int.from_bytes(UUID_bytes, byteorder="big") return UUID_int async def convert_int_to_uuid(self, i: int) -> str: - UUID_bytes = i.to_bytes(length=16, byteorder='big') + UUID_bytes = i.to_bytes(length=16, byteorder="big") UUID_data = NSData.alloc().initWithBytes_length_(UUID_bytes, len(UUID_bytes)) UUID_cb = CBUUID.alloc().initWithData_(UUID_data) return UUID_cb.UUIDString() diff --git a/bleak/backends/corebluetooth/corebleak.py b/bleak/backends/corebluetooth/corebleak.py index 1735e8ac..4a71f8bc 100644 --- a/bleak/backends/corebluetooth/corebleak.py +++ b/bleak/backends/corebluetooth/corebleak.py @@ -6,7 +6,9 @@ DIR_PATH = os.path.dirname(THIS_FILE) FRAMEWORK_PATH = os.path.join(DIR_PATH, "corebleak.framework") -__bundle__ = objc.initFrameworkWrapper("corebleak.framework", - frameworkIdentifier="com.kcdvs.corebleak", - frameworkPath=objc.pathForFramework(FRAMEWORK_PATH), - globals = globals()) +__bundle__ = objc.initFrameworkWrapper( + "corebleak.framework", + frameworkIdentifier="com.kcdvs.corebleak", + frameworkPath=objc.pathForFramework(FRAMEWORK_PATH), + globals=globals(), +) diff --git a/bleak/backends/corebluetooth/discovery.py b/bleak/backends/corebluetooth/discovery.py index 4ac0f2e6..816c8b9f 100644 --- a/bleak/backends/corebluetooth/discovery.py +++ b/bleak/backends/corebluetooth/discovery.py @@ -18,9 +18,8 @@ async def discover( - timeout: float = 5.0, - loop: AbstractEventLoop = None, - **kwargs) -> List[BLEDevice]: + timeout: float = 5.0, loop: AbstractEventLoop = None, **kwargs +) -> List[BLEDevice]: """Perform a Bluetooth LE Scan. Args: @@ -35,9 +34,7 @@ async def discover( if not cbapp.central_manager_delegate.enabled: raise BleakError("Bluetooth device is turned off") - scan_options = { - 'timeout': timeout - } + scan_options = {"timeout": timeout} await cbapp.central_manager_delegate.scanForPeripherals_(scan_options) @@ -56,15 +53,30 @@ async def discover( details = peripheral advertisementData = cbapp.central_manager_delegate.advertisement_data_list[i] - manufacturer_binary_data = advertisementData['kCBAdvDataManufacturerData'] if 'kCBAdvDataManufacturerData' in advertisementData.keys() else None + manufacturer_binary_data = ( + advertisementData["kCBAdvDataManufacturerData"] + if "kCBAdvDataManufacturerData" in advertisementData.keys() + else None + ) manufacturer_data = {} if manufacturer_binary_data: - manufacturer_id = int.from_bytes(manufacturer_binary_data[0:2], byteorder='little') - manufacturer_value = ''.join(list(map(lambda x: format(x, 'x') if len(format(x, 'x')) == 2 else "0{}".format(format(x, 'x')), list(manufacturer_binary_data)[2:]))) - manufacturer_data = { - manufacturer_id: manufacturer_value - } - - found.append(BLEDevice(address, name, details, manufacturer_data=manufacturer_data)) + manufacturer_id = int.from_bytes( + manufacturer_binary_data[0:2], byteorder="little" + ) + manufacturer_value = "".join( + list( + map( + lambda x: format(x, "x") + if len(format(x, "x")) == 2 + else "0{}".format(format(x, "x")), + list(manufacturer_binary_data)[2:], + ) + ) + ) + manufacturer_data = {manufacturer_id: manufacturer_value} + + found.append( + BLEDevice(address, name, details, manufacturer_data=manufacturer_data) + ) return found diff --git a/bleak/backends/corebluetooth/service.py b/bleak/backends/corebluetooth/service.py index d13cacf8..6e6ef4d5 100644 --- a/bleak/backends/corebluetooth/service.py +++ b/bleak/backends/corebluetooth/service.py @@ -2,7 +2,9 @@ from Foundation import CBService, CBUUID -from bleak.backends.corebluetooth.characteristic import BleakGATTCharacteristicCoreBluetooth +from bleak.backends.corebluetooth.characteristic import ( + BleakGATTCharacteristicCoreBluetooth +) from bleak.backends.service import BleakGATTService @@ -11,7 +13,7 @@ class BleakGATTServiceCoreBluetooth(BleakGATTService): def __init__(self, obj: CBService): super().__init__(obj) - self.__characteristics = [ ] + self.__characteristics = [] @property def uuid(self) -> str: @@ -22,7 +24,9 @@ def characteristics(self) -> List[BleakGATTCharacteristicCoreBluetooth]: """List of characteristics for this service""" return self.__characteristics - def get_characteristic(self, _uuid: CBUUID) -> Union[BleakGATTCharacteristicCoreBluetooth, None]: + def get_characteristic( + self, _uuid: CBUUID + ) -> Union[BleakGATTCharacteristicCoreBluetooth, None]: """Get a characteristic by UUID""" try: return next(filter(lambda x: x.uuid == _uuid, self.characteristics)) diff --git a/bleak/backends/dotnet/client.py b/bleak/backends/dotnet/client.py index 6b46d8ae..a3567f9b 100644 --- a/bleak/backends/dotnet/client.py +++ b/bleak/backends/dotnet/client.py @@ -97,7 +97,7 @@ async def connect(self, **kwargs) -> bool: """ # Try to find the desired device. - devices = await discover(timeout=kwargs.get('timeout', 2.0), loop=self.loop) + devices = await discover(timeout=kwargs.get("timeout", 2.0), loop=self.loop) sought_device = list( filter(lambda x: x.address.upper() == self.address.upper(), devices) ) diff --git a/bleak/backends/dotnet/discovery.py b/bleak/backends/dotnet/discovery.py index 8a43dbda..07292f88 100644 --- a/bleak/backends/dotnet/discovery.py +++ b/bleak/backends/dotnet/discovery.py @@ -100,6 +100,14 @@ def AdvertisementWatcher_Stopped(sender, e): reader = DataReader.FromBuffer(md) reader.ReadBytes(b) data[m.CompanyId] = bytes(b) - found.append(BLEDevice(bdaddr, d.Advertisement.LocalName, d, uuids=uuids, manufacturer_data=data)) + found.append( + BLEDevice( + bdaddr, + d.Advertisement.LocalName, + d, + uuids=uuids, + manufacturer_data=data, + ) + ) return found diff --git a/examples/enable_notifications.py b/examples/enable_notifications.py index 50158746..dc6ce0a6 100644 --- a/examples/enable_notifications.py +++ b/examples/enable_notifications.py @@ -16,7 +16,9 @@ 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 a6effa24..82ce4cc1 100644 --- a/examples/sensortag.py +++ b/examples/sensortag.py @@ -152,6 +152,10 @@ def keypress_handler(sender, data): import os os.environ["PYTHONASYNCIODEBUG"] = str(1) - address = "24:71:89:cc:09:05" if platform.system() != "Darwin" else "243E23AE-4A99-406C-B317-18F1BD7B4CBE" + address = ( + "24:71:89:cc:09:05" + if platform.system() != "Darwin" + else "243E23AE-4A99-406C-B317-18F1BD7B4CBE" + ) loop = asyncio.get_event_loop() loop.run_until_complete(run(address, loop, True)) diff --git a/examples/service_explorer.py b/examples/service_explorer.py index 7bd97080..9cc6e6af 100644 --- a/examples/service_explorer.py +++ b/examples/service_explorer.py @@ -55,8 +55,10 @@ async def run(address, loop, debug=False): if __name__ == "__main__": - address = "24:71:89:cc:09:05" if platform.system() != "Darwin" else "243E23AE-4A99-406C-B317-18F1BD7B4CBE" + address = ( + "24:71:89:cc:09:05" + if platform.system() != "Darwin" + else "243E23AE-4A99-406C-B317-18F1BD7B4CBE" + ) loop = asyncio.get_event_loop() loop.run_until_complete(run(address, loop, True)) - -