Files
bluetooth_low_energy/bluetooth_low_energy_darwin/darwin/Classes/MyCentralManager.swift
Mr剑侠客 4bec1c9f3a fix: 修复写入特征值无法完成和重启蓝牙后调用外围设备方法报错的问题 (#20)
* fix: 修复示例代码问题

* fix: 断开连接时清理缓存

* fix: 修复蓝牙重新打开后 GATT server 失效的问题

* fix: 修复问题

* fix: 修复写入特征值无法完成的问题

* fix: 修改版本号
2023-10-12 18:29:03 +08:00

665 lines
30 KiB
Swift

//
// MyCentralController.swift
// bluetooth_low_energy_ios
//
// Created by on 2023/8/13.
//
import Foundation
import CoreBluetooth
#if os(iOS)
import Flutter
#elseif os(macOS)
import FlutterMacOS
#else
#error("Unsupported platform.")
#endif
class MyCentralManager: MyCentralManagerHostApi {
init(_ binaryMessenger: FlutterBinaryMessenger) {
self.binaryMessenger = binaryMessenger
}
private let binaryMessenger: FlutterBinaryMessenger
private let centralManager = CBCentralManager()
private lazy var api = MyCentralManagerFlutterApi(binaryMessenger: binaryMessenger)
private lazy var centralManagerDelegate = MyCentralManagerDelegate(self)
private lazy var peripheralDelegate = MyPeripheralDelegate(self)
private var peripherals = [Int64: CBPeripheral]()
private var services = [Int64: CBService]()
private var characteristics = [Int64: CBCharacteristic]()
private var descriptors = [Int64: CBDescriptor]()
private var peripheralsArgs = [Int: MyPeripheralArgs]()
private var servicesArgsOfPeripheralsArgs = [Int64: [MyGattServiceArgs]]()
private var servicesArgs = [Int: MyGattServiceArgs]()
private var characteristicsArgs = [Int: MyGattCharacteristicArgs]()
private var descriptorsArgs = [Int: MyGattDescriptorArgs]()
private var setUpCompletion: ((Result<MyCentralManagerArgs, Error>) -> Void)?
private var connectCompletions = [Int64: (Result<Void, Error>) -> Void]()
private var disconnectCompletions = [Int64: (Result<Void, Error>) -> Void]()
private var readRssiCompletions = [Int64: (Result<Int64, Error>) -> Void]()
private var discoverGattCompletions = [Int64: (Result<[MyGattServiceArgs], Error>) -> Void]()
private var unfinishedServices = [Int64: [CBService]]()
private var unfinishedCharacteristics = [Int64: [CBCharacteristic]]()
private var readCharacteristicCompletions = [Int64: (Result<FlutterStandardTypedData, Error>) -> Void]()
private var writeCharacteristicCompletions = [Int64: (Result<Void, Error>) -> Void]()
private var notifyCharacteristicCompletions = [Int64: (Result<Void, Error>) -> Void]()
private var readDescriptorCompletions = [Int64: (Result<FlutterStandardTypedData, Error>) -> Void]()
private var writeDescriptorCompletions = [Int64: (Result<Void, Error>) -> Void]()
func setUp(completion: @escaping (Result<MyCentralManagerArgs, Error>) -> Void) {
do {
if setUpCompletion != nil {
throw MyError.illegalState
}
try tearDown()
centralManager.delegate = centralManagerDelegate
if centralManager.state == .unknown {
setUpCompletion = completion
} else {
let stateArgs = centralManager.state.toArgs()
let stateNumberArgs = Int64(stateArgs.rawValue)
let args = MyCentralManagerArgs(stateNumberArgs: stateNumberArgs)
completion(.success(args))
}
} catch {
completion(.failure(error))
}
}
func tearDown() throws {
if(centralManager.isScanning) {
centralManager.stopScan()
}
for peripheral in peripherals.values {
if peripheral.state != .disconnected {
centralManager.cancelPeripheralConnection(peripheral)
}
}
peripherals.removeAll()
services.removeAll()
characteristics.removeAll()
descriptors.removeAll()
peripheralsArgs.removeAll()
servicesArgsOfPeripheralsArgs.removeAll()
servicesArgs.removeAll()
characteristicsArgs.removeAll()
descriptorsArgs.removeAll()
setUpCompletion = nil
connectCompletions.removeAll()
disconnectCompletions.removeAll()
readRssiCompletions.removeAll()
discoverGattCompletions.removeAll()
unfinishedServices.removeAll()
unfinishedCharacteristics.removeAll()
readCharacteristicCompletions.removeAll()
writeCharacteristicCompletions.removeAll()
notifyCharacteristicCompletions.removeAll()
readDescriptorCompletions.removeAll()
writeDescriptorCompletions.removeAll()
}
func startDiscovery() throws {
let options = [CBCentralManagerScanOptionAllowDuplicatesKey: true]
centralManager.scanForPeripherals(withServices: nil, options: options)
}
func stopDiscovery() throws {
centralManager.stopScan()
}
func connect(peripheralHashCodeArgs: Int64, completion: @escaping (Result<Void, Error>) -> Void) {
do {
let unfinishedCompletion = connectCompletions[peripheralHashCodeArgs]
if unfinishedCompletion != nil {
throw MyError.illegalState
}
guard let peripheral = peripherals[peripheralHashCodeArgs] else {
throw MyError.illegalArgument
}
centralManager.connect(peripheral)
connectCompletions[peripheralHashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func disconnect(peripheralHashCodeArgs: Int64, completion: @escaping (Result<Void, Error>) -> Void) {
do {
let unfinishedCompletion = disconnectCompletions[peripheralHashCodeArgs]
if unfinishedCompletion != nil {
throw MyError.illegalState
}
guard let peripheral = peripherals[peripheralHashCodeArgs] else {
throw MyError.illegalArgument
}
centralManager.cancelPeripheralConnection(peripheral)
disconnectCompletions[peripheralHashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func getMaximumWriteLength(peripheralHashCodeArgs: Int64, typeNumberArgs: Int64) throws -> Int64 {
guard let peripheral = peripherals[peripheralHashCodeArgs] else {
throw MyError.illegalArgument
}
let typeRawValue = Int(typeNumberArgs)
guard let typeArgs = MyGattCharacteristicWriteTypeArgs(rawValue: typeRawValue) else {
throw MyError.illegalArgument
}
let type = typeArgs.toWriteType()
let maximumWriteLength = peripheral.maximumWriteValueLength(for: type)
let maximumWriteLengthArgs = Int64(maximumWriteLength)
return maximumWriteLengthArgs
}
func readRSSI(peripheralHashCodeArgs: Int64, completion: @escaping (Result<Int64, Error>) -> Void) {
do {
let unfinishedCompletion = readRssiCompletions[peripheralHashCodeArgs]
if unfinishedCompletion != nil {
throw MyError.illegalState
}
guard let peripheral = peripherals[peripheralHashCodeArgs] else {
throw MyError.illegalArgument
}
peripheral.readRSSI()
readRssiCompletions[peripheralHashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func discoverGATT(peripheralHashCodeArgs: Int64, completion: @escaping (Result<[MyGattServiceArgs], Error>) -> Void) {
do {
let unfinishedCompletion = discoverGattCompletions[peripheralHashCodeArgs]
if unfinishedCompletion != nil {
throw MyError.illegalState
}
guard let peripheral = peripherals[peripheralHashCodeArgs] else {
throw MyError.illegalArgument
}
peripheral.discoverServices(nil)
discoverGattCompletions[peripheralHashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func readCharacteristic(peripheralHashCodeArgs: Int64, characteristicHashCodeArgs: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
do {
let unfinishedCompletion = readCharacteristicCompletions[characteristicHashCodeArgs]
if unfinishedCompletion != nil {
throw MyError.illegalState
}
guard let peripheral = peripherals[peripheralHashCodeArgs] else {
throw MyError.illegalArgument
}
guard let characteristic = characteristics[characteristicHashCodeArgs] else {
throw MyError.illegalArgument
}
peripheral.readValue(for: characteristic)
readCharacteristicCompletions[characteristicHashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func writeCharacteristic(peripheralHashCodeArgs: Int64, characteristicHashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, typeNumberArgs: Int64, completion: @escaping (Result<Void, Error>) -> Void) {
do {
let unfinishedCompletion = writeCharacteristicCompletions[characteristicHashCodeArgs]
if unfinishedCompletion != nil {
throw MyError.illegalState
}
guard let peripheral = peripherals[peripheralHashCodeArgs] else {
throw MyError.illegalArgument
}
guard let characteristic = characteristics[characteristicHashCodeArgs] else {
throw MyError.illegalArgument
}
let data = valueArgs.data
let typeRawValue = Int(typeNumberArgs)
guard let typeArgs = MyGattCharacteristicWriteTypeArgs(rawValue: typeRawValue) else {
throw MyError.illegalArgument
}
let type = typeArgs.toWriteType()
peripheral.writeValue(data, for: characteristic, type: type)
if type == .withResponse {
writeCharacteristicCompletions[characteristicHashCodeArgs] = completion
} else {
completion(.success(()))
}
} catch {
completion(.failure(error))
}
}
func notifyCharacteristic(peripheralHashCodeArgs: Int64, characteristicHashCodeArgs: Int64, stateArgs: Bool, completion: @escaping (Result<Void, Error>) -> Void) {
do {
let unfinishedCompletion = notifyCharacteristicCompletions[characteristicHashCodeArgs]
if unfinishedCompletion != nil {
throw MyError.illegalState
}
guard let peripheral = peripherals[peripheralHashCodeArgs] else {
throw MyError.illegalArgument
}
guard let characteristic = characteristics[characteristicHashCodeArgs] else {
throw MyError.illegalArgument
}
let enabled = stateArgs
peripheral.setNotifyValue(enabled, for: characteristic)
notifyCharacteristicCompletions[characteristicHashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func readDescriptor(peripheralHashCodeArgs: Int64, descriptorHashCodeArgs: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
do {
let unfinishedCompletion = readDescriptorCompletions[descriptorHashCodeArgs]
if unfinishedCompletion != nil {
throw MyError.illegalState
}
guard let peripheral = peripherals[peripheralHashCodeArgs] else {
throw MyError.illegalArgument
}
guard let descriptor = descriptors[descriptorHashCodeArgs] else {
throw MyError.illegalArgument
}
peripheral.readValue(for: descriptor)
readDescriptorCompletions[descriptorHashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func writeDescriptor(peripheralHashCodeArgs: Int64, descriptorHashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void) {
do {
let unfinishedCompletion = writeDescriptorCompletions[descriptorHashCodeArgs]
if unfinishedCompletion != nil {
throw MyError.illegalState
}
guard let peripheral = peripherals[peripheralHashCodeArgs] else {
throw MyError.illegalArgument
}
guard let descriptor = descriptors[descriptorHashCodeArgs] else {
throw MyError.illegalArgument
}
let data = valueArgs.data
peripheral.writeValue(data, for: descriptor)
writeDescriptorCompletions[descriptorHashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func didUpdateState() {
let state = centralManager.state
let stateArgs = state.toArgs()
let stateNumberArgs = Int64(stateArgs.rawValue)
if state != .unknown && setUpCompletion != nil {
let args = MyCentralManagerArgs(stateNumberArgs: stateNumberArgs)
setUpCompletion!(.success(args))
setUpCompletion = nil
}
api.onStateChanged(stateNumberArgs: stateNumberArgs) {}
}
func didDiscover(_ peripheral: CBPeripheral, _ advertisementData: [String : Any], _ rssi: NSNumber) {
let peripheralArgs = peripheral.toArgs()
let peripheralHashCode = peripheral.hash
let peripheralHashCodeArgs = peripheralArgs.hashCodeArgs
peripheral.delegate = peripheralDelegate
peripherals[peripheralHashCodeArgs] = peripheral
peripheralsArgs[peripheralHashCode] = peripheralArgs
let rssiArgs = rssi.int64Value
let advertiseDataArgs = advertisementData.toAdvertiseDataArgs()
api.onDiscovered(peripheralArgs: peripheralArgs, rssiArgs: rssiArgs, advertiseDataArgs: advertiseDataArgs) {}
}
func didConnect(_ peripheral: CBPeripheral) {
let peripheralHashCode = peripheral.hash
guard let peripheralArgs = peripheralsArgs[peripheralHashCode] else {
return
}
let peripheralHashCodeArgs = peripheralArgs.hashCodeArgs
let completion = connectCompletions.removeValue(forKey: peripheralHashCodeArgs)
completion?(.success(()))
let stateArgs = true
api.onPeripheralStateChanged(peripheralArgs: peripheralArgs, stateArgs: stateArgs) {}
}
func didFailToConnect(_ peripheral: CBPeripheral, _ error: Error?) {
let peripheralHashCode = peripheral.hash
guard let peripheralArgs = peripheralsArgs[peripheralHashCode] else {
return
}
let peripheralHashCodeArgs = peripheralArgs.hashCodeArgs
let completion = connectCompletions.removeValue(forKey: peripheralHashCodeArgs)
completion?(.failure(error ?? MyError.unknown))
}
func didDisconnectPeripheral(_ peripheral: CBPeripheral, _ error: Error?) {
let peripheralHashCode = peripheral.hash
guard let peripheralArgs = peripheralsArgs[peripheralHashCode] else {
return
}
let peripheralHashCodeArgs = peripheralArgs.hashCodeArgs
let readRssiCompletion = readRssiCompletions.removeValue(forKey: peripheralHashCodeArgs)
readRssiCompletion?(.failure(error ?? MyError.unknown))
let discoverGattCompletion = discoverGattCompletions.removeValue(forKey: peripheralHashCodeArgs)
discoverGattCompletion?(.failure(error ?? MyError.unknown))
unfinishedServices.removeValue(forKey: peripheralHashCodeArgs)
unfinishedCharacteristics.removeValue(forKey: peripheralHashCodeArgs)
let servicesArgs = servicesArgsOfPeripheralsArgs.removeValue(forKey: peripheralHashCodeArgs) ?? []
for serviceArgs in servicesArgs {
let serviceHashCodeArgs = serviceArgs.hashCodeArgs
let service = services.removeValue(forKey: serviceHashCodeArgs)!
let serviceHashCode = service.hash
self.servicesArgs.removeValue(forKey: serviceHashCode)
let characteristicsArgs = serviceArgs.characteristicsArgs.map { args in args! }
for characteristicArgs in characteristicsArgs {
let characteristicHashCodeArgs = characteristicArgs.hashCodeArgs
let characteristic = characteristics.removeValue(forKey: characteristicHashCodeArgs)!
let characteristicHashCode = characteristic.hash
self.characteristicsArgs.removeValue(forKey: characteristicHashCode)
let readCharacteristicCompletion = readCharacteristicCompletions.removeValue(forKey: characteristicHashCodeArgs)
let writeCharacteristicCompletion = writeCharacteristicCompletions.removeValue(forKey: characteristicHashCodeArgs)
let notifyCharacteristicCompletion = notifyCharacteristicCompletions.removeValue(forKey: characteristicHashCodeArgs)
readCharacteristicCompletion?(.failure(error ?? MyError.unknown))
writeCharacteristicCompletion?(.failure(error ?? MyError.unknown))
notifyCharacteristicCompletion?(.failure(error ?? MyError.unknown))
let descriptorsArgs = characteristicArgs.descriptorsArgs.map { args in args! }
for descriptorArgs in descriptorsArgs {
let descriptorHashCodeArgs = descriptorArgs.hashCodeArgs
let descriptor = descriptors.removeValue(forKey: descriptorHashCodeArgs)!
let descriptorHashCode = descriptor.hash
self.descriptorsArgs.removeValue(forKey: descriptorHashCode)
let readDescriptorCompletion = readDescriptorCompletions.removeValue(forKey: descriptorHashCodeArgs)
let writeDescriptorCompletion = writeDescriptorCompletions.removeValue(forKey: descriptorHashCodeArgs)
readDescriptorCompletion?(.failure(error ?? MyError.unknown))
writeDescriptorCompletion?(.failure(error ?? MyError.unknown))
}
}
}
let stateArgs = false
api.onPeripheralStateChanged(peripheralArgs: peripheralArgs, stateArgs: stateArgs) {}
guard let completion = disconnectCompletions.removeValue(forKey: peripheralHashCodeArgs) else {
return
}
if error == nil {
completion(.success(()))
} else {
completion(.failure(error!))
}
}
func didReadRSSI(_ peripheral: CBPeripheral, _ rssi: NSNumber, _ error: Error?) {
let peripheralHashCode = peripheral.hash
guard let peripheralArgs = peripheralsArgs[peripheralHashCode] else {
return
}
let peripheralHashCodeArgs = peripheralArgs.hashCodeArgs
guard let completion = readRssiCompletions.removeValue(forKey: peripheralHashCodeArgs) else {
return
}
if error == nil {
let rssiArgs = rssi.int64Value
completion(.success((rssiArgs)))
} else {
completion(.failure(error!))
}
}
func didDiscoverServices(_ peripheral: CBPeripheral, _ error: Error?) {
let peripheralHashCode = peripheral.hash
guard let peripheralArgs = peripheralsArgs[peripheralHashCode] else {
return
}
let peripheralHashCodeArgs = peripheralArgs.hashCodeArgs
if error == nil {
var services = peripheral.services ?? []
if services.isEmpty {
didDiscoverGATT(peripheral, error)
} else {
let service = services.removeFirst()
unfinishedServices[peripheralHashCodeArgs] = services
peripheral.discoverCharacteristics(nil, for: service)
}
} else {
didDiscoverGATT(peripheral, error)
}
}
func didDiscoverCharacteristics(_ peripheral: CBPeripheral, _ service: CBService, _ error: Error?) {
let peripheralHashCode = peripheral.hash
guard let peripheralArgs = peripheralsArgs[peripheralHashCode] else {
return
}
let peripheralHashCodeArgs = peripheralArgs.hashCodeArgs
if error == nil {
var characteristics = service.characteristics ?? []
if characteristics.isEmpty {
var services = unfinishedServices.removeValue(forKey: peripheralHashCodeArgs) ?? []
if services.isEmpty {
didDiscoverGATT(peripheral, error)
} else {
let service = services.removeFirst()
unfinishedServices[peripheralHashCodeArgs] = services
peripheral.discoverCharacteristics(nil, for: service)
}
} else {
let characteristic = characteristics.removeFirst()
unfinishedCharacteristics[peripheralHashCodeArgs] = characteristics
peripheral.discoverDescriptors(for: characteristic)
}
} else {
didDiscoverGATT(peripheral, error)
}
}
func didDiscoverDescriptors(_ peripheral: CBPeripheral, _ characteristic: CBCharacteristic, _ error: Error?) {
let peripheralHashCode = peripheral.hash
guard let peripheralArgs = peripheralsArgs[peripheralHashCode] else {
return
}
let peripheralHashCodeArgs = peripheralArgs.hashCodeArgs
if error == nil {
var characteristics = unfinishedCharacteristics.removeValue(forKey: peripheralHashCodeArgs) ?? []
if (characteristics.isEmpty) {
var services = unfinishedServices.removeValue(forKey: peripheralHashCodeArgs) ?? []
if services.isEmpty {
didDiscoverGATT(peripheral, error)
} else {
let service = services.removeFirst()
unfinishedServices[peripheralHashCodeArgs] = services
peripheral.discoverCharacteristics(nil, for: service)
}
} else {
let characteristic = characteristics.removeFirst()
unfinishedCharacteristics[peripheralHashCodeArgs] = characteristics
peripheral.discoverDescriptors(for: characteristic)
}
} else {
didDiscoverGATT(peripheral, error)
}
}
private func didDiscoverGATT(_ peripheral: CBPeripheral, _ error: Error?) {
let peripheralHashCode = peripheral.hash
guard let peripheralArgs = peripheralsArgs[peripheralHashCode] else {
return
}
let peripheralhashCodeArgs = peripheralArgs.hashCodeArgs
guard let completion = discoverGattCompletions.removeValue(forKey: peripheralhashCodeArgs) else {
return
}
if error == nil {
let services = peripheral.services ?? []
var servicesArgs = [MyGattServiceArgs]()
for service in services {
let characteristics = service.characteristics ?? []
var characteristicsArgs = [MyGattCharacteristicArgs]()
for characteristic in characteristics {
let descriptors = characteristic.descriptors ?? []
var descriptorsArgs = [MyGattDescriptorArgs]()
for descriptor in descriptors {
let descriptorArgs = descriptor.toArgs()
let descriptorHashCode = descriptor.hash
let descriptorHashCodeArgs = descriptorArgs.hashCodeArgs
self.descriptors[descriptorHashCodeArgs] = descriptor
self.descriptorsArgs[descriptorHashCode] = descriptorArgs
descriptorsArgs.append(descriptorArgs)
}
let characteristicArgs = characteristic.toArgs(descriptorsArgs)
let characteristicHashCode = characteristic.hash
let characteristicHashCodeArgs = characteristicArgs.hashCodeArgs
self.characteristics[characteristicHashCodeArgs] = characteristic
self.characteristicsArgs[characteristicHashCode] = characteristicArgs
characteristicsArgs.append(characteristicArgs)
}
let serviceArgs = service.toArgs(characteristicsArgs)
let serviceHashCode = service.hash
let servcieHashCodeArgs = serviceArgs.hashCodeArgs
self.services[servcieHashCodeArgs] = service
self.servicesArgs[serviceHashCode] = serviceArgs
servicesArgs.append(serviceArgs)
}
servicesArgsOfPeripheralsArgs[peripheralhashCodeArgs] = servicesArgs
completion(.success((servicesArgs)))
} else {
completion(.failure(error!))
unfinishedServices.removeValue(forKey: peripheralhashCodeArgs)
unfinishedCharacteristics.removeValue(forKey: peripheralhashCodeArgs)
}
}
func didUpdateCharacteristicValue(_ characteristic: CBCharacteristic, _ error: Error?) {
let characteristicHashCode = characteristic.hash
guard let characteristicArgs = characteristicsArgs[characteristicHashCode] else {
return
}
let characteristicHashCodeArgs = characteristicArgs.hashCodeArgs
guard let completion = readCharacteristicCompletions.removeValue(forKey: characteristicHashCodeArgs) else {
let value = characteristic.value ?? Data()
let valueArgs = FlutterStandardTypedData(bytes: value)
api.onCharacteristicValueChanged(characteristicArgs: characteristicArgs, valueArgs: valueArgs) {}
return
}
if error == nil {
let value = characteristic.value ?? Data()
let valueArgs = FlutterStandardTypedData(bytes: value)
completion(.success(valueArgs))
} else {
completion(.failure(error!))
}
}
func didWriteCharacteristicValue(_ characteristic: CBCharacteristic, _ error: Error?) {
let characteristicHashCode = characteristic.hash
guard let characteristicArgs = characteristicsArgs[characteristicHashCode] else {
return
}
let characteristicHashCodeArgs = characteristicArgs.hashCodeArgs
guard let completion = writeCharacteristicCompletions.removeValue(forKey: characteristicHashCodeArgs) else {
return
}
if error == nil {
completion(.success(()))
} else {
completion(.failure(error!))
}
}
func didUpdateNotificationState(_ characteristic: CBCharacteristic, _ error: Error?) {
let characteristicHashCode = characteristic.hash
guard let characteristicArgs = characteristicsArgs[characteristicHashCode] else {
return
}
let characteristicHashCodeArgs = characteristicArgs.hashCodeArgs
guard let completion = notifyCharacteristicCompletions.removeValue(forKey: characteristicHashCodeArgs) else {
return
}
if error == nil {
completion(.success(()))
} else {
completion(.failure(error!))
}
}
func didUpdateDescriptorValue(_ descriptor: CBDescriptor, _ error: Error?) {
let descriptorHashCode = descriptor.hash
guard let descriptorArgs = descriptorsArgs[descriptorHashCode] else {
return
}
let descriptorHashCodeArgs = descriptorArgs.hashCodeArgs
guard let completion = readDescriptorCompletions.removeValue(forKey: descriptorHashCodeArgs) else {
return
}
if error == nil {
// TODO: Need to confirm wheather the corresponding descriptor type and value is correct.
let valueArgs: FlutterStandardTypedData
let value = descriptor.value
do {
switch descriptor.uuid.uuidString {
case CBUUIDCharacteristicExtendedPropertiesString:
fallthrough
case CBUUIDClientCharacteristicConfigurationString:
fallthrough
case CBUUIDServerCharacteristicConfigurationString:
guard let numberValue = value as? NSNumber else {
throw MyError.illegalArgument
}
valueArgs = FlutterStandardTypedData(bytes: numberValue.data)
case CBUUIDCharacteristicUserDescriptionString:
fallthrough
case CBUUIDCharacteristicAggregateFormatString:
guard let stringValue = value as? String else {
throw MyError.illegalArgument
}
valueArgs = FlutterStandardTypedData(bytes: stringValue.data)
case CBUUIDCharacteristicFormatString:
guard let bytes = value as? Data else {
throw MyError.illegalArgument
}
valueArgs = FlutterStandardTypedData(bytes: bytes)
case CBUUIDL2CAPPSMCharacteristicString:
guard let uint16Value = value as? UInt16 else {
throw MyError.illegalArgument
}
valueArgs = FlutterStandardTypedData(bytes: uint16Value.data)
default:
throw MyError.illegalArgument
}
} catch {
valueArgs = FlutterStandardTypedData()
}
completion(.success((valueArgs)))
} else {
completion(.failure(error!))
}
}
func didWriteDescriptorValue(_ descriptor: CBDescriptor, _ error: Error?) {
let descriptorHashCode = descriptor.hash
guard let descriptorArgs = descriptorsArgs[descriptorHashCode] else {
return
}
let descriptorHashCodeArgs = descriptorArgs.hashCodeArgs
guard let completion = writeDescriptorCompletions.removeValue(forKey: descriptorHashCodeArgs) else {
return
}
if error == nil {
completion(.success(()))
} else {
completion(.failure(error!))
}
}
}