Source code for bleak.backends.corebluetooth.characteristic

"""
Interface class for the Bleak representation of a GATT Characteristic

Created on 2019-06-28 by kevincar <kevincarrolldavis@gmail.com>

"""
from enum import Enum
from typing import Dict, List, Optional, Tuple, Union

from CoreBluetooth import CBCharacteristic

from bleak.backends.characteristic import BleakGATTCharacteristic
from bleak.backends.corebluetooth.descriptor import BleakGATTDescriptorCoreBluetooth
from bleak.backends.corebluetooth.utils import cb_uuid_to_str


[docs]class CBCharacteristicProperties(Enum): BROADCAST = 0x1 READ = 0x2 WRITE_WITHOUT_RESPONSE = 0x4 WRITE = 0x8 NOTIFY = 0x10 INDICATE = 0x20 AUTHENTICATED_SIGNED_WRITES = 0x40 EXTENDED_PROPERTIES = 0x80 NOTIFY_ENCRYPTION_REQUIRED = 0x100 INDICATE_ENCRYPTION_REQUIRED = 0x200
_GattCharacteristicsPropertiesEnum: Dict[Optional[int], Tuple[str, str]] = { None: ("None", "The characteristic doesn’t have any properties that apply"), 1: ("Broadcast".lower(), "The characteristic supports broadcasting"), 2: ("Read".lower(), "The characteristic is readable"), 4: ( "Write-Without-Response".lower(), "The characteristic supports Write Without Response", ), 8: ("Write".lower(), "The characteristic is writable"), 16: ("Notify".lower(), "The characteristic is notifiable"), 32: ("Indicate".lower(), "The characteristic is indicatable"), 64: ( "Authenticated-Signed-Writes".lower(), "The characteristic supports signed writes", ), 128: ( "Extended-Properties".lower(), "The ExtendedProperties Descriptor is present", ), 256: ("Reliable-Writes".lower(), "The characteristic supports reliable writes"), 512: ( "Writable-Auxiliaries".lower(), "The characteristic has writable auxiliaries", ), }
[docs]class BleakGATTCharacteristicCoreBluetooth(BleakGATTCharacteristic): """GATT Characteristic implementation for the CoreBluetooth backend""" def __init__(self, obj: CBCharacteristic, max_write_without_response_size: int): super().__init__(obj, max_write_without_response_size) self.__descriptors: List[BleakGATTDescriptorCoreBluetooth] = [] # self.__props = obj.properties() self.__props: List[str] = [ _GattCharacteristicsPropertiesEnum[v][0] for v in [2**n for n in range(10)] if (self.obj.properties() & v) ] self._uuid: str = cb_uuid_to_str(self.obj.UUID()) @property def service_uuid(self) -> str: """The uuid of the Service containing this characteristic""" return cb_uuid_to_str(self.obj.service().UUID()) @property def service_handle(self) -> int: return int(self.obj.service().startHandle()) @property def handle(self) -> int: """Integer handle for this characteristic""" return int(self.obj.handle()) @property def uuid(self) -> str: """The uuid of this characteristic""" return self._uuid @property def properties(self) -> List[str]: """Properties of this characteristic""" return self.__props @property def descriptors(self) -> List[BleakGATTDescriptorCoreBluetooth]: """List of descriptors for this service""" return self.__descriptors
[docs] 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) ) except StopIteration: return None
[docs] def add_descriptor(self, descriptor: BleakGATTDescriptorCoreBluetooth): """Add a :py:class:`~BleakGATTDescriptor` to the characteristic. Should not be used by end user, but rather by `bleak` itself. """ self.__descriptors.append(descriptor)