feat: 5.0.0 (#35)
* draft: 临时提交 * feat: 实现扫描功能 * fix: 优化广播逻辑 * feat: 添加协程方法 * fix: 修改宏定义 * draft: 临时提交 * feat: 调整接口 * fix: 修改版本号 * feat: 4.1.1 * draft: 临时提交 * feat: 5.0.0-dev.2 * fix: 修复版本号错误 * draft: 临时提交 * fix: 修复连接断开异常 * fix: 修复问题 * fix: 优化代码 * fix: 优化 short UUID 格式化逻辑 * fix: 尝试实现 read_rssi 接口,当前此接口不可用,会报异常 * feat: 删除 getMaximumWriteLength 方法 * fix: 更新 CHANGELOG.md * feat: 5.0.0-dev.1 * fix: 更新依赖项 * feat: linux-5.0.0-dev.1 * fix: 更新 CHANGELOG.md * fix: 开始搜索设备时清空设备列表 * fix: 开始扫描时清空设备列表 * feat: 5.0.0-dev.2 * fix: 优化 MyGattService 和 MyGattCharacteristic * feat: 更新 interface 版本 -> 5.0.0-dev.4 * feat: 更新 interface 版本 -> 5.0.0-dev.4 * feat: 实现 flutter 部分 5.0.0 * fix: 移除 maximumWriteLength * fix: 移除 rssi * feat: 5.0.0-dev.1 * feat: 5.0.0-dev.2 * fix: 更新依赖项 * fix: 5.0.0-dev.4 * fix: 更新依赖项 * draft: 临时提交 * feat: 5.0.0-dev.5 * draft: 删除 MyCentralManager 和 MyPeripheralManager * fix: 更新依赖项 * fix: 更新依赖项 * feat: 适配新接口 * feat: 5.0.0-dev.6 * draft: 临时提交 * feat: 5.0.0-dev.7 * fix: 修改版本号 * feat: 5.0.0-dev.8 * feat: 5.0.0-dev.9 * fix: 修复 trimGATT 错误 * feat: 5.0.0-dev.6 * feat: 5.0.0-dev.3 * feat: 5.0.0-dev.4 * fix: 更新 pubspec.lock * feat: 5.0.0-dev.7 * feat: 5.0.0-dev.3 * fix: balabala * fix: balabala * draft: 5.0.0-dev.1 * fix: trim GATT when call the `writeCharacteristic` method. * fix: make difference of `trim` and `fragment`. * feat: 5.0.0-dev.1 * feat: 5.0.0-dev.1 * feat: 优化示例程序 * fix: 更新 README.md * fix: 修复插件引用 * draft: XXXX * feat: 增加调试信息 * fix: 更新 pubspec.lock * feat: 5.0.0-dev.4 * feat: 5.0.0-dev.3 * feat: 5.0.0 * feat: 5.0.0 * feat: 5.0.0 * feat: 5.0.0 * feat: 5.0.0 * feat: 5.0.0
This commit is contained in:
@ -1,3 +1,29 @@
|
||||
## 5.0.0
|
||||
|
||||
* Now `CentralManager#writeCharacteristic` and `PeripheralManager#writeCharacteristic` will fragment the value automatically, the maximum write length is 512 bytes.
|
||||
* Add `UUID#fromAddress` constructor.
|
||||
* Add `GattCharacteristicReadEventArgs` and `GattCharacteristicWrittenEventArgs`.
|
||||
* Add `PeripheralManager#characteristicRead` and `PeripheralManager#characteristicWritten`.
|
||||
* Add `PeripheralManager#readCharacteristic`.
|
||||
* Remove `CentralManager#getMaximumWriteLength` method.
|
||||
* Remove `PeripheralManager#getMaximumWriteLength` method.
|
||||
* Remove `ReadGattCharacteristicCommandEventArgs` and `WriteGattCharacteristicCommandEventArgs`.
|
||||
* Remove `PeripheralManager#readCharacteristicCommandReceived` and `PeripheralManager#writeCharacteristicCommandReceived`.
|
||||
* Remove `PeripheralManager#sendReadCharacteristicReply` and `PeripheralManager#sendWriteCharacteristicReply`.
|
||||
* Move `CentralManager#state` to `CentralManager#getState()`.
|
||||
* Move `PeripheralStateChangedEventArgs` to `ConnectionStateChangedEventArgs`.
|
||||
* Move `CentralManager#peripheralStateChanged` to `CentralManager#connectionStateChanged`.
|
||||
* Move `GattCharacteristicValueChangedEventArgs` to `GattCharacteristicNotifiedEventArgs`.
|
||||
* Move `CentralManager#characteristicValueChanged` to `CentralManager#characteristicNotified`.
|
||||
* Move `CentralManager#notifyCharacteristic` to `CentralManager#setCharacteristicNotifyState`.
|
||||
* Move `PeripheralManager#notifyCharacteristicValueChanged` to `PeripheralManager#writeCharacteristic`.
|
||||
* Move `NotifyGattCharacteristicCommandEventArgs` to `GattCharacteristicNotifyStateChangedEventArgs`.
|
||||
* Move `PeripheralManager#notifyCharacteristicCommandReceived` to `PeripheralManager#characteristicNotifyStateChanged`.
|
||||
|
||||
## 5.0.0-dev.1
|
||||
|
||||
* Implements new Api.
|
||||
|
||||
## 4.0.0
|
||||
|
||||
* Remove `BluetoothLowEnergy` class.
|
||||
|
@ -11,15 +11,15 @@ import FlutterMacOS
|
||||
public class BluetoothLowEnergyDarwin: NSObject, FlutterPlugin {
|
||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
#if os(iOS)
|
||||
let binaryMessenger = registrar.messenger()
|
||||
let messenger = registrar.messenger()
|
||||
#elseif os(macOS)
|
||||
let binaryMessenger = registrar.messenger
|
||||
let messenger = registrar.messenger
|
||||
#else
|
||||
#error("Unsupported platform.")
|
||||
#endif
|
||||
let centralManager = MyCentralManager(binaryMessenger)
|
||||
let peripheralManager = MyPeripheralManager(binaryMessenger)
|
||||
MyCentralManagerHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: centralManager)
|
||||
MyPeripheralManagerHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: peripheralManager)
|
||||
let centralManager = MyCentralManager(messenger: messenger)
|
||||
let peripheralManager = MyPeripheralManager(messenger: messenger)
|
||||
MyCentralManagerHostApiSetup.setUp(binaryMessenger: messenger, api: centralManager)
|
||||
MyPeripheralManagerHostApiSetup.setUp(binaryMessenger: messenger, api: peripheralManager)
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Autogenerated from Pigeon (v12.0.1), do not edit directly.
|
||||
// Autogenerated from Pigeon (v15.0.2), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
|
||||
import Foundation
|
||||
@ -10,10 +10,6 @@ import FlutterMacOS
|
||||
#error("Unsupported platform.")
|
||||
#endif
|
||||
|
||||
private func isNullish(_ value: Any?) -> Bool {
|
||||
return value is NSNull || value == nil
|
||||
}
|
||||
|
||||
private func wrapResult(_ result: Any?) -> [Any?] {
|
||||
return [result]
|
||||
}
|
||||
@ -33,6 +29,14 @@ private func wrapError(_ error: Any) -> [Any?] {
|
||||
]
|
||||
}
|
||||
|
||||
private func createConnectionError(withChannelName channelName: String) -> FlutterError {
|
||||
return FlutterError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "")
|
||||
}
|
||||
|
||||
private func isNullish(_ value: Any?) -> Bool {
|
||||
return value is NSNull || value == nil
|
||||
}
|
||||
|
||||
private func nilOrValue<T>(_ value: Any?) -> T? {
|
||||
if value is NSNull { return nil }
|
||||
return value as! T?
|
||||
@ -40,10 +44,11 @@ private func nilOrValue<T>(_ value: Any?) -> T? {
|
||||
|
||||
enum MyBluetoothLowEnergyStateArgs: Int {
|
||||
case unknown = 0
|
||||
case unsupported = 1
|
||||
case unauthorized = 2
|
||||
case poweredOff = 3
|
||||
case poweredOn = 4
|
||||
case resetting = 1
|
||||
case unsupported = 2
|
||||
case unauthorized = 3
|
||||
case poweredOff = 4
|
||||
case poweredOn = 5
|
||||
}
|
||||
|
||||
enum MyGattCharacteristicPropertyArgs: Int {
|
||||
@ -59,82 +64,45 @@ enum MyGattCharacteristicWriteTypeArgs: Int {
|
||||
case withoutResponse = 1
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct MyCentralManagerArgs {
|
||||
var stateNumberArgs: Int64
|
||||
|
||||
static func fromList(_ list: [Any?]) -> MyCentralManagerArgs? {
|
||||
let stateNumberArgs = list[0] is Int64 ? list[0] as! Int64 : Int64(list[0] as! Int32)
|
||||
|
||||
return MyCentralManagerArgs(
|
||||
stateNumberArgs: stateNumberArgs
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
stateNumberArgs,
|
||||
]
|
||||
}
|
||||
enum MyGattErrorArgs: Int {
|
||||
case success = 0
|
||||
case invalidHandle = 1
|
||||
case readNotPermitted = 2
|
||||
case writeNotPermitted = 3
|
||||
case invalidPDU = 4
|
||||
case insufficientAuthentication = 5
|
||||
case requestNotSupported = 6
|
||||
case invalidOffset = 7
|
||||
case insufficientAuthorization = 8
|
||||
case prepareQueueFull = 9
|
||||
case attributeNotFound = 10
|
||||
case attributeNotLong = 11
|
||||
case insufficientEncryptionKeySize = 12
|
||||
case invalidAttributeValueLength = 13
|
||||
case unlikelyError = 14
|
||||
case insufficientEncryption = 15
|
||||
case unsupportedGroupType = 16
|
||||
case insufficientResources = 17
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct MyPeripheralManagerArgs {
|
||||
var stateNumberArgs: Int64
|
||||
struct MyManufacturerSpecificDataArgs {
|
||||
var idArgs: Int64
|
||||
var dataArgs: FlutterStandardTypedData
|
||||
|
||||
static func fromList(_ list: [Any?]) -> MyPeripheralManagerArgs? {
|
||||
let stateNumberArgs = list[0] is Int64 ? list[0] as! Int64 : Int64(list[0] as! Int32)
|
||||
static func fromList(_ list: [Any?]) -> MyManufacturerSpecificDataArgs? {
|
||||
let idArgs = list[0] is Int64 ? list[0] as! Int64 : Int64(list[0] as! Int32)
|
||||
let dataArgs = list[1] as! FlutterStandardTypedData
|
||||
|
||||
return MyPeripheralManagerArgs(
|
||||
stateNumberArgs: stateNumberArgs
|
||||
return MyManufacturerSpecificDataArgs(
|
||||
idArgs: idArgs,
|
||||
dataArgs: dataArgs
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
stateNumberArgs,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct MyCentralArgs {
|
||||
var hashCodeArgs: Int64
|
||||
var uuidArgs: String
|
||||
|
||||
static func fromList(_ list: [Any?]) -> MyCentralArgs? {
|
||||
let hashCodeArgs = list[0] is Int64 ? list[0] as! Int64 : Int64(list[0] as! Int32)
|
||||
let uuidArgs = list[1] as! String
|
||||
|
||||
return MyCentralArgs(
|
||||
hashCodeArgs: hashCodeArgs,
|
||||
uuidArgs: uuidArgs
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
hashCodeArgs,
|
||||
uuidArgs,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct MyPeripheralArgs {
|
||||
var hashCodeArgs: Int64
|
||||
var uuidArgs: String
|
||||
|
||||
static func fromList(_ list: [Any?]) -> MyPeripheralArgs? {
|
||||
let hashCodeArgs = list[0] is Int64 ? list[0] as! Int64 : Int64(list[0] as! Int32)
|
||||
let uuidArgs = list[1] as! String
|
||||
|
||||
return MyPeripheralArgs(
|
||||
hashCodeArgs: hashCodeArgs,
|
||||
uuidArgs: uuidArgs
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
hashCodeArgs,
|
||||
uuidArgs,
|
||||
idArgs,
|
||||
dataArgs,
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -173,49 +141,63 @@ struct MyAdvertisementArgs {
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct MyManufacturerSpecificDataArgs {
|
||||
var idArgs: Int64
|
||||
var dataArgs: FlutterStandardTypedData
|
||||
struct MyCentralArgs {
|
||||
var uuidArgs: String
|
||||
|
||||
static func fromList(_ list: [Any?]) -> MyManufacturerSpecificDataArgs? {
|
||||
let idArgs = list[0] is Int64 ? list[0] as! Int64 : Int64(list[0] as! Int32)
|
||||
let dataArgs = list[1] as! FlutterStandardTypedData
|
||||
static func fromList(_ list: [Any?]) -> MyCentralArgs? {
|
||||
let uuidArgs = list[0] as! String
|
||||
|
||||
return MyManufacturerSpecificDataArgs(
|
||||
idArgs: idArgs,
|
||||
dataArgs: dataArgs
|
||||
return MyCentralArgs(
|
||||
uuidArgs: uuidArgs
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
idArgs,
|
||||
dataArgs,
|
||||
uuidArgs,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct MyGattServiceArgs {
|
||||
struct MyPeripheralArgs {
|
||||
var uuidArgs: String
|
||||
|
||||
static func fromList(_ list: [Any?]) -> MyPeripheralArgs? {
|
||||
let uuidArgs = list[0] as! String
|
||||
|
||||
return MyPeripheralArgs(
|
||||
uuidArgs: uuidArgs
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
uuidArgs,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct MyGattDescriptorArgs {
|
||||
var hashCodeArgs: Int64
|
||||
var uuidArgs: String
|
||||
var characteristicsArgs: [MyGattCharacteristicArgs?]
|
||||
var valueArgs: FlutterStandardTypedData? = nil
|
||||
|
||||
static func fromList(_ list: [Any?]) -> MyGattServiceArgs? {
|
||||
static func fromList(_ list: [Any?]) -> MyGattDescriptorArgs? {
|
||||
let hashCodeArgs = list[0] is Int64 ? list[0] as! Int64 : Int64(list[0] as! Int32)
|
||||
let uuidArgs = list[1] as! String
|
||||
let characteristicsArgs = list[2] as! [MyGattCharacteristicArgs?]
|
||||
let valueArgs: FlutterStandardTypedData? = nilOrValue(list[2])
|
||||
|
||||
return MyGattServiceArgs(
|
||||
return MyGattDescriptorArgs(
|
||||
hashCodeArgs: hashCodeArgs,
|
||||
uuidArgs: uuidArgs,
|
||||
characteristicsArgs: characteristicsArgs
|
||||
valueArgs: valueArgs
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
hashCodeArgs,
|
||||
uuidArgs,
|
||||
characteristicsArgs,
|
||||
valueArgs,
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -251,27 +233,27 @@ struct MyGattCharacteristicArgs {
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct MyGattDescriptorArgs {
|
||||
struct MyGattServiceArgs {
|
||||
var hashCodeArgs: Int64
|
||||
var uuidArgs: String
|
||||
var valueArgs: FlutterStandardTypedData? = nil
|
||||
var characteristicsArgs: [MyGattCharacteristicArgs?]
|
||||
|
||||
static func fromList(_ list: [Any?]) -> MyGattDescriptorArgs? {
|
||||
static func fromList(_ list: [Any?]) -> MyGattServiceArgs? {
|
||||
let hashCodeArgs = list[0] is Int64 ? list[0] as! Int64 : Int64(list[0] as! Int32)
|
||||
let uuidArgs = list[1] as! String
|
||||
let valueArgs: FlutterStandardTypedData? = nilOrValue(list[2])
|
||||
let characteristicsArgs = list[2] as! [MyGattCharacteristicArgs?]
|
||||
|
||||
return MyGattDescriptorArgs(
|
||||
return MyGattServiceArgs(
|
||||
hashCodeArgs: hashCodeArgs,
|
||||
uuidArgs: uuidArgs,
|
||||
valueArgs: valueArgs
|
||||
characteristicsArgs: characteristicsArgs
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
hashCodeArgs,
|
||||
uuidArgs,
|
||||
valueArgs,
|
||||
characteristicsArgs,
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -280,12 +262,10 @@ private class MyCentralManagerHostApiCodecReader: FlutterStandardReader {
|
||||
override func readValue(ofType type: UInt8) -> Any? {
|
||||
switch type {
|
||||
case 128:
|
||||
return MyCentralManagerArgs.fromList(self.readValue() as! [Any?])
|
||||
case 129:
|
||||
return MyGattCharacteristicArgs.fromList(self.readValue() as! [Any?])
|
||||
case 130:
|
||||
case 129:
|
||||
return MyGattDescriptorArgs.fromList(self.readValue() as! [Any?])
|
||||
case 131:
|
||||
case 130:
|
||||
return MyGattServiceArgs.fromList(self.readValue() as! [Any?])
|
||||
default:
|
||||
return super.readValue(ofType: type)
|
||||
@ -295,17 +275,14 @@ private class MyCentralManagerHostApiCodecReader: FlutterStandardReader {
|
||||
|
||||
private class MyCentralManagerHostApiCodecWriter: FlutterStandardWriter {
|
||||
override func writeValue(_ value: Any) {
|
||||
if let value = value as? MyCentralManagerArgs {
|
||||
if let value = value as? MyGattCharacteristicArgs {
|
||||
super.writeByte(128)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? MyGattCharacteristicArgs {
|
||||
} else if let value = value as? MyGattDescriptorArgs {
|
||||
super.writeByte(129)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? MyGattDescriptorArgs {
|
||||
super.writeByte(130)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? MyGattServiceArgs {
|
||||
super.writeByte(131)
|
||||
super.writeByte(130)
|
||||
super.writeValue(value.toList())
|
||||
} else {
|
||||
super.writeValue(value)
|
||||
@ -329,19 +306,21 @@ class MyCentralManagerHostApiCodec: FlutterStandardMessageCodec {
|
||||
|
||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||
protocol MyCentralManagerHostApi {
|
||||
func setUp(completion: @escaping (Result<MyCentralManagerArgs, Error>) -> Void)
|
||||
func setUp() throws
|
||||
func startDiscovery() throws
|
||||
func stopDiscovery() throws
|
||||
func connect(peripheralHashCodeArgs: Int64, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func disconnect(peripheralHashCodeArgs: Int64, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func getMaximumWriteLength(peripheralHashCodeArgs: Int64, typeNumberArgs: Int64) throws -> Int64
|
||||
func readRSSI(peripheralHashCodeArgs: Int64, completion: @escaping (Result<Int64, Error>) -> Void)
|
||||
func discoverGATT(peripheralHashCodeArgs: Int64, completion: @escaping (Result<[MyGattServiceArgs], Error>) -> Void)
|
||||
func readCharacteristic(peripheralHashCodeArgs: Int64, characteristicHashCodeArgs: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void)
|
||||
func writeCharacteristic(peripheralHashCodeArgs: Int64, characteristicHashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, typeNumberArgs: Int64, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func notifyCharacteristic(peripheralHashCodeArgs: Int64, characteristicHashCodeArgs: Int64, stateArgs: Bool, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func readDescriptor(peripheralHashCodeArgs: Int64, descriptorHashCodeArgs: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void)
|
||||
func writeDescriptor(peripheralHashCodeArgs: Int64, descriptorHashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func connect(uuidArgs: String, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func disconnect(uuidArgs: String, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func getMaximumWriteValueLength(uuidArgs: String, typeNumberArgs: Int64) throws -> Int64
|
||||
func readRSSI(uuidArgs: String, completion: @escaping (Result<Int64, Error>) -> Void)
|
||||
func discoverServices(uuidArgs: String, completion: @escaping (Result<[MyGattServiceArgs], Error>) -> Void)
|
||||
func discoverCharacteristics(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<[MyGattCharacteristicArgs], Error>) -> Void)
|
||||
func discoverDescriptors(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<[MyGattDescriptorArgs], Error>) -> Void)
|
||||
func readCharacteristic(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void)
|
||||
func writeCharacteristic(uuidArgs: String, hashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, typeNumberArgs: Int64, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func setCharacteristicNotifyState(uuidArgs: String, hashCodeArgs: Int64, stateArgs: Bool, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func readDescriptor(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void)
|
||||
func writeDescriptor(uuidArgs: String, hashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
}
|
||||
|
||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||
@ -353,13 +332,11 @@ class MyCentralManagerHostApiSetup {
|
||||
let setUpChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerHostApi.setUp", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
setUpChannel.setMessageHandler { _, reply in
|
||||
api.setUp() { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
do {
|
||||
try api.setUp()
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -395,8 +372,8 @@ class MyCentralManagerHostApiSetup {
|
||||
if let api = api {
|
||||
connectChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let peripheralHashCodeArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
api.connect(peripheralHashCodeArgs: peripheralHashCodeArgsArg) { result in
|
||||
let uuidArgsArg = args[0] as! String
|
||||
api.connect(uuidArgs: uuidArgsArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
@ -412,8 +389,8 @@ class MyCentralManagerHostApiSetup {
|
||||
if let api = api {
|
||||
disconnectChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let peripheralHashCodeArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
api.disconnect(peripheralHashCodeArgs: peripheralHashCodeArgsArg) { result in
|
||||
let uuidArgsArg = args[0] as! String
|
||||
api.disconnect(uuidArgs: uuidArgsArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
@ -425,28 +402,28 @@ class MyCentralManagerHostApiSetup {
|
||||
} else {
|
||||
disconnectChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getMaximumWriteLengthChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerHostApi.getMaximumWriteLength", binaryMessenger: binaryMessenger, codec: codec)
|
||||
let getMaximumWriteValueLengthChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerHostApi.getMaximumWriteValueLength", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getMaximumWriteLengthChannel.setMessageHandler { message, reply in
|
||||
getMaximumWriteValueLengthChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let peripheralHashCodeArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let uuidArgsArg = args[0] as! String
|
||||
let typeNumberArgsArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
do {
|
||||
let result = try api.getMaximumWriteLength(peripheralHashCodeArgs: peripheralHashCodeArgsArg, typeNumberArgs: typeNumberArgsArg)
|
||||
let result = try api.getMaximumWriteValueLength(uuidArgs: uuidArgsArg, typeNumberArgs: typeNumberArgsArg)
|
||||
reply(wrapResult(result))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getMaximumWriteLengthChannel.setMessageHandler(nil)
|
||||
getMaximumWriteValueLengthChannel.setMessageHandler(nil)
|
||||
}
|
||||
let readRSSIChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerHostApi.readRSSI", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
readRSSIChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let peripheralHashCodeArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
api.readRSSI(peripheralHashCodeArgs: peripheralHashCodeArgsArg) { result in
|
||||
let uuidArgsArg = args[0] as! String
|
||||
api.readRSSI(uuidArgs: uuidArgsArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
@ -458,12 +435,12 @@ class MyCentralManagerHostApiSetup {
|
||||
} else {
|
||||
readRSSIChannel.setMessageHandler(nil)
|
||||
}
|
||||
let discoverGATTChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerHostApi.discoverGATT", binaryMessenger: binaryMessenger, codec: codec)
|
||||
let discoverServicesChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerHostApi.discoverServices", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
discoverGATTChannel.setMessageHandler { message, reply in
|
||||
discoverServicesChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let peripheralHashCodeArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
api.discoverGATT(peripheralHashCodeArgs: peripheralHashCodeArgsArg) { result in
|
||||
let uuidArgsArg = args[0] as! String
|
||||
api.discoverServices(uuidArgs: uuidArgsArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
@ -473,15 +450,51 @@ class MyCentralManagerHostApiSetup {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
discoverGATTChannel.setMessageHandler(nil)
|
||||
discoverServicesChannel.setMessageHandler(nil)
|
||||
}
|
||||
let discoverCharacteristicsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerHostApi.discoverCharacteristics", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
discoverCharacteristicsChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let uuidArgsArg = args[0] as! String
|
||||
let hashCodeArgsArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
api.discoverCharacteristics(uuidArgs: uuidArgsArg, hashCodeArgs: hashCodeArgsArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
discoverCharacteristicsChannel.setMessageHandler(nil)
|
||||
}
|
||||
let discoverDescriptorsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerHostApi.discoverDescriptors", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
discoverDescriptorsChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let uuidArgsArg = args[0] as! String
|
||||
let hashCodeArgsArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
api.discoverDescriptors(uuidArgs: uuidArgsArg, hashCodeArgs: hashCodeArgsArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
discoverDescriptorsChannel.setMessageHandler(nil)
|
||||
}
|
||||
let readCharacteristicChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerHostApi.readCharacteristic", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
readCharacteristicChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let peripheralHashCodeArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let characteristicHashCodeArgsArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
api.readCharacteristic(peripheralHashCodeArgs: peripheralHashCodeArgsArg, characteristicHashCodeArgs: characteristicHashCodeArgsArg) { result in
|
||||
let uuidArgsArg = args[0] as! String
|
||||
let hashCodeArgsArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
api.readCharacteristic(uuidArgs: uuidArgsArg, hashCodeArgs: hashCodeArgsArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
@ -497,11 +510,11 @@ class MyCentralManagerHostApiSetup {
|
||||
if let api = api {
|
||||
writeCharacteristicChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let peripheralHashCodeArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let characteristicHashCodeArgsArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let uuidArgsArg = args[0] as! String
|
||||
let hashCodeArgsArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let valueArgsArg = args[2] as! FlutterStandardTypedData
|
||||
let typeNumberArgsArg = args[3] is Int64 ? args[3] as! Int64 : Int64(args[3] as! Int32)
|
||||
api.writeCharacteristic(peripheralHashCodeArgs: peripheralHashCodeArgsArg, characteristicHashCodeArgs: characteristicHashCodeArgsArg, valueArgs: valueArgsArg, typeNumberArgs: typeNumberArgsArg) { result in
|
||||
api.writeCharacteristic(uuidArgs: uuidArgsArg, hashCodeArgs: hashCodeArgsArg, valueArgs: valueArgsArg, typeNumberArgs: typeNumberArgsArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
@ -513,14 +526,14 @@ class MyCentralManagerHostApiSetup {
|
||||
} else {
|
||||
writeCharacteristicChannel.setMessageHandler(nil)
|
||||
}
|
||||
let notifyCharacteristicChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerHostApi.notifyCharacteristic", binaryMessenger: binaryMessenger, codec: codec)
|
||||
let setCharacteristicNotifyStateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerHostApi.setCharacteristicNotifyState", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
notifyCharacteristicChannel.setMessageHandler { message, reply in
|
||||
setCharacteristicNotifyStateChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let peripheralHashCodeArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let characteristicHashCodeArgsArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let uuidArgsArg = args[0] as! String
|
||||
let hashCodeArgsArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let stateArgsArg = args[2] as! Bool
|
||||
api.notifyCharacteristic(peripheralHashCodeArgs: peripheralHashCodeArgsArg, characteristicHashCodeArgs: characteristicHashCodeArgsArg, stateArgs: stateArgsArg) { result in
|
||||
api.setCharacteristicNotifyState(uuidArgs: uuidArgsArg, hashCodeArgs: hashCodeArgsArg, stateArgs: stateArgsArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
@ -530,15 +543,15 @@ class MyCentralManagerHostApiSetup {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
notifyCharacteristicChannel.setMessageHandler(nil)
|
||||
setCharacteristicNotifyStateChannel.setMessageHandler(nil)
|
||||
}
|
||||
let readDescriptorChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerHostApi.readDescriptor", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
readDescriptorChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let peripheralHashCodeArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let descriptorHashCodeArgsArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
api.readDescriptor(peripheralHashCodeArgs: peripheralHashCodeArgsArg, descriptorHashCodeArgs: descriptorHashCodeArgsArg) { result in
|
||||
let uuidArgsArg = args[0] as! String
|
||||
let hashCodeArgsArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
api.readDescriptor(uuidArgs: uuidArgsArg, hashCodeArgs: hashCodeArgsArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
@ -554,10 +567,10 @@ class MyCentralManagerHostApiSetup {
|
||||
if let api = api {
|
||||
writeDescriptorChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let peripheralHashCodeArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let descriptorHashCodeArgsArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let uuidArgsArg = args[0] as! String
|
||||
let hashCodeArgsArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let valueArgsArg = args[2] as! FlutterStandardTypedData
|
||||
api.writeDescriptor(peripheralHashCodeArgs: peripheralHashCodeArgsArg, descriptorHashCodeArgs: descriptorHashCodeArgsArg, valueArgs: valueArgsArg) { result in
|
||||
api.writeDescriptor(uuidArgs: uuidArgsArg, hashCodeArgs: hashCodeArgsArg, valueArgs: valueArgsArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
@ -577,12 +590,8 @@ private class MyCentralManagerFlutterApiCodecReader: FlutterStandardReader {
|
||||
case 128:
|
||||
return MyAdvertisementArgs.fromList(self.readValue() as! [Any?])
|
||||
case 129:
|
||||
return MyGattCharacteristicArgs.fromList(self.readValue() as! [Any?])
|
||||
case 130:
|
||||
return MyGattDescriptorArgs.fromList(self.readValue() as! [Any?])
|
||||
case 131:
|
||||
return MyManufacturerSpecificDataArgs.fromList(self.readValue() as! [Any?])
|
||||
case 132:
|
||||
case 130:
|
||||
return MyPeripheralArgs.fromList(self.readValue() as! [Any?])
|
||||
default:
|
||||
return super.readValue(ofType: type)
|
||||
@ -595,17 +604,11 @@ private class MyCentralManagerFlutterApiCodecWriter: FlutterStandardWriter {
|
||||
if let value = value as? MyAdvertisementArgs {
|
||||
super.writeByte(128)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? MyGattCharacteristicArgs {
|
||||
} else if let value = value as? MyManufacturerSpecificDataArgs {
|
||||
super.writeByte(129)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? MyGattDescriptorArgs {
|
||||
super.writeByte(130)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? MyManufacturerSpecificDataArgs {
|
||||
super.writeByte(131)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? MyPeripheralArgs {
|
||||
super.writeByte(132)
|
||||
super.writeByte(130)
|
||||
super.writeValue(value.toList())
|
||||
} else {
|
||||
super.writeValue(value)
|
||||
@ -629,10 +632,10 @@ class MyCentralManagerFlutterApiCodec: FlutterStandardMessageCodec {
|
||||
|
||||
/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift.
|
||||
protocol MyCentralManagerFlutterApiProtocol {
|
||||
func onStateChanged(stateNumberArgs stateNumberArgsArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
func onDiscovered(peripheralArgs peripheralArgsArg: MyPeripheralArgs, rssiArgs rssiArgsArg: Int64, advertisementArgs advertisementArgsArg: MyAdvertisementArgs, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
func onPeripheralStateChanged(peripheralArgs peripheralArgsArg: MyPeripheralArgs, stateArgs stateArgsArg: Bool, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
func onCharacteristicValueChanged(characteristicArgs characteristicArgsArg: MyGattCharacteristicArgs, valueArgs valueArgsArg: FlutterStandardTypedData, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
func onStateChanged(stateNumberArgs stateNumberArgsArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
func onDiscovered(peripheralArgs peripheralArgsArg: MyPeripheralArgs, rssiArgs rssiArgsArg: Int64, advertisementArgs advertisementArgsArg: MyAdvertisementArgs, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
func onConnectionStateChanged(uuidArgs uuidArgsArg: String, stateArgs stateArgsArg: Bool, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
func onCharacteristicNotified(uuidArgs uuidArgsArg: String, hashCodeArgs hashCodeArgsArg: Int64, valueArgs valueArgsArg: FlutterStandardTypedData, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
}
|
||||
class MyCentralManagerFlutterApi: MyCentralManagerFlutterApiProtocol {
|
||||
private let binaryMessenger: FlutterBinaryMessenger
|
||||
@ -642,28 +645,76 @@ class MyCentralManagerFlutterApi: MyCentralManagerFlutterApiProtocol {
|
||||
var codec: FlutterStandardMessageCodec {
|
||||
return MyCentralManagerFlutterApiCodec.shared
|
||||
}
|
||||
func onStateChanged(stateNumberArgs stateNumberArgsArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerFlutterApi.onStateChanged", binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([stateNumberArgsArg] as [Any?]) { _ in
|
||||
completion(.success(Void()))
|
||||
func onStateChanged(stateNumberArgs stateNumberArgsArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
let channelName: String = "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerFlutterApi.onStateChanged"
|
||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([stateNumberArgsArg] as [Any?]) { response in
|
||||
guard let listResponse = response as? [Any?] else {
|
||||
completion(.failure(createConnectionError(withChannelName:channelName)))
|
||||
return
|
||||
}
|
||||
if (listResponse.count > 1) {
|
||||
let code: String = listResponse[0] as! String
|
||||
let message: String? = nilOrValue(listResponse[1])
|
||||
let details: String? = nilOrValue(listResponse[2])
|
||||
completion(.failure(FlutterError(code: code, message: message, details: details)));
|
||||
} else {
|
||||
completion(.success(Void()))
|
||||
}
|
||||
}
|
||||
}
|
||||
func onDiscovered(peripheralArgs peripheralArgsArg: MyPeripheralArgs, rssiArgs rssiArgsArg: Int64, advertisementArgs advertisementArgsArg: MyAdvertisementArgs, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerFlutterApi.onDiscovered", binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([peripheralArgsArg, rssiArgsArg, advertisementArgsArg] as [Any?]) { _ in
|
||||
completion(.success(Void()))
|
||||
func onDiscovered(peripheralArgs peripheralArgsArg: MyPeripheralArgs, rssiArgs rssiArgsArg: Int64, advertisementArgs advertisementArgsArg: MyAdvertisementArgs, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
let channelName: String = "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerFlutterApi.onDiscovered"
|
||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([peripheralArgsArg, rssiArgsArg, advertisementArgsArg] as [Any?]) { response in
|
||||
guard let listResponse = response as? [Any?] else {
|
||||
completion(.failure(createConnectionError(withChannelName:channelName)))
|
||||
return
|
||||
}
|
||||
if (listResponse.count > 1) {
|
||||
let code: String = listResponse[0] as! String
|
||||
let message: String? = nilOrValue(listResponse[1])
|
||||
let details: String? = nilOrValue(listResponse[2])
|
||||
completion(.failure(FlutterError(code: code, message: message, details: details)));
|
||||
} else {
|
||||
completion(.success(Void()))
|
||||
}
|
||||
}
|
||||
}
|
||||
func onPeripheralStateChanged(peripheralArgs peripheralArgsArg: MyPeripheralArgs, stateArgs stateArgsArg: Bool, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerFlutterApi.onPeripheralStateChanged", binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([peripheralArgsArg, stateArgsArg] as [Any?]) { _ in
|
||||
completion(.success(Void()))
|
||||
func onConnectionStateChanged(uuidArgs uuidArgsArg: String, stateArgs stateArgsArg: Bool, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
let channelName: String = "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerFlutterApi.onConnectionStateChanged"
|
||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([uuidArgsArg, stateArgsArg] as [Any?]) { response in
|
||||
guard let listResponse = response as? [Any?] else {
|
||||
completion(.failure(createConnectionError(withChannelName:channelName)))
|
||||
return
|
||||
}
|
||||
if (listResponse.count > 1) {
|
||||
let code: String = listResponse[0] as! String
|
||||
let message: String? = nilOrValue(listResponse[1])
|
||||
let details: String? = nilOrValue(listResponse[2])
|
||||
completion(.failure(FlutterError(code: code, message: message, details: details)));
|
||||
} else {
|
||||
completion(.success(Void()))
|
||||
}
|
||||
}
|
||||
}
|
||||
func onCharacteristicValueChanged(characteristicArgs characteristicArgsArg: MyGattCharacteristicArgs, valueArgs valueArgsArg: FlutterStandardTypedData, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerFlutterApi.onCharacteristicValueChanged", binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([characteristicArgsArg, valueArgsArg] as [Any?]) { _ in
|
||||
completion(.success(Void()))
|
||||
func onCharacteristicNotified(uuidArgs uuidArgsArg: String, hashCodeArgs hashCodeArgsArg: Int64, valueArgs valueArgsArg: FlutterStandardTypedData, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
let channelName: String = "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralManagerFlutterApi.onCharacteristicNotified"
|
||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([uuidArgsArg, hashCodeArgsArg, valueArgsArg] as [Any?]) { response in
|
||||
guard let listResponse = response as? [Any?] else {
|
||||
completion(.failure(createConnectionError(withChannelName:channelName)))
|
||||
return
|
||||
}
|
||||
if (listResponse.count > 1) {
|
||||
let code: String = listResponse[0] as! String
|
||||
let message: String? = nilOrValue(listResponse[1])
|
||||
let details: String? = nilOrValue(listResponse[2])
|
||||
completion(.failure(FlutterError(code: code, message: message, details: details)));
|
||||
} else {
|
||||
completion(.success(Void()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -680,8 +731,6 @@ private class MyPeripheralManagerHostApiCodecReader: FlutterStandardReader {
|
||||
return MyGattServiceArgs.fromList(self.readValue() as! [Any?])
|
||||
case 132:
|
||||
return MyManufacturerSpecificDataArgs.fromList(self.readValue() as! [Any?])
|
||||
case 133:
|
||||
return MyPeripheralManagerArgs.fromList(self.readValue() as! [Any?])
|
||||
default:
|
||||
return super.readValue(ofType: type)
|
||||
}
|
||||
@ -705,9 +754,6 @@ private class MyPeripheralManagerHostApiCodecWriter: FlutterStandardWriter {
|
||||
} else if let value = value as? MyManufacturerSpecificDataArgs {
|
||||
super.writeByte(132)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? MyPeripheralManagerArgs {
|
||||
super.writeByte(133)
|
||||
super.writeValue(value.toList())
|
||||
} else {
|
||||
super.writeValue(value)
|
||||
}
|
||||
@ -730,16 +776,15 @@ class MyPeripheralManagerHostApiCodec: FlutterStandardMessageCodec {
|
||||
|
||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||
protocol MyPeripheralManagerHostApi {
|
||||
func setUp(completion: @escaping (Result<MyPeripheralManagerArgs, Error>) -> Void)
|
||||
func setUp() throws
|
||||
func addService(serviceArgs: MyGattServiceArgs, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func removeService(serviceHashCodeArgs: Int64) throws
|
||||
func removeService(hashCodeArgs: Int64) throws
|
||||
func clearServices() throws
|
||||
func startAdvertising(advertisementArgs: MyAdvertisementArgs, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func stopAdvertising() throws
|
||||
func getMaximumWriteLength(centralHashCodeArgs: Int64) throws -> Int64
|
||||
func sendReadCharacteristicReply(centralHashCodeArgs: Int64, characteristicHashCodeArgs: Int64, idArgs: Int64, offsetArgs: Int64, statusArgs: Bool, valueArgs: FlutterStandardTypedData) throws
|
||||
func sendWriteCharacteristicReply(centralHashCodeArgs: Int64, characteristicHashCodeArgs: Int64, idArgs: Int64, offsetArgs: Int64, statusArgs: Bool) throws
|
||||
func notifyCharacteristicValueChanged(centralHashCodeArgs: Int64, characteristicHashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func getMaximumUpdateValueLength(uuidArgs: String) throws -> Int64
|
||||
func respond(idArgs: Int64, errorNumberArgs: Int64, valueArgs: FlutterStandardTypedData?) throws
|
||||
func updateCharacteristic(hashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, uuidsArgs: [String]?, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
}
|
||||
|
||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||
@ -751,13 +796,11 @@ class MyPeripheralManagerHostApiSetup {
|
||||
let setUpChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyPeripheralManagerHostApi.setUp", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
setUpChannel.setMessageHandler { _, reply in
|
||||
api.setUp() { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
do {
|
||||
try api.setUp()
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -784,9 +827,9 @@ class MyPeripheralManagerHostApiSetup {
|
||||
if let api = api {
|
||||
removeServiceChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let serviceHashCodeArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let hashCodeArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
do {
|
||||
try api.removeService(serviceHashCodeArgs: serviceHashCodeArgsArg)
|
||||
try api.removeService(hashCodeArgs: hashCodeArgsArg)
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
@ -838,68 +881,46 @@ class MyPeripheralManagerHostApiSetup {
|
||||
} else {
|
||||
stopAdvertisingChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getMaximumWriteLengthChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyPeripheralManagerHostApi.getMaximumWriteLength", binaryMessenger: binaryMessenger, codec: codec)
|
||||
let getMaximumUpdateValueLengthChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyPeripheralManagerHostApi.getMaximumUpdateValueLength", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getMaximumWriteLengthChannel.setMessageHandler { message, reply in
|
||||
getMaximumUpdateValueLengthChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let centralHashCodeArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let uuidArgsArg = args[0] as! String
|
||||
do {
|
||||
let result = try api.getMaximumWriteLength(centralHashCodeArgs: centralHashCodeArgsArg)
|
||||
let result = try api.getMaximumUpdateValueLength(uuidArgs: uuidArgsArg)
|
||||
reply(wrapResult(result))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getMaximumWriteLengthChannel.setMessageHandler(nil)
|
||||
getMaximumUpdateValueLengthChannel.setMessageHandler(nil)
|
||||
}
|
||||
let sendReadCharacteristicReplyChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyPeripheralManagerHostApi.sendReadCharacteristicReply", binaryMessenger: binaryMessenger, codec: codec)
|
||||
let respondChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyPeripheralManagerHostApi.respond", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
sendReadCharacteristicReplyChannel.setMessageHandler { message, reply in
|
||||
respondChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let centralHashCodeArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let characteristicHashCodeArgsArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let idArgsArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32)
|
||||
let offsetArgsArg = args[3] is Int64 ? args[3] as! Int64 : Int64(args[3] as! Int32)
|
||||
let statusArgsArg = args[4] as! Bool
|
||||
let valueArgsArg = args[5] as! FlutterStandardTypedData
|
||||
let idArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let errorNumberArgsArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let valueArgsArg: FlutterStandardTypedData? = nilOrValue(args[2])
|
||||
do {
|
||||
try api.sendReadCharacteristicReply(centralHashCodeArgs: centralHashCodeArgsArg, characteristicHashCodeArgs: characteristicHashCodeArgsArg, idArgs: idArgsArg, offsetArgs: offsetArgsArg, statusArgs: statusArgsArg, valueArgs: valueArgsArg)
|
||||
try api.respond(idArgs: idArgsArg, errorNumberArgs: errorNumberArgsArg, valueArgs: valueArgsArg)
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sendReadCharacteristicReplyChannel.setMessageHandler(nil)
|
||||
respondChannel.setMessageHandler(nil)
|
||||
}
|
||||
let sendWriteCharacteristicReplyChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyPeripheralManagerHostApi.sendWriteCharacteristicReply", binaryMessenger: binaryMessenger, codec: codec)
|
||||
let updateCharacteristicChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyPeripheralManagerHostApi.updateCharacteristic", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
sendWriteCharacteristicReplyChannel.setMessageHandler { message, reply in
|
||||
updateCharacteristicChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let centralHashCodeArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let characteristicHashCodeArgsArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let idArgsArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32)
|
||||
let offsetArgsArg = args[3] is Int64 ? args[3] as! Int64 : Int64(args[3] as! Int32)
|
||||
let statusArgsArg = args[4] as! Bool
|
||||
do {
|
||||
try api.sendWriteCharacteristicReply(centralHashCodeArgs: centralHashCodeArgsArg, characteristicHashCodeArgs: characteristicHashCodeArgsArg, idArgs: idArgsArg, offsetArgs: offsetArgsArg, statusArgs: statusArgsArg)
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sendWriteCharacteristicReplyChannel.setMessageHandler(nil)
|
||||
}
|
||||
let notifyCharacteristicValueChangedChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyPeripheralManagerHostApi.notifyCharacteristicValueChanged", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
notifyCharacteristicValueChangedChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let centralHashCodeArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let characteristicHashCodeArgsArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let valueArgsArg = args[2] as! FlutterStandardTypedData
|
||||
api.notifyCharacteristicValueChanged(centralHashCodeArgs: centralHashCodeArgsArg, characteristicHashCodeArgs: characteristicHashCodeArgsArg, valueArgs: valueArgsArg) { result in
|
||||
let hashCodeArgsArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let valueArgsArg = args[1] as! FlutterStandardTypedData
|
||||
let uuidsArgsArg: [String]? = nilOrValue(args[2])
|
||||
api.updateCharacteristic(hashCodeArgs: hashCodeArgsArg, valueArgs: valueArgsArg, uuidsArgs: uuidsArgsArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
@ -909,7 +930,7 @@ class MyPeripheralManagerHostApiSetup {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
notifyCharacteristicValueChangedChannel.setMessageHandler(nil)
|
||||
updateCharacteristicChannel.setMessageHandler(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -918,10 +939,6 @@ private class MyPeripheralManagerFlutterApiCodecReader: FlutterStandardReader {
|
||||
switch type {
|
||||
case 128:
|
||||
return MyCentralArgs.fromList(self.readValue() as! [Any?])
|
||||
case 129:
|
||||
return MyGattCharacteristicArgs.fromList(self.readValue() as! [Any?])
|
||||
case 130:
|
||||
return MyGattDescriptorArgs.fromList(self.readValue() as! [Any?])
|
||||
default:
|
||||
return super.readValue(ofType: type)
|
||||
}
|
||||
@ -933,12 +950,6 @@ private class MyPeripheralManagerFlutterApiCodecWriter: FlutterStandardWriter {
|
||||
if let value = value as? MyCentralArgs {
|
||||
super.writeByte(128)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? MyGattCharacteristicArgs {
|
||||
super.writeByte(129)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? MyGattDescriptorArgs {
|
||||
super.writeByte(130)
|
||||
super.writeValue(value.toList())
|
||||
} else {
|
||||
super.writeValue(value)
|
||||
}
|
||||
@ -961,10 +972,10 @@ class MyPeripheralManagerFlutterApiCodec: FlutterStandardMessageCodec {
|
||||
|
||||
/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift.
|
||||
protocol MyPeripheralManagerFlutterApiProtocol {
|
||||
func onStateChanged(stateNumberArgs stateNumberArgsArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
func onReadCharacteristicCommandReceived(centralArgs centralArgsArg: MyCentralArgs, characteristicArgs characteristicArgsArg: MyGattCharacteristicArgs, idArgs idArgsArg: Int64, offsetArgs offsetArgsArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
func onWriteCharacteristicCommandReceived(centralArgs centralArgsArg: MyCentralArgs, characteristicArgs characteristicArgsArg: MyGattCharacteristicArgs, idArgs idArgsArg: Int64, offsetArgs offsetArgsArg: Int64, valueArgs valueArgsArg: FlutterStandardTypedData, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
func onNotifyCharacteristicCommandReceived(centralArgs centralArgsArg: MyCentralArgs, characteristicArgs characteristicArgsArg: MyGattCharacteristicArgs, stateArgs stateArgsArg: Bool, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
func onStateChanged(stateNumberArgs stateNumberArgsArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
func onCharacteristicReadRequest(centralArgs centralArgsArg: MyCentralArgs, hashCodeArgs hashCodeArgsArg: Int64, idArgs idArgsArg: Int64, offsetArgs offsetArgsArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
func onCharacteristicWriteRequest(centralArgs centralArgsArg: MyCentralArgs, hashCodeArgs hashCodeArgsArg: Int64, idArgs idArgsArg: Int64, offsetArgs offsetArgsArg: Int64, valueArgs valueArgsArg: FlutterStandardTypedData, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
func onCharacteristicNotifyStateChanged(centralArgs centralArgsArg: MyCentralArgs, hashCodeArgs hashCodeArgsArg: Int64, stateArgs stateArgsArg: Bool, completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||
}
|
||||
class MyPeripheralManagerFlutterApi: MyPeripheralManagerFlutterApiProtocol {
|
||||
private let binaryMessenger: FlutterBinaryMessenger
|
||||
@ -974,28 +985,76 @@ class MyPeripheralManagerFlutterApi: MyPeripheralManagerFlutterApiProtocol {
|
||||
var codec: FlutterStandardMessageCodec {
|
||||
return MyPeripheralManagerFlutterApiCodec.shared
|
||||
}
|
||||
func onStateChanged(stateNumberArgs stateNumberArgsArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyPeripheralManagerFlutterApi.onStateChanged", binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([stateNumberArgsArg] as [Any?]) { _ in
|
||||
completion(.success(Void()))
|
||||
func onStateChanged(stateNumberArgs stateNumberArgsArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
let channelName: String = "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyPeripheralManagerFlutterApi.onStateChanged"
|
||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([stateNumberArgsArg] as [Any?]) { response in
|
||||
guard let listResponse = response as? [Any?] else {
|
||||
completion(.failure(createConnectionError(withChannelName:channelName)))
|
||||
return
|
||||
}
|
||||
if (listResponse.count > 1) {
|
||||
let code: String = listResponse[0] as! String
|
||||
let message: String? = nilOrValue(listResponse[1])
|
||||
let details: String? = nilOrValue(listResponse[2])
|
||||
completion(.failure(FlutterError(code: code, message: message, details: details)));
|
||||
} else {
|
||||
completion(.success(Void()))
|
||||
}
|
||||
}
|
||||
}
|
||||
func onReadCharacteristicCommandReceived(centralArgs centralArgsArg: MyCentralArgs, characteristicArgs characteristicArgsArg: MyGattCharacteristicArgs, idArgs idArgsArg: Int64, offsetArgs offsetArgsArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyPeripheralManagerFlutterApi.onReadCharacteristicCommandReceived", binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([centralArgsArg, characteristicArgsArg, idArgsArg, offsetArgsArg] as [Any?]) { _ in
|
||||
completion(.success(Void()))
|
||||
func onCharacteristicReadRequest(centralArgs centralArgsArg: MyCentralArgs, hashCodeArgs hashCodeArgsArg: Int64, idArgs idArgsArg: Int64, offsetArgs offsetArgsArg: Int64, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
let channelName: String = "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyPeripheralManagerFlutterApi.onCharacteristicReadRequest"
|
||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([centralArgsArg, hashCodeArgsArg, idArgsArg, offsetArgsArg] as [Any?]) { response in
|
||||
guard let listResponse = response as? [Any?] else {
|
||||
completion(.failure(createConnectionError(withChannelName:channelName)))
|
||||
return
|
||||
}
|
||||
if (listResponse.count > 1) {
|
||||
let code: String = listResponse[0] as! String
|
||||
let message: String? = nilOrValue(listResponse[1])
|
||||
let details: String? = nilOrValue(listResponse[2])
|
||||
completion(.failure(FlutterError(code: code, message: message, details: details)));
|
||||
} else {
|
||||
completion(.success(Void()))
|
||||
}
|
||||
}
|
||||
}
|
||||
func onWriteCharacteristicCommandReceived(centralArgs centralArgsArg: MyCentralArgs, characteristicArgs characteristicArgsArg: MyGattCharacteristicArgs, idArgs idArgsArg: Int64, offsetArgs offsetArgsArg: Int64, valueArgs valueArgsArg: FlutterStandardTypedData, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyPeripheralManagerFlutterApi.onWriteCharacteristicCommandReceived", binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([centralArgsArg, characteristicArgsArg, idArgsArg, offsetArgsArg, valueArgsArg] as [Any?]) { _ in
|
||||
completion(.success(Void()))
|
||||
func onCharacteristicWriteRequest(centralArgs centralArgsArg: MyCentralArgs, hashCodeArgs hashCodeArgsArg: Int64, idArgs idArgsArg: Int64, offsetArgs offsetArgsArg: Int64, valueArgs valueArgsArg: FlutterStandardTypedData, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
let channelName: String = "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyPeripheralManagerFlutterApi.onCharacteristicWriteRequest"
|
||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([centralArgsArg, hashCodeArgsArg, idArgsArg, offsetArgsArg, valueArgsArg] as [Any?]) { response in
|
||||
guard let listResponse = response as? [Any?] else {
|
||||
completion(.failure(createConnectionError(withChannelName:channelName)))
|
||||
return
|
||||
}
|
||||
if (listResponse.count > 1) {
|
||||
let code: String = listResponse[0] as! String
|
||||
let message: String? = nilOrValue(listResponse[1])
|
||||
let details: String? = nilOrValue(listResponse[2])
|
||||
completion(.failure(FlutterError(code: code, message: message, details: details)));
|
||||
} else {
|
||||
completion(.success(Void()))
|
||||
}
|
||||
}
|
||||
}
|
||||
func onNotifyCharacteristicCommandReceived(centralArgs centralArgsArg: MyCentralArgs, characteristicArgs characteristicArgsArg: MyGattCharacteristicArgs, stateArgs stateArgsArg: Bool, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyPeripheralManagerFlutterApi.onNotifyCharacteristicCommandReceived", binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([centralArgsArg, characteristicArgsArg, stateArgsArg] as [Any?]) { _ in
|
||||
completion(.success(Void()))
|
||||
func onCharacteristicNotifyStateChanged(centralArgs centralArgsArg: MyCentralArgs, hashCodeArgs hashCodeArgsArg: Int64, stateArgs stateArgsArg: Bool, completion: @escaping (Result<Void, FlutterError>) -> Void) {
|
||||
let channelName: String = "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyPeripheralManagerFlutterApi.onCharacteristicNotifyStateChanged"
|
||||
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([centralArgsArg, hashCodeArgsArg, stateArgsArg] as [Any?]) { response in
|
||||
guard let listResponse = response as? [Any?] else {
|
||||
completion(.failure(createConnectionError(withChannelName:channelName)))
|
||||
return
|
||||
}
|
||||
if (listResponse.count > 1) {
|
||||
let code: String = listResponse[0] as! String
|
||||
let message: String? = nilOrValue(listResponse[1])
|
||||
let details: String? = nilOrValue(listResponse[2])
|
||||
completion(.failure(FlutterError(code: code, message: message, details: details)));
|
||||
} else {
|
||||
completion(.success(Void()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,85 +16,40 @@ import FlutterMacOS
|
||||
#error("Unsupported platform.")
|
||||
#endif
|
||||
|
||||
// This extension of Error is required to do use FlutterError in any Swift code.
|
||||
extension FlutterError: Error {}
|
||||
|
||||
extension CBManagerState {
|
||||
func toArgs() -> MyBluetoothLowEnergyStateArgs {
|
||||
switch self {
|
||||
case .unauthorized:
|
||||
return .unauthorized
|
||||
case .poweredOff:
|
||||
return .poweredOff
|
||||
case .poweredOn:
|
||||
return .poweredOn
|
||||
default:
|
||||
return .unsupported
|
||||
// ToObj
|
||||
extension [MyGattCharacteristicPropertyArgs] {
|
||||
func toProperties() -> CBCharacteristicProperties {
|
||||
var properties: CBCharacteristicProperties = []
|
||||
for args in self {
|
||||
switch args {
|
||||
case .read:
|
||||
properties.insert(.read)
|
||||
case .write:
|
||||
properties.insert(.write)
|
||||
case .writeWithoutResponse:
|
||||
properties.insert(.writeWithoutResponse)
|
||||
case .notify:
|
||||
properties.insert(.notify)
|
||||
case .indicate:
|
||||
properties.insert(.indicate)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension CBPeer {
|
||||
var uuidArgs: String { identifier.uuidString }
|
||||
}
|
||||
|
||||
extension CBCentral {
|
||||
func toArgs() -> MyCentralArgs {
|
||||
let hashCodeArgs = Int64(hash)
|
||||
return MyCentralArgs(hashCodeArgs: hashCodeArgs, uuidArgs: uuidArgs)
|
||||
}
|
||||
}
|
||||
|
||||
extension CBPeripheral {
|
||||
func toArgs() -> MyPeripheralArgs {
|
||||
let hashCodeArgs = Int64(hash)
|
||||
return MyPeripheralArgs(hashCodeArgs: hashCodeArgs, uuidArgs: uuidArgs)
|
||||
}
|
||||
}
|
||||
|
||||
extension CBAttribute {
|
||||
var uuidArgs: String { uuid.uuidString }
|
||||
}
|
||||
|
||||
extension CBService {
|
||||
func toArgs(_ characteristicsArgs: [MyGattCharacteristicArgs]) -> MyGattServiceArgs {
|
||||
let hashCodeArgs = Int64(hash)
|
||||
return MyGattServiceArgs(hashCodeArgs: hashCodeArgs, uuidArgs: uuidArgs, characteristicsArgs: characteristicsArgs)
|
||||
}
|
||||
}
|
||||
|
||||
extension CBCharacteristic {
|
||||
func toArgs(_ descriptorsArgs: [MyGattDescriptorArgs]) -> MyGattCharacteristicArgs {
|
||||
let hashCodeArgs = Int64(hash)
|
||||
return MyGattCharacteristicArgs(hashCodeArgs: hashCodeArgs, uuidArgs: uuidArgs, propertyNumbersArgs: propertyNumbersArgs, descriptorsArgs: descriptorsArgs)
|
||||
return properties
|
||||
}
|
||||
|
||||
var propertyNumbersArgs: [Int64] {
|
||||
var propertiesArgs = [MyGattCharacteristicPropertyArgs]()
|
||||
let properties = self.properties
|
||||
if properties.contains(.read) {
|
||||
propertiesArgs.append(.read)
|
||||
func toPermissions() -> CBAttributePermissions {
|
||||
var permissions: CBAttributePermissions = []
|
||||
for args in self {
|
||||
switch args {
|
||||
case .read:
|
||||
permissions.insert(.readable)
|
||||
case .write, .writeWithoutResponse:
|
||||
permissions.insert(.writeable)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
if properties.contains(.write) {
|
||||
propertiesArgs.append(.write)
|
||||
}
|
||||
if properties.contains(.writeWithoutResponse) {
|
||||
propertiesArgs.append(.writeWithoutResponse)
|
||||
}
|
||||
if properties.contains(.notify) {
|
||||
propertiesArgs.append(.notify)
|
||||
}
|
||||
if properties.contains(.indicate) {
|
||||
propertiesArgs.append(.indicate)
|
||||
}
|
||||
return propertiesArgs.map { args in Int64(args.rawValue) }
|
||||
}
|
||||
}
|
||||
|
||||
extension CBDescriptor {
|
||||
func toArgs() -> MyGattDescriptorArgs {
|
||||
let hashCodeArgs = Int64(hash)
|
||||
return MyGattDescriptorArgs(hashCodeArgs: hashCodeArgs, uuidArgs: uuidArgs)
|
||||
return permissions
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,21 +64,151 @@ extension MyGattCharacteristicWriteTypeArgs {
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
var data: Data { data(using: String.Encoding.utf8)! }
|
||||
}
|
||||
|
||||
extension NSNumber {
|
||||
var data: Data {
|
||||
var source = self
|
||||
return Data(bytes: &source, count: MemoryLayout<NSNumber>.size)
|
||||
extension MyGattErrorArgs {
|
||||
func toError() -> CBATTError.Code {
|
||||
switch self {
|
||||
case .success:
|
||||
return .success
|
||||
case .invalidHandle:
|
||||
return .invalidHandle
|
||||
case .readNotPermitted:
|
||||
return .readNotPermitted
|
||||
case .writeNotPermitted:
|
||||
return .writeNotPermitted
|
||||
case .invalidPDU:
|
||||
return .invalidPdu
|
||||
case .insufficientAuthentication:
|
||||
return .insufficientAuthentication
|
||||
case .requestNotSupported:
|
||||
return .requestNotSupported
|
||||
case .invalidOffset:
|
||||
return .invalidOffset
|
||||
case .insufficientAuthorization:
|
||||
return .insufficientAuthorization
|
||||
case .prepareQueueFull:
|
||||
return .prepareQueueFull
|
||||
case .attributeNotFound:
|
||||
return .attributeNotFound
|
||||
case .attributeNotLong:
|
||||
return .attributeNotLong
|
||||
case .insufficientEncryptionKeySize:
|
||||
return .insufficientEncryptionKeySize
|
||||
case .invalidAttributeValueLength:
|
||||
return .invalidAttributeValueLength
|
||||
case .unlikelyError:
|
||||
return .unlikelyError
|
||||
case .insufficientEncryption:
|
||||
return .insufficientEncryption
|
||||
case .unsupportedGroupType:
|
||||
return .unsupportedGroupType
|
||||
case .insufficientResources:
|
||||
return .insufficientResources
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension UInt16 {
|
||||
var data: Data {
|
||||
var source = self
|
||||
return Data(bytes: &source, count: MemoryLayout<UInt16>.size)
|
||||
extension MyAdvertisementArgs {
|
||||
func toAdvertisement() -> [String : Any] {
|
||||
// CoreBluetooth only support `CBAdvertisementDataLocalNameKey` and `CBAdvertisementDataServiceUUIDsKey`
|
||||
// see https://developer.apple.com/documentation/corebluetooth/cbperipheralmanager/1393252-startadvertising
|
||||
var advertisement = [String: Any]()
|
||||
if nameArgs != nil {
|
||||
let name = nameArgs!
|
||||
advertisement[CBAdvertisementDataLocalNameKey] = name
|
||||
}
|
||||
if serviceUUIDsArgs.count > 0 {
|
||||
var serviceUUIDs = [CBUUID]()
|
||||
for args in serviceUUIDsArgs {
|
||||
guard let uuidArgs = args else {
|
||||
continue
|
||||
}
|
||||
let uuid = uuidArgs.toCBUUID()
|
||||
serviceUUIDs.append(uuid)
|
||||
}
|
||||
advertisement[CBAdvertisementDataServiceUUIDsKey] = serviceUUIDs
|
||||
}
|
||||
return advertisement
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattDescriptorArgs {
|
||||
func toDescriptor() -> CBMutableDescriptor {
|
||||
let type = uuidArgs.toCBUUID()
|
||||
let value = valueArgs?.data
|
||||
return CBMutableDescriptor(type: type, value: value)
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattCharacteristicArgs {
|
||||
func toCharacteristic() -> CBMutableCharacteristic {
|
||||
let type = uuidArgs.toCBUUID()
|
||||
var propertiesArgs = [MyGattCharacteristicPropertyArgs]()
|
||||
for args in propertyNumbersArgs {
|
||||
guard let propertyNumberArgs = args else {
|
||||
continue
|
||||
}
|
||||
let propertyNumber = propertyNumberArgs.toInt()
|
||||
guard let propertyArgs = MyGattCharacteristicPropertyArgs(rawValue: propertyNumber) else {
|
||||
continue
|
||||
}
|
||||
propertiesArgs.append(propertyArgs)
|
||||
}
|
||||
let properties = propertiesArgs.toProperties()
|
||||
let permissions = propertiesArgs.toPermissions()
|
||||
return CBMutableCharacteristic(type: type, properties: properties, value: nil, permissions: permissions)
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattServiceArgs {
|
||||
func toService() -> CBMutableService {
|
||||
let type = uuidArgs.toCBUUID()
|
||||
let primary = true
|
||||
return CBMutableService(type: type, primary: primary)
|
||||
}
|
||||
}
|
||||
|
||||
extension Int64 {
|
||||
func toInt() -> Int {
|
||||
return Int(self)
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
func toCBUUID() -> CBUUID {
|
||||
return CBUUID(string: self)
|
||||
}
|
||||
}
|
||||
|
||||
// ToArgs
|
||||
extension CBManagerState {
|
||||
func toArgs() -> MyBluetoothLowEnergyStateArgs {
|
||||
switch self {
|
||||
case .resetting:
|
||||
return .resetting
|
||||
case .unsupported:
|
||||
return .unsupported
|
||||
case .unauthorized:
|
||||
return .unauthorized
|
||||
case .poweredOff:
|
||||
return .poweredOff
|
||||
case .poweredOn:
|
||||
return .poweredOn
|
||||
default:
|
||||
return .unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Data {
|
||||
func toManufacturerSpecificDataArgs() -> MyManufacturerSpecificDataArgs? {
|
||||
if count > 2 {
|
||||
let idArgs = Int64(self[0]) | (Int64(self[1]) << 8)
|
||||
let data = self[2...count - 1]
|
||||
let dataArgs = FlutterStandardTypedData(bytes: data)
|
||||
return MyManufacturerSpecificDataArgs(idArgs: idArgs, dataArgs: dataArgs)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,160 +230,105 @@ extension [String: Any] {
|
||||
}
|
||||
}
|
||||
|
||||
extension Data {
|
||||
func toManufacturerSpecificDataArgs() -> MyManufacturerSpecificDataArgs? {
|
||||
if count > 2 {
|
||||
let idArgs = Int64(self[0]) | (Int64(self[1]) << 8)
|
||||
let data = self[2...count - 1]
|
||||
let dataArgs = FlutterStandardTypedData(bytes: data)
|
||||
return MyManufacturerSpecificDataArgs(idArgs: idArgs, dataArgs: dataArgs)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
extension CBCentral {
|
||||
func toArgs() -> MyCentralArgs {
|
||||
let uuidArgs = identifier.toArgs()
|
||||
return MyCentralArgs(uuidArgs: uuidArgs)
|
||||
}
|
||||
}
|
||||
|
||||
extension MyAdvertisementArgs {
|
||||
func toAdvertisement() throws -> [String : Any] {
|
||||
// CoreBluetooth only support `CBAdvertisementDataLocalNameKey` and `CBAdvertisementDataServiceUUIDsKey`, see https://developer.apple.com/documentation/corebluetooth/cbperipheralmanager/1393252-startadvertising
|
||||
var advertisement = [String: Any]()
|
||||
if nameArgs != nil {
|
||||
let name = nameArgs!
|
||||
advertisement[CBAdvertisementDataLocalNameKey] = name
|
||||
}
|
||||
if serviceUUIDsArgs.count > 0 {
|
||||
var serviceUUIDs = [CBUUID]()
|
||||
for args in serviceUUIDsArgs {
|
||||
guard let uuidArgs = args else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let uuid = CBUUID(string: uuidArgs)
|
||||
serviceUUIDs.append(uuid)
|
||||
}
|
||||
advertisement[CBAdvertisementDataServiceUUIDsKey] = serviceUUIDs
|
||||
}
|
||||
// if serviceDataArgs.count > 0 {
|
||||
// var serviceData = [CBUUID: Data]()
|
||||
// for args in serviceDataArgs {
|
||||
// guard let uuidArgs = args.key else {
|
||||
// throw MyError.illegalArgument
|
||||
// }
|
||||
// guard let dataArgs = args.value else {
|
||||
// throw MyError.illegalArgument
|
||||
// }
|
||||
// let uuid = CBUUID(string: uuidArgs)
|
||||
// let data = dataArgs.data
|
||||
// serviceData[uuid] = data
|
||||
// }
|
||||
// advertisement[CBAdvertisementDataServiceDataKey] = serviceData
|
||||
// }
|
||||
// if manufacturerSpecificDataArgs != nil {
|
||||
// let manufacturerSpecificData = manufacturerSpecificDataArgs!.toManufacturerSpecificData()
|
||||
// advertisement[CBAdvertisementDataManufacturerDataKey] = manufacturerSpecificData
|
||||
// }
|
||||
return advertisement
|
||||
extension CBPeripheral {
|
||||
func toArgs() -> MyPeripheralArgs {
|
||||
let uuidArgs = identifier.toArgs()
|
||||
return MyPeripheralArgs(uuidArgs: uuidArgs)
|
||||
}
|
||||
}
|
||||
|
||||
//extension MyManufacturerSpecificDataArgs {
|
||||
// func toManufacturerSpecificData() -> Data {
|
||||
// let id = UInt16(idArgs).data
|
||||
// let data = dataArgs.data
|
||||
// return id + data
|
||||
// }
|
||||
//}
|
||||
|
||||
extension MyGattServiceArgs {
|
||||
func toService() -> CBMutableService {
|
||||
let type = CBUUID(string: uuidArgs)
|
||||
let primary = true
|
||||
return CBMutableService(type: type, primary: primary)
|
||||
extension CBDescriptor {
|
||||
func toArgs() -> MyGattDescriptorArgs {
|
||||
let hashCodeArgs = hash.toInt64()
|
||||
let uuidArgs = uuid.toArgs()
|
||||
return MyGattDescriptorArgs(hashCodeArgs: hashCodeArgs, uuidArgs: uuidArgs)
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattCharacteristicArgs {
|
||||
func toCharacteristic() -> CBMutableCharacteristic {
|
||||
let type = CBUUID(string: uuidArgs)
|
||||
return CBMutableCharacteristic(type: type, properties: properties, value: nil, permissions: permissions)
|
||||
}
|
||||
|
||||
var properties: CBCharacteristicProperties {
|
||||
var properties: CBCharacteristicProperties = []
|
||||
for args in propertyNumbersArgs {
|
||||
guard let rawArgs = args else {
|
||||
continue
|
||||
}
|
||||
let rawValue = Int(rawArgs)
|
||||
let property = MyGattCharacteristicPropertyArgs(rawValue: rawValue)
|
||||
switch property {
|
||||
case .read:
|
||||
properties.insert(.read)
|
||||
case .write:
|
||||
properties.insert(.write)
|
||||
case .writeWithoutResponse:
|
||||
properties.insert(.writeWithoutResponse)
|
||||
case .notify:
|
||||
properties.insert(.notify)
|
||||
case .indicate:
|
||||
properties.insert(.indicate)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
return properties
|
||||
}
|
||||
|
||||
var permissions: CBAttributePermissions {
|
||||
var permissions: CBAttributePermissions = []
|
||||
for args in propertyNumbersArgs {
|
||||
guard let rawArgs = args else {
|
||||
continue
|
||||
}
|
||||
let rawValue = Int(rawArgs)
|
||||
let property = MyGattCharacteristicPropertyArgs(rawValue: rawValue)
|
||||
switch property {
|
||||
case .read:
|
||||
permissions.insert(.readable)
|
||||
case .write, .writeWithoutResponse:
|
||||
permissions.insert(.writeable)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
return permissions
|
||||
extension CBCharacteristic {
|
||||
func toArgs() -> MyGattCharacteristicArgs {
|
||||
let hashCodeArgs = hash.toInt64()
|
||||
let uuidArgs = uuid.toArgs()
|
||||
let propertyNumbersArgs = properties.toArgs().map { args in args.rawValue.toInt64() }
|
||||
let descriptorsArgs = descriptors?.map { descriptor in descriptor.toArgs() } ?? []
|
||||
return MyGattCharacteristicArgs(hashCodeArgs: hashCodeArgs, uuidArgs: uuidArgs, propertyNumbersArgs: propertyNumbersArgs, descriptorsArgs: descriptorsArgs)
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattDescriptorArgs {
|
||||
func toDescriptor() -> CBMutableDescriptor {
|
||||
let type = CBUUID(string: uuidArgs)
|
||||
let value = valueArgs?.data
|
||||
return CBMutableDescriptor(type: type, value: value)
|
||||
extension CBCharacteristicProperties {
|
||||
func toArgs() -> [MyGattCharacteristicPropertyArgs] {
|
||||
var args = [MyGattCharacteristicPropertyArgs]()
|
||||
if contains(.read) {
|
||||
args.append(.read)
|
||||
}
|
||||
if contains(.write) {
|
||||
args.append(.write)
|
||||
}
|
||||
if contains(.writeWithoutResponse) {
|
||||
args.append(.writeWithoutResponse)
|
||||
}
|
||||
if contains(.notify) {
|
||||
args.append(.notify)
|
||||
}
|
||||
if contains(.indicate) {
|
||||
args.append(.indicate)
|
||||
}
|
||||
return args
|
||||
}
|
||||
}
|
||||
|
||||
extension CBService {
|
||||
func toArgs() -> MyGattServiceArgs {
|
||||
let hashCodeArgs = hash.toInt64()
|
||||
let uuidArgs = uuid.toArgs()
|
||||
let characteristicsArgs = characteristics?.map { characteristic in characteristic.toArgs() } ?? []
|
||||
return MyGattServiceArgs(hashCodeArgs: hashCodeArgs, uuidArgs: uuidArgs, characteristicsArgs: characteristicsArgs)
|
||||
}
|
||||
}
|
||||
|
||||
extension Int {
|
||||
func coerceIn(_ minimum: Int, _ maximum: Int) throws -> Int {
|
||||
if minimum > maximum {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
if self < minimum {
|
||||
return minimum
|
||||
}
|
||||
if self > maximum {
|
||||
return maximum
|
||||
}
|
||||
return self
|
||||
func toInt64() -> Int64 {
|
||||
return Int64(self)
|
||||
}
|
||||
}
|
||||
|
||||
extension Dictionary {
|
||||
mutating func getOrPut(_ key: Key, _ defaultValue: () -> Value) -> Value {
|
||||
guard let value = self[key] else {
|
||||
let value1 = defaultValue()
|
||||
self[key] = value1
|
||||
return value1
|
||||
}
|
||||
return value
|
||||
extension UUID {
|
||||
func toArgs() -> String {
|
||||
return uuidString.lowercased()
|
||||
}
|
||||
}
|
||||
|
||||
extension CBUUID {
|
||||
func toArgs() -> String {
|
||||
return uuidString.lowercased()
|
||||
}
|
||||
}
|
||||
|
||||
// This extension of Error is required to do use FlutterError in any Swift code.
|
||||
extension FlutterError: Error {}
|
||||
|
||||
extension String {
|
||||
var data: Data { data(using: String.Encoding.utf8)! }
|
||||
}
|
||||
|
||||
extension NSNumber {
|
||||
var data: Data {
|
||||
var source = self
|
||||
// TODO: resolve warning: Forming 'UnsafeRawPointer' to a variable of type 'NSNumber'; this is likely incorrect because 'NSNumber' may contain an object reference.
|
||||
return Data(bytes: &source, count: MemoryLayout<NSNumber>.size)
|
||||
}
|
||||
}
|
||||
|
||||
extension UInt16 {
|
||||
var data: Data {
|
||||
var source = self
|
||||
return Data(bytes: &source, count: MemoryLayout<UInt16>.size)
|
||||
}
|
||||
}
|
||||
|
@ -17,220 +17,192 @@ import FlutterMacOS
|
||||
#endif
|
||||
|
||||
class MyCentralManager: MyCentralManagerHostApi {
|
||||
init(_ binaryMessenger: FlutterBinaryMessenger) {
|
||||
self.binaryMessenger = binaryMessenger
|
||||
private let _api: MyCentralManagerFlutterApi
|
||||
private let _centralManager: CBCentralManager
|
||||
|
||||
private lazy var _centralManagerDelegate = MyCentralManagerDelegate(centralManager: self)
|
||||
private lazy var _peripheralDelegate = MyPeripheralDelegate(centralManager: self)
|
||||
|
||||
private var _peripherals: [String: CBPeripheral]
|
||||
private var _services: [String: [Int64: CBService]]
|
||||
private var _characteristics: [String: [Int64: CBCharacteristic]]
|
||||
private var _descriptors: [String: [Int64: CBDescriptor]]
|
||||
|
||||
private var _connectCompletions: [String: (Result<Void, Error>) -> Void]
|
||||
private var _disconnectCompletions: [String: (Result<Void, Error>) -> Void]
|
||||
private var _readRssiCompletions: [String: (Result<Int64, Error>) -> Void]
|
||||
private var _discoverServicesCompletions: [String: (Result<[MyGattServiceArgs], Error>) -> Void]
|
||||
private var _discoverCharacteristicsCompletions: [String: [Int64: (Result<[MyGattCharacteristicArgs], Error>) -> Void]]
|
||||
private var _discoverDescriptorsCompletions: [String: [Int64: (Result<[MyGattDescriptorArgs], Error>) -> Void]]
|
||||
private var _readCharacteristicCompletions: [String: [Int64: (Result<FlutterStandardTypedData, Error>) -> Void]]
|
||||
private var _writeCharacteristicCompletions: [String: [Int64: (Result<Void, Error>) -> Void]]
|
||||
private var _setCharacteristicNotifyStateCompletions: [String: [Int64: (Result<Void, Error>) -> Void]]
|
||||
private var _readDescriptorCompletions: [String: [Int64: (Result<FlutterStandardTypedData, Error>) -> Void]]
|
||||
private var _writeDescriptorCompletions: [String: [Int64: (Result<Void, Error>) -> Void]]
|
||||
|
||||
init(messenger: FlutterBinaryMessenger) {
|
||||
_api = MyCentralManagerFlutterApi(binaryMessenger: messenger)
|
||||
_centralManager = CBCentralManager()
|
||||
|
||||
_peripherals = [:]
|
||||
_services = [:]
|
||||
_characteristics = [:]
|
||||
_descriptors = [:]
|
||||
|
||||
_connectCompletions = [:]
|
||||
_disconnectCompletions = [:]
|
||||
_readRssiCompletions = [:]
|
||||
_discoverServicesCompletions = [:]
|
||||
_discoverCharacteristicsCompletions = [:]
|
||||
_discoverDescriptorsCompletions = [:]
|
||||
_readCharacteristicCompletions = [:]
|
||||
_writeCharacteristicCompletions = [:]
|
||||
_setCharacteristicNotifyStateCompletions = [:]
|
||||
_readDescriptorCompletions = [:]
|
||||
_writeDescriptorCompletions = [:]
|
||||
}
|
||||
|
||||
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 setUp() throws {
|
||||
_clearState()
|
||||
if _centralManager.delegate == nil {
|
||||
_centralManager.delegate = _centralManagerDelegate
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
_onStateChanged()
|
||||
}
|
||||
|
||||
func startDiscovery() throws {
|
||||
let options = [CBCentralManagerScanOptionAllowDuplicatesKey: true]
|
||||
centralManager.scanForPeripherals(withServices: nil, options: options)
|
||||
_centralManager.scanForPeripherals(withServices: nil, options: options)
|
||||
}
|
||||
|
||||
func stopDiscovery() throws {
|
||||
centralManager.stopScan()
|
||||
_centralManager.stopScan()
|
||||
}
|
||||
|
||||
func connect(peripheralHashCodeArgs: Int64, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
func connect(uuidArgs: String, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
let unfinishedCompletion = connectCompletions[peripheralHashCodeArgs]
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
guard let peripheral = peripherals[peripheralHashCodeArgs] else {
|
||||
guard let peripheral = _peripherals[uuidArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
centralManager.connect(peripheral)
|
||||
connectCompletions[peripheralHashCodeArgs] = completion
|
||||
_centralManager.connect(peripheral)
|
||||
_connectCompletions[uuidArgs] = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func disconnect(peripheralHashCodeArgs: Int64, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
func disconnect(uuidArgs: String, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
let unfinishedCompletion = disconnectCompletions[peripheralHashCodeArgs]
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
guard let peripheral = peripherals[peripheralHashCodeArgs] else {
|
||||
guard let peripheral = _peripherals[uuidArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
centralManager.cancelPeripheralConnection(peripheral)
|
||||
disconnectCompletions[peripheralHashCodeArgs] = completion
|
||||
_centralManager.cancelPeripheralConnection(peripheral)
|
||||
_disconnectCompletions[uuidArgs] = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func getMaximumWriteLength(peripheralHashCodeArgs: Int64, typeNumberArgs: Int64) throws -> Int64 {
|
||||
guard let peripheral = peripherals[peripheralHashCodeArgs] else {
|
||||
func getMaximumWriteValueLength(uuidArgs: String, typeNumberArgs: Int64) throws -> Int64 {
|
||||
guard let peripheral = _peripherals[uuidArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let typeRawValue = Int(typeNumberArgs)
|
||||
guard let typeArgs = MyGattCharacteristicWriteTypeArgs(rawValue: typeRawValue) else {
|
||||
let typeNumber = typeNumberArgs.toInt()
|
||||
guard let typeArgs = MyGattCharacteristicWriteTypeArgs(rawValue: typeNumber) else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let type = typeArgs.toWriteType()
|
||||
let maximumWriteLength = try peripheral.maximumWriteValueLength(for: type).coerceIn(20, 512)
|
||||
let maximumWriteLengthArgs = Int64(maximumWriteLength)
|
||||
return maximumWriteLengthArgs
|
||||
let maximumWriteValueLength = peripheral.maximumWriteValueLength(for: type)
|
||||
let maximumWriteValueLengthArgs = maximumWriteValueLength.toInt64()
|
||||
return maximumWriteValueLengthArgs
|
||||
}
|
||||
|
||||
func readRSSI(peripheralHashCodeArgs: Int64, completion: @escaping (Result<Int64, Error>) -> Void) {
|
||||
func readRSSI(uuidArgs: String, completion: @escaping (Result<Int64, Error>) -> Void) {
|
||||
do {
|
||||
let unfinishedCompletion = readRssiCompletions[peripheralHashCodeArgs]
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
guard let peripheral = peripherals[peripheralHashCodeArgs] else {
|
||||
guard let peripheral = _peripherals[uuidArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
peripheral.readRSSI()
|
||||
readRssiCompletions[peripheralHashCodeArgs] = completion
|
||||
_readRssiCompletions[uuidArgs] = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func discoverGATT(peripheralHashCodeArgs: Int64, completion: @escaping (Result<[MyGattServiceArgs], Error>) -> Void) {
|
||||
func discoverServices(uuidArgs: String, completion: @escaping (Result<[MyGattServiceArgs], Error>) -> Void) {
|
||||
do {
|
||||
let unfinishedCompletion = discoverGattCompletions[peripheralHashCodeArgs]
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
guard let peripheral = peripherals[peripheralHashCodeArgs] else {
|
||||
guard let peripheral = _peripherals[uuidArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
peripheral.discoverServices(nil)
|
||||
discoverGattCompletions[peripheralHashCodeArgs] = completion
|
||||
_discoverServicesCompletions[uuidArgs] = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func readCharacteristic(peripheralHashCodeArgs: Int64, characteristicHashCodeArgs: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
|
||||
func discoverCharacteristics(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<[MyGattCharacteristicArgs], Error>) -> Void) {
|
||||
do {
|
||||
let unfinishedCompletion = readCharacteristicCompletions[characteristicHashCodeArgs]
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
guard let peripheral = peripherals[peripheralHashCodeArgs] else {
|
||||
guard let peripheral = _peripherals[uuidArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
guard let characteristic = characteristics[characteristicHashCodeArgs] else {
|
||||
guard let service = _retrieveService(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs) else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
peripheral.discoverCharacteristics(nil, for: service)
|
||||
_discoverCharacteristicsCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func discoverDescriptors(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<[MyGattDescriptorArgs], Error>) -> Void){
|
||||
do {
|
||||
guard let peripheral = _peripherals[uuidArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
guard let characteristic = _retrieveCharacteristic(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs) else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
peripheral.discoverDescriptors(for: characteristic)
|
||||
_discoverDescriptorsCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func readCharacteristic(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
|
||||
do {
|
||||
guard let peripheral = _peripherals[uuidArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
guard let characteristic = _retrieveCharacteristic(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs) else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
peripheral.readValue(for: characteristic)
|
||||
readCharacteristicCompletions[characteristicHashCodeArgs] = completion
|
||||
_readCharacteristicCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func writeCharacteristic(peripheralHashCodeArgs: Int64, characteristicHashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, typeNumberArgs: Int64, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
func writeCharacteristic(uuidArgs: String, hashCodeArgs: 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 {
|
||||
guard let peripheral = _peripherals[uuidArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
guard let characteristic = characteristics[characteristicHashCodeArgs] else {
|
||||
guard let characteristic = _retrieveCharacteristic(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs) else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let data = valueArgs.data
|
||||
let typeRawValue = Int(typeNumberArgs)
|
||||
guard let typeArgs = MyGattCharacteristicWriteTypeArgs(rawValue: typeRawValue) else {
|
||||
let typeNumber = typeNumberArgs.toInt()
|
||||
guard let typeArgs = MyGattCharacteristicWriteTypeArgs(rawValue: typeNumber) else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let type = typeArgs.toWriteType()
|
||||
peripheral.writeValue(data, for: characteristic, type: type)
|
||||
if type == .withResponse {
|
||||
writeCharacteristicCompletions[characteristicHashCodeArgs] = completion
|
||||
_writeCharacteristicCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
|
||||
} else {
|
||||
completion(.success(()))
|
||||
}
|
||||
@ -239,159 +211,149 @@ class MyCentralManager: MyCentralManagerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
func notifyCharacteristic(peripheralHashCodeArgs: Int64, characteristicHashCodeArgs: Int64, stateArgs: Bool, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
func setCharacteristicNotifyState(uuidArgs: String, hashCodeArgs: 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 {
|
||||
guard let peripheral = _peripherals[uuidArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
guard let characteristic = characteristics[characteristicHashCodeArgs] else {
|
||||
guard let characteristic = _retrieveCharacteristic(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs) else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let enabled = stateArgs
|
||||
peripheral.setNotifyValue(enabled, for: characteristic)
|
||||
notifyCharacteristicCompletions[characteristicHashCodeArgs] = completion
|
||||
_setCharacteristicNotifyStateCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func readDescriptor(peripheralHashCodeArgs: Int64, descriptorHashCodeArgs: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
|
||||
func readDescriptor(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
|
||||
do {
|
||||
let unfinishedCompletion = readDescriptorCompletions[descriptorHashCodeArgs]
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
guard let peripheral = peripherals[peripheralHashCodeArgs] else {
|
||||
guard let peripheral = _peripherals[uuidArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
guard let descriptor = descriptors[descriptorHashCodeArgs] else {
|
||||
guard let descriptor = _retrieveDescriptor(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs) else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
peripheral.readValue(for: descriptor)
|
||||
readDescriptorCompletions[descriptorHashCodeArgs] = completion
|
||||
_readDescriptorCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func writeDescriptor(peripheralHashCodeArgs: Int64, descriptorHashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
func writeDescriptor(uuidArgs: String, hashCodeArgs: 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 {
|
||||
guard let peripheral = _peripherals[uuidArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
guard let descriptor = descriptors[descriptorHashCodeArgs] else {
|
||||
guard let descriptor = _retrieveDescriptor(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs) else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let data = valueArgs.data
|
||||
peripheral.writeValue(data, for: descriptor)
|
||||
writeDescriptorCompletions[descriptorHashCodeArgs] = completion
|
||||
_writeDescriptorCompletions[uuidArgs, default: [:]][hashCodeArgs] = 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) {_ in }
|
||||
func didUpdateState(central: CBCentralManager) {
|
||||
_onStateChanged()
|
||||
}
|
||||
|
||||
func didDiscover(_ peripheral: CBPeripheral, _ advertisementData: [String : Any], _ rssi: NSNumber) {
|
||||
func didDiscover(central: CBCentralManager, 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 uuidArgs = peripheralArgs.uuidArgs
|
||||
let rssiArgs = rssi.int64Value
|
||||
let advertisementArgs = advertisementData.toAdvertisementArgs()
|
||||
api.onDiscovered(peripheralArgs: peripheralArgs, rssiArgs: rssiArgs, advertisementArgs: advertisementArgs) {_ in }
|
||||
if peripheral.delegate == nil {
|
||||
peripheral.delegate = _peripheralDelegate
|
||||
}
|
||||
_peripherals[uuidArgs] = peripheral
|
||||
_api.onDiscovered(peripheralArgs: peripheralArgs, rssiArgs: rssiArgs, advertisementArgs: advertisementArgs) {_ in }
|
||||
}
|
||||
|
||||
func didConnect(_ peripheral: CBPeripheral) {
|
||||
let peripheralHashCode = peripheral.hash
|
||||
guard let peripheralArgs = peripheralsArgs[peripheralHashCode] else {
|
||||
return
|
||||
}
|
||||
let peripheralHashCodeArgs = peripheralArgs.hashCodeArgs
|
||||
func didConnect(central: CBCentralManager, peripheral: CBPeripheral) {
|
||||
let uuidArgs = peripheral.identifier.toArgs()
|
||||
let stateArgs = true
|
||||
api.onPeripheralStateChanged(peripheralArgs: peripheralArgs, stateArgs: stateArgs) {_ in }
|
||||
guard let completion = connectCompletions.removeValue(forKey: peripheralHashCodeArgs) else {
|
||||
_api.onConnectionStateChanged(uuidArgs: uuidArgs, stateArgs: stateArgs) {_ in }
|
||||
guard let completion = _connectCompletions.removeValue(forKey: uuidArgs) else {
|
||||
return
|
||||
}
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
func didFailToConnect(_ peripheral: CBPeripheral, _ error: Error?) {
|
||||
let peripheralHashCode = peripheral.hash
|
||||
guard let peripheralArgs = peripheralsArgs[peripheralHashCode] else {
|
||||
func didFailToConnect(central: CBCentralManager, peripheral: CBPeripheral, error: Error?) {
|
||||
let uuidArgs = peripheral.identifier.toArgs()
|
||||
guard let completion = _connectCompletions.removeValue(forKey: uuidArgs) else {
|
||||
return
|
||||
}
|
||||
let peripheralHashCodeArgs = peripheralArgs.hashCodeArgs
|
||||
let completion = connectCompletions.removeValue(forKey: peripheralHashCodeArgs)
|
||||
completion?(.failure(error ?? MyError.unknown))
|
||||
completion(.failure(error ?? MyError.unknown))
|
||||
}
|
||||
|
||||
func didDisconnectPeripheral(_ peripheral: CBPeripheral, _ error: Error?) {
|
||||
let peripheralHashCode = peripheral.hash
|
||||
guard let peripheralArgs = peripheralsArgs[peripheralHashCode] else {
|
||||
return
|
||||
func didDisconnectPeripheral(central: CBCentralManager, peripheral: CBPeripheral, error: Error?) {
|
||||
let uuidArgs = peripheral.identifier.toArgs()
|
||||
_services.removeValue(forKey: uuidArgs)
|
||||
_characteristics.removeValue(forKey: uuidArgs)
|
||||
_descriptors.removeValue(forKey: uuidArgs)
|
||||
let errorNotNil = error ?? MyError.unknown
|
||||
let readRssiCompletion = _readRssiCompletions.removeValue(forKey: uuidArgs)
|
||||
readRssiCompletion?(.failure(errorNotNil))
|
||||
let discoverServicesCompletion = _discoverServicesCompletions.removeValue(forKey: uuidArgs)
|
||||
discoverServicesCompletion?(.failure(errorNotNil))
|
||||
let discoverCharacteristicsCompletions = _discoverCharacteristicsCompletions.removeValue(forKey: uuidArgs)
|
||||
if discoverCharacteristicsCompletions != nil {
|
||||
let completions = discoverCharacteristicsCompletions!.values
|
||||
for completion in completions {
|
||||
completion(.failure(errorNotNil))
|
||||
}
|
||||
}
|
||||
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 discoverDescriptorsCompletions = _discoverDescriptorsCompletions.removeValue(forKey: uuidArgs)
|
||||
if discoverDescriptorsCompletions != nil {
|
||||
let completions = discoverDescriptorsCompletions!.values
|
||||
for completion in completions {
|
||||
completion(.failure(errorNotNil))
|
||||
}
|
||||
}
|
||||
let readCharacteristicCompletions = _readCharacteristicCompletions.removeValue(forKey: uuidArgs)
|
||||
if readCharacteristicCompletions != nil {
|
||||
let completions = readCharacteristicCompletions!.values
|
||||
for completion in completions {
|
||||
completion(.failure(errorNotNil))
|
||||
}
|
||||
}
|
||||
let writeCharacteristicCompletions = _writeCharacteristicCompletions.removeValue(forKey: uuidArgs)
|
||||
if writeCharacteristicCompletions != nil {
|
||||
let completions = writeCharacteristicCompletions!.values
|
||||
for completion in completions {
|
||||
completion(.failure(errorNotNil))
|
||||
}
|
||||
}
|
||||
let notifyCharacteristicCompletions = _setCharacteristicNotifyStateCompletions.removeValue(forKey: uuidArgs)
|
||||
if notifyCharacteristicCompletions != nil {
|
||||
let completions = notifyCharacteristicCompletions!.values
|
||||
for completioin in completions {
|
||||
completioin(.failure(errorNotNil))
|
||||
}
|
||||
}
|
||||
let readDescriptorCompletions = _readDescriptorCompletions.removeValue(forKey: uuidArgs)
|
||||
if readDescriptorCompletions != nil {
|
||||
let completions = readDescriptorCompletions!.values
|
||||
for completioin in completions {
|
||||
completioin(.failure(errorNotNil))
|
||||
}
|
||||
}
|
||||
let writeDescriptorCompletions = _writeDescriptorCompletions.removeValue(forKey: uuidArgs)
|
||||
if writeDescriptorCompletions != nil {
|
||||
let completions = writeDescriptorCompletions!.values
|
||||
for completion in completions {
|
||||
completion(.failure(errorNotNil))
|
||||
}
|
||||
}
|
||||
let stateArgs = false
|
||||
api.onPeripheralStateChanged(peripheralArgs: peripheralArgs, stateArgs: stateArgs) {_ in }
|
||||
guard let completion = disconnectCompletions.removeValue(forKey: peripheralHashCodeArgs) else {
|
||||
_api.onConnectionStateChanged(uuidArgs: uuidArgs, stateArgs: stateArgs) {_ in }
|
||||
guard let completion = _disconnectCompletions.removeValue(forKey: uuidArgs) else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
@ -401,13 +363,9 @@ class MyCentralManager: MyCentralManagerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
func didReadRSSI(peripheral: CBPeripheral, rssi: NSNumber, error: Error?) {
|
||||
let uuidArgs = peripheral.identifier.toArgs()
|
||||
guard let completion = _readRssiCompletions.removeValue(forKey: uuidArgs) else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
@ -418,157 +376,110 @@ class MyCentralManager: MyCentralManagerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
func didDiscoverServices(peripheral: CBPeripheral, error: Error?) {
|
||||
let uuidArgs = peripheral.identifier.toArgs()
|
||||
guard let completion = _discoverServicesCompletions.removeValue(forKey: uuidArgs) 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)
|
||||
let servicesArgs = services.map { service in service.toArgs() }
|
||||
let elements = services.flatMap { service in
|
||||
let hashCodeArgs = service.hash.toInt64()
|
||||
return [hashCodeArgs: service]
|
||||
}
|
||||
servicesArgsOfPeripheralsArgs[peripheralhashCodeArgs] = servicesArgs
|
||||
completion(.success((servicesArgs)))
|
||||
var items = _services[uuidArgs]
|
||||
if items == nil {
|
||||
_services[uuidArgs] = Dictionary(uniqueKeysWithValues: elements)
|
||||
} else {
|
||||
items!.merge(elements) { service1, service2 in service2 }
|
||||
}
|
||||
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 {
|
||||
func didDiscoverCharacteristics(peripheral: CBPeripheral, service: CBService, error: Error?) {
|
||||
let uuidArgs = peripheral.identifier.toArgs()
|
||||
let hashCodeArgs = service.hash.toInt64()
|
||||
guard var completions = _discoverCharacteristicsCompletions[uuidArgs] 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) {_ in }
|
||||
guard let completion = completions.removeValue(forKey: hashCodeArgs) else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
let characteristics = service.characteristics ?? []
|
||||
let characteristicsArgs = characteristics.map { characteristic in characteristic.toArgs() }
|
||||
let elements = characteristics.flatMap { characteristic in
|
||||
let hashCodeArgs = characteristic.hash.toInt64()
|
||||
return [hashCodeArgs: characteristic]
|
||||
}
|
||||
var items = _characteristics[uuidArgs]
|
||||
if items == nil {
|
||||
_characteristics[uuidArgs] = Dictionary(uniqueKeysWithValues: elements)
|
||||
} else {
|
||||
items!.merge(elements) { characteristic1, characteristic2 in characteristic2 }
|
||||
}
|
||||
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 var completions = _discoverDescriptorsCompletions[uuidArgs] else {
|
||||
return
|
||||
}
|
||||
guard let completion = completions.removeValue(forKey: hashCodeArgs) else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
let descriptors = characteristic.descriptors ?? []
|
||||
let descriptorsArgs = descriptors.map { descriptor in descriptor.toArgs() }
|
||||
let elements = descriptors.flatMap { descriptor in
|
||||
let hashCodeArgs = descriptor.hash.toInt64()
|
||||
return [hashCodeArgs: descriptor]
|
||||
}
|
||||
var items = _descriptors[uuidArgs]
|
||||
if items == nil {
|
||||
_descriptors[uuidArgs] = Dictionary(uniqueKeysWithValues: elements)
|
||||
} else {
|
||||
items!.merge(elements) { descriptor1, descriptor2 in descriptor2 }
|
||||
}
|
||||
completion(.success(descriptorsArgs))
|
||||
} else {
|
||||
completion(.failure(error!))
|
||||
}
|
||||
}
|
||||
|
||||
func didUpdateCharacteristicValue(peripheral: CBPeripheral, characteristic: CBCharacteristic, error: Error?) {
|
||||
let uuidArgs = peripheral.identifier.toArgs()
|
||||
let hashCodeArgs = characteristic.hash.toInt64()
|
||||
let value = characteristic.value ?? Data()
|
||||
let valueArgs = FlutterStandardTypedData(bytes: value)
|
||||
var completions = _readCharacteristicCompletions[uuidArgs]
|
||||
guard let completion = completions?.removeValue(forKey: hashCodeArgs) else {
|
||||
_api.onCharacteristicNotified(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs, valueArgs: valueArgs) {_ in }
|
||||
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 {
|
||||
func didWriteCharacteristicValue(peripheral: CBPeripheral, characteristic: CBCharacteristic, error: Error?) {
|
||||
let uuidArgs = peripheral.identifier.toArgs()
|
||||
let hashCodeArgs = characteristic.hash.toInt64()
|
||||
guard var completions = _writeCharacteristicCompletions[uuidArgs] else {
|
||||
return
|
||||
}
|
||||
let characteristicHashCodeArgs = characteristicArgs.hashCodeArgs
|
||||
guard let completion = writeCharacteristicCompletions.removeValue(forKey: characteristicHashCodeArgs) else {
|
||||
guard let completion = completions.removeValue(forKey: hashCodeArgs) else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
@ -578,13 +489,13 @@ class MyCentralManager: MyCentralManagerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
func didUpdateNotificationState(_ characteristic: CBCharacteristic, _ error: Error?) {
|
||||
let characteristicHashCode = characteristic.hash
|
||||
guard let characteristicArgs = characteristicsArgs[characteristicHashCode] else {
|
||||
func didUpdateCharacteristicNotificationState(peripheral: CBPeripheral, characteristic: CBCharacteristic, error: Error?) {
|
||||
let uuidArgs = peripheral.identifier.toArgs()
|
||||
let hashCodeArgs = characteristic.hash.toInt64()
|
||||
guard var completions = _setCharacteristicNotifyStateCompletions[uuidArgs] else {
|
||||
return
|
||||
}
|
||||
let characteristicHashCodeArgs = characteristicArgs.hashCodeArgs
|
||||
guard let completion = notifyCharacteristicCompletions.removeValue(forKey: characteristicHashCodeArgs) else {
|
||||
guard let completion = completions.removeValue(forKey: hashCodeArgs) else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
@ -594,17 +505,17 @@ class MyCentralManager: MyCentralManagerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
func didUpdateDescriptorValue(_ descriptor: CBDescriptor, _ error: Error?) {
|
||||
let descriptorHashCode = descriptor.hash
|
||||
guard let descriptorArgs = descriptorsArgs[descriptorHashCode] else {
|
||||
func didUpdateDescriptorValue(peripheral: CBPeripheral, descriptor: CBDescriptor, error: Error?) {
|
||||
let uuidArgs = peripheral.identifier.toArgs()
|
||||
let hashCodeArgs = descriptor.hash.toInt64()
|
||||
guard var completions = _readDescriptorCompletions[uuidArgs] else {
|
||||
return
|
||||
}
|
||||
let descriptorHashCodeArgs = descriptorArgs.hashCodeArgs
|
||||
guard let completion = readDescriptorCompletions.removeValue(forKey: descriptorHashCodeArgs) else {
|
||||
guard let completion = completions.removeValue(forKey: hashCodeArgs) else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
// TODO: Need to confirm wheather the corresponding descriptor type and value is correct.
|
||||
// TODO: confirm the corresponding descriptor types and values are correct.
|
||||
let valueArgs: FlutterStandardTypedData
|
||||
let value = descriptor.value
|
||||
do {
|
||||
@ -647,13 +558,13 @@ class MyCentralManager: MyCentralManagerHostApi {
|
||||
}
|
||||
}
|
||||
|
||||
func didWriteDescriptorValue(_ descriptor: CBDescriptor, _ error: Error?) {
|
||||
let descriptorHashCode = descriptor.hash
|
||||
guard let descriptorArgs = descriptorsArgs[descriptorHashCode] else {
|
||||
func didWriteDescriptorValue(peripheral: CBPeripheral, descriptor: CBDescriptor, error: Error?) {
|
||||
let uuidArgs = peripheral.identifier.toArgs()
|
||||
let hashCodeArgs = descriptor.hash.toInt64()
|
||||
guard var completions = _writeDescriptorCompletions[uuidArgs] else {
|
||||
return
|
||||
}
|
||||
let descriptorHashCodeArgs = descriptorArgs.hashCodeArgs
|
||||
guard let completion = writeDescriptorCompletions.removeValue(forKey: descriptorHashCodeArgs) else {
|
||||
guard let completion = completions.removeValue(forKey: hashCodeArgs) else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
@ -662,4 +573,60 @@ class MyCentralManager: MyCentralManagerHostApi {
|
||||
completion(.failure(error!))
|
||||
}
|
||||
}
|
||||
|
||||
private func _clearState() {
|
||||
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()
|
||||
|
||||
_connectCompletions.removeAll()
|
||||
_disconnectCompletions.removeAll()
|
||||
_readRssiCompletions.removeAll()
|
||||
_discoverServicesCompletions.removeAll()
|
||||
_discoverCharacteristicsCompletions.removeAll()
|
||||
_discoverDescriptorsCompletions.removeAll()
|
||||
_readCharacteristicCompletions.removeAll()
|
||||
_writeCharacteristicCompletions.removeAll()
|
||||
_setCharacteristicNotifyStateCompletions.removeAll()
|
||||
_readDescriptorCompletions.removeAll()
|
||||
_writeDescriptorCompletions.removeAll()
|
||||
}
|
||||
|
||||
private func _retrieveService(uuidArgs: String, hashCodeArgs: Int64) -> CBService? {
|
||||
guard let services = _services[uuidArgs] else {
|
||||
return nil
|
||||
}
|
||||
return services[hashCodeArgs]
|
||||
}
|
||||
|
||||
private func _retrieveCharacteristic(uuidArgs: String, hashCodeArgs: Int64) -> CBCharacteristic? {
|
||||
guard let characteristics = _characteristics[uuidArgs] else {
|
||||
return nil
|
||||
}
|
||||
return characteristics[hashCodeArgs]
|
||||
}
|
||||
|
||||
private func _retrieveDescriptor(uuidArgs: String, hashCodeArgs: Int64) -> CBDescriptor? {
|
||||
guard let descriptors = _descriptors[uuidArgs] else {
|
||||
return nil
|
||||
}
|
||||
return descriptors[hashCodeArgs]
|
||||
}
|
||||
|
||||
private func _onStateChanged() {
|
||||
let state = _centralManager.state
|
||||
let stateArgs = state.toArgs()
|
||||
let stateNumberArgs = stateArgs.rawValue.toInt64()
|
||||
_api.onStateChanged(stateNumberArgs: stateNumberArgs) {_ in }
|
||||
}
|
||||
}
|
||||
|
@ -9,29 +9,29 @@ import Foundation
|
||||
import CoreBluetooth
|
||||
|
||||
class MyCentralManagerDelegate: NSObject, CBCentralManagerDelegate {
|
||||
init(_ centralManager: MyCentralManager) {
|
||||
self.centralManager = centralManager
|
||||
private let _centralManager: MyCentralManager
|
||||
|
||||
init(centralManager: MyCentralManager) {
|
||||
_centralManager = centralManager
|
||||
}
|
||||
|
||||
private let centralManager: MyCentralManager
|
||||
|
||||
func centralManagerDidUpdateState(_ central: CBCentralManager) {
|
||||
centralManager.didUpdateState()
|
||||
_centralManager.didUpdateState(central: central)
|
||||
}
|
||||
|
||||
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
|
||||
centralManager.didDiscover(peripheral, advertisementData, RSSI)
|
||||
_centralManager.didDiscover(central: central, peripheral: peripheral, advertisementData: advertisementData, rssi: RSSI)
|
||||
}
|
||||
|
||||
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
|
||||
centralManager.didConnect(peripheral)
|
||||
_centralManager.didConnect(central: central, peripheral: peripheral)
|
||||
}
|
||||
|
||||
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
|
||||
centralManager.didFailToConnect(peripheral, error)
|
||||
_centralManager.didFailToConnect(central: central, peripheral: peripheral, error: error)
|
||||
}
|
||||
|
||||
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
|
||||
centralManager.didDisconnectPeripheral(peripheral, error)
|
||||
_centralManager.didDisconnectPeripheral(central: central, peripheral: peripheral, error: error)
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,5 @@ import Foundation
|
||||
// TODO: 优化错误内容
|
||||
enum MyError: Error {
|
||||
case illegalArgument
|
||||
case illegalState
|
||||
case unknown
|
||||
}
|
||||
|
@ -9,45 +9,45 @@ import Foundation
|
||||
import CoreBluetooth
|
||||
|
||||
class MyPeripheralDelegate: NSObject, CBPeripheralDelegate {
|
||||
private let centralManager: MyCentralManager
|
||||
private let _centralManager: MyCentralManager
|
||||
|
||||
init(_ centralManager: MyCentralManager) {
|
||||
self.centralManager = centralManager
|
||||
init(centralManager: MyCentralManager) {
|
||||
_centralManager = centralManager
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: Error?) {
|
||||
centralManager.didReadRSSI(peripheral, RSSI, error)
|
||||
_centralManager.didReadRSSI(peripheral: peripheral, rssi: RSSI, error: error)
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
|
||||
centralManager.didDiscoverServices(peripheral, error)
|
||||
_centralManager.didDiscoverServices(peripheral: peripheral, error: error)
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
|
||||
centralManager.didDiscoverCharacteristics(peripheral, service, error)
|
||||
_centralManager.didDiscoverCharacteristics(peripheral: peripheral, service: service, error: error)
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didDiscoverDescriptorsFor characteristic: CBCharacteristic, error: Error?) {
|
||||
centralManager.didDiscoverDescriptors(peripheral, characteristic, error)
|
||||
_centralManager.didDiscoverDescriptors(peripheral: peripheral, characteristic: characteristic, error: error)
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
|
||||
centralManager.didUpdateCharacteristicValue(characteristic, error)
|
||||
_centralManager.didUpdateCharacteristicValue(peripheral: peripheral, characteristic: characteristic, error: error)
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
|
||||
centralManager.didWriteCharacteristicValue(characteristic, error)
|
||||
_centralManager.didWriteCharacteristicValue(peripheral: peripheral, characteristic: characteristic, error: error)
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
|
||||
centralManager.didUpdateNotificationState(characteristic, error)
|
||||
_centralManager.didUpdateCharacteristicNotificationState(peripheral: peripheral, characteristic: characteristic, error: error)
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor descriptor: CBDescriptor, error: Error?) {
|
||||
centralManager.didUpdateDescriptorValue(descriptor, error)
|
||||
_centralManager.didUpdateDescriptorValue(peripheral: peripheral, descriptor: descriptor, error: error)
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor descriptor: CBDescriptor, error: Error?) {
|
||||
centralManager.didWriteDescriptorValue(descriptor, error)
|
||||
_centralManager.didWriteDescriptorValue(peripheral: peripheral, descriptor: descriptor, error: error)
|
||||
}
|
||||
}
|
||||
|
@ -17,138 +17,308 @@ import FlutterMacOS
|
||||
#endif
|
||||
|
||||
class MyPeripheralManager: MyPeripheralManagerHostApi {
|
||||
init(_ binaryMessenger: FlutterBinaryMessenger) {
|
||||
self.binaryMessenger = binaryMessenger
|
||||
private let _api: MyPeripheralManagerFlutterApi
|
||||
private let _peripheralManager: CBPeripheralManager
|
||||
|
||||
private lazy var _peripheralManagerDelegate = MyPeripheralManagerDelegate(peripheralManager: self)
|
||||
|
||||
private var _servicesArgs: [Int: MyGattServiceArgs]
|
||||
private var _characteristicsArgs: [Int: MyGattCharacteristicArgs]
|
||||
private var _descriptorsArgs: [Int: MyGattDescriptorArgs]
|
||||
|
||||
private var _centrals: [String: CBCentral]
|
||||
private var _services: [Int64: CBMutableService]
|
||||
private var _characteristics: [Int64: CBMutableCharacteristic]
|
||||
private var _descriptors: [Int64: CBMutableDescriptor]
|
||||
private var _requests: [Int64: CBATTRequest]
|
||||
|
||||
private var _addServiceCompletion: ((Result<Void, Error>) -> Void)?
|
||||
private var _startAdvertisingCompletion: ((Result<Void, Error>) -> Void)?
|
||||
private var _isReadyToUpdateSubscribersCallbacks: [() -> Void]
|
||||
|
||||
init(messenger: FlutterBinaryMessenger) {
|
||||
_api = MyPeripheralManagerFlutterApi(binaryMessenger: messenger)
|
||||
_peripheralManager = CBPeripheralManager()
|
||||
|
||||
_servicesArgs = [:]
|
||||
_characteristicsArgs = [:]
|
||||
_descriptorsArgs = [:]
|
||||
|
||||
_centrals = [:]
|
||||
_services = [:]
|
||||
_characteristics = [:]
|
||||
_descriptors = [:]
|
||||
_requests = [:]
|
||||
|
||||
_addServiceCompletion = nil
|
||||
_startAdvertisingCompletion = nil
|
||||
_isReadyToUpdateSubscribersCallbacks = []
|
||||
}
|
||||
|
||||
private let binaryMessenger: FlutterBinaryMessenger
|
||||
private let peripheralManager = CBPeripheralManager()
|
||||
|
||||
private lazy var api = MyPeripheralManagerFlutterApi(binaryMessenger: binaryMessenger)
|
||||
private lazy var peripheralManagerDelegate = MyPeripheralManagerDelegate(self)
|
||||
|
||||
private var centrals = [Int64: CBCentral]()
|
||||
private var services = [Int64: CBMutableService]()
|
||||
private var characteristics = [Int64: CBMutableCharacteristic]()
|
||||
private var descriptors = [Int64: CBMutableDescriptor]()
|
||||
private var requests = [Int64: CBATTRequest]()
|
||||
|
||||
private var centralsArgs = [Int: MyCentralArgs]()
|
||||
private var servicesArgs = [Int: MyGattServiceArgs]()
|
||||
private var characteristicsArgs = [Int: MyGattCharacteristicArgs]()
|
||||
private var descriptorsArgs = [Int: MyGattDescriptorArgs]()
|
||||
|
||||
private var setUpCompletion: ((Result<MyPeripheralManagerArgs, Error>) -> Void)?
|
||||
private var addServiceCompletion: ((Result<Void, Error>) -> Void)?
|
||||
private var startAdvertisingCompletion: ((Result<Void, Error>) -> Void)?
|
||||
private var notifyCharacteristicValueChangedCallbacks = [() -> Void]()
|
||||
|
||||
func setUp(completion: @escaping (Result<MyPeripheralManagerArgs, Error>) -> Void) {
|
||||
do {
|
||||
if setUpCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
try tearDown()
|
||||
peripheralManager.delegate = peripheralManagerDelegate
|
||||
if peripheralManager.state == .unknown {
|
||||
setUpCompletion = completion
|
||||
} else {
|
||||
let stateArgs = peripheralManager.state.toArgs()
|
||||
let stateNumberArgs = Int64(stateArgs.rawValue)
|
||||
let args = MyPeripheralManagerArgs(stateNumberArgs: stateNumberArgs)
|
||||
completion(.success(args))
|
||||
}
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
func setUp() throws {
|
||||
_clearState()
|
||||
if _peripheralManager.delegate == nil {
|
||||
_peripheralManager.delegate = _peripheralManagerDelegate
|
||||
}
|
||||
}
|
||||
|
||||
func tearDown() throws {
|
||||
if(peripheralManager.isAdvertising) {
|
||||
peripheralManager.stopAdvertising()
|
||||
}
|
||||
centrals.removeAll()
|
||||
services.removeAll()
|
||||
characteristics.removeAll()
|
||||
descriptors.removeAll()
|
||||
requests.removeAll()
|
||||
centralsArgs.removeAll()
|
||||
servicesArgs.removeAll()
|
||||
characteristicsArgs.removeAll()
|
||||
descriptorsArgs.removeAll()
|
||||
setUpCompletion = nil
|
||||
addServiceCompletion = nil
|
||||
startAdvertisingCompletion = nil
|
||||
notifyCharacteristicValueChangedCallbacks.removeAll()
|
||||
_onStateChanged()
|
||||
}
|
||||
|
||||
func addService(serviceArgs: MyGattServiceArgs, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
if addServiceCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
let service = serviceArgs.toService()
|
||||
var characteristics = [CBMutableCharacteristic]()
|
||||
let characteristicsArgs = serviceArgs.characteristicsArgs
|
||||
for args in characteristicsArgs {
|
||||
guard let characteristicArgs = args else {
|
||||
continue
|
||||
}
|
||||
let service = serviceArgs.toService()
|
||||
var characteristics = [CBMutableCharacteristic]()
|
||||
let characteristicsArgs = serviceArgs.characteristicsArgs
|
||||
for args in characteristicsArgs {
|
||||
guard let characteristicArgs = args else {
|
||||
let characteristic = characteristicArgs.toCharacteristic()
|
||||
characteristics.append(characteristic)
|
||||
var descriptors = [CBMutableDescriptor]()
|
||||
let descriptorsArgs = characteristicArgs.descriptorsArgs
|
||||
for args in descriptorsArgs {
|
||||
guard let descriptorArgs = args else {
|
||||
continue
|
||||
}
|
||||
let characteristic = characteristicArgs.toCharacteristic()
|
||||
var descriptors = [CBMutableDescriptor]()
|
||||
let descriptorsArgs = characteristicArgs.descriptorsArgs
|
||||
for args in descriptorsArgs {
|
||||
guard let descriptorArgs = args else {
|
||||
continue
|
||||
}
|
||||
let descriptor = descriptorArgs.toDescriptor()
|
||||
descriptors.append(descriptor)
|
||||
let descriptorHashCodeArgs = descriptorArgs.hashCodeArgs
|
||||
let descriptorHashCode = descriptor.hash
|
||||
self.descriptorsArgs[descriptorHashCode] = descriptorArgs
|
||||
self.descriptors[descriptorHashCodeArgs] = descriptor
|
||||
}
|
||||
characteristic.descriptors = descriptors
|
||||
characteristics.append(characteristic)
|
||||
let characteristicHashCodeArgs = characteristicArgs.hashCodeArgs
|
||||
let characteristicHashCode = characteristic.hash
|
||||
self.characteristicsArgs[characteristicHashCode] = characteristicArgs
|
||||
self.characteristics[characteristicHashCodeArgs] = characteristic
|
||||
let descriptor = descriptorArgs.toDescriptor()
|
||||
descriptors.append(descriptor)
|
||||
let descriptorHashCodeArgs = descriptorArgs.hashCodeArgs
|
||||
let descriptorHashCode = descriptor.hash
|
||||
_descriptorsArgs[descriptorHashCode] = descriptorArgs
|
||||
_descriptors[descriptorHashCodeArgs] = descriptor
|
||||
}
|
||||
characteristic.descriptors = descriptors
|
||||
let characteristicHashCodeArgs = characteristicArgs.hashCodeArgs
|
||||
let characteristicHashCode = characteristic.hash
|
||||
_characteristicsArgs[characteristicHashCode] = characteristicArgs
|
||||
_characteristics[characteristicHashCodeArgs] = characteristic
|
||||
}
|
||||
service.characteristics = characteristics
|
||||
let serviceHashCodeArgs = serviceArgs.hashCodeArgs
|
||||
let serviceHashCode = service.hash
|
||||
_servicesArgs[serviceHashCode] = serviceArgs
|
||||
_services[serviceHashCodeArgs] = service
|
||||
_peripheralManager.add(service)
|
||||
_addServiceCompletion = completion
|
||||
}
|
||||
|
||||
func removeService(hashCodeArgs: Int64) throws {
|
||||
guard let service = _services[hashCodeArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let hashCode = service.hash
|
||||
guard let serviceArgs = _servicesArgs[hashCode] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
_peripheralManager.remove(service)
|
||||
_clearService(serviceArgs: serviceArgs)
|
||||
}
|
||||
|
||||
func clearServices() throws {
|
||||
_peripheralManager.removeAllServices()
|
||||
let servicesArgs = _servicesArgs.values
|
||||
for serviceArgs in servicesArgs {
|
||||
_clearService(serviceArgs: serviceArgs)
|
||||
}
|
||||
}
|
||||
|
||||
func startAdvertising(advertisementArgs: MyAdvertisementArgs, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
let advertisement = advertisementArgs.toAdvertisement()
|
||||
_peripheralManager.startAdvertising(advertisement)
|
||||
_startAdvertisingCompletion = completion
|
||||
}
|
||||
|
||||
func stopAdvertising() throws {
|
||||
_peripheralManager.stopAdvertising()
|
||||
}
|
||||
|
||||
func getMaximumUpdateValueLength(uuidArgs: String) throws -> Int64 {
|
||||
guard let central = _centrals[uuidArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let maximumUpdateValueLength = central.maximumUpdateValueLength
|
||||
let maximumUpdateValueLengthArgs = maximumUpdateValueLength.toInt64()
|
||||
return maximumUpdateValueLengthArgs
|
||||
}
|
||||
|
||||
func respond(idArgs: Int64, errorNumberArgs: Int64, valueArgs: FlutterStandardTypedData?) throws {
|
||||
guard let request = _requests.removeValue(forKey: idArgs) else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
if valueArgs != nil {
|
||||
request.value = valueArgs?.data
|
||||
}
|
||||
let errorArgsRawValue = errorNumberArgs.toInt()
|
||||
guard let errorArgs = MyGattErrorArgs(rawValue: errorArgsRawValue) else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let result = errorArgs.toError()
|
||||
_peripheralManager.respond(to: request, withResult: result)
|
||||
}
|
||||
|
||||
func updateCharacteristic(hashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, uuidsArgs: [String]?, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
let centrals = try uuidsArgs?.map { uuidArgs in
|
||||
guard let central = _centrals[uuidArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
return central
|
||||
}
|
||||
guard let characteristic = _characteristics[hashCodeArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let value = valueArgs.data
|
||||
let updated = _peripheralManager.updateValue(value, for: characteristic, onSubscribedCentrals: centrals)
|
||||
if updated {
|
||||
completion(.success(()))
|
||||
} else {
|
||||
_isReadyToUpdateSubscribersCallbacks.append {
|
||||
self.updateCharacteristic(hashCodeArgs: hashCodeArgs, valueArgs: valueArgs, uuidsArgs: uuidsArgs, completion: completion)
|
||||
}
|
||||
}
|
||||
service.characteristics = characteristics
|
||||
let serviceHashCodeArgs = serviceArgs.hashCodeArgs
|
||||
let serviceHashCode = service.hash
|
||||
self.servicesArgs[serviceHashCode] = serviceArgs
|
||||
self.services[serviceHashCodeArgs] = service
|
||||
peripheralManager.add(service)
|
||||
addServiceCompletion = completion
|
||||
} catch {
|
||||
freeService(serviceArgs)
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func removeService(serviceHashCodeArgs: Int64) throws {
|
||||
guard let service = services[serviceHashCodeArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let serviceHashCode = service.hash
|
||||
guard let serviceArgs = servicesArgs[serviceHashCode] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
peripheralManager.remove(service)
|
||||
freeService(serviceArgs)
|
||||
func didUpdateState(peripheral: CBPeripheralManager) {
|
||||
_onStateChanged()
|
||||
}
|
||||
|
||||
func clearServices() throws {
|
||||
peripheralManager.removeAllServices()
|
||||
let servicesArgs = self.servicesArgs.values
|
||||
for serviceArgs in servicesArgs {
|
||||
freeService(serviceArgs)
|
||||
func didAdd(peripheral: CBPeripheralManager, service: CBService, error: Error?) {
|
||||
guard let completion = _addServiceCompletion else {
|
||||
return
|
||||
}
|
||||
_addServiceCompletion = nil
|
||||
if error == nil {
|
||||
completion(.success(()))
|
||||
} else {
|
||||
completion(.failure(error!))
|
||||
let hashCode = service.hash
|
||||
guard let serviceArgs = _servicesArgs[hashCode] else {
|
||||
return
|
||||
}
|
||||
_clearService(serviceArgs: serviceArgs)
|
||||
}
|
||||
}
|
||||
|
||||
private func freeService(_ serviceArgs: MyGattServiceArgs) {
|
||||
func didStartAdvertising(peripheral: CBPeripheralManager, error: Error?) {
|
||||
guard let completion = _startAdvertisingCompletion else {
|
||||
return
|
||||
}
|
||||
_startAdvertisingCompletion = nil
|
||||
if error == nil {
|
||||
completion(.success(()))
|
||||
} else {
|
||||
completion(.failure(error!))
|
||||
}
|
||||
}
|
||||
|
||||
func didReceiveRead(peripheral: CBPeripheralManager, request: CBATTRequest) {
|
||||
let central = request.central
|
||||
let centralArgs = central.toArgs()
|
||||
_centrals[centralArgs.uuidArgs] = central
|
||||
let characteristic = request.characteristic
|
||||
let hashCode = characteristic.hash
|
||||
guard let characteristicArgs = _characteristicsArgs[hashCode] else {
|
||||
_peripheralManager.respond(to: request, withResult: .attributeNotFound)
|
||||
return
|
||||
}
|
||||
let hashCodeArgs = characteristicArgs.hashCodeArgs
|
||||
let idArgs = request.hash.toInt64()
|
||||
let offsetArgs = request.offset.toInt64()
|
||||
_requests[idArgs] = request
|
||||
_api.onCharacteristicReadRequest(centralArgs: centralArgs, hashCodeArgs: hashCodeArgs, idArgs: idArgs, offsetArgs: offsetArgs) {_ in }
|
||||
}
|
||||
|
||||
func didReceiveWrite(peripheral: CBPeripheralManager, requests: [CBATTRequest]) {
|
||||
// When you respond to a write request, note that the first parameter of the respond(to:with
|
||||
// Result:) method expects a single CBATTRequest object, even though you received an array of
|
||||
// them from the peripheralManager(_:didReceiveWrite:) method. To respond properly,
|
||||
// pass in the first request of the requests array.
|
||||
// see: https://developer.apple.com/documentation/corebluetooth/cbperipheralmanagerdelegate/1393315-peripheralmanager#discussion
|
||||
guard let request = requests.first else {
|
||||
return
|
||||
}
|
||||
if requests.count > 1 {
|
||||
// TODO: 支持多写入请求,暂时不清楚此处应如何处理
|
||||
let result = CBATTError.requestNotSupported
|
||||
_peripheralManager.respond(to: request, withResult: result)
|
||||
return
|
||||
}
|
||||
let central = request.central
|
||||
let centralArgs = central.toArgs()
|
||||
_centrals[centralArgs.uuidArgs] = central
|
||||
let characteristic = request.characteristic
|
||||
let hashCode = characteristic.hash
|
||||
guard let characteristicArgs = _characteristicsArgs[hashCode] else {
|
||||
_peripheralManager.respond(to: request, withResult: .attributeNotFound)
|
||||
return
|
||||
}
|
||||
let hashCodeArgs = characteristicArgs.hashCodeArgs
|
||||
let idArgs = request.hash.toInt64()
|
||||
let offsetArgs = request.offset.toInt64()
|
||||
guard let value = request.value else {
|
||||
_peripheralManager.respond(to: request, withResult: .requestNotSupported)
|
||||
return
|
||||
}
|
||||
let valueArgs = FlutterStandardTypedData(bytes: value)
|
||||
_requests[idArgs] = request
|
||||
_api.onCharacteristicWriteRequest(centralArgs: centralArgs, hashCodeArgs: hashCodeArgs, idArgs: idArgs, offsetArgs: offsetArgs, valueArgs: valueArgs) {_ in }
|
||||
}
|
||||
|
||||
func didSubscribeTo(peripheral: CBPeripheralManager, central: CBCentral, characteristic: CBCharacteristic) {
|
||||
let centralArgs = central.toArgs()
|
||||
_centrals[centralArgs.uuidArgs] = central
|
||||
let hashCode = characteristic.hash
|
||||
guard let characteristicArgs = _characteristicsArgs[hashCode] else {
|
||||
return
|
||||
}
|
||||
let hashCodeArgs = characteristicArgs.hashCodeArgs
|
||||
let stateArgs = true
|
||||
_api.onCharacteristicNotifyStateChanged(centralArgs: centralArgs, hashCodeArgs: hashCodeArgs, stateArgs: stateArgs) {_ in }
|
||||
}
|
||||
|
||||
func didUnsubscribeFrom(peripheral: CBPeripheralManager, central: CBCentral, characteristic: CBCharacteristic) {
|
||||
let centralArgs = central.toArgs()
|
||||
_centrals[centralArgs.uuidArgs] = central
|
||||
let hashCode = characteristic.hash
|
||||
guard let characteristicArgs = _characteristicsArgs[hashCode] else {
|
||||
return
|
||||
}
|
||||
let hashCodeArgs = characteristicArgs.hashCodeArgs
|
||||
let stateArgs = false
|
||||
_api.onCharacteristicNotifyStateChanged(centralArgs: centralArgs, hashCodeArgs: hashCodeArgs, stateArgs: stateArgs) {_ in }
|
||||
}
|
||||
|
||||
func isReadyToUpdateSubscribers(peripheral: CBPeripheralManager) {
|
||||
let callbacks = _isReadyToUpdateSubscribersCallbacks
|
||||
_isReadyToUpdateSubscribersCallbacks.removeAll()
|
||||
for callback in callbacks {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
private func _clearState() {
|
||||
if(_peripheralManager.isAdvertising) {
|
||||
_peripheralManager.stopAdvertising()
|
||||
}
|
||||
|
||||
_servicesArgs.removeAll()
|
||||
_characteristicsArgs.removeAll()
|
||||
_descriptorsArgs.removeAll()
|
||||
|
||||
_centrals.removeAll()
|
||||
_services.removeAll()
|
||||
_characteristics.removeAll()
|
||||
_descriptors.removeAll()
|
||||
_requests.removeAll()
|
||||
|
||||
_addServiceCompletion = nil
|
||||
_startAdvertisingCompletion = nil
|
||||
_isReadyToUpdateSubscribersCallbacks.removeAll()
|
||||
}
|
||||
|
||||
private func _clearService(serviceArgs: MyGattServiceArgs) {
|
||||
let characteristicsArgs = serviceArgs.characteristicsArgs
|
||||
for args in characteristicsArgs {
|
||||
guard let characteristicArgs = args else {
|
||||
@ -160,223 +330,31 @@ class MyPeripheralManager: MyPeripheralManagerHostApi {
|
||||
continue
|
||||
}
|
||||
let descriptorHashCodeArgs = descriptorArgs.hashCodeArgs
|
||||
guard let descriptor = self.descriptors.removeValue(forKey: descriptorHashCodeArgs) else {
|
||||
guard let descriptor = _descriptors.removeValue(forKey: descriptorHashCodeArgs) else {
|
||||
continue
|
||||
}
|
||||
let descriptorHashCode = descriptor.hash
|
||||
self.descriptorsArgs.removeValue(forKey: descriptorHashCode)
|
||||
_descriptorsArgs.removeValue(forKey: descriptorHashCode)
|
||||
}
|
||||
let characteristicHashCodeArgs = characteristicArgs.hashCodeArgs
|
||||
guard let characteristic = self.characteristics.removeValue(forKey: characteristicHashCodeArgs) else {
|
||||
guard let characteristic = _characteristics.removeValue(forKey: characteristicHashCodeArgs) else {
|
||||
continue
|
||||
}
|
||||
let characteristicHashCode = characteristic.hash
|
||||
self.characteristicsArgs.removeValue(forKey: characteristicHashCode)
|
||||
_characteristicsArgs.removeValue(forKey: characteristicHashCode)
|
||||
}
|
||||
let serviceHashCodeArgs = serviceArgs.hashCodeArgs
|
||||
guard let service = self.services.removeValue(forKey: serviceHashCodeArgs) else {
|
||||
guard let service = _services.removeValue(forKey: serviceHashCodeArgs) else {
|
||||
return
|
||||
}
|
||||
let serviceHashCode = service.hash
|
||||
self.servicesArgs.removeValue(forKey: serviceHashCode)
|
||||
_servicesArgs.removeValue(forKey: serviceHashCode)
|
||||
}
|
||||
|
||||
func startAdvertising(advertisementArgs: MyAdvertisementArgs, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
if startAdvertisingCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
let advertisement = try advertisementArgs.toAdvertisement()
|
||||
peripheralManager.startAdvertising(advertisement)
|
||||
startAdvertisingCompletion = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func stopAdvertising() throws {
|
||||
peripheralManager.stopAdvertising()
|
||||
}
|
||||
|
||||
func getMaximumWriteLength(centralHashCodeArgs: Int64) throws -> Int64 {
|
||||
guard let central = centrals[centralHashCodeArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let maximumWriteLength = try central.maximumUpdateValueLength.coerceIn(20, 512)
|
||||
let maximumWriteLengthArgs = Int64(maximumWriteLength)
|
||||
return maximumWriteLengthArgs
|
||||
}
|
||||
|
||||
func sendReadCharacteristicReply(centralHashCodeArgs: Int64, characteristicHashCodeArgs: Int64, idArgs: Int64, offsetArgs: Int64, statusArgs: Bool, valueArgs: FlutterStandardTypedData) throws {
|
||||
guard let request = requests.removeValue(forKey: idArgs) else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
request.value = valueArgs.data
|
||||
let result = statusArgs ? CBATTError.Code.success : CBATTError.Code.requestNotSupported
|
||||
peripheralManager.respond(to: request, withResult: result)
|
||||
}
|
||||
|
||||
func sendWriteCharacteristicReply(centralHashCodeArgs: Int64, characteristicHashCodeArgs: Int64, idArgs: Int64, offsetArgs: Int64, statusArgs: Bool) throws {
|
||||
guard let request = requests.removeValue(forKey: idArgs) else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let result = statusArgs ? CBATTError.Code.success : CBATTError.Code.requestNotSupported
|
||||
peripheralManager.respond(to: request, withResult: result)
|
||||
}
|
||||
|
||||
func notifyCharacteristicValueChanged(centralHashCodeArgs: Int64, characteristicHashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
if notifyCharacteristicValueChangedCallbacks.count > 0 {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
let value = valueArgs.data
|
||||
guard let characteristic = characteristics[characteristicHashCodeArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
guard let central = centrals[centralHashCodeArgs] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let centrals = [central]
|
||||
let updated = peripheralManager.updateValue(value, for: characteristic, onSubscribedCentrals: centrals)
|
||||
if updated {
|
||||
completion(.success(()))
|
||||
} else {
|
||||
notifyCharacteristicValueChangedCallbacks.append {
|
||||
let updated = self.peripheralManager.updateValue(value, for: characteristic, onSubscribedCentrals: centrals)
|
||||
if updated {
|
||||
completion(.success(()))
|
||||
} else {
|
||||
completion(.failure(MyError.unknown))
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func didUpdateState() {
|
||||
let state = peripheralManager.state
|
||||
private func _onStateChanged() {
|
||||
let state = _peripheralManager.state
|
||||
let stateArgs = state.toArgs()
|
||||
let stateNumberArgs = Int64(stateArgs.rawValue)
|
||||
if state != .unknown && setUpCompletion != nil {
|
||||
let args = MyPeripheralManagerArgs(stateNumberArgs: stateNumberArgs)
|
||||
setUpCompletion!(.success(args))
|
||||
setUpCompletion = nil
|
||||
}
|
||||
api.onStateChanged(stateNumberArgs: stateNumberArgs) {_ in }
|
||||
}
|
||||
|
||||
func didAdd(_ service: CBService, _ error: Error?) {
|
||||
guard let completion = addServiceCompletion else {
|
||||
return
|
||||
}
|
||||
addServiceCompletion = nil
|
||||
if error == nil {
|
||||
completion(.success(()))
|
||||
} else {
|
||||
completion(.failure(error!))
|
||||
let serviceHashCode = service.hash
|
||||
guard let serviceArgs = servicesArgs[serviceHashCode] else {
|
||||
return
|
||||
}
|
||||
freeService(serviceArgs)
|
||||
}
|
||||
}
|
||||
|
||||
func didStartAdvertising(_ error: Error?) {
|
||||
guard let completion = startAdvertisingCompletion else {
|
||||
return
|
||||
}
|
||||
startAdvertisingCompletion = nil
|
||||
if error == nil {
|
||||
completion(.success(()))
|
||||
} else {
|
||||
completion(.failure(error!))
|
||||
}
|
||||
}
|
||||
|
||||
func didReceiveRead(_ request: CBATTRequest) {
|
||||
let central = request.central
|
||||
let centralHashCode = central.hash
|
||||
let centralArgs = centralsArgs.getOrPut(centralHashCode) { central.toArgs() }
|
||||
let centralHashCodeArgs = centralArgs.hashCodeArgs
|
||||
centrals[centralHashCodeArgs] = central
|
||||
let characteristic = request.characteristic
|
||||
let characteristicHashCode = characteristic.hash
|
||||
guard let characteristicArgs = characteristicsArgs[characteristicHashCode] else {
|
||||
peripheralManager.respond(to: request, withResult: .attributeNotFound)
|
||||
return
|
||||
}
|
||||
let idArgs = Int64(request.hash)
|
||||
requests[idArgs] = request
|
||||
let offsetArgs = Int64(request.offset)
|
||||
api.onReadCharacteristicCommandReceived(centralArgs: centralArgs, characteristicArgs: characteristicArgs, idArgs: idArgs, offsetArgs: offsetArgs) {_ in }
|
||||
}
|
||||
|
||||
func didReceiveWrite(_ requests: [CBATTRequest]) {
|
||||
// 根据官方文档,仅响应第一个写入请求
|
||||
guard let request = requests.first else {
|
||||
return
|
||||
}
|
||||
if requests.count > 1 {
|
||||
// TODO: 支持多写入请求,暂时不清楚此处应如何处理
|
||||
let result = CBATTError.requestNotSupported
|
||||
peripheralManager.respond(to: request, withResult: result)
|
||||
}
|
||||
let central = request.central
|
||||
let centralHashCode = central.hash
|
||||
let centralArgs = centralsArgs.getOrPut(centralHashCode) { central.toArgs() }
|
||||
let centralHashCodeArgs = centralArgs.hashCodeArgs
|
||||
centrals[centralHashCodeArgs] = central
|
||||
let characteristic = request.characteristic
|
||||
let characteristicHashCode = characteristic.hash
|
||||
guard let characteristicArgs = characteristicsArgs[characteristicHashCode] else {
|
||||
peripheralManager.respond(to: request, withResult: .attributeNotFound)
|
||||
return
|
||||
}
|
||||
let idArgs = Int64(request.hash)
|
||||
self.requests[idArgs] = request
|
||||
let offsetArgs = Int64(request.offset)
|
||||
guard let value = request.value else {
|
||||
peripheralManager.respond(to: request, withResult: .requestNotSupported)
|
||||
return
|
||||
}
|
||||
let valueArgs = FlutterStandardTypedData(bytes: value)
|
||||
api.onWriteCharacteristicCommandReceived(centralArgs: centralArgs, characteristicArgs: characteristicArgs, idArgs: idArgs, offsetArgs: offsetArgs, valueArgs: valueArgs) {_ in }
|
||||
}
|
||||
|
||||
func didSubscribeTo(_ central: CBCentral, _ characteristic: CBCharacteristic) {
|
||||
let centralHashCode = central.hash
|
||||
let centralArgs = centralsArgs.getOrPut(centralHashCode) { central.toArgs() }
|
||||
let centralHashCodeArgs = centralArgs.hashCodeArgs
|
||||
centrals[centralHashCodeArgs] = central
|
||||
let characteristicHashCode = characteristic.hash
|
||||
guard let characteristicArgs = characteristicsArgs[characteristicHashCode] else {
|
||||
return
|
||||
}
|
||||
let stateArgs = true
|
||||
api.onNotifyCharacteristicCommandReceived(centralArgs: centralArgs, characteristicArgs: characteristicArgs, stateArgs: stateArgs) {_ in }
|
||||
}
|
||||
|
||||
func didUnsubscribeFrom(_ central: CBCentral, _ characteristic: CBCharacteristic) {
|
||||
let centralHashCode = central.hash
|
||||
let centralArgs = centralsArgs.getOrPut(centralHashCode) { central.toArgs() }
|
||||
let centralHashCodeArgs = centralArgs.hashCodeArgs
|
||||
centrals[centralHashCodeArgs] = central
|
||||
let characteristicHashCode = characteristic.hash
|
||||
guard let characteristicArgs = characteristicsArgs[characteristicHashCode] else {
|
||||
return
|
||||
}
|
||||
let stateArgs = false
|
||||
api.onNotifyCharacteristicCommandReceived(centralArgs: centralArgs, characteristicArgs: characteristicArgs, stateArgs: stateArgs) {_ in }
|
||||
}
|
||||
|
||||
func isReadyToUpdateSubscribers() {
|
||||
let callbacks = notifyCharacteristicValueChangedCallbacks
|
||||
notifyCharacteristicValueChangedCallbacks.removeAll()
|
||||
for callback in callbacks {
|
||||
callback()
|
||||
}
|
||||
let stateNumberArgs = stateArgs.rawValue.toInt64()
|
||||
_api.onStateChanged(stateNumberArgs: stateNumberArgs) {_ in }
|
||||
}
|
||||
}
|
||||
|
@ -9,41 +9,41 @@ import Foundation
|
||||
import CoreBluetooth
|
||||
|
||||
class MyPeripheralManagerDelegate: NSObject, CBPeripheralManagerDelegate {
|
||||
init(_ peripheralManager: MyPeripheralManager) {
|
||||
self.peripheralManager = peripheralManager
|
||||
private let _peripheralManager: MyPeripheralManager
|
||||
|
||||
init(peripheralManager: MyPeripheralManager) {
|
||||
_peripheralManager = peripheralManager
|
||||
}
|
||||
|
||||
private let peripheralManager: MyPeripheralManager
|
||||
|
||||
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
|
||||
peripheralManager.didUpdateState()
|
||||
_peripheralManager.didUpdateState(peripheral: peripheral)
|
||||
}
|
||||
|
||||
func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) {
|
||||
peripheralManager.didAdd(service, error)
|
||||
_peripheralManager.didAdd(peripheral: peripheral, service: service, error: error)
|
||||
}
|
||||
|
||||
func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {
|
||||
peripheralManager.didStartAdvertising(error)
|
||||
_peripheralManager.didStartAdvertising(peripheral: peripheral, error: error)
|
||||
}
|
||||
|
||||
func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveRead request: CBATTRequest) {
|
||||
peripheralManager.didReceiveRead(request)
|
||||
_peripheralManager.didReceiveRead(peripheral: peripheral, request: request)
|
||||
}
|
||||
|
||||
func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) {
|
||||
peripheralManager.didReceiveWrite(requests)
|
||||
_peripheralManager.didReceiveWrite(peripheral: peripheral, requests: requests)
|
||||
}
|
||||
|
||||
func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didSubscribeTo characteristic: CBCharacteristic) {
|
||||
peripheralManager.didSubscribeTo(central, characteristic)
|
||||
_peripheralManager.didSubscribeTo(peripheral: peripheral, central: central, characteristic: characteristic)
|
||||
}
|
||||
|
||||
func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didUnsubscribeFrom characteristic: CBCharacteristic) {
|
||||
peripheralManager.didUnsubscribeFrom(central, characteristic)
|
||||
_peripheralManager.didUnsubscribeFrom(peripheral: peripheral, central: central, characteristic: characteristic)
|
||||
}
|
||||
|
||||
func peripheralManagerIsReady(toUpdateSubscribers peripheral: CBPeripheralManager) {
|
||||
peripheralManager.isReadyToUpdateSubscribers()
|
||||
_peripheralManager.isReadyToUpdateSubscribers(peripheral: peripheral)
|
||||
}
|
||||
}
|
||||
|
@ -26,4 +26,4 @@ SPEC CHECKSUMS:
|
||||
|
||||
PODFILE CHECKSUM: 70d9d25280d0dd177a5f637cdb0f0b0b12c6a189
|
||||
|
||||
COCOAPODS: 1.12.1
|
||||
COCOAPODS: 1.14.3
|
||||
|
@ -8,18 +8,17 @@ import 'package:convert/convert.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
CentralManager get centralManager => CentralManager.instance;
|
||||
PeripheralManager get peripheralManager => PeripheralManager.instance;
|
||||
|
||||
void main() {
|
||||
runZonedGuarded(onStartUp, onCrashed);
|
||||
}
|
||||
|
||||
void onStartUp() async {
|
||||
Logger.root.onRecord.listen(onLogRecord);
|
||||
// hierarchicalLoggingEnabled = true;
|
||||
// CentralManager.instance.logLevel = Level.WARNING;
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
await centralManager.setUp();
|
||||
await peripheralManager.setUp();
|
||||
await CentralManager.instance.setUp();
|
||||
await PeripheralManager.instance.setUp();
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
@ -58,6 +57,8 @@ class _MyAppState extends State<MyApp> {
|
||||
return MaterialApp(
|
||||
theme: ThemeData.light(
|
||||
useMaterial3: true,
|
||||
).copyWith(
|
||||
materialTapTargetSize: MaterialTapTargetSize.padded,
|
||||
),
|
||||
home: const HomeView(),
|
||||
routes: {
|
||||
@ -168,15 +169,15 @@ class _ScannerViewState extends State<ScannerView> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
state = ValueNotifier(centralManager.state);
|
||||
state = ValueNotifier(BluetoothLowEnergyState.unknown);
|
||||
discovering = ValueNotifier(false);
|
||||
discoveredEventArgs = ValueNotifier([]);
|
||||
stateChangedSubscription = centralManager.stateChanged.listen(
|
||||
stateChangedSubscription = CentralManager.instance.stateChanged.listen(
|
||||
(eventArgs) {
|
||||
state.value = eventArgs.state;
|
||||
},
|
||||
);
|
||||
discoveredSubscription = centralManager.discovered.listen(
|
||||
discoveredSubscription = CentralManager.instance.discovered.listen(
|
||||
(eventArgs) {
|
||||
final items = discoveredEventArgs.value;
|
||||
final i = items.indexWhere(
|
||||
@ -190,6 +191,11 @@ class _ScannerViewState extends State<ScannerView> {
|
||||
}
|
||||
},
|
||||
);
|
||||
_initialize();
|
||||
}
|
||||
|
||||
void _initialize() async {
|
||||
state.value = await CentralManager.instance.getState();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -233,12 +239,13 @@ class _ScannerViewState extends State<ScannerView> {
|
||||
}
|
||||
|
||||
Future<void> startDiscovery() async {
|
||||
await centralManager.startDiscovery();
|
||||
discoveredEventArgs.value = [];
|
||||
await CentralManager.instance.startDiscovery();
|
||||
discovering.value = true;
|
||||
}
|
||||
|
||||
Future<void> stopDiscovery() async {
|
||||
await centralManager.stopDiscovery();
|
||||
await CentralManager.instance.stopDiscovery();
|
||||
discovering.value = false;
|
||||
}
|
||||
|
||||
@ -340,7 +347,13 @@ class _ScannerViewState extends State<ScannerView> {
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
trailing: RssiWidget(rssi),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
RssiWidget(rssi),
|
||||
Text('$rssi'),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, i) {
|
||||
@ -378,44 +391,39 @@ class PeripheralView extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _PeripheralViewState extends State<PeripheralView> {
|
||||
late final ValueNotifier<bool> state;
|
||||
late final ValueNotifier<bool> connectionState;
|
||||
late final DiscoveredEventArgs eventArgs;
|
||||
late final ValueNotifier<List<GattService>> services;
|
||||
late final ValueNotifier<List<GattCharacteristic>> characteristics;
|
||||
late final ValueNotifier<GattService?> service;
|
||||
late final ValueNotifier<GattCharacteristic?> characteristic;
|
||||
late final ValueNotifier<GattCharacteristicWriteType> writeType;
|
||||
late final ValueNotifier<int> maximumWriteLength;
|
||||
late final ValueNotifier<int> rssi;
|
||||
late final ValueNotifier<List<Log>> logs;
|
||||
late final TextEditingController writeController;
|
||||
late final StreamSubscription stateChangedSubscription;
|
||||
late final StreamSubscription valueChangedSubscription;
|
||||
late final StreamSubscription rssiChangedSubscription;
|
||||
late final Timer rssiTimer;
|
||||
late final StreamSubscription connectionStateChangedSubscription;
|
||||
late final StreamSubscription characteristicNotifiedSubscription;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
eventArgs = widget.eventArgs;
|
||||
state = ValueNotifier(false);
|
||||
connectionState = ValueNotifier(false);
|
||||
services = ValueNotifier([]);
|
||||
characteristics = ValueNotifier([]);
|
||||
service = ValueNotifier(null);
|
||||
characteristic = ValueNotifier(null);
|
||||
writeType = ValueNotifier(GattCharacteristicWriteType.withResponse);
|
||||
maximumWriteLength = ValueNotifier(0);
|
||||
rssi = ValueNotifier(-100);
|
||||
logs = ValueNotifier([]);
|
||||
writeController = TextEditingController();
|
||||
stateChangedSubscription = centralManager.peripheralStateChanged.listen(
|
||||
connectionStateChangedSubscription =
|
||||
CentralManager.instance.connectionStateChanged.listen(
|
||||
(eventArgs) {
|
||||
if (eventArgs.peripheral != this.eventArgs.peripheral) {
|
||||
return;
|
||||
}
|
||||
final state = eventArgs.state;
|
||||
this.state.value = state;
|
||||
if (!state) {
|
||||
final connectionState = eventArgs.connectionState;
|
||||
this.connectionState.value = connectionState;
|
||||
if (!connectionState) {
|
||||
services.value = [];
|
||||
characteristics.value = [];
|
||||
service.value = null;
|
||||
@ -424,12 +432,13 @@ class _PeripheralViewState extends State<PeripheralView> {
|
||||
}
|
||||
},
|
||||
);
|
||||
valueChangedSubscription = centralManager.characteristicValueChanged.listen(
|
||||
characteristicNotifiedSubscription =
|
||||
CentralManager.instance.characteristicNotified.listen(
|
||||
(eventArgs) {
|
||||
final characteristic = this.characteristic.value;
|
||||
if (eventArgs.characteristic != characteristic) {
|
||||
return;
|
||||
}
|
||||
// final characteristic = this.characteristic.value;
|
||||
// if (eventArgs.characteristic != characteristic) {
|
||||
// return;
|
||||
// }
|
||||
const type = LogType.notify;
|
||||
final log = Log(type, eventArgs.value);
|
||||
logs.value = [
|
||||
@ -438,28 +447,16 @@ class _PeripheralViewState extends State<PeripheralView> {
|
||||
];
|
||||
},
|
||||
);
|
||||
rssiTimer = Timer.periodic(
|
||||
const Duration(seconds: 5),
|
||||
(timer) async {
|
||||
final state = this.state.value;
|
||||
if (state) {
|
||||
rssi.value = await centralManager.readRSSI(eventArgs.peripheral);
|
||||
} else {
|
||||
rssi.value = -100;
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
if (state.value) {
|
||||
return PopScope(
|
||||
onPopInvoked: (didPop) async {
|
||||
if (connectionState.value) {
|
||||
final peripheral = eventArgs.peripheral;
|
||||
await centralManager.disconnect(peripheral);
|
||||
await CentralManager.instance.disconnect(peripheral);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
child: Scaffold(
|
||||
appBar: buildAppBar(context),
|
||||
@ -474,25 +471,17 @@ class _PeripheralViewState extends State<PeripheralView> {
|
||||
title: Text(title),
|
||||
actions: [
|
||||
ValueListenableBuilder(
|
||||
valueListenable: state,
|
||||
valueListenable: connectionState,
|
||||
builder: (context, state, child) {
|
||||
return TextButton(
|
||||
onPressed: () async {
|
||||
final peripheral = eventArgs.peripheral;
|
||||
if (state) {
|
||||
await centralManager.disconnect(peripheral);
|
||||
maximumWriteLength.value = 0;
|
||||
rssi.value = 0;
|
||||
await CentralManager.instance.disconnect(peripheral);
|
||||
} else {
|
||||
await centralManager.connect(peripheral);
|
||||
await CentralManager.instance.connect(peripheral);
|
||||
services.value =
|
||||
await centralManager.discoverGATT(peripheral);
|
||||
maximumWriteLength.value =
|
||||
await centralManager.getMaximumWriteLength(
|
||||
peripheral,
|
||||
type: writeType.value,
|
||||
);
|
||||
rssi.value = await centralManager.readRSSI(peripheral);
|
||||
await CentralManager.instance.discoverGATT(peripheral);
|
||||
}
|
||||
},
|
||||
child: Text(state ? 'DISCONNECT' : 'CONNECT'),
|
||||
@ -566,7 +555,32 @@ class _PeripheralViewState extends State<PeripheralView> {
|
||||
hint: const Text('CHOOSE A CHARACTERISTIC'),
|
||||
value: characteristic,
|
||||
onChanged: (characteristic) {
|
||||
if (characteristic == null) {
|
||||
return;
|
||||
}
|
||||
this.characteristic.value = characteristic;
|
||||
final writeType = this.writeType.value;
|
||||
final canWrite = characteristic.properties.contains(
|
||||
GattCharacteristicProperty.write,
|
||||
);
|
||||
final canWriteWithoutResponse =
|
||||
characteristic.properties.contains(
|
||||
GattCharacteristicProperty.writeWithoutResponse,
|
||||
);
|
||||
if (writeType ==
|
||||
GattCharacteristicWriteType.withResponse &&
|
||||
!canWrite &&
|
||||
canWriteWithoutResponse) {
|
||||
this.writeType.value =
|
||||
GattCharacteristicWriteType.withoutResponse;
|
||||
}
|
||||
if (writeType ==
|
||||
GattCharacteristicWriteType.withoutResponse &&
|
||||
!canWriteWithoutResponse &&
|
||||
canWrite) {
|
||||
this.writeType.value =
|
||||
GattCharacteristicWriteType.withResponse;
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
@ -624,129 +638,45 @@ class _PeripheralViewState extends State<PeripheralView> {
|
||||
},
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
ValueListenableBuilder(
|
||||
valueListenable: writeType,
|
||||
builder: (context, writeType, child) {
|
||||
return ToggleButtons(
|
||||
onPressed: (i) async {
|
||||
final type = GattCharacteristicWriteType.values[i];
|
||||
this.writeType.value = type;
|
||||
maximumWriteLength.value =
|
||||
await centralManager.getMaximumWriteLength(
|
||||
eventArgs.peripheral,
|
||||
type: type,
|
||||
);
|
||||
},
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 0.0,
|
||||
minHeight: 0.0,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(4.0),
|
||||
isSelected: GattCharacteristicWriteType.values
|
||||
.map((type) => type == writeType)
|
||||
.toList(),
|
||||
children: GattCharacteristicWriteType.values.map((type) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: 8.0,
|
||||
vertical: 4.0,
|
||||
),
|
||||
child: Text(type.name),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
// final segments =
|
||||
// GattCharacteristicWriteType.values.map((type) {
|
||||
// return ButtonSegment(
|
||||
// value: type,
|
||||
// label: Text(type.name),
|
||||
// );
|
||||
// }).toList();
|
||||
// return SegmentedButton(
|
||||
// segments: segments,
|
||||
// selected: {writeType},
|
||||
// showSelectedIcon: false,
|
||||
// style: OutlinedButton.styleFrom(
|
||||
// tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
// padding: EdgeInsets.zero,
|
||||
// visualDensity: VisualDensity.compact,
|
||||
// shape: RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.circular(8.0),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
},
|
||||
),
|
||||
const SizedBox(width: 8.0),
|
||||
ValueListenableBuilder(
|
||||
valueListenable: state,
|
||||
builder: (context, state, child) {
|
||||
return ValueListenableBuilder(
|
||||
valueListenable: maximumWriteLength,
|
||||
builder: (context, maximumWriteLength, child) {
|
||||
return Text('$maximumWriteLength');
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
const Spacer(),
|
||||
ValueListenableBuilder(
|
||||
valueListenable: rssi,
|
||||
builder: (context, rssi, child) {
|
||||
return RssiWidget(rssi);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
margin: const EdgeInsets.only(bottom: 16.0),
|
||||
height: 160.0,
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: characteristic,
|
||||
builder: (context, characteristic, child) {
|
||||
final bool canNotify, canRead, canWrite;
|
||||
if (characteristic == null) {
|
||||
canNotify = canRead = canWrite = false;
|
||||
} else {
|
||||
final properties = characteristic.properties;
|
||||
canNotify = properties.contains(
|
||||
GattCharacteristicProperty.notify,
|
||||
);
|
||||
canRead = properties.contains(
|
||||
GattCharacteristicProperty.read,
|
||||
);
|
||||
canWrite = properties.contains(
|
||||
GattCharacteristicProperty.write,
|
||||
);
|
||||
}
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: writeController,
|
||||
enabled: canWrite,
|
||||
expands: true,
|
||||
maxLines: null,
|
||||
textAlignVertical: TextAlignVertical.top,
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
horizontal: 12.0,
|
||||
vertical: 8.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
ValueListenableBuilder(
|
||||
valueListenable: characteristic,
|
||||
builder: (context, characteristic, chld) {
|
||||
final bool canNotify, canRead, canWrite, canWriteWithoutResponse;
|
||||
if (characteristic == null) {
|
||||
canNotify =
|
||||
canRead = canWrite = canWriteWithoutResponse = false;
|
||||
} else {
|
||||
final properties = characteristic.properties;
|
||||
canNotify = properties.contains(
|
||||
GattCharacteristicProperty.notify,
|
||||
) ||
|
||||
properties.contains(
|
||||
GattCharacteristicProperty.indicate,
|
||||
);
|
||||
canRead = properties.contains(
|
||||
GattCharacteristicProperty.read,
|
||||
);
|
||||
canWrite = properties.contains(
|
||||
GattCharacteristicProperty.write,
|
||||
);
|
||||
canWriteWithoutResponse = properties.contains(
|
||||
GattCharacteristicProperty.writeWithoutResponse,
|
||||
);
|
||||
}
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 4.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
ElevatedButton(
|
||||
onPressed: characteristic != null && canNotify
|
||||
? () async {
|
||||
await centralManager.notifyCharacteristic(
|
||||
await CentralManager.instance
|
||||
.setCharacteristicNotifyState(
|
||||
characteristic,
|
||||
state: true,
|
||||
);
|
||||
@ -754,10 +684,11 @@ class _PeripheralViewState extends State<PeripheralView> {
|
||||
: null,
|
||||
child: const Text('NOTIFY'),
|
||||
),
|
||||
TextButton(
|
||||
const SizedBox(width: 8.0),
|
||||
ElevatedButton(
|
||||
onPressed: characteristic != null && canRead
|
||||
? () async {
|
||||
final value = await centralManager
|
||||
final value = await CentralManager.instance
|
||||
.readCharacteristic(characteristic);
|
||||
const type = LogType.read;
|
||||
final log = Log(type, value);
|
||||
@ -765,31 +696,124 @@ class _PeripheralViewState extends State<PeripheralView> {
|
||||
}
|
||||
: null,
|
||||
child: const Text('READ'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: characteristic != null && canWrite
|
||||
? () async {
|
||||
final text = writeController.text;
|
||||
final elements = utf8.encode(text);
|
||||
final value = Uint8List.fromList(elements);
|
||||
final type = writeType.value;
|
||||
await centralManager.writeCharacteristic(
|
||||
characteristic,
|
||||
value: value,
|
||||
type: type,
|
||||
);
|
||||
final log = Log(LogType.write, value);
|
||||
logs.value = [...logs.value, log];
|
||||
}
|
||||
: null,
|
||||
child: const Text('WRITE'),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 160.0,
|
||||
child: TextField(
|
||||
controller: writeController,
|
||||
enabled: canWrite || canWriteWithoutResponse,
|
||||
expands: true,
|
||||
maxLines: null,
|
||||
textAlignVertical: TextAlignVertical.top,
|
||||
decoration: const InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
horizontal: 12.0,
|
||||
vertical: 8.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
ValueListenableBuilder(
|
||||
valueListenable: writeType,
|
||||
builder: (context, writeType, child) {
|
||||
return ToggleButtons(
|
||||
onPressed: canWrite || canWriteWithoutResponse
|
||||
? (i) {
|
||||
if (!canWrite || !canWriteWithoutResponse) {
|
||||
return;
|
||||
}
|
||||
final type =
|
||||
GattCharacteristicWriteType.values[i];
|
||||
this.writeType.value = type;
|
||||
}
|
||||
: null,
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 0.0,
|
||||
minHeight: 0.0,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(4.0),
|
||||
isSelected: GattCharacteristicWriteType.values
|
||||
.map((type) => type == writeType)
|
||||
.toList(),
|
||||
children: GattCharacteristicWriteType.values.map(
|
||||
(type) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: 8.0,
|
||||
vertical: 4.0,
|
||||
),
|
||||
child: Text(type.name),
|
||||
);
|
||||
},
|
||||
).toList(),
|
||||
);
|
||||
// final segments =
|
||||
// GattCharacteristicWriteType.values.map((type) {
|
||||
// return ButtonSegment(
|
||||
// value: type,
|
||||
// label: Text(type.name),
|
||||
// );
|
||||
// }).toList();
|
||||
// return SegmentedButton(
|
||||
// segments: segments,
|
||||
// selected: {writeType},
|
||||
// showSelectedIcon: false,
|
||||
// style: OutlinedButton.styleFrom(
|
||||
// tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
// padding: EdgeInsets.zero,
|
||||
// visualDensity: VisualDensity.compact,
|
||||
// shape: RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.circular(8.0),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
},
|
||||
),
|
||||
const Spacer(),
|
||||
ElevatedButton(
|
||||
onPressed: characteristic != null && canWrite
|
||||
? () async {
|
||||
final text = writeController.text;
|
||||
final elements = utf8.encode(text);
|
||||
final value = Uint8List.fromList(elements);
|
||||
final type = writeType.value;
|
||||
// Fragments the value by 512 bytes.
|
||||
const fragmentSize = 512;
|
||||
var start = 0;
|
||||
while (start < value.length) {
|
||||
final end = start + fragmentSize;
|
||||
final fragmentedValue = end < value.length
|
||||
? value.sublist(start, end)
|
||||
: value.sublist(start);
|
||||
await CentralManager.instance
|
||||
.writeCharacteristic(
|
||||
characteristic,
|
||||
value: fragmentedValue,
|
||||
type: type,
|
||||
);
|
||||
final log = Log(
|
||||
LogType.write,
|
||||
fragmentedValue,
|
||||
);
|
||||
logs.value = [...logs.value, log];
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
: null,
|
||||
child: const Text('WRITE'),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16.0),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -799,17 +823,14 @@ class _PeripheralViewState extends State<PeripheralView> {
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
rssiTimer.cancel();
|
||||
stateChangedSubscription.cancel();
|
||||
valueChangedSubscription.cancel();
|
||||
state.dispose();
|
||||
connectionStateChangedSubscription.cancel();
|
||||
characteristicNotifiedSubscription.cancel();
|
||||
connectionState.dispose();
|
||||
services.dispose();
|
||||
characteristics.dispose();
|
||||
service.dispose();
|
||||
characteristic.dispose();
|
||||
writeType.dispose();
|
||||
maximumWriteLength.dispose();
|
||||
rssi.dispose();
|
||||
logs.dispose();
|
||||
writeController.dispose();
|
||||
}
|
||||
@ -828,87 +849,63 @@ class _AdvertiserViewState extends State<AdvertiserView>
|
||||
late final ValueNotifier<bool> advertising;
|
||||
late final ValueNotifier<List<Log>> logs;
|
||||
late final StreamSubscription stateChangedSubscription;
|
||||
late final StreamSubscription readCharacteristicCommandReceivedSubscription;
|
||||
late final StreamSubscription writeCharacteristicCommandReceivedSubscription;
|
||||
late final StreamSubscription notifyCharacteristicCommandReceivedSubscription;
|
||||
late final StreamSubscription characteristicReadSubscription;
|
||||
late final StreamSubscription characteristicWrittenSubscription;
|
||||
late final StreamSubscription characteristicNotifyStateChangedSubscription;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
state = ValueNotifier(peripheralManager.state);
|
||||
state = ValueNotifier(BluetoothLowEnergyState.unknown);
|
||||
advertising = ValueNotifier(false);
|
||||
logs = ValueNotifier([]);
|
||||
stateChangedSubscription = peripheralManager.stateChanged.listen(
|
||||
stateChangedSubscription = PeripheralManager.instance.stateChanged.listen(
|
||||
(eventArgs) {
|
||||
state.value = eventArgs.state;
|
||||
},
|
||||
);
|
||||
readCharacteristicCommandReceivedSubscription =
|
||||
peripheralManager.readCharacteristicCommandReceived.listen(
|
||||
characteristicReadSubscription =
|
||||
PeripheralManager.instance.characteristicRead.listen(
|
||||
(eventArgs) async {
|
||||
final central = eventArgs.central;
|
||||
final characteristic = eventArgs.characteristic;
|
||||
final id = eventArgs.id;
|
||||
final offset = eventArgs.offset;
|
||||
final value = eventArgs.value;
|
||||
final log = Log(
|
||||
LogType.read,
|
||||
Uint8List.fromList([]),
|
||||
'central: ${central.uuid}; characteristic: ${characteristic.uuid}; id: $id; offset: $offset',
|
||||
value,
|
||||
'central: ${central.uuid}; characteristic: ${characteristic.uuid}',
|
||||
);
|
||||
logs.value = [
|
||||
...logs.value,
|
||||
log,
|
||||
];
|
||||
// final maximumWriteLength = peripheralManager.getMaximumWriteLength(
|
||||
// central,
|
||||
// );
|
||||
const status = true;
|
||||
final value = Uint8List.fromList([0x01, 0x02, 0x03]);
|
||||
await peripheralManager.sendReadCharacteristicReply(
|
||||
central,
|
||||
characteristic: characteristic,
|
||||
id: id,
|
||||
offset: offset,
|
||||
status: status,
|
||||
value: value,
|
||||
);
|
||||
},
|
||||
);
|
||||
writeCharacteristicCommandReceivedSubscription =
|
||||
peripheralManager.writeCharacteristicCommandReceived.listen(
|
||||
characteristicWrittenSubscription =
|
||||
PeripheralManager.instance.characteristicWritten.listen(
|
||||
(eventArgs) async {
|
||||
final central = eventArgs.central;
|
||||
final characteristic = eventArgs.characteristic;
|
||||
final id = eventArgs.id;
|
||||
final offset = eventArgs.offset;
|
||||
final value = eventArgs.value;
|
||||
final log = Log(
|
||||
LogType.write,
|
||||
value,
|
||||
'central: ${central.uuid}; characteristic: ${characteristic.uuid}; id: $id; offset: $offset',
|
||||
'central: ${central.uuid}; characteristic: ${characteristic.uuid}',
|
||||
);
|
||||
logs.value = [
|
||||
...logs.value,
|
||||
log,
|
||||
];
|
||||
const status = true;
|
||||
await peripheralManager.sendWriteCharacteristicReply(
|
||||
central,
|
||||
characteristic: characteristic,
|
||||
id: id,
|
||||
offset: offset,
|
||||
status: status,
|
||||
);
|
||||
},
|
||||
);
|
||||
notifyCharacteristicCommandReceivedSubscription =
|
||||
peripheralManager.notifyCharacteristicCommandReceived.listen(
|
||||
characteristicNotifyStateChangedSubscription =
|
||||
PeripheralManager.instance.characteristicNotifyStateChanged.listen(
|
||||
(eventArgs) async {
|
||||
final central = eventArgs.central;
|
||||
final characteristic = eventArgs.characteristic;
|
||||
final state = eventArgs.state;
|
||||
final log = Log(
|
||||
LogType.write,
|
||||
LogType.notify,
|
||||
Uint8List.fromList([]),
|
||||
'central: ${central.uuid}; characteristic: ${characteristic.uuid}; state: $state',
|
||||
);
|
||||
@ -918,15 +915,21 @@ class _AdvertiserViewState extends State<AdvertiserView>
|
||||
];
|
||||
// Write someting to the central when notify started.
|
||||
if (state) {
|
||||
final value = Uint8List.fromList([0x03, 0x02, 0x01]);
|
||||
await peripheralManager.notifyCharacteristicValueChanged(
|
||||
central,
|
||||
characteristic: characteristic,
|
||||
final elements = List.generate(2000, (i) => i % 256);
|
||||
final value = Uint8List.fromList(elements);
|
||||
await PeripheralManager.instance.writeCharacteristic(
|
||||
characteristic,
|
||||
value: value,
|
||||
central: central,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
_initialize();
|
||||
}
|
||||
|
||||
void _initialize() async {
|
||||
state.value = await PeripheralManager.instance.getState();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -970,7 +973,9 @@ class _AdvertiserViewState extends State<AdvertiserView>
|
||||
}
|
||||
|
||||
Future<void> startAdvertising() async {
|
||||
await peripheralManager.clearServices();
|
||||
await PeripheralManager.instance.clearServices();
|
||||
final elements = List.generate(1000, (i) => i % 256);
|
||||
final value = Uint8List.fromList(elements);
|
||||
final service = GattService(
|
||||
uuid: UUID.short(100),
|
||||
characteristics: [
|
||||
@ -979,15 +984,16 @@ class _AdvertiserViewState extends State<AdvertiserView>
|
||||
properties: [
|
||||
GattCharacteristicProperty.read,
|
||||
],
|
||||
value: value,
|
||||
descriptors: [],
|
||||
),
|
||||
GattCharacteristic(
|
||||
uuid: UUID.short(201),
|
||||
properties: [
|
||||
GattCharacteristicProperty.read,
|
||||
GattCharacteristicProperty.write,
|
||||
GattCharacteristicProperty.writeWithoutResponse,
|
||||
],
|
||||
value: Uint8List.fromList([]),
|
||||
descriptors: [],
|
||||
),
|
||||
GattCharacteristic(
|
||||
@ -996,24 +1002,41 @@ class _AdvertiserViewState extends State<AdvertiserView>
|
||||
GattCharacteristicProperty.notify,
|
||||
GattCharacteristicProperty.indicate,
|
||||
],
|
||||
value: Uint8List.fromList([]),
|
||||
descriptors: [],
|
||||
),
|
||||
GattCharacteristic(
|
||||
uuid: UUID.short(203),
|
||||
properties: [
|
||||
GattCharacteristicProperty.notify,
|
||||
],
|
||||
value: Uint8List.fromList([]),
|
||||
descriptors: [],
|
||||
),
|
||||
GattCharacteristic(
|
||||
uuid: UUID.short(204),
|
||||
properties: [
|
||||
GattCharacteristicProperty.indicate,
|
||||
],
|
||||
value: Uint8List.fromList([]),
|
||||
descriptors: [],
|
||||
),
|
||||
],
|
||||
);
|
||||
await peripheralManager.addService(service);
|
||||
await PeripheralManager.instance.addService(service);
|
||||
final advertisement = Advertisement(
|
||||
name: 'flutter',
|
||||
name: 'le12138',
|
||||
manufacturerSpecificData: ManufacturerSpecificData(
|
||||
id: 0x2e19,
|
||||
data: Uint8List.fromList([0x01, 0x02, 0x03]),
|
||||
),
|
||||
);
|
||||
await peripheralManager.startAdvertising(advertisement);
|
||||
await PeripheralManager.instance.startAdvertising(advertisement);
|
||||
advertising.value = true;
|
||||
}
|
||||
|
||||
Future<void> stopAdvertising() async {
|
||||
await peripheralManager.stopAdvertising();
|
||||
await PeripheralManager.instance.stopAdvertising();
|
||||
advertising.value = false;
|
||||
}
|
||||
|
||||
@ -1074,9 +1097,9 @@ class _AdvertiserViewState extends State<AdvertiserView>
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
stateChangedSubscription.cancel();
|
||||
readCharacteristicCommandReceivedSubscription.cancel();
|
||||
writeCharacteristicCommandReceivedSubscription.cancel();
|
||||
notifyCharacteristicCommandReceivedSubscription.cancel();
|
||||
characteristicReadSubscription.cancel();
|
||||
characteristicWrittenSubscription.cancel();
|
||||
characteristicNotifyStateChangedSubscription.cancel();
|
||||
state.dispose();
|
||||
advertising.dispose();
|
||||
logs.dispose();
|
||||
|
@ -20,4 +20,4 @@ SPEC CHECKSUMS:
|
||||
|
||||
PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367
|
||||
|
||||
COCOAPODS: 1.12.1
|
||||
COCOAPODS: 1.14.3
|
||||
|
@ -15,15 +15,15 @@ packages:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "4.0.0"
|
||||
version: "5.0.0"
|
||||
bluetooth_low_energy_platform_interface:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: bluetooth_low_energy_platform_interface
|
||||
sha256: a01819f4ef89d033edaa979465ec8c3af13b2618dc718d90fe681be91b6c4356
|
||||
sha256: "54f92ab2d7746fb6f2b4a40a48cd7eb8e3bf772f3ee89e1979d4d7b741fb2a05"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
version: "5.0.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -52,10 +52,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.17.2"
|
||||
version: "1.18.0"
|
||||
convert:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -102,10 +102,10 @@ packages:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: ad76540d21c066228ee3f9d1dad64a9f7e46530e8bb7c85011a88bc1fd874bc5
|
||||
sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
version: "3.0.1"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
@ -125,10 +125,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
|
||||
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.18.1"
|
||||
version: "0.19.0"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -173,10 +173,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
|
||||
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
version: "1.10.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -189,18 +189,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
|
||||
sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
version: "3.1.2"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d
|
||||
sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.6"
|
||||
version: "2.1.7"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -226,18 +226,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.11.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -266,10 +266,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.0"
|
||||
version: "0.6.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -290,18 +290,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: c620a6f783fa22436da68e42db7ebbf18b8c44b9a46ab911f666ff09ffd9153f
|
||||
sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.7.1"
|
||||
version: "11.10.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
|
||||
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.4-beta"
|
||||
version: "0.3.0"
|
||||
webdriver:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -311,5 +311,5 @@ packages:
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
sdks:
|
||||
dart: ">=3.1.0-185.0.dev <4.0.0"
|
||||
dart: ">=3.2.0-194.0.dev <4.0.0"
|
||||
flutter: ">=3.3.0"
|
||||
|
@ -17,7 +17,7 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
bluetooth_low_energy_platform_interface: ^4.0.0
|
||||
bluetooth_low_energy_platform_interface: ^5.0.0
|
||||
bluetooth_low_energy_darwin:
|
||||
# When depending on this package from a real application you should use:
|
||||
# bluetooth_low_energy: ^x.y.z
|
||||
@ -30,7 +30,7 @@ dependencies:
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.2
|
||||
convert: ^3.1.1
|
||||
intl: ^0.18.1
|
||||
intl: ^0.19.0
|
||||
logging: ^1.2.0
|
||||
|
||||
dev_dependencies:
|
||||
|
@ -1,11 +1,11 @@
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
|
||||
import 'src/my_central_manager_2.dart';
|
||||
import 'src/my_peripheral_manager_2.dart';
|
||||
import 'src/my_central_manager.dart';
|
||||
import 'src/my_peripheral_manager.dart';
|
||||
|
||||
abstract class BluetoothLowEnergyDarwin {
|
||||
static void registerWith() {
|
||||
MyCentralManager.instance = MyCentralManager2();
|
||||
MyPeripheralManager.instance = MyPeripheralManager2();
|
||||
CentralManager.instance = MyCentralManager();
|
||||
PeripheralManager.instance = MyPeripheralManager();
|
||||
}
|
||||
}
|
||||
|
@ -9,22 +9,51 @@ import 'my_gatt_service2.dart';
|
||||
|
||||
export 'my_api.g.dart';
|
||||
|
||||
// ToObject
|
||||
extension MyBluetoothLowEnergyStateArgsX on MyBluetoothLowEnergyStateArgs {
|
||||
BluetoothLowEnergyState toState() {
|
||||
return BluetoothLowEnergyState.values[index];
|
||||
switch (this) {
|
||||
case MyBluetoothLowEnergyStateArgs.unknown:
|
||||
case MyBluetoothLowEnergyStateArgs.resetting:
|
||||
return BluetoothLowEnergyState.unknown;
|
||||
case MyBluetoothLowEnergyStateArgs.unsupported:
|
||||
return BluetoothLowEnergyState.unsupported;
|
||||
case MyBluetoothLowEnergyStateArgs.unauthorized:
|
||||
return BluetoothLowEnergyState.unauthorized;
|
||||
case MyBluetoothLowEnergyStateArgs.poweredOff:
|
||||
return BluetoothLowEnergyState.poweredOff;
|
||||
case MyBluetoothLowEnergyStateArgs.poweredOn:
|
||||
return BluetoothLowEnergyState.poweredOn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattCharacteristicPropertyArgsX
|
||||
on MyGattCharacteristicPropertyArgs {
|
||||
GattCharacteristicProperty toProperty() {
|
||||
return GattCharacteristicProperty.values[index];
|
||||
}
|
||||
}
|
||||
|
||||
extension MyManufacturerSpecificDataArgsX on MyManufacturerSpecificDataArgs {
|
||||
ManufacturerSpecificData toManufacturerSpecificData() {
|
||||
final id = idArgs;
|
||||
final data = dataArgs;
|
||||
return ManufacturerSpecificData(
|
||||
id: id,
|
||||
data: data,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension MyAdvertisementArgsX on MyAdvertisementArgs {
|
||||
Advertisement toAdvertisement() {
|
||||
final name = nameArgs;
|
||||
final serviceUUIDs = serviceUUIDsArgs
|
||||
.cast<String>()
|
||||
.map((args) => UUID.fromString(args))
|
||||
.toList();
|
||||
final serviceUUIDs =
|
||||
serviceUUIDsArgs.cast<String>().map((args) => args.toUUID()).toList();
|
||||
final serviceData = serviceDataArgs.cast<String, Uint8List>().map(
|
||||
(uuidArgs, dataArgs) {
|
||||
final uuid = UUID.fromString(uuidArgs);
|
||||
final uuid = uuidArgs.toUUID();
|
||||
final data = dataArgs;
|
||||
return MapEntry(uuid, data);
|
||||
},
|
||||
@ -40,61 +69,40 @@ extension MyAdvertisementArgsX on MyAdvertisementArgs {
|
||||
}
|
||||
}
|
||||
|
||||
extension MyManufacturerSpecificDataArgsX on MyManufacturerSpecificDataArgs {
|
||||
ManufacturerSpecificData toManufacturerSpecificData() {
|
||||
final id = idArgs;
|
||||
final data = dataArgs;
|
||||
return ManufacturerSpecificData(
|
||||
id: id,
|
||||
data: data,
|
||||
extension MyCentralArgsX on MyCentralArgs {
|
||||
MyCentral toCentral() {
|
||||
final uuid = uuidArgs.toUUID();
|
||||
return MyCentral(
|
||||
uuid: uuid,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattCharacteristicPropertyArgsX
|
||||
on MyGattCharacteristicPropertyArgs {
|
||||
GattCharacteristicProperty toProperty() {
|
||||
return GattCharacteristicProperty.values[index];
|
||||
}
|
||||
}
|
||||
|
||||
extension GattCharacteristicWriteTypeX on GattCharacteristicWriteType {
|
||||
MyGattCharacteristicWriteTypeArgs toArgs() {
|
||||
return MyGattCharacteristicWriteTypeArgs.values[index];
|
||||
}
|
||||
}
|
||||
|
||||
extension MyPeripheralArgsX on MyPeripheralArgs {
|
||||
Peripheral toPeripheral() {
|
||||
final hashCode = hashCodeArgs;
|
||||
final uuid = UUID.fromString(uuidArgs);
|
||||
MyPeripheral toPeripheral() {
|
||||
final uuid = uuidArgs.toUUID();
|
||||
return MyPeripheral(
|
||||
hashCode: hashCode,
|
||||
uuid: uuid,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattServiceArgsX on MyGattServiceArgs {
|
||||
MyGattService2 toService2() {
|
||||
extension MyGattDescriptorArgsX on MyGattDescriptorArgs {
|
||||
MyGattDescriptor2 toDescriptor2(MyPeripheral peripheral) {
|
||||
final hashCode = hashCodeArgs;
|
||||
final uuid = UUID.fromString(uuidArgs);
|
||||
final characteristics = characteristicsArgs
|
||||
.cast<MyGattCharacteristicArgs>()
|
||||
.map((args) => args.toCharacteristic2())
|
||||
.toList();
|
||||
return MyGattService2(
|
||||
final uuid = uuidArgs.toUUID();
|
||||
return MyGattDescriptor2(
|
||||
peripheral: peripheral,
|
||||
hashCode: hashCode,
|
||||
uuid: uuid,
|
||||
characteristics: characteristics,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattCharacteristicArgsX on MyGattCharacteristicArgs {
|
||||
MyGattCharacteristic2 toCharacteristic2() {
|
||||
MyGattCharacteristic2 toCharacteristic2(MyPeripheral peripheral) {
|
||||
final hashCode = hashCodeArgs;
|
||||
final uuid = UUID.fromString(uuidArgs);
|
||||
final uuid = uuidArgs.toUUID();
|
||||
final properties = propertyNumbersArgs.cast<int>().map(
|
||||
(args) {
|
||||
final propertyArgs = MyGattCharacteristicPropertyArgs.values[args];
|
||||
@ -103,9 +111,10 @@ extension MyGattCharacteristicArgsX on MyGattCharacteristicArgs {
|
||||
).toList();
|
||||
final descriptors = descriptorsArgs
|
||||
.cast<MyGattDescriptorArgs>()
|
||||
.map((args) => args.toDescriptor2())
|
||||
.map((args) => args.toDescriptor2(peripheral))
|
||||
.toList();
|
||||
return MyGattCharacteristic2(
|
||||
peripheral: peripheral,
|
||||
hashCode: hashCode,
|
||||
uuid: uuid,
|
||||
properties: properties,
|
||||
@ -114,45 +123,39 @@ extension MyGattCharacteristicArgsX on MyGattCharacteristicArgs {
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattDescriptorArgsX on MyGattDescriptorArgs {
|
||||
MyGattDescriptor2 toDescriptor2() {
|
||||
extension MyGattServiceArgsX on MyGattServiceArgs {
|
||||
MyGattService2 toService2(MyPeripheral peripheral) {
|
||||
final hashCode = hashCodeArgs;
|
||||
final uuid = UUID.fromString(uuidArgs);
|
||||
return MyGattDescriptor2(
|
||||
final uuid = uuidArgs.toUUID();
|
||||
final characteristics = characteristicsArgs
|
||||
.cast<MyGattCharacteristicArgs>()
|
||||
.map((args) => args.toCharacteristic2(peripheral))
|
||||
.toList();
|
||||
return MyGattService2(
|
||||
peripheral: peripheral,
|
||||
hashCode: hashCode,
|
||||
uuid: uuid,
|
||||
characteristics: characteristics,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension MyCentralArgsX on MyCentralArgs {
|
||||
MyCentral toCentral() {
|
||||
final hashCode = hashCodeArgs;
|
||||
final uuid = UUID.fromString(uuidArgs);
|
||||
return MyCentral(
|
||||
hashCode: hashCode,
|
||||
uuid: uuid,
|
||||
);
|
||||
extension MyUuidArgsX on String {
|
||||
UUID toUUID() {
|
||||
return UUID.fromString(this);
|
||||
}
|
||||
}
|
||||
|
||||
extension AdvertisementX on Advertisement {
|
||||
MyAdvertisementArgs toArgs() {
|
||||
final nameArgs = name;
|
||||
final serviceUUIDsArgs =
|
||||
serviceUUIDs.map((uuid) => uuid.toString()).toList();
|
||||
final serviceDataArgs = serviceData.map((uuid, data) {
|
||||
final uuidArgs = uuid.toString();
|
||||
final dataArgs = data;
|
||||
return MapEntry(uuidArgs, dataArgs);
|
||||
});
|
||||
final manufacturerSpecificDataArgs = manufacturerSpecificData?.toArgs();
|
||||
return MyAdvertisementArgs(
|
||||
nameArgs: nameArgs,
|
||||
serviceUUIDsArgs: serviceUUIDsArgs,
|
||||
serviceDataArgs: serviceDataArgs,
|
||||
manufacturerSpecificDataArgs: manufacturerSpecificDataArgs,
|
||||
);
|
||||
// ToArgs
|
||||
extension GattCharacteristicPropertyX on GattCharacteristicProperty {
|
||||
MyGattCharacteristicPropertyArgs toArgs() {
|
||||
return MyGattCharacteristicPropertyArgs.values[index];
|
||||
}
|
||||
}
|
||||
|
||||
extension GattCharacteristicWriteTypeX on GattCharacteristicWriteType {
|
||||
MyGattCharacteristicWriteTypeArgs toArgs() {
|
||||
return MyGattCharacteristicWriteTypeArgs.values[index];
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,18 +170,34 @@ extension ManufacturerSpecificDataX on ManufacturerSpecificData {
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattServiceX on MyGattService {
|
||||
MyGattServiceArgs toArgs() {
|
||||
extension AdvertisementX on Advertisement {
|
||||
MyAdvertisementArgs toArgs() {
|
||||
final nameArgs = name;
|
||||
final serviceUUIDsArgs = serviceUUIDs.map((uuid) => uuid.toArgs()).toList();
|
||||
final serviceDataArgs = serviceData.map((uuid, data) {
|
||||
final uuidArgs = uuid.toArgs();
|
||||
final dataArgs = data;
|
||||
return MapEntry(uuidArgs, dataArgs);
|
||||
});
|
||||
final manufacturerSpecificDataArgs = manufacturerSpecificData?.toArgs();
|
||||
return MyAdvertisementArgs(
|
||||
nameArgs: nameArgs,
|
||||
serviceUUIDsArgs: serviceUUIDsArgs,
|
||||
serviceDataArgs: serviceDataArgs,
|
||||
manufacturerSpecificDataArgs: manufacturerSpecificDataArgs,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattDescriptorX on MyGattDescriptor {
|
||||
MyGattDescriptorArgs toArgs() {
|
||||
final hashCodeArgs = hashCode;
|
||||
final uuidArgs = uuid.toString();
|
||||
final characteristicsArgs = characteristics
|
||||
.cast<MyGattCharacteristic>()
|
||||
.map((characteristic) => characteristic.toArgs())
|
||||
.toList();
|
||||
return MyGattServiceArgs(
|
||||
final uuidArgs = uuid.toArgs();
|
||||
final valueArgs = value;
|
||||
return MyGattDescriptorArgs(
|
||||
hashCodeArgs: hashCodeArgs,
|
||||
uuidArgs: uuidArgs,
|
||||
characteristicsArgs: characteristicsArgs,
|
||||
valueArgs: valueArgs,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -186,7 +205,7 @@ extension MyGattServiceX on MyGattService {
|
||||
extension MyGattCharacteristicX on MyGattCharacteristic {
|
||||
MyGattCharacteristicArgs toArgs() {
|
||||
final hashCodeArgs = hashCode;
|
||||
final uuidArgs = uuid.toString();
|
||||
final uuidArgs = uuid.toArgs();
|
||||
final propertyNumbersArgs = properties.map((property) {
|
||||
final propertyArgs = property.toArgs();
|
||||
return propertyArgs.index;
|
||||
@ -204,21 +223,24 @@ extension MyGattCharacteristicX on MyGattCharacteristic {
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattDescriptorX on MyGattDescriptor {
|
||||
MyGattDescriptorArgs toArgs() {
|
||||
extension MyGattServiceX on MyGattService {
|
||||
MyGattServiceArgs toArgs() {
|
||||
final hashCodeArgs = hashCode;
|
||||
final uuidArgs = uuid.toString();
|
||||
final valueArgs = value;
|
||||
return MyGattDescriptorArgs(
|
||||
final uuidArgs = uuid.toArgs();
|
||||
final characteristicsArgs = characteristics
|
||||
.cast<MyGattCharacteristic>()
|
||||
.map((characteristic) => characteristic.toArgs())
|
||||
.toList();
|
||||
return MyGattServiceArgs(
|
||||
hashCodeArgs: hashCodeArgs,
|
||||
uuidArgs: uuidArgs,
|
||||
valueArgs: valueArgs,
|
||||
characteristicsArgs: characteristicsArgs,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension GattCharacteristicPropertyX on GattCharacteristicProperty {
|
||||
MyGattCharacteristicPropertyArgs toArgs() {
|
||||
return MyGattCharacteristicPropertyArgs.values[index];
|
||||
extension UuidX on UUID {
|
||||
String toArgs() {
|
||||
return toString().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
331
bluetooth_low_energy_darwin/lib/src/my_central_manager.dart
Normal file
331
bluetooth_low_energy_darwin/lib/src/my_central_manager.dart
Normal file
@ -0,0 +1,331 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'my_api.dart';
|
||||
import 'my_gatt_characteristic2.dart';
|
||||
import 'my_gatt_descriptor2.dart';
|
||||
|
||||
class MyCentralManager extends CentralManager
|
||||
implements MyCentralManagerFlutterApi {
|
||||
final MyCentralManagerHostApi _api;
|
||||
final StreamController<BluetoothLowEnergyStateChangedEventArgs>
|
||||
_stateChangedController;
|
||||
final StreamController<DiscoveredEventArgs> _discoveredController;
|
||||
final StreamController<ConnectionStateChangedEventArgs>
|
||||
_connectionStateChangedController;
|
||||
final StreamController<GattCharacteristicNotifiedEventArgs>
|
||||
_characteristicNotifiedController;
|
||||
final Map<String, MyPeripheral> _peripherals;
|
||||
final Map<String, Map<int, MyGattCharacteristic2>> _characteristics;
|
||||
|
||||
BluetoothLowEnergyState _state;
|
||||
|
||||
MyCentralManager()
|
||||
: _api = MyCentralManagerHostApi(),
|
||||
_stateChangedController = StreamController.broadcast(),
|
||||
_discoveredController = StreamController.broadcast(),
|
||||
_connectionStateChangedController = StreamController.broadcast(),
|
||||
_characteristicNotifiedController = StreamController.broadcast(),
|
||||
_peripherals = {},
|
||||
_characteristics = {},
|
||||
_state = BluetoothLowEnergyState.unknown;
|
||||
|
||||
@override
|
||||
Stream<BluetoothLowEnergyStateChangedEventArgs> get stateChanged =>
|
||||
_stateChangedController.stream;
|
||||
@override
|
||||
Stream<DiscoveredEventArgs> get discovered => _discoveredController.stream;
|
||||
@override
|
||||
Stream<ConnectionStateChangedEventArgs> get connectionStateChanged =>
|
||||
_connectionStateChangedController.stream;
|
||||
@override
|
||||
Stream<GattCharacteristicNotifiedEventArgs> get characteristicNotified =>
|
||||
_characteristicNotifiedController.stream;
|
||||
|
||||
@override
|
||||
Future<void> setUp() async {
|
||||
logger.info('setUp');
|
||||
await _api.setUp();
|
||||
MyCentralManagerFlutterApi.setup(this);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<BluetoothLowEnergyState> getState() {
|
||||
logger.info('getState');
|
||||
return Future.value(_state);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> startDiscovery() async {
|
||||
logger.info('startDiscovery');
|
||||
await _api.startDiscovery();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stopDiscovery() async {
|
||||
logger.info('stopDiscovery');
|
||||
await _api.stopDiscovery();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> connect(Peripheral peripheral) async {
|
||||
if (peripheral is! MyPeripheral) {
|
||||
throw TypeError();
|
||||
}
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
logger.info('connect: $uuidArgs');
|
||||
await _api.connect(uuidArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> disconnect(Peripheral peripheral) async {
|
||||
if (peripheral is! MyPeripheral) {
|
||||
throw TypeError();
|
||||
}
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
logger.info('disconnect: $uuidArgs');
|
||||
await _api.disconnect(uuidArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> readRSSI(Peripheral peripheral) async {
|
||||
if (peripheral is! MyPeripheral) {
|
||||
throw TypeError();
|
||||
}
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
logger.info('readRSSI: $uuidArgs');
|
||||
final rssi = await _api.readRSSI(uuidArgs);
|
||||
return rssi;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<GattService>> discoverGATT(Peripheral peripheral) async {
|
||||
if (peripheral is! MyPeripheral) {
|
||||
throw TypeError();
|
||||
}
|
||||
// 发现 GATT 服务
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
logger.info('discoverServices: $uuidArgs');
|
||||
final servicesArgs = await _api
|
||||
.discoverServices(uuidArgs)
|
||||
.then((args) => args.cast<MyGattServiceArgs>());
|
||||
for (var serviceArgs in servicesArgs) {
|
||||
// 发现 GATT 特征值
|
||||
final hashCodeArgs = serviceArgs.hashCodeArgs;
|
||||
logger.info('discoverCharacteristics: $uuidArgs.$hashCodeArgs');
|
||||
final characteristicsArgs = await _api
|
||||
.discoverCharacteristics(uuidArgs, hashCodeArgs)
|
||||
.then((args) => args.cast<MyGattCharacteristicArgs>());
|
||||
for (var characteristicArgs in characteristicsArgs) {
|
||||
// 发现 GATT 描述值
|
||||
final hashCodeArgs = characteristicArgs.hashCodeArgs;
|
||||
logger.info('discoverDescriptors: $uuidArgs.$hashCodeArgs');
|
||||
final descriptorsArgs = await _api
|
||||
.discoverDescriptors(uuidArgs, hashCodeArgs)
|
||||
.then((args) => args.cast<MyGattDescriptorArgs>());
|
||||
characteristicArgs.descriptorsArgs = descriptorsArgs;
|
||||
}
|
||||
serviceArgs.characteristicsArgs = characteristicsArgs;
|
||||
}
|
||||
final services =
|
||||
servicesArgs.map((args) => args.toService2(peripheral)).toList();
|
||||
final characteristics =
|
||||
services.expand((service) => service.characteristics).toList();
|
||||
_characteristics[uuidArgs] = {
|
||||
for (var characteristic in characteristics)
|
||||
characteristic.hashCode: characteristic
|
||||
};
|
||||
return services;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> readCharacteristic(
|
||||
GattCharacteristic characteristic,
|
||||
) async {
|
||||
if (characteristic is! MyGattCharacteristic2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final peripheral = characteristic.peripheral;
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
final hashCodeArgs = characteristic.hashCode;
|
||||
logger.info('readCharacteristic: $uuidArgs.$hashCodeArgs');
|
||||
final value = await _api.readCharacteristic(uuidArgs, hashCodeArgs);
|
||||
return value;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeCharacteristic(
|
||||
GattCharacteristic characteristic, {
|
||||
required Uint8List value,
|
||||
required GattCharacteristicWriteType type,
|
||||
}) async {
|
||||
if (characteristic is! MyGattCharacteristic2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final peripheral = characteristic.peripheral;
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
final hashCodeArgs = characteristic.hashCode;
|
||||
final trimmedValueArgs = value.trimGATT();
|
||||
final typeArgs = type.toArgs();
|
||||
final typeNumberArgs = typeArgs.index;
|
||||
final fragmentSize = await _api.getMaximumWriteValueLength(
|
||||
uuidArgs,
|
||||
typeNumberArgs,
|
||||
);
|
||||
var start = 0;
|
||||
while (start < trimmedValueArgs.length) {
|
||||
final end = start + fragmentSize;
|
||||
final fragmentedValueArgs = end < trimmedValueArgs.length
|
||||
? trimmedValueArgs.sublist(start, end)
|
||||
: trimmedValueArgs.sublist(start);
|
||||
logger.info(
|
||||
'writeCharacteristic: $uuidArgs.$hashCodeArgs - $fragmentedValueArgs, $typeArgs');
|
||||
await _api.writeCharacteristic(
|
||||
uuidArgs,
|
||||
hashCodeArgs,
|
||||
fragmentedValueArgs,
|
||||
typeNumberArgs,
|
||||
);
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setCharacteristicNotifyState(
|
||||
GattCharacteristic characteristic, {
|
||||
required bool state,
|
||||
}) async {
|
||||
if (characteristic is! MyGattCharacteristic2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final peripheral = characteristic.peripheral;
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
final hashCodeArgs = characteristic.hashCode;
|
||||
final stateArgs = state;
|
||||
logger.info(
|
||||
'setCharacteristicNotifyState: $uuidArgs.$hashCodeArgs - $stateArgs');
|
||||
await _api.setCharacteristicNotifyState(
|
||||
uuidArgs,
|
||||
hashCodeArgs,
|
||||
stateArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> readDescriptor(GattDescriptor descriptor) async {
|
||||
if (descriptor is! MyGattDescriptor2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final peripheral = descriptor.peripheral;
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
final hashCodeArgs = descriptor.hashCode;
|
||||
logger.info('readDescriptor: $uuidArgs.$hashCodeArgs');
|
||||
final value = await _api.readDescriptor(
|
||||
uuidArgs,
|
||||
hashCodeArgs,
|
||||
);
|
||||
return value;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeDescriptor(
|
||||
GattDescriptor descriptor, {
|
||||
required Uint8List value,
|
||||
}) async {
|
||||
if (descriptor is! MyGattDescriptor2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final peripheral = descriptor.peripheral;
|
||||
final uuidArgs = peripheral.uuid.toArgs();
|
||||
final hashCodeArgs = descriptor.hashCode;
|
||||
final trimmedValueArgs = value.trimGATT();
|
||||
logger.info('writeDescriptor: $uuidArgs.$hashCodeArgs - $trimmedValueArgs');
|
||||
await _api.writeDescriptor(uuidArgs, hashCodeArgs, trimmedValueArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onStateChanged(int stateNumberArgs) {
|
||||
final stateArgs = MyBluetoothLowEnergyStateArgs.values[stateNumberArgs];
|
||||
logger.info('onStateChanged: $stateArgs');
|
||||
final state = stateArgs.toState();
|
||||
if (_state == state) {
|
||||
return;
|
||||
}
|
||||
_state = state;
|
||||
final eventArgs = BluetoothLowEnergyStateChangedEventArgs(state);
|
||||
_stateChangedController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onDiscovered(
|
||||
MyPeripheralArgs peripheralArgs,
|
||||
int rssiArgs,
|
||||
MyAdvertisementArgs advertisementArgs,
|
||||
) {
|
||||
final uuidArgs = peripheralArgs.uuidArgs;
|
||||
logger.info('onDiscovered: $uuidArgs - $rssiArgs, $advertisementArgs');
|
||||
final peripheral = _peripherals.putIfAbsent(
|
||||
peripheralArgs.uuidArgs,
|
||||
() => peripheralArgs.toPeripheral(),
|
||||
);
|
||||
final rssi = rssiArgs;
|
||||
final advertisement = advertisementArgs.toAdvertisement();
|
||||
final eventArgs = DiscoveredEventArgs(
|
||||
peripheral,
|
||||
rssi,
|
||||
advertisement,
|
||||
);
|
||||
_discoveredController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onConnectionStateChanged(
|
||||
String uuidArgs,
|
||||
bool stateArgs,
|
||||
) {
|
||||
logger.info('onConnectionStateChanged: $uuidArgs - $stateArgs');
|
||||
final peripheral = _peripherals[uuidArgs];
|
||||
if (peripheral == null) {
|
||||
return;
|
||||
}
|
||||
final state = stateArgs;
|
||||
final eventArgs = ConnectionStateChangedEventArgs(peripheral, state);
|
||||
_connectionStateChangedController.add(eventArgs);
|
||||
if (!state) {
|
||||
_characteristics.remove(uuidArgs);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onCharacteristicNotified(
|
||||
String uuidArgs,
|
||||
int hashCodeArgs,
|
||||
Uint8List valueArgs,
|
||||
) {
|
||||
logger
|
||||
.info('onCharacteristicNotified: $uuidArgs.$hashCodeArgs - $valueArgs');
|
||||
final characteristic = _retrieveCharacteristic(uuidArgs, hashCodeArgs);
|
||||
if (characteristic == null) {
|
||||
return;
|
||||
}
|
||||
final value = valueArgs;
|
||||
final eventArgs = GattCharacteristicNotifiedEventArgs(
|
||||
characteristic,
|
||||
value,
|
||||
);
|
||||
_characteristicNotifiedController.add(eventArgs);
|
||||
}
|
||||
|
||||
MyGattCharacteristic2? _retrieveCharacteristic(
|
||||
String uuidArgs,
|
||||
int hashCodeArgs,
|
||||
) {
|
||||
final characteristics = _characteristics[uuidArgs];
|
||||
if (characteristics == null) {
|
||||
return null;
|
||||
}
|
||||
return characteristics[hashCodeArgs];
|
||||
}
|
||||
}
|
@ -1,297 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'my_api.dart';
|
||||
import 'my_gatt_characteristic2.dart';
|
||||
import 'my_gatt_descriptor2.dart';
|
||||
|
||||
class MyCentralManager2 extends MyCentralManager
|
||||
implements MyCentralManagerFlutterApi {
|
||||
final MyCentralManagerHostApi _api;
|
||||
BluetoothLowEnergyState _state;
|
||||
final StreamController<BluetoothLowEnergyStateChangedEventArgs>
|
||||
_stateChangedController;
|
||||
final StreamController<DiscoveredEventArgs> _discoveredController;
|
||||
final StreamController<PeripheralStateChangedEventArgs>
|
||||
_peripheralStateChangedController;
|
||||
final StreamController<GattCharacteristicValueChangedEventArgs>
|
||||
_characteristicValueChangedController;
|
||||
|
||||
MyCentralManager2()
|
||||
: _api = MyCentralManagerHostApi(),
|
||||
_state = BluetoothLowEnergyState.unknown,
|
||||
_stateChangedController = StreamController.broadcast(),
|
||||
_discoveredController = StreamController.broadcast(),
|
||||
_peripheralStateChangedController = StreamController.broadcast(),
|
||||
_characteristicValueChangedController = StreamController.broadcast();
|
||||
|
||||
@override
|
||||
BluetoothLowEnergyState get state => _state;
|
||||
@protected
|
||||
set state(BluetoothLowEnergyState value) {
|
||||
if (_state == value) {
|
||||
return;
|
||||
}
|
||||
_state = value;
|
||||
final eventArgs = BluetoothLowEnergyStateChangedEventArgs(state);
|
||||
_stateChangedController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<BluetoothLowEnergyStateChangedEventArgs> get stateChanged =>
|
||||
_stateChangedController.stream;
|
||||
@override
|
||||
Stream<DiscoveredEventArgs> get discovered => _discoveredController.stream;
|
||||
@override
|
||||
Stream<PeripheralStateChangedEventArgs> get peripheralStateChanged =>
|
||||
_peripheralStateChangedController.stream;
|
||||
@override
|
||||
Stream<GattCharacteristicValueChangedEventArgs>
|
||||
get characteristicValueChanged =>
|
||||
_characteristicValueChangedController.stream;
|
||||
|
||||
Future<void> _throwWithoutState(BluetoothLowEnergyState state) async {
|
||||
if (this.state != state) {
|
||||
throw StateError(
|
||||
'$state is expected, but current state is ${this.state}.');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setUp() async {
|
||||
final args = await _api.setUp();
|
||||
final stateArgs =
|
||||
MyBluetoothLowEnergyStateArgs.values[args.stateNumberArgs];
|
||||
state = stateArgs.toState();
|
||||
MyCentralManagerFlutterApi.setup(this);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> startDiscovery() async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
await _api.startDiscovery();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stopDiscovery() async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
await _api.stopDiscovery();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> connect(Peripheral peripheral) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
await _api.connect(peripheralHashCodeArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> disconnect(Peripheral peripheral) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
await _api.disconnect(peripheralHashCodeArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> getMaximumWriteLength(
|
||||
Peripheral peripheral, {
|
||||
required GattCharacteristicWriteType type,
|
||||
}) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
final typeArgs = type.toArgs();
|
||||
final typeNumberArgs = typeArgs.index;
|
||||
final maximumWriteLength = await _api.getMaximumWriteLength(
|
||||
peripheralHashCodeArgs,
|
||||
typeNumberArgs,
|
||||
);
|
||||
return maximumWriteLength;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> readRSSI(Peripheral peripheral) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
final rssi = await _api.readRSSI(peripheralHashCodeArgs);
|
||||
return rssi;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<GattService>> discoverGATT(Peripheral peripheral) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
if (peripheral is! MyPeripheral) {
|
||||
throw TypeError();
|
||||
}
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
final servicesArgs = await _api.discoverGATT(peripheralHashCodeArgs);
|
||||
final services = servicesArgs
|
||||
.cast<MyGattServiceArgs>()
|
||||
.map((args) => args.toService2())
|
||||
.toList();
|
||||
for (var service in services) {
|
||||
for (var charactersitic in service.characteristics) {
|
||||
for (var descriptor in charactersitic.descriptors) {
|
||||
descriptor.characteristic = charactersitic;
|
||||
}
|
||||
charactersitic.service = service;
|
||||
}
|
||||
service.peripheral = peripheral;
|
||||
}
|
||||
return services;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> readCharacteristic(
|
||||
GattCharacteristic characteristic,
|
||||
) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
if (characteristic is! MyGattCharacteristic2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final service = characteristic.service;
|
||||
final peripheral = service.peripheral;
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
final characteristicHashCodeArgs = characteristic.hashCode;
|
||||
final value = await _api.readCharacteristic(
|
||||
peripheralHashCodeArgs,
|
||||
characteristicHashCodeArgs,
|
||||
);
|
||||
return value;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeCharacteristic(
|
||||
GattCharacteristic characteristic, {
|
||||
required Uint8List value,
|
||||
required GattCharacteristicWriteType type,
|
||||
}) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
if (characteristic is! MyGattCharacteristic2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final service = characteristic.service;
|
||||
final peripheral = service.peripheral;
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
final characteristicHashCodeArgs = characteristic.hashCode;
|
||||
final valueArgs = value;
|
||||
final typeArgs = type.toArgs();
|
||||
final typeNumberArgs = typeArgs.index;
|
||||
await _api.writeCharacteristic(
|
||||
peripheralHashCodeArgs,
|
||||
characteristicHashCodeArgs,
|
||||
valueArgs,
|
||||
typeNumberArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> notifyCharacteristic(
|
||||
GattCharacteristic characteristic, {
|
||||
required bool state,
|
||||
}) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
if (characteristic is! MyGattCharacteristic2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final service = characteristic.service;
|
||||
final peripheral = service.peripheral;
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
final characteristicHashCodeArgs = characteristic.hashCode;
|
||||
final stateArgs = state;
|
||||
await _api.notifyCharacteristic(
|
||||
peripheralHashCodeArgs,
|
||||
characteristicHashCodeArgs,
|
||||
stateArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> readDescriptor(GattDescriptor descriptor) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
if (descriptor is! MyGattDescriptor2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final characteristic = descriptor.characteristic;
|
||||
final service = characteristic.service;
|
||||
final peripheral = service.peripheral;
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
final descriptorHashCodeArgs = descriptor.hashCode;
|
||||
final value = await _api.readDescriptor(
|
||||
peripheralHashCodeArgs,
|
||||
descriptorHashCodeArgs,
|
||||
);
|
||||
return value;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeDescriptor(
|
||||
GattDescriptor descriptor, {
|
||||
required Uint8List value,
|
||||
}) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
if (descriptor is! MyGattDescriptor2) {
|
||||
throw TypeError();
|
||||
}
|
||||
final characteristic = descriptor.characteristic;
|
||||
final service = characteristic.service;
|
||||
final peripheral = service.peripheral;
|
||||
final peripheralHashCodeArgs = peripheral.hashCode;
|
||||
final descriptorHashCodeArgs = descriptor.hashCode;
|
||||
final valueArgs = value;
|
||||
await _api.writeDescriptor(
|
||||
peripheralHashCodeArgs,
|
||||
descriptorHashCodeArgs,
|
||||
valueArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onStateChanged(int stateNumberArgs) {
|
||||
final stateArgs = MyBluetoothLowEnergyStateArgs.values[stateNumberArgs];
|
||||
state = stateArgs.toState();
|
||||
}
|
||||
|
||||
@override
|
||||
void onDiscovered(
|
||||
MyPeripheralArgs peripheralArgs,
|
||||
int rssiArgs,
|
||||
MyAdvertisementArgs advertisementArgs,
|
||||
) {
|
||||
final peripheral = peripheralArgs.toPeripheral();
|
||||
final rssi = rssiArgs;
|
||||
final advertisement = advertisementArgs.toAdvertisement();
|
||||
final eventArgs = DiscoveredEventArgs(
|
||||
peripheral,
|
||||
rssi,
|
||||
advertisement,
|
||||
);
|
||||
_discoveredController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onPeripheralStateChanged(
|
||||
MyPeripheralArgs peripheralArgs,
|
||||
bool stateArgs,
|
||||
) {
|
||||
final peripheral = peripheralArgs.toPeripheral();
|
||||
final state = stateArgs;
|
||||
final eventArgs = PeripheralStateChangedEventArgs(peripheral, state);
|
||||
_peripheralStateChangedController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onCharacteristicValueChanged(
|
||||
MyGattCharacteristicArgs characteristicArgs,
|
||||
Uint8List valueArgs,
|
||||
) {
|
||||
final characteristic = characteristicArgs.toCharacteristic2();
|
||||
final value = valueArgs;
|
||||
final eventArgs = GattCharacteristicValueChangedEventArgs(
|
||||
characteristic,
|
||||
value,
|
||||
);
|
||||
_characteristicValueChangedController.add(eventArgs);
|
||||
}
|
||||
}
|
@ -1,13 +1,15 @@
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
|
||||
import 'my_gatt_descriptor2.dart';
|
||||
import 'my_gatt_service2.dart';
|
||||
|
||||
class MyGattCharacteristic2 extends MyGattCharacteristic {
|
||||
late final MyGattService2 service;
|
||||
final MyPeripheral peripheral;
|
||||
@override
|
||||
final int hashCode;
|
||||
|
||||
MyGattCharacteristic2({
|
||||
super.hashCode,
|
||||
required this.peripheral,
|
||||
required this.hashCode,
|
||||
required super.uuid,
|
||||
required super.properties,
|
||||
required List<MyGattDescriptor2> descriptors,
|
||||
@ -16,4 +18,11 @@ class MyGattCharacteristic2 extends MyGattCharacteristic {
|
||||
@override
|
||||
List<MyGattDescriptor2> get descriptors =>
|
||||
super.descriptors.cast<MyGattDescriptor2>();
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is MyGattCharacteristic2 &&
|
||||
other.peripheral == peripheral &&
|
||||
other.hashCode == hashCode;
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,20 @@
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
|
||||
import 'my_gatt_characteristic2.dart';
|
||||
|
||||
class MyGattDescriptor2 extends MyGattDescriptor {
|
||||
late final MyGattCharacteristic2 characteristic;
|
||||
final MyPeripheral peripheral;
|
||||
@override
|
||||
final int hashCode;
|
||||
|
||||
MyGattDescriptor2({
|
||||
super.hashCode,
|
||||
required this.peripheral,
|
||||
required this.hashCode,
|
||||
required super.uuid,
|
||||
});
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is MyGattDescriptor2 &&
|
||||
other.peripheral == peripheral &&
|
||||
other.hashCode == hashCode;
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,13 @@ import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_pla
|
||||
import 'my_gatt_characteristic2.dart';
|
||||
|
||||
class MyGattService2 extends MyGattService {
|
||||
late final MyPeripheral peripheral;
|
||||
final MyPeripheral peripheral;
|
||||
@override
|
||||
final int hashCode;
|
||||
|
||||
MyGattService2({
|
||||
super.hashCode,
|
||||
required this.peripheral,
|
||||
required this.hashCode,
|
||||
required super.uuid,
|
||||
required List<MyGattCharacteristic2> characteristics,
|
||||
}) : super(characteristics: characteristics);
|
||||
@ -14,4 +17,11 @@ class MyGattService2 extends MyGattService {
|
||||
@override
|
||||
List<MyGattCharacteristic2> get characteristics =>
|
||||
super.characteristics.cast<MyGattCharacteristic2>();
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is MyGattService2 &&
|
||||
other.peripheral == peripheral &&
|
||||
other.hashCode == hashCode;
|
||||
}
|
||||
}
|
||||
|
315
bluetooth_low_energy_darwin/lib/src/my_peripheral_manager.dart
Normal file
315
bluetooth_low_energy_darwin/lib/src/my_peripheral_manager.dart
Normal file
@ -0,0 +1,315 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'my_api.dart';
|
||||
|
||||
class MyPeripheralManager extends PeripheralManager
|
||||
implements MyPeripheralManagerFlutterApi {
|
||||
final MyPeripheralManagerHostApi _api;
|
||||
final StreamController<BluetoothLowEnergyStateChangedEventArgs>
|
||||
_stateChangedController;
|
||||
final StreamController<GattCharacteristicReadEventArgs>
|
||||
_characteristicReadController;
|
||||
final StreamController<GattCharacteristicWrittenEventArgs>
|
||||
_characteristicWrittenController;
|
||||
final StreamController<GattCharacteristicNotifyStateChangedEventArgs>
|
||||
_characteristicNotifyStateChangedController;
|
||||
|
||||
final Map<int, Map<int, MyGattCharacteristic>> _characteristics;
|
||||
final Map<String, Map<int, bool>> _listeners;
|
||||
|
||||
BluetoothLowEnergyState _state;
|
||||
|
||||
MyPeripheralManager()
|
||||
: _api = MyPeripheralManagerHostApi(),
|
||||
_stateChangedController = StreamController.broadcast(),
|
||||
_characteristicReadController = StreamController.broadcast(),
|
||||
_characteristicWrittenController = StreamController.broadcast(),
|
||||
_characteristicNotifyStateChangedController =
|
||||
StreamController.broadcast(),
|
||||
_characteristics = {},
|
||||
_listeners = {},
|
||||
_state = BluetoothLowEnergyState.unknown;
|
||||
|
||||
@override
|
||||
Stream<BluetoothLowEnergyStateChangedEventArgs> get stateChanged =>
|
||||
_stateChangedController.stream;
|
||||
@override
|
||||
Stream<GattCharacteristicReadEventArgs> get characteristicRead =>
|
||||
_characteristicReadController.stream;
|
||||
@override
|
||||
Stream<GattCharacteristicWrittenEventArgs> get characteristicWritten =>
|
||||
_characteristicWrittenController.stream;
|
||||
@override
|
||||
Stream<GattCharacteristicNotifyStateChangedEventArgs>
|
||||
get characteristicNotifyStateChanged =>
|
||||
_characteristicNotifyStateChangedController.stream;
|
||||
|
||||
@override
|
||||
Future<void> setUp() async {
|
||||
logger.info('setUp');
|
||||
await _api.setUp();
|
||||
MyPeripheralManagerFlutterApi.setup(this);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<BluetoothLowEnergyState> getState() {
|
||||
logger.info('getState');
|
||||
return Future.value(_state);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> addService(GattService service) async {
|
||||
if (service is! MyGattService) {
|
||||
throw TypeError();
|
||||
}
|
||||
final serviceArgs = service.toArgs();
|
||||
final hashCodeArgs = serviceArgs.hashCodeArgs;
|
||||
logger.info('addService: $hashCodeArgs');
|
||||
await _api.addService(serviceArgs);
|
||||
_characteristics[hashCodeArgs] = {
|
||||
for (var characteristics in service.characteristics)
|
||||
characteristics.hashCode: characteristics
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> removeService(GattService service) async {
|
||||
final hashCodeArgs = service.hashCode;
|
||||
logger.info('removeService: $hashCodeArgs');
|
||||
await _api.removeService(hashCodeArgs);
|
||||
_characteristics.remove(hashCodeArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> clearServices() async {
|
||||
logger.info('clearServices');
|
||||
await _api.clearServices();
|
||||
_characteristics.clear();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> startAdvertising(Advertisement advertisement) async {
|
||||
final advertisementArgs = advertisement.toArgs();
|
||||
logger.info('startAdvertising: $advertisementArgs');
|
||||
await _api.startAdvertising(advertisementArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stopAdvertising() async {
|
||||
logger.info('stopAdvertising');
|
||||
await _api.stopAdvertising();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> readCharacteristic(GattCharacteristic characteristic) {
|
||||
if (characteristic is! MyGattCharacteristic) {
|
||||
throw TypeError();
|
||||
}
|
||||
final hashCodeArgs = characteristic.hashCode;
|
||||
logger.info('readCharacteristic: $hashCodeArgs');
|
||||
final value = characteristic.value;
|
||||
return Future.value(value);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeCharacteristic(
|
||||
GattCharacteristic characteristic, {
|
||||
required Uint8List value,
|
||||
Central? central,
|
||||
}) async {
|
||||
if (characteristic is! MyGattCharacteristic) {
|
||||
throw TypeError();
|
||||
}
|
||||
characteristic.value = value;
|
||||
if (central == null) {
|
||||
return;
|
||||
}
|
||||
if (central is! MyCentral) {
|
||||
throw TypeError();
|
||||
}
|
||||
final uuidArgs = central.uuid.toArgs();
|
||||
final hashCodeArgs = characteristic.hashCode;
|
||||
final listener = _retrieveListener(uuidArgs, hashCodeArgs);
|
||||
if (listener == null) {
|
||||
logger.warning('The central is not listening.');
|
||||
return;
|
||||
}
|
||||
final uuidsArgs = [uuidArgs];
|
||||
final trimmedValueArgs = characteristic.value;
|
||||
final fragmentSize = await _api.getMaximumUpdateValueLength(uuidArgs);
|
||||
var start = 0;
|
||||
while (start < trimmedValueArgs.length) {
|
||||
final end = start + fragmentSize;
|
||||
final fragmentedValueArgs = end < trimmedValueArgs.length
|
||||
? trimmedValueArgs.sublist(start, end)
|
||||
: trimmedValueArgs.sublist(start);
|
||||
logger.info(
|
||||
'notifyCharacteristicChanged: $hashCodeArgs - $fragmentedValueArgs, $uuidsArgs');
|
||||
await _api.updateCharacteristic(
|
||||
hashCodeArgs,
|
||||
fragmentedValueArgs,
|
||||
uuidsArgs,
|
||||
);
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onStateChanged(int stateNumberArgs) {
|
||||
final stateArgs = MyBluetoothLowEnergyStateArgs.values[stateNumberArgs];
|
||||
logger.info('onStateChanged: $stateArgs');
|
||||
final state = stateArgs.toState();
|
||||
if (_state == state) {
|
||||
return;
|
||||
}
|
||||
_state = state;
|
||||
final eventArgs = BluetoothLowEnergyStateChangedEventArgs(state);
|
||||
_stateChangedController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onCharacteristicReadRequest(
|
||||
MyCentralArgs centralArgs,
|
||||
int hashCodeArgs,
|
||||
int idArgs,
|
||||
int offsetArgs,
|
||||
) async {
|
||||
final uuidArgs = centralArgs.uuidArgs;
|
||||
logger.info(
|
||||
'onCharacteristicReadRequest: $uuidArgs.$hashCodeArgs - $idArgs, $offsetArgs');
|
||||
final central = centralArgs.toCentral();
|
||||
final characteristic = _retrieveCharacteristic(hashCodeArgs);
|
||||
if (characteristic == null) {
|
||||
return;
|
||||
}
|
||||
const errorArgs = MyGattErrorArgs.success;
|
||||
final offset = offsetArgs;
|
||||
final valueArgs = _onCharacteristicRead(central, characteristic, offset);
|
||||
await _tryRespond(
|
||||
idArgs,
|
||||
errorArgs,
|
||||
valueArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onCharacteristicWriteRequest(
|
||||
MyCentralArgs centralArgs,
|
||||
int hashCodeArgs,
|
||||
int idArgs,
|
||||
int offsetArgs,
|
||||
Uint8List valueArgs,
|
||||
) async {
|
||||
final uuidArgs = centralArgs.uuidArgs;
|
||||
logger.info(
|
||||
'onCharacteristicWriteRequest: $uuidArgs.$hashCodeArgs - $idArgs, $offsetArgs, $valueArgs');
|
||||
final central = centralArgs.toCentral();
|
||||
final characteristic = _retrieveCharacteristic(hashCodeArgs);
|
||||
if (characteristic == null) {
|
||||
return;
|
||||
}
|
||||
const errorArgs = MyGattErrorArgs.success;
|
||||
final value = valueArgs;
|
||||
_onCharacteristicWritten(central, characteristic, value);
|
||||
await _tryRespond(
|
||||
idArgs,
|
||||
errorArgs,
|
||||
null,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onCharacteristicNotifyStateChanged(
|
||||
MyCentralArgs centralArgs,
|
||||
int hashCodeArgs,
|
||||
bool stateArgs,
|
||||
) {
|
||||
final uuidArgs = centralArgs.uuidArgs;
|
||||
logger.info(
|
||||
'onCharacteristicNotifyStateChanged: $uuidArgs.$hashCodeArgs - $stateArgs');
|
||||
final central = centralArgs.toCentral();
|
||||
final characteristic = _retrieveCharacteristic(hashCodeArgs);
|
||||
if (characteristic == null) {
|
||||
return;
|
||||
}
|
||||
final state = stateArgs;
|
||||
final listeners = _listeners.putIfAbsent(uuidArgs, () => {});
|
||||
if (state) {
|
||||
listeners[hashCodeArgs] = true;
|
||||
} else {
|
||||
listeners.remove(hashCodeArgs);
|
||||
}
|
||||
final eventArgs = GattCharacteristicNotifyStateChangedEventArgs(
|
||||
central,
|
||||
characteristic,
|
||||
state,
|
||||
);
|
||||
_characteristicNotifyStateChangedController.add(eventArgs);
|
||||
}
|
||||
|
||||
MyGattCharacteristic? _retrieveCharacteristic(int hashCodeArgs) {
|
||||
final characteristics = _characteristics.values
|
||||
.reduce((value, element) => value..addAll(element));
|
||||
return characteristics[hashCodeArgs];
|
||||
}
|
||||
|
||||
bool? _retrieveListener(String uuidArgs, int hashCodeArgs) {
|
||||
final listeners = _listeners[uuidArgs];
|
||||
if (listeners == null) {
|
||||
return null;
|
||||
}
|
||||
return listeners[hashCodeArgs];
|
||||
}
|
||||
|
||||
Future<void> _tryRespond(
|
||||
int idArgs,
|
||||
MyGattErrorArgs errorArgs,
|
||||
Uint8List? valueArgs,
|
||||
) async {
|
||||
final errorNumberArgs = errorArgs.index;
|
||||
try {
|
||||
_api.respond(
|
||||
idArgs,
|
||||
errorNumberArgs,
|
||||
valueArgs,
|
||||
);
|
||||
} catch (e, stack) {
|
||||
logger.shout('Respond failed.', e, stack);
|
||||
}
|
||||
}
|
||||
|
||||
Uint8List _onCharacteristicRead(
|
||||
MyCentral central,
|
||||
MyGattCharacteristic characteristic,
|
||||
int offset,
|
||||
) {
|
||||
final value = characteristic.value;
|
||||
final trimmedValue = value.sublist(offset);
|
||||
if (offset == 0) {
|
||||
final eventArgs = GattCharacteristicReadEventArgs(
|
||||
central,
|
||||
characteristic,
|
||||
value,
|
||||
);
|
||||
_characteristicReadController.add(eventArgs);
|
||||
}
|
||||
return trimmedValue;
|
||||
}
|
||||
|
||||
void _onCharacteristicWritten(
|
||||
MyCentral central,
|
||||
MyGattCharacteristic characteristic,
|
||||
Uint8List value,
|
||||
) async {
|
||||
final trimmedValue = value.trimGATT();
|
||||
final eventArgs = GattCharacteristicWrittenEventArgs(
|
||||
central,
|
||||
characteristic,
|
||||
trimmedValue,
|
||||
);
|
||||
_characteristicWrittenController.add(eventArgs);
|
||||
}
|
||||
}
|
@ -1,252 +0,0 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'my_api.dart';
|
||||
|
||||
class MyPeripheralManager2 extends MyPeripheralManager
|
||||
implements MyPeripheralManagerFlutterApi {
|
||||
final MyPeripheralManagerHostApi _api;
|
||||
BluetoothLowEnergyState _state;
|
||||
final StreamController<BluetoothLowEnergyStateChangedEventArgs>
|
||||
_stateChangedController;
|
||||
final StreamController<ReadGattCharacteristicCommandEventArgs>
|
||||
_readCharacteristicCommandReceivedController;
|
||||
final StreamController<WriteGattCharacteristicCommandEventArgs>
|
||||
_writeCharacteristicCommandReceivedController;
|
||||
final StreamController<NotifyGattCharacteristicCommandEventArgs>
|
||||
_notifyCharacteristicCommandReceivedController;
|
||||
|
||||
MyPeripheralManager2()
|
||||
: _api = MyPeripheralManagerHostApi(),
|
||||
_state = BluetoothLowEnergyState.unknown,
|
||||
_stateChangedController = StreamController.broadcast(),
|
||||
_readCharacteristicCommandReceivedController =
|
||||
StreamController.broadcast(),
|
||||
_writeCharacteristicCommandReceivedController =
|
||||
StreamController.broadcast(),
|
||||
_notifyCharacteristicCommandReceivedController =
|
||||
StreamController.broadcast();
|
||||
|
||||
@override
|
||||
BluetoothLowEnergyState get state => _state;
|
||||
@protected
|
||||
set state(BluetoothLowEnergyState value) {
|
||||
if (_state == value) {
|
||||
return;
|
||||
}
|
||||
_state = value;
|
||||
final eventArgs = BluetoothLowEnergyStateChangedEventArgs(state);
|
||||
_stateChangedController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<BluetoothLowEnergyStateChangedEventArgs> get stateChanged =>
|
||||
_stateChangedController.stream;
|
||||
@override
|
||||
Stream<ReadGattCharacteristicCommandEventArgs>
|
||||
get readCharacteristicCommandReceived =>
|
||||
_readCharacteristicCommandReceivedController.stream;
|
||||
@override
|
||||
Stream<WriteGattCharacteristicCommandEventArgs>
|
||||
get writeCharacteristicCommandReceived =>
|
||||
_writeCharacteristicCommandReceivedController.stream;
|
||||
@override
|
||||
Stream<NotifyGattCharacteristicCommandEventArgs>
|
||||
get notifyCharacteristicCommandReceived =>
|
||||
_notifyCharacteristicCommandReceivedController.stream;
|
||||
|
||||
Future<void> _throwWithoutState(BluetoothLowEnergyState state) async {
|
||||
if (this.state != state) {
|
||||
throw StateError(
|
||||
'$state is expected, but current state is ${this.state}.');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setUp() async {
|
||||
final args = await _api.setUp();
|
||||
final stateArgs =
|
||||
MyBluetoothLowEnergyStateArgs.values[args.stateNumberArgs];
|
||||
state = stateArgs.toState();
|
||||
MyPeripheralManagerFlutterApi.setup(this);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> addService(GattService service) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
if (service is! MyGattService) {
|
||||
throw TypeError();
|
||||
}
|
||||
final serviceArgs = service.toArgs();
|
||||
await _api.addService(serviceArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> removeService(GattService service) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final serviceHashCodeArgs = service.hashCode;
|
||||
await _api.removeService(serviceHashCodeArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> clearServices() async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
await _api.clearServices();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> startAdvertising(Advertisement advertisement) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final advertisementArgs = advertisement.toArgs();
|
||||
await _api.startAdvertising(advertisementArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stopAdvertising() async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
await _api.stopAdvertising();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int> getMaximumWriteLength(Central central) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final centralHashCodeArgs = central.hashCode;
|
||||
final maximumWriteLength =
|
||||
await _api.getMaximumWriteLength(centralHashCodeArgs);
|
||||
return maximumWriteLength;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> sendReadCharacteristicReply(
|
||||
Central central, {
|
||||
required GattCharacteristic characteristic,
|
||||
required int id,
|
||||
required int offset,
|
||||
required bool status,
|
||||
required Uint8List value,
|
||||
}) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final centralHashCodeArgs = central.hashCode;
|
||||
final characteristicHashCodeArgs = characteristic.hashCode;
|
||||
final idArgs = id;
|
||||
final offsetArgs = offset;
|
||||
final statusArgs = status;
|
||||
final valueArgs = value;
|
||||
await _api.sendReadCharacteristicReply(
|
||||
centralHashCodeArgs,
|
||||
characteristicHashCodeArgs,
|
||||
idArgs,
|
||||
offsetArgs,
|
||||
statusArgs,
|
||||
valueArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> sendWriteCharacteristicReply(
|
||||
Central central, {
|
||||
required GattCharacteristic characteristic,
|
||||
required int id,
|
||||
required int offset,
|
||||
required bool status,
|
||||
}) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final centralHashCodeArgs = central.hashCode;
|
||||
final characteristicHashCodeArgs = characteristic.hashCode;
|
||||
final idArgs = id;
|
||||
final offsetArgs = offset;
|
||||
final statusArgs = status;
|
||||
await _api.sendWriteCharacteristicReply(
|
||||
centralHashCodeArgs,
|
||||
characteristicHashCodeArgs,
|
||||
idArgs,
|
||||
offsetArgs,
|
||||
statusArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> notifyCharacteristicValueChanged(
|
||||
Central central, {
|
||||
required GattCharacteristic characteristic,
|
||||
required Uint8List value,
|
||||
}) async {
|
||||
await _throwWithoutState(BluetoothLowEnergyState.poweredOn);
|
||||
final centralHashCodeArgs = central.hashCode;
|
||||
final characteristicHashCodeArgs = characteristic.hashCode;
|
||||
final valueArgs = value;
|
||||
await _api.notifyCharacteristicValueChanged(
|
||||
centralHashCodeArgs,
|
||||
characteristicHashCodeArgs,
|
||||
valueArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onStateChanged(int stateNumberArgs) {
|
||||
final stateArgs = MyBluetoothLowEnergyStateArgs.values[stateNumberArgs];
|
||||
state = stateArgs.toState();
|
||||
}
|
||||
|
||||
@override
|
||||
void onReadCharacteristicCommandReceived(
|
||||
MyCentralArgs centralArgs,
|
||||
MyGattCharacteristicArgs characteristicArgs,
|
||||
int idArgs,
|
||||
int offsetArgs,
|
||||
) {
|
||||
final central = centralArgs.toCentral();
|
||||
final characteristic = characteristicArgs.toCharacteristic2();
|
||||
final id = idArgs;
|
||||
final offset = offsetArgs;
|
||||
final eventArgs = ReadGattCharacteristicCommandEventArgs(
|
||||
central,
|
||||
characteristic,
|
||||
id,
|
||||
offset,
|
||||
);
|
||||
_readCharacteristicCommandReceivedController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onWriteCharacteristicCommandReceived(
|
||||
MyCentralArgs centralArgs,
|
||||
MyGattCharacteristicArgs characteristicArgs,
|
||||
int idArgs,
|
||||
int offsetArgs,
|
||||
Uint8List valueArgs,
|
||||
) {
|
||||
final central = centralArgs.toCentral();
|
||||
final characteristic = characteristicArgs.toCharacteristic2();
|
||||
final id = idArgs;
|
||||
final offset = offsetArgs;
|
||||
final value = valueArgs;
|
||||
final eventArgs = WriteGattCharacteristicCommandEventArgs(
|
||||
central,
|
||||
characteristic,
|
||||
id,
|
||||
offset,
|
||||
value,
|
||||
);
|
||||
_writeCharacteristicCommandReceivedController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onNotifyCharacteristicCommandReceived(
|
||||
MyCentralArgs centralArgs,
|
||||
MyGattCharacteristicArgs characteristicArgs,
|
||||
bool stateArgs,
|
||||
) {
|
||||
final central = centralArgs.toCentral();
|
||||
final characteristic = characteristicArgs.toCharacteristic2();
|
||||
final state = stateArgs;
|
||||
final eventArgs = NotifyGattCharacteristicCommandEventArgs(
|
||||
central,
|
||||
characteristic,
|
||||
state,
|
||||
);
|
||||
_notifyCharacteristicCommandReceivedController.add(eventArgs);
|
||||
}
|
||||
}
|
@ -8,152 +8,54 @@ import 'package:pigeon/pigeon.dart';
|
||||
swiftOptions: SwiftOptions(),
|
||||
),
|
||||
)
|
||||
@HostApi()
|
||||
abstract class MyCentralManagerHostApi {
|
||||
@async
|
||||
MyCentralManagerArgs setUp();
|
||||
void startDiscovery();
|
||||
void stopDiscovery();
|
||||
@async
|
||||
void connect(int peripheralHashCodeArgs);
|
||||
@async
|
||||
void disconnect(int peripheralHashCodeArgs);
|
||||
int getMaximumWriteLength(int peripheralHashCodeArgs, int typeNumberArgs);
|
||||
@async
|
||||
int readRSSI(int peripheralHashCodeArgs);
|
||||
@async
|
||||
List<MyGattServiceArgs> discoverGATT(int peripheralHashCodeArgs);
|
||||
@async
|
||||
Uint8List readCharacteristic(
|
||||
int peripheralHashCodeArgs,
|
||||
int characteristicHashCodeArgs,
|
||||
);
|
||||
@async
|
||||
void writeCharacteristic(
|
||||
int peripheralHashCodeArgs,
|
||||
int characteristicHashCodeArgs,
|
||||
Uint8List valueArgs,
|
||||
int typeNumberArgs,
|
||||
);
|
||||
@async
|
||||
void notifyCharacteristic(
|
||||
int peripheralHashCodeArgs,
|
||||
int characteristicHashCodeArgs,
|
||||
bool stateArgs,
|
||||
);
|
||||
@async
|
||||
Uint8List readDescriptor(
|
||||
int peripheralHashCodeArgs,
|
||||
int descriptorHashCodeArgs,
|
||||
);
|
||||
@async
|
||||
void writeDescriptor(
|
||||
int peripheralHashCodeArgs,
|
||||
int descriptorHashCodeArgs,
|
||||
Uint8List valueArgs,
|
||||
);
|
||||
enum MyBluetoothLowEnergyStateArgs {
|
||||
unknown,
|
||||
resetting,
|
||||
unsupported,
|
||||
unauthorized,
|
||||
poweredOff,
|
||||
poweredOn,
|
||||
}
|
||||
|
||||
@FlutterApi()
|
||||
abstract class MyCentralManagerFlutterApi {
|
||||
void onStateChanged(int stateNumberArgs);
|
||||
void onDiscovered(
|
||||
MyPeripheralArgs peripheralArgs,
|
||||
int rssiArgs,
|
||||
MyAdvertisementArgs advertisementArgs,
|
||||
);
|
||||
void onPeripheralStateChanged(
|
||||
MyPeripheralArgs peripheralArgs,
|
||||
bool stateArgs,
|
||||
);
|
||||
void onCharacteristicValueChanged(
|
||||
MyGattCharacteristicArgs characteristicArgs,
|
||||
Uint8List valueArgs,
|
||||
);
|
||||
enum MyGattCharacteristicPropertyArgs {
|
||||
read,
|
||||
write,
|
||||
writeWithoutResponse,
|
||||
notify,
|
||||
indicate,
|
||||
}
|
||||
|
||||
@HostApi()
|
||||
abstract class MyPeripheralManagerHostApi {
|
||||
@async
|
||||
MyPeripheralManagerArgs setUp();
|
||||
@async
|
||||
void addService(MyGattServiceArgs serviceArgs);
|
||||
void removeService(int serviceHashCodeArgs);
|
||||
void clearServices();
|
||||
@async
|
||||
void startAdvertising(MyAdvertisementArgs advertisementArgs);
|
||||
void stopAdvertising();
|
||||
int getMaximumWriteLength(int centralHashCodeArgs);
|
||||
void sendReadCharacteristicReply(
|
||||
int centralHashCodeArgs,
|
||||
int characteristicHashCodeArgs,
|
||||
int idArgs,
|
||||
int offsetArgs,
|
||||
bool statusArgs,
|
||||
Uint8List valueArgs,
|
||||
);
|
||||
void sendWriteCharacteristicReply(
|
||||
int centralHashCodeArgs,
|
||||
int characteristicHashCodeArgs,
|
||||
int idArgs,
|
||||
int offsetArgs,
|
||||
bool statusArgs,
|
||||
);
|
||||
@async
|
||||
void notifyCharacteristicValueChanged(
|
||||
int centralHashCodeArgs,
|
||||
int characteristicHashCodeArgs,
|
||||
Uint8List valueArgs,
|
||||
);
|
||||
enum MyGattCharacteristicWriteTypeArgs {
|
||||
withResponse,
|
||||
withoutResponse,
|
||||
}
|
||||
|
||||
@FlutterApi()
|
||||
abstract class MyPeripheralManagerFlutterApi {
|
||||
void onStateChanged(int stateNumberArgs);
|
||||
void onReadCharacteristicCommandReceived(
|
||||
MyCentralArgs centralArgs,
|
||||
MyGattCharacteristicArgs characteristicArgs,
|
||||
int idArgs,
|
||||
int offsetArgs,
|
||||
);
|
||||
void onWriteCharacteristicCommandReceived(
|
||||
MyCentralArgs centralArgs,
|
||||
MyGattCharacteristicArgs characteristicArgs,
|
||||
int idArgs,
|
||||
int offsetArgs,
|
||||
Uint8List valueArgs,
|
||||
);
|
||||
void onNotifyCharacteristicCommandReceived(
|
||||
MyCentralArgs centralArgs,
|
||||
MyGattCharacteristicArgs characteristicArgs,
|
||||
bool stateArgs,
|
||||
);
|
||||
enum MyGattErrorArgs {
|
||||
success,
|
||||
invalidHandle,
|
||||
readNotPermitted,
|
||||
writeNotPermitted,
|
||||
invalidPDU,
|
||||
insufficientAuthentication,
|
||||
requestNotSupported,
|
||||
invalidOffset,
|
||||
insufficientAuthorization,
|
||||
prepareQueueFull,
|
||||
attributeNotFound,
|
||||
attributeNotLong,
|
||||
insufficientEncryptionKeySize,
|
||||
invalidAttributeValueLength,
|
||||
unlikelyError,
|
||||
insufficientEncryption,
|
||||
unsupportedGroupType,
|
||||
insufficientResources,
|
||||
}
|
||||
|
||||
class MyCentralManagerArgs {
|
||||
final int stateNumberArgs;
|
||||
class MyManufacturerSpecificDataArgs {
|
||||
final int idArgs;
|
||||
final Uint8List dataArgs;
|
||||
|
||||
MyCentralManagerArgs(this.stateNumberArgs);
|
||||
}
|
||||
|
||||
class MyPeripheralManagerArgs {
|
||||
final int stateNumberArgs;
|
||||
|
||||
MyPeripheralManagerArgs(this.stateNumberArgs);
|
||||
}
|
||||
|
||||
class MyCentralArgs {
|
||||
final int hashCodeArgs;
|
||||
final String uuidArgs;
|
||||
|
||||
MyCentralArgs(this.hashCodeArgs, this.uuidArgs);
|
||||
}
|
||||
|
||||
class MyPeripheralArgs {
|
||||
final int hashCodeArgs;
|
||||
final String uuidArgs;
|
||||
|
||||
MyPeripheralArgs(this.hashCodeArgs, this.uuidArgs);
|
||||
MyManufacturerSpecificDataArgs(this.idArgs, this.dataArgs);
|
||||
}
|
||||
|
||||
class MyAdvertisementArgs {
|
||||
@ -170,22 +72,27 @@ class MyAdvertisementArgs {
|
||||
);
|
||||
}
|
||||
|
||||
class MyManufacturerSpecificDataArgs {
|
||||
final int idArgs;
|
||||
final Uint8List dataArgs;
|
||||
class MyCentralArgs {
|
||||
final String uuidArgs;
|
||||
|
||||
MyManufacturerSpecificDataArgs(this.idArgs, this.dataArgs);
|
||||
MyCentralArgs(this.uuidArgs);
|
||||
}
|
||||
|
||||
class MyGattServiceArgs {
|
||||
class MyPeripheralArgs {
|
||||
final String uuidArgs;
|
||||
|
||||
MyPeripheralArgs(this.uuidArgs);
|
||||
}
|
||||
|
||||
class MyGattDescriptorArgs {
|
||||
final int hashCodeArgs;
|
||||
final String uuidArgs;
|
||||
final List<MyGattCharacteristicArgs?> characteristicsArgs;
|
||||
final Uint8List? valueArgs;
|
||||
|
||||
MyGattServiceArgs(
|
||||
MyGattDescriptorArgs(
|
||||
this.hashCodeArgs,
|
||||
this.uuidArgs,
|
||||
this.characteristicsArgs,
|
||||
this.valueArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@ -203,39 +110,118 @@ class MyGattCharacteristicArgs {
|
||||
);
|
||||
}
|
||||
|
||||
class MyGattDescriptorArgs {
|
||||
class MyGattServiceArgs {
|
||||
final int hashCodeArgs;
|
||||
final String uuidArgs;
|
||||
final Uint8List? valueArgs;
|
||||
final List<MyGattCharacteristicArgs?> characteristicsArgs;
|
||||
|
||||
MyGattDescriptorArgs(
|
||||
MyGattServiceArgs(
|
||||
this.hashCodeArgs,
|
||||
this.uuidArgs,
|
||||
this.valueArgs,
|
||||
this.characteristicsArgs,
|
||||
);
|
||||
}
|
||||
|
||||
enum MyBluetoothLowEnergyStateArgs {
|
||||
unknown,
|
||||
unsupported,
|
||||
unauthorized,
|
||||
poweredOff,
|
||||
poweredOn,
|
||||
@HostApi()
|
||||
abstract class MyCentralManagerHostApi {
|
||||
void setUp();
|
||||
void startDiscovery();
|
||||
void stopDiscovery();
|
||||
@async
|
||||
void connect(String uuidArgs);
|
||||
@async
|
||||
void disconnect(String uuidArgs);
|
||||
int getMaximumWriteValueLength(String uuidArgs, int typeNumberArgs);
|
||||
@async
|
||||
int readRSSI(String uuidArgs);
|
||||
@async
|
||||
List<MyGattServiceArgs> discoverServices(String uuidArgs);
|
||||
@async
|
||||
List<MyGattCharacteristicArgs> discoverCharacteristics(
|
||||
String uuidArgs,
|
||||
int hashCodeArgs,
|
||||
);
|
||||
@async
|
||||
List<MyGattDescriptorArgs> discoverDescriptors(
|
||||
String uuidArgs,
|
||||
int hashCodeArgs,
|
||||
);
|
||||
@async
|
||||
Uint8List readCharacteristic(String uuidArgs, int hashCodeArgs);
|
||||
@async
|
||||
void writeCharacteristic(
|
||||
String uuidArgs,
|
||||
int hashCodeArgs,
|
||||
Uint8List valueArgs,
|
||||
int typeNumberArgs,
|
||||
);
|
||||
@async
|
||||
void setCharacteristicNotifyState(
|
||||
String uuidArgs,
|
||||
int hashCodeArgs,
|
||||
bool stateArgs,
|
||||
);
|
||||
@async
|
||||
Uint8List readDescriptor(String uuidArgs, int hashCodeArgs);
|
||||
@async
|
||||
void writeDescriptor(String uuidArgs, int hashCodeArgs, Uint8List valueArgs);
|
||||
}
|
||||
|
||||
enum MyGattCharacteristicPropertyArgs {
|
||||
read,
|
||||
write,
|
||||
writeWithoutResponse,
|
||||
notify,
|
||||
indicate,
|
||||
@FlutterApi()
|
||||
abstract class MyCentralManagerFlutterApi {
|
||||
void onStateChanged(int stateNumberArgs);
|
||||
void onDiscovered(
|
||||
MyPeripheralArgs peripheralArgs,
|
||||
int rssiArgs,
|
||||
MyAdvertisementArgs advertisementArgs,
|
||||
);
|
||||
void onConnectionStateChanged(String uuidArgs, bool stateArgs);
|
||||
void onCharacteristicNotified(
|
||||
String uuidArgs,
|
||||
int hashCodeArgs,
|
||||
Uint8List valueArgs,
|
||||
);
|
||||
}
|
||||
|
||||
enum MyGattCharacteristicWriteTypeArgs {
|
||||
// Write with response
|
||||
withResponse,
|
||||
// Write without response
|
||||
withoutResponse,
|
||||
// Write with response and waiting for confirmation
|
||||
// reliable,
|
||||
@HostApi()
|
||||
abstract class MyPeripheralManagerHostApi {
|
||||
void setUp();
|
||||
@async
|
||||
void addService(MyGattServiceArgs serviceArgs);
|
||||
void removeService(int hashCodeArgs);
|
||||
void clearServices();
|
||||
@async
|
||||
void startAdvertising(MyAdvertisementArgs advertisementArgs);
|
||||
void stopAdvertising();
|
||||
int getMaximumUpdateValueLength(String uuidArgs);
|
||||
void respond(int idArgs, int errorNumberArgs, Uint8List? valueArgs);
|
||||
@async
|
||||
void updateCharacteristic(
|
||||
int hashCodeArgs,
|
||||
Uint8List valueArgs,
|
||||
List<String>? uuidsArgs,
|
||||
);
|
||||
}
|
||||
|
||||
@FlutterApi()
|
||||
abstract class MyPeripheralManagerFlutterApi {
|
||||
void onStateChanged(int stateNumberArgs);
|
||||
void onCharacteristicReadRequest(
|
||||
MyCentralArgs centralArgs,
|
||||
int hashCodeArgs,
|
||||
int idArgs,
|
||||
int offsetArgs,
|
||||
);
|
||||
void onCharacteristicWriteRequest(
|
||||
MyCentralArgs centralArgs,
|
||||
int hashCodeArgs,
|
||||
int idArgs,
|
||||
int offsetArgs,
|
||||
Uint8List valueArgs,
|
||||
);
|
||||
void onCharacteristicNotifyStateChanged(
|
||||
MyCentralArgs centralArgs,
|
||||
int hashCodeArgs,
|
||||
bool stateArgs,
|
||||
);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
name: bluetooth_low_energy_darwin
|
||||
description: iOS and macOS implementation of the bluetooth_low_energy plugin.
|
||||
version: 4.0.0
|
||||
version: 5.0.0
|
||||
homepage: https://github.com/yanshouwang/bluetooth_low_energy
|
||||
|
||||
environment:
|
||||
@ -10,13 +10,13 @@ environment:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
bluetooth_low_energy_platform_interface: ^4.0.0
|
||||
bluetooth_low_energy_platform_interface: ^5.0.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^3.0.0
|
||||
pigeon: ^12.0.1
|
||||
pigeon: ^15.0.2
|
||||
|
||||
flutter:
|
||||
plugin:
|
||||
|
Reference in New Issue
Block a user