@@ -456,6 +456,13 @@ def characteristic_enable_notifications_failed(self, characteristic, error):
456456 # To be implemented by subclass
457457 pass
458458
459+ def descriptor_read_value_failed (self , descriptor , error ):
460+ """
461+ Called when a descriptor read command failed.
462+ """
463+ # To be implemented by subclass
464+ pass
465+
459466
460467class Service :
461468 """
@@ -505,6 +512,35 @@ def characteristics_resolved(self):
505512 self ._connect_characteristic_signals ()
506513
507514
515+ class Descriptor :
516+ """
517+ Represents a GATT Descriptor which can contain metadata or configuration of its characteristic.
518+ """
519+
520+ def __init__ (self , characteristic , path , uuid ):
521+ self .characteristic = characteristic
522+ self .uuid = uuid
523+ self ._bus = characteristic ._bus
524+ self ._path = path
525+ self ._object = self ._bus .get_object ('org.bluez' , self ._path )
526+
527+ def read_value (self , offset = 0 ):
528+ """
529+ Reads the value of this descriptor.
530+
531+ When successful, the value will be returned, otherwise `descriptor_read_value_failed()` of the related
532+ device is invoked.
533+ """
534+ try :
535+ val = self ._object .ReadValue (
536+ {'offset' : dbus .UInt16 (offset , variant_level = 1 )},
537+ dbus_interface = 'org.bluez.GattDescriptor1' )
538+ return val
539+ except dbus .exceptions .DBusException as e :
540+ error = _error_from_dbus_error (e )
541+ self .service .device .descriptor_read_value_failed (self , error = error )
542+
543+
508544class Characteristic :
509545 """
510546 Represents a GATT characteristic.
@@ -521,6 +557,13 @@ def __init__(self, service, path, uuid):
521557 self ._properties = dbus .Interface (self ._object , "org.freedesktop.DBus.Properties" )
522558 self ._properties_signal = None
523559
560+ descriptor_regex = re .compile (self ._path + '/desc[0-9abcdef]{4}$' )
561+ self .descriptors = [
562+ Descriptor (self , desc [0 ], desc [1 ]['org.bluez.GattDescriptor1' ]['UUID' ])
563+ for desc in self ._object_manager .GetManagedObjects ().items ()
564+ if descriptor_regex .match (desc [0 ])
565+ ]
566+
524567 def _connect_signals (self ):
525568 if self ._properties_signal is None :
526569 self ._properties_signal = self ._properties .connect_to_signal ('PropertiesChanged' , self .properties_changed )
0 commit comments