@@ -456,6 +456,13 @@ def characteristic_enable_notifications_failed(self, characteristic, error):
456
456
# To be implemented by subclass
457
457
pass
458
458
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
+
459
466
460
467
class Service :
461
468
"""
@@ -505,6 +512,35 @@ def characteristics_resolved(self):
505
512
self ._connect_characteristic_signals ()
506
513
507
514
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
+
508
544
class Characteristic :
509
545
"""
510
546
Represents a GATT characteristic.
@@ -521,6 +557,13 @@ def __init__(self, service, path, uuid):
521
557
self ._properties = dbus .Interface (self ._object , "org.freedesktop.DBus.Properties" )
522
558
self ._properties_signal = None
523
559
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
+
524
567
def _connect_signals (self ):
525
568
if self ._properties_signal is None :
526
569
self ._properties_signal = self ._properties .connect_to_signal ('PropertiesChanged' , self .properties_changed )
0 commit comments