212 lines
9.6 KiB
Swift
212 lines
9.6 KiB
Swift
//
|
|
// MyPeripheralDelegate.swift
|
|
// bluetooth_low_energy
|
|
//
|
|
// Created by 闫守旺 on 2022/9/20.
|
|
//
|
|
|
|
import Foundation
|
|
import CoreBluetooth
|
|
|
|
class MyPeripheralDelegate: NSObject, CBPeripheralDelegate {
|
|
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
|
|
let id = String(peripheral.hash)
|
|
let completion = instances.removeValue(forKey: "\(id)/\(KEY_DISCOVER_SERVICES_COMPLETION)") as! ([FlutterStandardTypedData]?, FlutterError?) -> Void
|
|
if error == nil {
|
|
var serviceBuffers = [FlutterStandardTypedData]()
|
|
let services = peripheral.services
|
|
if services != nil {
|
|
for service in services! {
|
|
let serviceBuffer = registerService(service)
|
|
serviceBuffers.append(serviceBuffer)
|
|
}
|
|
}
|
|
completion(serviceBuffers, nil)
|
|
} else {
|
|
let errorMessage = error!.localizedDescription
|
|
let flutterError = FlutterError(code: BLUETOOTH_LOW_ENERGY_ERROR, message: errorMessage, details: nil)
|
|
completion(nil, flutterError)
|
|
}
|
|
}
|
|
|
|
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
|
|
let id = String(service.hash)
|
|
let completion = instances.removeValue(forKey: "\(id)/\(KEY_DISCOVER_CHARACTERISTICS_COMPLETION)") as! ([FlutterStandardTypedData]?, FlutterError?) -> Void
|
|
if error == nil {
|
|
var characteristicBuffers = [FlutterStandardTypedData]()
|
|
let characteristics = service.characteristics
|
|
if characteristics != nil {
|
|
for characteristic in characteristics! {
|
|
let characteristicBuffer = registerCharacteristic(characteristic)
|
|
characteristicBuffers.append(characteristicBuffer)
|
|
}
|
|
}
|
|
completion(characteristicBuffers, nil)
|
|
} else {
|
|
let errorMessage = error!.localizedDescription
|
|
let flutterError = FlutterError(code: BLUETOOTH_LOW_ENERGY_ERROR, message: errorMessage, details: nil)
|
|
completion(nil, flutterError)
|
|
}
|
|
}
|
|
|
|
func peripheral(_ peripheral: CBPeripheral, didDiscoverDescriptorsFor characteristic: CBCharacteristic, error: Error?) {
|
|
let id = String(characteristic.hash)
|
|
let completion = instances.removeValue(forKey: "\(id)/\(KEY_DISCOVER_DESCRIPTORS_COMPLETION)") as! ([FlutterStandardTypedData]?, FlutterError?) -> Void
|
|
if error == nil {
|
|
var descriptorBuffers = [FlutterStandardTypedData]()
|
|
let descriptors = characteristic.descriptors
|
|
if descriptors != nil {
|
|
for descriptor in descriptors! {
|
|
let descriptorBuffer = registerDescriptor(descriptor)
|
|
descriptorBuffers.append(descriptorBuffer)
|
|
}
|
|
}
|
|
completion(descriptorBuffers, nil)
|
|
} else {
|
|
let errorMessage = error!.localizedDescription
|
|
let flutterError = FlutterError(code: BLUETOOTH_LOW_ENERGY_ERROR, message: errorMessage, details: nil)
|
|
completion(nil, flutterError)
|
|
}
|
|
}
|
|
|
|
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
|
|
let id = String(characteristic.hash)
|
|
let completion = instances.removeValue(forKey: "\(id)/\(KEY_READ_COMPLETION)") as? (FlutterStandardTypedData?, FlutterError?) -> Void
|
|
let characteristicValue = characteristic.value
|
|
let value = characteristicValue == nil ? FlutterStandardTypedData() : FlutterStandardTypedData(bytes: characteristicValue!)
|
|
if completion == nil {
|
|
characteristicFlutterApi.onValueChanged(id, value: value) {_ in }
|
|
} else if error == nil {
|
|
completion!(value, nil)
|
|
} else {
|
|
let errorMessage = error!.localizedDescription
|
|
let flutterError = FlutterError(code: BLUETOOTH_LOW_ENERGY_ERROR, message: errorMessage, details: nil)
|
|
completion!(nil, flutterError)
|
|
}
|
|
}
|
|
|
|
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
|
|
let id = String(characteristic.hash)
|
|
let completion = instances.removeValue(forKey: "\(id)/\(KEY_WRITE_COMPLETION)") as! (FlutterError?) -> Void
|
|
if error == nil {
|
|
completion(nil)
|
|
} else {
|
|
let errorMessage = error!.localizedDescription
|
|
let flutterError = FlutterError(code: BLUETOOTH_LOW_ENERGY_ERROR, message: errorMessage, details: nil)
|
|
completion(flutterError)
|
|
}
|
|
}
|
|
|
|
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
|
|
let id = String(characteristic.hash)
|
|
let completion = instances.removeValue(forKey: "\(id)/\(KEY_SET_NOTIFY_COMPLETION)") as! (FlutterError?) -> Void
|
|
if error == nil {
|
|
completion(nil)
|
|
} else {
|
|
let errorMessage = error!.localizedDescription
|
|
let flutterError = FlutterError(code: BLUETOOTH_LOW_ENERGY_ERROR, message: errorMessage, details: nil)
|
|
completion(flutterError)
|
|
}
|
|
}
|
|
|
|
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor descriptor: CBDescriptor, error: Error?) {
|
|
let id = String(descriptor.hash)
|
|
let completion = instances.removeValue(forKey: "\(id)/\(KEY_READ_COMPLETION)") as! (FlutterStandardTypedData?, FlutterError?) -> Void
|
|
if error == nil {
|
|
let value: FlutterStandardTypedData
|
|
if descriptor.value == nil {
|
|
value = FlutterStandardTypedData()
|
|
} else {
|
|
switch descriptor.uuid.uuidString {
|
|
case CBUUIDCharacteristicExtendedPropertiesString:
|
|
fallthrough
|
|
case CBUUIDClientCharacteristicConfigurationString:
|
|
fallthrough
|
|
case CBUUIDServerCharacteristicConfigurationString:
|
|
let item = descriptor.value as! NSNumber
|
|
value = FlutterStandardTypedData(bytes: item.data)
|
|
case CBUUIDCharacteristicUserDescriptionString:
|
|
fallthrough
|
|
case CBUUIDCharacteristicAggregateFormatString:
|
|
let item = descriptor.value as! String
|
|
value = FlutterStandardTypedData(bytes: item.data)
|
|
case CBUUIDCharacteristicFormatString:
|
|
let data = descriptor.value as! Data
|
|
value = FlutterStandardTypedData(bytes: data)
|
|
case CBUUIDL2CAPPSMCharacteristicString:
|
|
let item = descriptor.value as! UInt16
|
|
value = FlutterStandardTypedData(bytes: item.data)
|
|
default:
|
|
value = FlutterStandardTypedData()
|
|
}
|
|
}
|
|
completion(value, nil)
|
|
} else {
|
|
let errorMessage = error!.localizedDescription
|
|
let flutterError = FlutterError(code: BLUETOOTH_LOW_ENERGY_ERROR, message: errorMessage, details: nil)
|
|
completion(nil, flutterError)
|
|
}
|
|
}
|
|
|
|
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor descriptor: CBDescriptor, error: Error?) {
|
|
let id = String(descriptor.hash)
|
|
let completion = instances.removeValue(forKey: "\(id)/\(KEY_WRITE_COMPLETION)") as! (FlutterError?) -> Void
|
|
if error == nil {
|
|
completion(nil)
|
|
} else {
|
|
let errorMessage = error!.localizedDescription
|
|
let flutterError = FlutterError(code: BLUETOOTH_LOW_ENERGY_ERROR, message: errorMessage, details: nil)
|
|
completion(flutterError)
|
|
}
|
|
}
|
|
|
|
private func registerService(_ service: CBService) -> FlutterStandardTypedData {
|
|
let id = String(service.hash)
|
|
var items = register(id)
|
|
items[KEY_SERVICE] = service
|
|
// This is a copy on write.
|
|
instances[id] = items
|
|
let data = try! Proto_GattService.with {
|
|
$0.id = id
|
|
$0.uuid = Proto_UUID.with {
|
|
$0.value = service.uuid.uuidString
|
|
}
|
|
}.serializedData()
|
|
return FlutterStandardTypedData(bytes: data)
|
|
}
|
|
|
|
private func registerCharacteristic(_ characteristic: CBCharacteristic) -> FlutterStandardTypedData {
|
|
let id = String(characteristic.hash)
|
|
var items = register(id)
|
|
items[KEY_CHARACTERISTIC] = characteristic
|
|
// This is a copy on write.
|
|
instances[id] = items
|
|
let data = try! Proto_GattCharacteristic.with {
|
|
$0.id = id
|
|
$0.uuid = Proto_UUID.with {
|
|
$0.value = characteristic.uuid.uuidString
|
|
}
|
|
$0.canRead = characteristic.properties.contains(.read)
|
|
$0.canWrite = characteristic.properties.contains(.write)
|
|
$0.canWriteWithoutResponse = characteristic.properties.contains(.writeWithoutResponse)
|
|
$0.canNotify = characteristic.properties.contains(.notify)
|
|
}.serializedData()
|
|
return FlutterStandardTypedData(bytes: data)
|
|
}
|
|
|
|
private func registerDescriptor(_ descriptor: CBDescriptor) -> FlutterStandardTypedData {
|
|
let id = String(descriptor.hash)
|
|
var items = register(id)
|
|
items[KEY_DESCRIPTOR] = descriptor
|
|
// This is a copy on write.
|
|
instances[id] = items
|
|
let data = try! Proto_GattDescriptor.with {
|
|
$0.id = id
|
|
$0.uuid = Proto_UUID.with {
|
|
$0.value = descriptor.uuid.uuidString
|
|
}
|
|
}.serializedData()
|
|
return FlutterStandardTypedData(bytes: data)
|
|
}
|
|
}
|