@@ -328,14 +328,65 @@ public final class AndroidCentral: CentralManager {
328328 public func discoverDescriptors(
329329 for characteristic: Characteristic < Peripheral , AttributeID >
330330 ) async throws -> [ Descriptor < Peripheral , AttributeID > ] {
331- fatalError ( )
331+
332+ log ? ( " \( type ( of: self ) ) \( #function) " )
333+
334+ return try await storage. update { state in
335+
336+ guard let cache = state. cache [ characteristic. peripheral]
337+ else { throw CentralError . disconnected }
338+
339+ guard let gattCharacteristic = cache. characteristics. values [ characteristic. id] ? . attribute
340+ else { throw AndroidCentralError . characteristicNotFound }
341+
342+ guard let services = state. cache [ characteristic. peripheral] ? . update ( gattCharacteristics, for: service) else {
343+ assertionFailure ( " Missing connection cache " )
344+ return [ ]
345+ }
346+
347+ return services
348+ }
332349 }
333350
334351 /// Read descriptor
335352 public func readValue(
336353 for descriptor: Descriptor < Peripheral , AttributeID >
337354 ) async throws -> Data {
338- fatalError ( )
355+
356+ log ? ( " \( type ( of: self ) ) \( #function) " )
357+
358+ guard hostController. isEnabled ( )
359+ else { throw AndroidCentralError . bluetoothDisabled }
360+
361+ let peripheral = descriptor. peripheral
362+
363+ return try await withCheckedThrowingContinuation { continuation in
364+ Task {
365+ do {
366+ try await storage. update { state in
367+ // store continuation
368+ state. cache [ peripheral] ? . continuation. readDescriptor = continuation
369+
370+ guard state. scan. peripherals. keys. contains ( peripheral)
371+ else { throw CentralError . unknownPeripheral }
372+
373+ guard let gatt = state. cache [ peripheral] ? . gatt
374+ else { throw CentralError . disconnected }
375+
376+ let characteristicID = descriptor
377+
378+ guard let gattDescriptor = cache. characteristics. values [ descriptor. id] ? . attribute
379+ else { throw AndroidCentralError . characteristicNotFound }
380+
381+ guard gatt. readDescriptor ( descriptor: gattDescriptor)
382+ else { throw AndroidCentralError . binderFailure }
383+ }
384+ }
385+ catch {
386+ continuation. resume ( throwing: error)
387+ }
388+ }
389+ }
339390 }
340391
341392 /// Write descriptor
@@ -344,6 +395,41 @@ public final class AndroidCentral: CentralManager {
344395 for descriptor: Descriptor < Peripheral , AttributeID >
345396 ) async throws {
346397
398+ log ? ( " \( type ( of: self ) ) \( #function) " )
399+
400+ guard hostController. isEnabled ( )
401+ else { throw AndroidCentralError . bluetoothDisabled }
402+
403+ let peripheral = descriptor. peripheral
404+
405+ return try await withCheckedThrowingContinuation { continuation in
406+ Task {
407+ do {
408+ try await storage. update { state in
409+ // store continuation
410+ state. cache [ peripheral] ? . continuation. writeDescriptor = continuation
411+
412+ guard state. scan. peripherals. keys. contains ( peripheral)
413+ else { throw CentralError . unknownPeripheral }
414+
415+ guard let cache = state. cache [ peripheral]
416+ else { throw CentralError . disconnected }
417+
418+ guard let gattDescriptor = cache. characteristics. values [ descriptor. id] ? . attribute
419+ else { throw AndroidCentralError . characteristicNotFound }
420+
421+ let dataArray = [ UInt8] ( data)
422+ let _ = gattDescriptor. setValue ( value: unsafeBitCast ( dataArray, to: [ Int8 ] . self) )
423+
424+ guard cache. gatt. writeDescriptor ( descriptor: gattDescriptor)
425+ else { throw AndroidCentralError . binderFailure }
426+ }
427+ }
428+ catch {
429+ continuation. resume ( throwing: error)
430+ }
431+ }
432+ }
347433 }
348434
349435 /// Start Notifications
@@ -594,7 +680,7 @@ public final class AndroidCentral: CentralManager {
594680 ) {
595681 let log = central? . log
596682 log ? ( " \( type ( of: self ) ) : \( #function) " )
597- log ? ( " Status: \( status) - newState = \( newState) " )
683+ log ? ( " Status: \( status) - newState: \( newState) " )
598684
599685 let peripheral = Peripheral ( gatt)
600686
@@ -696,9 +782,8 @@ public final class AndroidCentral: CentralManager {
696782 status: Android . Bluetooth . Gatt . Status
697783 ) {
698784 let log = central? . log
699- log ? ( " \( type ( of: self ) ) : \( #function) " )
700785 let peripheral = Peripheral ( gatt)
701- log ? ( " \( peripheral) Status: \( status) " )
786+ log ? ( " \( type ( of : self ) ) : \( #function ) \( peripheral) Status: \( status) " )
702787
703788 Task {
704789 await central? . storage. update { state in
@@ -744,9 +829,29 @@ public final class AndroidCentral: CentralManager {
744829 descriptor: Android . Bluetooth . GattDescriptor ,
745830 status: Android . Bluetooth . Gatt . Status
746831 ) {
832+ let peripheral = Peripheral ( gatt)
747833
748- central? . log ? ( " \( type ( of: self ) ) : \( #function) " )
834+ guard let uuid = descriptor. getUUID ( ) . toString ( ) else {
835+ assertionFailure ( )
836+ return
837+ }
838+
839+ central? . log ? ( " \( type ( of: self ) ) : \( #function) \( uuid) " )
749840
841+ Task {
842+ await central? . storage. update { state in
843+
844+ switch status {
845+ case . success:
846+ let data = descriptor. getValue ( )
847+ . map { Data ( unsafeBitCast ( $0, to: [ UInt8 ] . self) ) } ?? Data ( )
848+ state. cache [ peripheral] ? . continuation. readDescriptor? . resume ( returning: data)
849+ default :
850+ state. cache [ peripheral] ? . continuation. readDescriptor? . resume ( throwing: status)
851+ }
852+ state. cache [ peripheral] ? . continuation. readDescriptor = nil
853+ }
854+ }
750855 }
751856
752857 public override func onDescriptorWrite(
@@ -768,11 +873,11 @@ public final class AndroidCentral: CentralManager {
768873 await central? . storage. update { state in
769874 switch status {
770875 case . success:
771- state. cache [ peripheral] ? . continuation. writeCharacteristic ? . resume ( )
876+ state. cache [ peripheral] ? . continuation. writeDescriptor ? . resume ( )
772877 default :
773- state. cache [ peripheral] ? . continuation. writeCharacteristic ? . resume ( throwing: status)
878+ state. cache [ peripheral] ? . continuation. writeDescriptor ? . resume ( throwing: status)
774879 }
775- state. cache [ peripheral] ? . continuation. writeCharacteristic = nil
880+ state. cache [ peripheral] ? . continuation. writeDescriptor = nil
776881 }
777882 }
778883 }
@@ -831,16 +936,16 @@ public final class AndroidCentral: CentralManager {
831936 central? . log ? ( " \( type ( of: self ) ) : \( #function) \( rssi) \( status) " )
832937
833938 let peripheral = Peripheral ( gatt)
834-
939+
835940 Task {
836941 await central? . storage. update { state in
837942 switch status {
838943 case . success:
839- state. cache [ peripheral] ? . continuation. writeCharacteristic ? . resume ( )
944+ state. cache [ peripheral] ? . continuation. readRemoteRSSI ? . resume ( returning : rssi )
840945 default :
841- state. cache [ peripheral] ? . continuation. writeCharacteristic ? . resume ( throwing: status)
946+ state. cache [ peripheral] ? . continuation. readRemoteRSSI ? . resume ( throwing: status)
842947 }
843- state. cache [ peripheral] ? . continuation. writeCharacteristic = nil
948+ state. cache [ peripheral] ? . continuation. readRemoteRSSI = nil
844949 }
845950 }
846951 }
@@ -946,14 +1051,23 @@ internal extension AndroidCentral {
9461051
9471052 struct Characteristics {
9481053
949- fileprivate( set) var values : [ AndroidCentral . AttributeID : ( attribute : Android . Bluetooth . GattCharacteristic , notification : ( ( Data ) -> ( ) ) ? ) ] = [ : ]
1054+ fileprivate( set) var values : [ AndroidCentral . AttributeID : CharacteristicCache ] = [ : ]
9501055 }
9511056
9521057 struct Services {
9531058
9541059 fileprivate( set) var values : [ AndroidCentral . AttributeID : Android . Bluetooth . GattService ] = [ : ]
9551060 }
9561061
1062+ struct CharacteristicCache {
1063+
1064+ let object : Android . Bluetooth . GattCharacteristic
1065+
1066+ var descriptors : [ Android . Bluetooth . GattDescriptor ] = [ ]
1067+
1068+ var notification : AsyncIndefiniteStream < Data > . Continuation ?
1069+ }
1070+
9571071 fileprivate func identifier< T> ( for attribute: T ) -> AndroidCentral . AttributeID where T: AndroidCentralAttribute {
9581072 let peripheral = Peripheral ( gatt)
9591073 let instanceID = attribute. getInstanceId ( )
@@ -964,8 +1078,19 @@ internal extension AndroidCentral {
9641078 return " \( peripheral. id) / \( instanceID) / \( uuid) "
9651079 }
9661080
1081+ fileprivate func identifier(
1082+ for descriptor: Android . Bluetooth . GattDescriptor ,
1083+ characteristic: Characteristic < Peripheral , AttributeID >
1084+ ) -> AndroidCentral . AttributeID {
1085+ guard let uuid = descriptor. getUUID ( ) . toString ( ) else {
1086+ fatalError ( )
1087+ }
1088+ return characteristic. id + " /Descriptor/ \( uuid) "
1089+ }
1090+
9671091 fileprivate mutating func update( _ newValues: [ Android . Bluetooth . GattService ] ) -> [ Service < Peripheral , AttributeID > ] {
9681092 services. values. removeAll ( keepingCapacity: true )
1093+ characteristics. values. removeAll ( keepingCapacity: true )
9691094 return newValues. map {
9701095 let id = identifier ( for: $0)
9711096 let peripheral = Peripheral ( gatt)
@@ -987,15 +1112,14 @@ internal extension AndroidCentral {
9871112 _ newValues: [ Android . Bluetooth . GattCharacteristic ] ,
9881113 for service: Service < Peripheral , AttributeID >
9891114 ) -> [ Characteristic < Peripheral , AttributeID > ] {
990- characteristics. values. removeAll ( keepingCapacity: true )
9911115 return newValues. map {
9921116 let id = identifier ( for: $0)
9931117 let peripheral = Peripheral ( gatt)
9941118 let uuid = BluetoothUUID ( android: $0. getUUID ( ) )
9951119 let properties = BitMaskOptionSet < CharacteristicProperty > ( rawValue: UInt8 ( $0. getProperties ( ) ) )
9961120 // cache
997- characteristics. values [ id] = ( $0 , nil )
998- //
1121+ characteristics. values [ id] = CharacteristicCache ( object : $0 )
1122+ // return Swift value
9991123 return Characteristic (
10001124 id: id,
10011125 uuid: uuid,
@@ -1004,6 +1128,25 @@ internal extension AndroidCentral {
10041128 )
10051129 }
10061130 }
1131+
1132+ fileprivate mutating func update(
1133+ _ newValues: [ Android . Bluetooth . GattDescriptor ] ,
1134+ for characteristic: Characteristic < Peripheral , AttributeID >
1135+ ) -> [ Descriptor < Peripheral , AttributeID > ] {
1136+ // cache
1137+ characteristics. values [ characteristic. id] ? . descriptors = newValues
1138+ // return swift value
1139+ return newValues. map {
1140+ let id = identifier ( for: $0, characteristic: characteristic)
1141+ let peripheral = Peripheral ( gatt)
1142+ let uuid = BluetoothUUID ( android: $0. getUUID ( ) )
1143+ return Descriptor (
1144+ id: id,
1145+ uuid: uuid,
1146+ peripheral: peripheral
1147+ )
1148+ }
1149+ }
10071150 }
10081151
10091152 struct PeripheralContinuation {
0 commit comments