Files
bluetooth_low_energy/bluetooth_low_energy_darwin/darwin/Classes/MyCentralManager.swift
渐渐被你吸引 108b6a804f 6.0.0 (#74)
* 调整接口

* 临时提交

* 重构 Android 平台代码

* 临时提交

* 临时提交

* Android 6.0.0-dev.0

* 临时提交

* 实现 Windows 接口

* windows-6.0.0-dev.0

* Darwin 6.0.0-dev.0

* 临时提交

* 1

* 临时提交

* 调整接口

* windows-6.0.0-dev.1

* 临时提交

* interface-6.0.0-dev.7

* interface-6.0.0-dev.8

* 临时提交

* windows-6.0.0-dev.2

* 删除多余脚本

* interface-6.0.0-dev.9

* 临时提交

* 临时提交

* interface-6.0.0-dev.10

* android-6.0.0-dev.1

* windows-6.0.0-dev.3

* 临时提交

* interface-6.0.0-dev.11

* windows-6.0.0-dev.4

* 更新 pubspec.lock

* 1

* interface-6.0.0-dev.12

* interface-6.0.0-dev.13

* interface-6.0.0-dev.14

* 临时提交

* interface-6.0.0-dev.15

* 临时提交

* interface-6.0.0-dev.16

* android-6.0.0-dev.2

* 临时提交

* windows-6.0.0-dev.5

* 临时提交

* 临时提交

* windows-6.0.0-dev.6

* 优化注释和代码样式

* 优化代码

* 临时提交

* 实现 Dart 接口

* darwin-6.0.0-dev.0

* linux-6.0.0-dev.0

* 修复已知问题

* 修复问题

* 6.0.0-dev.0

* 修改包名

* 更新版本

* 移除原生部分

* 临时提交

* 修复问题

* 更新 pigeon 19.0.0

* 更新 README,添加迁移文档

* linux-6.0.0-dev.1

* 解析扫描回复和扩展广播

* 修复 googletest 版本警告问题

* Use centralArgs instead of addressArgs

* interface-6.0.0-dev.18

* android-6.0.0-dev.4

* linux-6.0.0-dev.2

* windows-6.0.0-dev.8

* darwin-6.0.0-dev.2

* 6.0.0-dev.1

* Update LICENSE

* clang-format

* Combine ADV_IND and SCAN_RES

* TEMP commit: update exampe

* Adjust advertisement combine logic

* Implement `MyPeripheralMananger` on Windows

* Added NuGet auto download and scan for names on peripheral (#67)

* fetch nuget using other technique

* move FetchContent to right location in CMakeLists.txt

* also added hash for googletest

---------

Co-authored-by: Kevin De Keyser <kevin@dekeyser.ch>

* Fix errors.

* Check BluetoothAdapter role supported state and implement PeripheralManager on Flutter side.

* Sort code

* Fix known errors

* interface-6.0.0-dev.19

* windows-6.0.0-dev.9

* Optimize example

* android-6.0.0-dev.5

* Optimize the Adverrtisement BottomSheet.

* linux-6.0.0-dev.3

* Update dependency

* Fix example errors.

* Temp commit.

* darwin-6.0.0-dev.3

* 6.0.0-dev.2

* Update README.md

* 6.0.0

* darwin-6.0.0-dev.4

* android-6.0.0-dev.6

* 6.0.0-dev.3

* Update docs.

* interface-6.0.0

* android-6.0.0

* darwin-6.0.0

* linux-6.0.0

* windows-6.0.0

* 6.0.0

* Update dependency

---------

Co-authored-by: Kevin De Keyser <dekeyser.kevin97@gmail.com>
Co-authored-by: Kevin De Keyser <kevin@dekeyser.ch>
2024-06-04 00:44:39 +08:00

625 lines
27 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 {
private let mAPI: MyCentralManagerFlutterAPI
private let mCentralManager: CBCentralManager
private lazy var mCentralManagerDelegate = MyCentralManagerDelegate(centralManager: self)
private lazy var peripheralDelegate = MyPeripheralDelegate(centralManager: self)
private var mPeripherals: [String: CBPeripheral]
private var mServices: [String: [Int64: CBService]]
private var mCharacteristics: [String: [Int64: CBCharacteristic]]
private var mDescriptors: [String: [Int64: CBDescriptor]]
private var mConnectCompletions: [String: (Result<Void, Error>) -> Void]
private var mDisconnectCompletions: [String: (Result<Void, Error>) -> Void]
private var mReadRSSICompletions: [String: (Result<Int64, Error>) -> Void]
private var mDiscoverServicesCompletions: [String: (Result<[MyGATTServiceArgs], Error>) -> Void]
private var mDiscoverIncludedServicesCompletions: [String: [Int64: (Result<[MyGATTServiceArgs], Error>) -> Void]]
private var mDiscoverCharacteristicsCompletions: [String: [Int64: (Result<[MyGATTCharacteristicArgs], Error>) -> Void]]
private var mDiscoverDescriptorsCompletions: [String: [Int64: (Result<[MyGATTDescriptorArgs], Error>) -> Void]]
private var mReadCharacteristicCompletions: [String: [Int64: (Result<FlutterStandardTypedData, Error>) -> Void]]
private var mWriteCharacteristicCompletions: [String: [Int64: (Result<Void, Error>) -> Void]]
private var mSetCharacteristicNotifyStateCompletions: [String: [Int64: (Result<Void, Error>) -> Void]]
private var mReadDescriptorCompletions: [String: [Int64: (Result<FlutterStandardTypedData, Error>) -> Void]]
private var mWriteDescriptorCompletions: [String: [Int64: (Result<Void, Error>) -> Void]]
init(messenger: FlutterBinaryMessenger) {
mAPI = MyCentralManagerFlutterAPI(binaryMessenger: messenger)
mCentralManager = CBCentralManager()
mPeripherals = [:]
mServices = [:]
mCharacteristics = [:]
mDescriptors = [:]
mConnectCompletions = [:]
mDisconnectCompletions = [:]
mReadRSSICompletions = [:]
mDiscoverServicesCompletions = [:]
mDiscoverIncludedServicesCompletions = [:]
mDiscoverCharacteristicsCompletions = [:]
mDiscoverDescriptorsCompletions = [:]
mReadCharacteristicCompletions = [:]
mWriteCharacteristicCompletions = [:]
mSetCharacteristicNotifyStateCompletions = [:]
mReadDescriptorCompletions = [:]
mWriteDescriptorCompletions = [:]
}
func initialize() throws {
if(mCentralManager.isScanning) {
mCentralManager.stopScan()
}
for peripheral in mPeripherals.values {
if peripheral.state != .disconnected {
mCentralManager.cancelPeripheralConnection(peripheral)
}
}
mPeripherals.removeAll()
mServices.removeAll()
mCharacteristics.removeAll()
mDescriptors.removeAll()
mConnectCompletions.removeAll()
mDisconnectCompletions.removeAll()
mReadRSSICompletions.removeAll()
mDiscoverServicesCompletions.removeAll()
mDiscoverIncludedServicesCompletions.removeAll()
mDiscoverCharacteristicsCompletions.removeAll()
mDiscoverDescriptorsCompletions.removeAll()
mReadCharacteristicCompletions.removeAll()
mWriteCharacteristicCompletions.removeAll()
mSetCharacteristicNotifyStateCompletions.removeAll()
mReadDescriptorCompletions.removeAll()
mWriteDescriptorCompletions.removeAll()
mCentralManager.delegate = mCentralManagerDelegate
}
func getState() throws -> MyBluetoothLowEnergyStateArgs {
let state = mCentralManager.state
let stateArgs = state.toArgs()
return stateArgs
}
func showAppSettings(completion: @escaping (Result<Void, any Error>) -> Void) {
#if os(iOS)
do {
guard let url = URL(string: UIApplication.openSettingsURLString) else {
throw MyError.illegalArgument
}
UIApplication.shared.open(url) { success in
if (success) {
completion(.success(()))
} else {
completion(.failure(MyError.unknown))
}
}
} catch {
completion(.failure(error))
}
#else
completion(.failure(MyError.unsupported))
#endif
}
func startDiscovery(serviceUUIDsArgs: [String]) throws {
let serviceUUIDs = serviceUUIDsArgs.isEmpty ? nil : serviceUUIDsArgs.map { serviceUUIDArgs in serviceUUIDArgs.toCBUUID() }
let options = [CBCentralManagerScanOptionAllowDuplicatesKey: true]
mCentralManager.scanForPeripherals(withServices: serviceUUIDs, options: options)
}
func stopDiscovery() throws {
mCentralManager.stopScan()
}
func retrieveConnectedPeripherals() throws -> [MyPeripheralArgs] {
let peripherals = mCentralManager.retrieveConnectedPeripherals(withServices: [])
let peripheralsArgs = peripherals.map { peripheral in
let peripheralArgs = peripheral.toArgs()
let uuidArgs = peripheralArgs.uuidArgs
if peripheral.delegate == nil {
peripheral.delegate = peripheralDelegate
}
self.mPeripherals[uuidArgs] = peripheral
return peripheralArgs
}
return peripheralsArgs
}
func connect(uuidArgs: String, completion: @escaping (Result<Void, Error>) -> Void) {
do {
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
mCentralManager.connect(peripheral)
mConnectCompletions[uuidArgs] = completion
} catch {
completion(.failure(error))
}
}
func disconnect(uuidArgs: String, completion: @escaping (Result<Void, Error>) -> Void) {
do {
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
mCentralManager.cancelPeripheralConnection(peripheral)
mDisconnectCompletions[uuidArgs] = completion
} catch {
completion(.failure(error))
}
}
func getMaximumWriteLength(uuidArgs: String, typeArgs: MyGATTCharacteristicWriteTypeArgs) throws -> Int64 {
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let type = typeArgs.toWriteType()
let maximumWriteLength = peripheral.maximumWriteValueLength(for: type)
let maximumWriteLengthArgs = maximumWriteLength.toInt64()
return maximumWriteLengthArgs
}
func readRSSI(uuidArgs: String, completion: @escaping (Result<Int64, Error>) -> Void) {
do {
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
peripheral.readRSSI()
mReadRSSICompletions[uuidArgs] = completion
} catch {
completion(.failure(error))
}
}
func discoverServices(uuidArgs: String, completion: @escaping (Result<[MyGATTServiceArgs], Error>) -> Void) {
do {
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
peripheral.discoverServices(nil)
mDiscoverServicesCompletions[uuidArgs] = completion
} catch {
completion(.failure(error))
}
}
func discoverIncludedServices(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<[MyGATTServiceArgs], Error>) -> Void) {
do {
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let service = try retrieveService(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs)
peripheral.discoverIncludedServices(nil, for: service)
mDiscoverIncludedServicesCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func discoverCharacteristics(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<[MyGATTCharacteristicArgs], Error>) -> Void) {
do {
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let service = try retrieveService(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs)
peripheral.discoverCharacteristics(nil, for: service)
mDiscoverCharacteristicsCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func discoverDescriptors(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<[MyGATTDescriptorArgs], Error>) -> Void){
do {
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let characteristic = try retrieveCharacteristic(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs)
peripheral.discoverDescriptors(for: characteristic)
mDiscoverDescriptorsCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func readCharacteristic(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
do {
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let characteristic = try retrieveCharacteristic(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs)
peripheral.readValue(for: characteristic)
mReadCharacteristicCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func writeCharacteristic(uuidArgs: String, hashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, typeArgs: MyGATTCharacteristicWriteTypeArgs, completion: @escaping (Result<Void, Error>) -> Void) {
do {
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let characteristic = try retrieveCharacteristic(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs)
let data = valueArgs.data
let type = typeArgs.toWriteType()
peripheral.writeValue(data, for: characteristic, type: type)
if type == .withResponse {
mWriteCharacteristicCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
} else {
completion(.success(()))
}
} catch {
completion(.failure(error))
}
}
func setCharacteristicNotifyState(uuidArgs: String, hashCodeArgs: Int64, stateArgs: Bool, completion: @escaping (Result<Void, Error>) -> Void) {
do {
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let characteristic = try retrieveCharacteristic(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs)
let enabled = stateArgs
peripheral.setNotifyValue(enabled, for: characteristic)
mSetCharacteristicNotifyStateCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func readDescriptor(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
do {
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let descriptor = try retrieveDescriptor(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs)
peripheral.readValue(for: descriptor)
mReadDescriptorCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func writeDescriptor(uuidArgs: String, hashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void) {
do {
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let descriptor = try retrieveDescriptor(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs)
let data = valueArgs.data
peripheral.writeValue(data, for: descriptor)
mWriteDescriptorCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func didUpdateState(central: CBCentralManager) {
let state = central.state
let stateArgs = state.toArgs()
mAPI.onStateChanged(stateArgs: stateArgs) { _ in }
}
func didDiscover(central: CBCentralManager, peripheral: CBPeripheral, advertisementData: [String : Any], rssi: NSNumber) {
let peripheralArgs = peripheral.toArgs()
let uuidArgs = peripheralArgs.uuidArgs
let rssiArgs = rssi.int64Value
let advertisementArgs = advertisementData.toAdvertisementArgs()
if peripheral.delegate == nil {
peripheral.delegate = peripheralDelegate
}
mPeripherals[uuidArgs] = peripheral
mAPI.onDiscovered(peripheralArgs: peripheralArgs, rssiArgs: rssiArgs, advertisementArgs: advertisementArgs) {_ in }
}
func didConnect(central: CBCentralManager, peripheral: CBPeripheral) {
let peripheralArgs = peripheral.toArgs()
let uuidArgs = peripheralArgs.uuidArgs
let stateArgs = MyConnectionStateArgs.connected
mAPI.onConnectionStateChanged(peripheralArgs: peripheralArgs, stateArgs: stateArgs) { _ in }
guard let completion = mConnectCompletions.removeValue(forKey: uuidArgs) else {
return
}
completion(.success(()))
}
func didFailToConnect(central: CBCentralManager, peripheral: CBPeripheral, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
guard let completion = mConnectCompletions.removeValue(forKey: uuidArgs) else {
return
}
completion(.failure(error ?? MyError.unknown))
}
func didDisconnectPeripheral(central: CBCentralManager, peripheral: CBPeripheral, error: Error?) {
let peripheralArgs = peripheral.toArgs()
let uuidArgs = peripheralArgs.uuidArgs
mServices.removeValue(forKey: uuidArgs)
mCharacteristics.removeValue(forKey: uuidArgs)
mDescriptors.removeValue(forKey: uuidArgs)
let errorNotNil = error ?? MyError.unknown
let readRssiCompletion = mReadRSSICompletions.removeValue(forKey: uuidArgs)
readRssiCompletion?(.failure(errorNotNil))
let discoverServicesCompletion = mDiscoverServicesCompletions.removeValue(forKey: uuidArgs)
discoverServicesCompletion?(.failure(errorNotNil))
let discoverIncludedServicesCompletions = self.mDiscoverIncludedServicesCompletions.removeValue(forKey: uuidArgs)
if discoverIncludedServicesCompletions != nil {
let completions = discoverIncludedServicesCompletions!.values
for completion in completions {
completion(.failure(errorNotNil))
}
}
let discoverCharacteristicsCompletions = self.mDiscoverCharacteristicsCompletions.removeValue(forKey: uuidArgs)
if discoverCharacteristicsCompletions != nil {
let completions = discoverCharacteristicsCompletions!.values
for completion in completions {
completion(.failure(errorNotNil))
}
}
let discoverDescriptorsCompletions = self.mDiscoverDescriptorsCompletions.removeValue(forKey: uuidArgs)
if discoverDescriptorsCompletions != nil {
let completions = discoverDescriptorsCompletions!.values
for completion in completions {
completion(.failure(errorNotNil))
}
}
let readCharacteristicCompletions = self.mReadCharacteristicCompletions.removeValue(forKey: uuidArgs)
if readCharacteristicCompletions != nil {
let completions = readCharacteristicCompletions!.values
for completion in completions {
completion(.failure(errorNotNil))
}
}
let writeCharacteristicCompletions = self.mWriteCharacteristicCompletions.removeValue(forKey: uuidArgs)
if writeCharacteristicCompletions != nil {
let completions = writeCharacteristicCompletions!.values
for completion in completions {
completion(.failure(errorNotNil))
}
}
let notifyCharacteristicCompletions = self.mSetCharacteristicNotifyStateCompletions.removeValue(forKey: uuidArgs)
if notifyCharacteristicCompletions != nil {
let completions = notifyCharacteristicCompletions!.values
for completioin in completions {
completioin(.failure(errorNotNil))
}
}
let readDescriptorCompletions = self.mReadDescriptorCompletions.removeValue(forKey: uuidArgs)
if readDescriptorCompletions != nil {
let completions = readDescriptorCompletions!.values
for completioin in completions {
completioin(.failure(errorNotNil))
}
}
let writeDescriptorCompletions = self.mWriteDescriptorCompletions.removeValue(forKey: uuidArgs)
if writeDescriptorCompletions != nil {
let completions = writeDescriptorCompletions!.values
for completion in completions {
completion(.failure(errorNotNil))
}
}
let stateArgs = MyConnectionStateArgs.disconnected
mAPI.onConnectionStateChanged(peripheralArgs: peripheralArgs, stateArgs: stateArgs) { _ in }
guard let completion = mDisconnectCompletions.removeValue(forKey: uuidArgs) else {
return
}
if error == nil {
completion(.success(()))
} else {
completion(.failure(error!))
}
}
func didReadRSSI(peripheral: CBPeripheral, rssi: NSNumber, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
guard let completion = mReadRSSICompletions.removeValue(forKey: uuidArgs) else {
return
}
if error == nil {
let rssiArgs = rssi.int64Value
completion(.success((rssiArgs)))
} else {
completion(.failure(error!))
}
}
func didDiscoverServices(peripheral: CBPeripheral, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
guard let completion = mDiscoverServicesCompletions.removeValue(forKey: uuidArgs) else {
return
}
if error == nil {
let services = peripheral.services ?? []
var servicesArgs = [MyGATTServiceArgs]()
for service in services {
let serviceArgs = service.toArgs()
self.mServices[uuidArgs, default: [:]][serviceArgs.hashCodeArgs] = service
servicesArgs.append(serviceArgs)
}
completion(.success(servicesArgs))
} else {
completion(.failure(error!))
}
}
func didDiscoverIncludedServices(peripheral: CBPeripheral, service: CBService, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
let hashCodeArgs = service.hash.toInt64()
guard let completion = mDiscoverIncludedServicesCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
return
}
if error == nil {
let includedServices = service.includedServices ?? []
var includedServicesArgs = [MyGATTServiceArgs]()
for includedService in includedServices {
let includedServiceArgs = includedService.toArgs()
self.mServices[uuidArgs, default: [:]][includedServiceArgs.hashCodeArgs] = includedService
includedServicesArgs.append(includedServiceArgs)
}
completion(.success(includedServicesArgs))
} else {
completion(.failure(error!))
}
}
func didDiscoverCharacteristics(peripheral: CBPeripheral, service: CBService, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
let hashCodeArgs = service.hash.toInt64()
guard let completion = mDiscoverCharacteristicsCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
return
}
if error == nil {
let characteristics = service.characteristics ?? []
var characteristicsArgs = [MyGATTCharacteristicArgs]()
for characteristic in characteristics {
let characteristicArgs = characteristic.toArgs()
self.mCharacteristics[uuidArgs, default: [:]][characteristicArgs.hashCodeArgs] = characteristic
characteristicsArgs.append(characteristicArgs)
}
completion(.success(characteristicsArgs))
} else {
completion(.failure(error!))
}
}
func didDiscoverDescriptors(peripheral: CBPeripheral, characteristic: CBCharacteristic, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
let hashCodeArgs = characteristic.hash.toInt64()
guard let completion = mDiscoverDescriptorsCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
return
}
if error == nil {
let descriptors = characteristic.descriptors ?? []
var descriptorsArgs = [MyGATTDescriptorArgs]()
for descriptor in descriptors {
let descriptorArgs = descriptor.toArgs()
self.mDescriptors[uuidArgs, default: [:]][descriptorArgs.hashCodeArgs] = descriptor
descriptorsArgs.append(descriptorArgs)
}
completion(.success(descriptorsArgs))
} else {
completion(.failure(error!))
}
}
func didUpdateCharacteristicValue(peripheral: CBPeripheral, characteristic: CBCharacteristic, error: Error?) {
let peripheralArgs = peripheral.toArgs()
let uuidArgs = peripheralArgs.uuidArgs
let characteristicArgs = characteristic.toArgs()
let hashCodeArgs = characteristicArgs.hashCodeArgs
let value = characteristic.value ?? Data()
let valueArgs = FlutterStandardTypedData(bytes: value)
guard let completion = mReadCharacteristicCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
mAPI.onCharacteristicNotified(peripheralArgs: peripheralArgs, characteristicArgs: characteristicArgs, valueArgs: valueArgs) { _ in }
return
}
if error == nil {
completion(.success(valueArgs))
} else {
completion(.failure(error!))
}
}
func didWriteCharacteristicValue(peripheral: CBPeripheral, characteristic: CBCharacteristic, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
let hashCodeArgs = characteristic.hash.toInt64()
guard let completion = mWriteCharacteristicCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
return
}
if error == nil {
completion(.success(()))
} else {
completion(.failure(error!))
}
}
func didUpdateCharacteristicNotificationState(peripheral: CBPeripheral, characteristic: CBCharacteristic, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
let hashCodeArgs = characteristic.hash.toInt64()
guard let completion = mSetCharacteristicNotifyStateCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
return
}
if error == nil {
completion(.success(()))
} else {
completion(.failure(error!))
}
}
func didUpdateDescriptorValue(peripheral: CBPeripheral, descriptor: CBDescriptor, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
let hashCodeArgs = descriptor.hash.toInt64()
guard let completion = mReadDescriptorCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
return
}
if error == nil {
let valueArgs: FlutterStandardTypedData
switch descriptor.value {
case let bytes as Data:
valueArgs = FlutterStandardTypedData(bytes: bytes)
case let value as String:
let bytes = value.data(using: .utf8) ?? Data()
valueArgs = FlutterStandardTypedData(bytes: bytes)
case let value as UInt16:
let bytes = value.data
valueArgs = FlutterStandardTypedData(bytes: bytes)
case let value as NSNumber:
let bytes = withUnsafeBytes(of: value) { elements in Data(elements) }
valueArgs = FlutterStandardTypedData(bytes: bytes)
default:
valueArgs = FlutterStandardTypedData()
}
completion(.success((valueArgs)))
} else {
completion(.failure(error!))
}
}
func didWriteDescriptorValue(peripheral: CBPeripheral, descriptor: CBDescriptor, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
let hashCodeArgs = descriptor.hash.toInt64()
guard let completion = mWriteDescriptorCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
return
}
if error == nil {
completion(.success(()))
} else {
completion(.failure(error!))
}
}
private func retrievePeripheral(uuidArgs: String) throws -> CBPeripheral {
guard let peripheral = mPeripherals[uuidArgs] else {
throw MyError.illegalArgument
}
return peripheral
}
private func retrieveService(uuidArgs: String, hashCodeArgs: Int64) throws -> CBService {
guard let services = self.mServices[uuidArgs] else {
throw MyError.illegalArgument
}
guard let service = services[hashCodeArgs] else {
throw MyError.illegalArgument
}
return service
}
private func retrieveCharacteristic(uuidArgs: String, hashCodeArgs: Int64) throws -> CBCharacteristic {
guard let characteristics = self.mCharacteristics[uuidArgs] else {
throw MyError.illegalArgument
}
guard let characteristic = characteristics[hashCodeArgs] else {
throw MyError.illegalArgument
}
return characteristic
}
private func retrieveDescriptor(uuidArgs: String, hashCodeArgs: Int64) throws -> CBDescriptor {
guard let descriptors = self.mDescriptors[uuidArgs] else {
throw MyError.illegalArgument
}
guard let descriptor = descriptors[hashCodeArgs] else {
throw MyError.illegalArgument
}
return descriptor
}
}