Skip to content

Commit 493d165

Browse files
committed
Fixing descriptor read
1 parent c7856b5 commit 493d165

1 file changed

Lines changed: 160 additions & 17 deletions

File tree

Sources/AndroidBluetooth/AndroidCentral.swift

Lines changed: 160 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)