From b89f9030a0ae1a49f1d7d284de88163b9c6bcd33 Mon Sep 17 00:00:00 2001 From: Alan Rosenthal Date: Wed, 23 Nov 2022 13:06:31 -0500 Subject: [PATCH] Added class CharacteristicDeclaration, gatt_server getters * Converted CharacteristicDeclaration implementation to class * Added ability to get a gatt_server attribute by service UUID, characteristics UUID, descriptor UUID --- bumble/gatt.py | 17 +++++++++++ bumble/gatt_server.py | 71 +++++++++++++++++++++++++++++++++++++------ tests/gatt_test.py | 32 +++++++++++++++++++ 3 files changed, 110 insertions(+), 10 deletions(-) diff --git a/bumble/gatt.py b/bumble/gatt.py index 889eaa44..d2aaf571 100644 --- a/bumble/gatt.py +++ b/bumble/gatt.py @@ -271,6 +271,23 @@ class Characteristic(Attribute): return f'Characteristic(handle=0x{self.handle:04X}, end=0x{self.end_group_handle:04X}, uuid={self.uuid}, properties={Characteristic.properties_as_string(self.properties)})' +# ----------------------------------------------------------------------------- +class CharacteristicDeclaration(Attribute): + ''' + See Vol 3, Part G - 3.3.1 CHARACTERISTIC DECLARATION + ''' + def __init__(self, characteristic, value_handle): + declaration_bytes = struct.pack( + ' Optional[Service]: + return next( + ( + attribute + for attribute in self.attributes + if attribute.type == GATT_PRIMARY_SERVICE_ATTRIBUTE_TYPE + and attribute.uuid == service_uuid + ), + None, + ) + + def get_characteristic_attributes( + self, service_uuid: UUID, characteristic_uuid: UUID + ) -> Optional[Tuple[CharacteristicDeclaration, Characteristic]]: + service_handle = self.get_service_attribute(service_uuid) + if not service_handle: + return None + + return next( + ( + (attribute, self.get_attribute(attribute.characteristic.handle)) + for attribute in map( + self.get_attribute, + range(service_handle.handle, service_handle.end_group_handle + 1), + ) + if attribute.type == GATT_CHARACTERISTIC_ATTRIBUTE_TYPE + and attribute.characteristic.uuid == characteristic_uuid + ), + None, + ) + + def get_descriptor_attribute( + self, service_uuid: UUID, characteristic_uuid: UUID, descriptor_uuid: UUID + ) -> Optional[Descriptor]: + characteristics = self.get_characteristic_attributes( + service_uuid, characteristic_uuid + ) + if not characteristics: + return None + + (_, characteristic_value) = characteristics + + return next( + ( + attribute + for attribute in map( + self.get_attribute, + range( + characteristic_value.handle + 1, + characteristic_value.end_group_handle + 1, + ), + ) + if attribute.type == descriptor_uuid + ), + None, + ) + def add_attribute(self, attribute): # Assign a handle to this attribute attribute.handle = self.next_handle() @@ -95,16 +153,9 @@ class Server(EventEmitter): # Add all characteristics for characteristic in service.characteristics: - # Add a Characteristic Declaration (Vol 3, Part G - 3.3.1 Characteristic Declaration) - declaration_bytes = struct.pack( - '