2.0.2 (#11)
* fix: 重构 * fix: 1 * fix: 重构 * fix: 修复 iOS 和 macOS 代码错误 * fix: 优化项目 * fix: 构建项目 * fix: 修复权限问题 * fix: 解决 macOS 沙盒权限问题 * fix: 修复代码问题 * fix: 更新依赖 * fix: 更新依赖项 * fix: 添加缺失的位置权限
This commit is contained in:
30
bluetooth_low_energy_darwin/.gitignore
vendored
Normal file
30
bluetooth_low_energy_darwin/.gitignore
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||
/pubspec.lock
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
.packages
|
||||
build/
|
33
bluetooth_low_energy_darwin/.metadata
Normal file
33
bluetooth_low_energy_darwin/.metadata
Normal file
@ -0,0 +1,33 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "efbf63d9c66b9f6ec30e9ad4611189aa80003d31"
|
||||
channel: "stable"
|
||||
|
||||
project_type: plugin
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
||||
base_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
||||
- platform: ios
|
||||
create_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
||||
base_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
||||
- platform: macos
|
||||
create_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
||||
base_revision: efbf63d9c66b9f6ec30e9ad4611189aa80003d31
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
4
bluetooth_low_energy_darwin/CHANGELOG.md
Normal file
4
bluetooth_low_energy_darwin/CHANGELOG.md
Normal file
@ -0,0 +1,4 @@
|
||||
## 2.0.2
|
||||
|
||||
- Combine iOS and macOS projects.
|
||||
- Optimize project structure.
|
21
bluetooth_low_energy_darwin/LICENSE
Normal file
21
bluetooth_low_energy_darwin/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 yanshouwang
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
15
bluetooth_low_energy_darwin/README.md
Normal file
15
bluetooth_low_energy_darwin/README.md
Normal file
@ -0,0 +1,15 @@
|
||||
# bluetooth_low_energy_darwin
|
||||
|
||||
The iOS and macOS implementation of [`bluetooth_low_energy`][1].
|
||||
|
||||
## Usage
|
||||
|
||||
This package is [endorsed][2], which means you can simply use `bluetooth_low_energy`
|
||||
normally. This package will be automatically included in your app when you do,
|
||||
so you do not need to add it to your `pubspec.yaml`.
|
||||
|
||||
However, if you `import` this package to use any of its APIs directly, you
|
||||
should add it to your `pubspec.yaml` as usual.
|
||||
|
||||
[1]: https://pub.dev/packages/bluetooth_low_energy
|
||||
[2]: https://flutter.dev/docs/development/packages-and-plugins/developing-packages#endorsed-federated-plugin
|
4
bluetooth_low_energy_darwin/analysis_options.yaml
Normal file
4
bluetooth_low_energy_darwin/analysis_options.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
@ -0,0 +1,23 @@
|
||||
#if os(iOS)
|
||||
import Flutter
|
||||
import UIKit
|
||||
#elseif os(macOS)
|
||||
import Cocoa
|
||||
import FlutterMacOS
|
||||
#else
|
||||
#error("Unsupported platform.")
|
||||
#endif
|
||||
|
||||
public class BluetoothLowEnergyDarwin: NSObject, FlutterPlugin {
|
||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
#if os(iOS)
|
||||
let binaryMessenger = registrar.messenger()
|
||||
#elseif os(macOS)
|
||||
let binaryMessenger = registrar.messenger
|
||||
#else
|
||||
#error("Unsupported platform.")
|
||||
#endif
|
||||
let centralController = MyCentralController(binaryMessenger)
|
||||
MyCentralControllerHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: centralController)
|
||||
}
|
||||
}
|
599
bluetooth_low_energy_darwin/darwin/Classes/MyApi.g.swift
Normal file
599
bluetooth_low_energy_darwin/darwin/Classes/MyApi.g.swift
Normal file
@ -0,0 +1,599 @@
|
||||
// Autogenerated from Pigeon (v10.1.6), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
|
||||
import Foundation
|
||||
#if os(iOS)
|
||||
import Flutter
|
||||
#elseif os(macOS)
|
||||
import FlutterMacOS
|
||||
#else
|
||||
#error("Unsupported platform.")
|
||||
#endif
|
||||
|
||||
private func wrapResult(_ result: Any?) -> [Any?] {
|
||||
return [result]
|
||||
}
|
||||
|
||||
private func wrapError(_ error: Any) -> [Any?] {
|
||||
if let flutterError = error as? FlutterError {
|
||||
return [
|
||||
flutterError.code,
|
||||
flutterError.message,
|
||||
flutterError.details
|
||||
]
|
||||
}
|
||||
return [
|
||||
"\(error)",
|
||||
"\(type(of: error))",
|
||||
"Stacktrace: \(Thread.callStackSymbols)"
|
||||
]
|
||||
}
|
||||
|
||||
private func nilOrValue<T>(_ value: Any?) -> T? {
|
||||
if value is NSNull { return nil }
|
||||
return value as! T?
|
||||
}
|
||||
|
||||
enum MyCentralStateArgs: Int {
|
||||
case unknown = 0
|
||||
case unsupported = 1
|
||||
case unauthorized = 2
|
||||
case poweredOff = 3
|
||||
case poweredOn = 4
|
||||
}
|
||||
|
||||
enum MyGattCharacteristicPropertyArgs: Int {
|
||||
case read = 0
|
||||
case write = 1
|
||||
case writeWithoutResponse = 2
|
||||
case notify = 3
|
||||
case indicate = 4
|
||||
}
|
||||
|
||||
enum MyGattCharacteristicWriteTypeArgs: Int {
|
||||
case withResponse = 0
|
||||
case withoutResponse = 1
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct MyCentralControllerArgs {
|
||||
var myStateNumber: Int64
|
||||
|
||||
static func fromList(_ list: [Any?]) -> MyCentralControllerArgs? {
|
||||
let myStateNumber = list[0] is Int64 ? list[0] as! Int64 : Int64(list[0] as! Int32)
|
||||
|
||||
return MyCentralControllerArgs(
|
||||
myStateNumber: myStateNumber
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
myStateNumber,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct MyPeripheralArgs {
|
||||
var key: Int64
|
||||
var uuid: String
|
||||
|
||||
static func fromList(_ list: [Any?]) -> MyPeripheralArgs? {
|
||||
let key = list[0] is Int64 ? list[0] as! Int64 : Int64(list[0] as! Int32)
|
||||
let uuid = list[1] as! String
|
||||
|
||||
return MyPeripheralArgs(
|
||||
key: key,
|
||||
uuid: uuid
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
key,
|
||||
uuid,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct MyAdvertisementArgs {
|
||||
var name: String? = nil
|
||||
var manufacturerSpecificData: [Int64?: FlutterStandardTypedData?]
|
||||
var serviceUUIDs: [String?]
|
||||
var serviceData: [String?: FlutterStandardTypedData?]
|
||||
|
||||
static func fromList(_ list: [Any?]) -> MyAdvertisementArgs? {
|
||||
let name: String? = nilOrValue(list[0])
|
||||
let manufacturerSpecificData = list[1] as! [Int64?: FlutterStandardTypedData?]
|
||||
let serviceUUIDs = list[2] as! [String?]
|
||||
let serviceData = list[3] as! [String?: FlutterStandardTypedData?]
|
||||
|
||||
return MyAdvertisementArgs(
|
||||
name: name,
|
||||
manufacturerSpecificData: manufacturerSpecificData,
|
||||
serviceUUIDs: serviceUUIDs,
|
||||
serviceData: serviceData
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
name,
|
||||
manufacturerSpecificData,
|
||||
serviceUUIDs,
|
||||
serviceData,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct MyGattServiceArgs {
|
||||
var key: Int64
|
||||
var uuid: String
|
||||
|
||||
static func fromList(_ list: [Any?]) -> MyGattServiceArgs? {
|
||||
let key = list[0] is Int64 ? list[0] as! Int64 : Int64(list[0] as! Int32)
|
||||
let uuid = list[1] as! String
|
||||
|
||||
return MyGattServiceArgs(
|
||||
key: key,
|
||||
uuid: uuid
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
key,
|
||||
uuid,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct MyGattCharacteristicArgs {
|
||||
var key: Int64
|
||||
var uuid: String
|
||||
var myPropertyNumbers: [Int64?]
|
||||
|
||||
static func fromList(_ list: [Any?]) -> MyGattCharacteristicArgs? {
|
||||
let key = list[0] is Int64 ? list[0] as! Int64 : Int64(list[0] as! Int32)
|
||||
let uuid = list[1] as! String
|
||||
let myPropertyNumbers = list[2] as! [Int64?]
|
||||
|
||||
return MyGattCharacteristicArgs(
|
||||
key: key,
|
||||
uuid: uuid,
|
||||
myPropertyNumbers: myPropertyNumbers
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
key,
|
||||
uuid,
|
||||
myPropertyNumbers,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct MyGattDescriptorArgs {
|
||||
var key: Int64
|
||||
var uuid: String
|
||||
|
||||
static func fromList(_ list: [Any?]) -> MyGattDescriptorArgs? {
|
||||
let key = list[0] is Int64 ? list[0] as! Int64 : Int64(list[0] as! Int32)
|
||||
let uuid = list[1] as! String
|
||||
|
||||
return MyGattDescriptorArgs(
|
||||
key: key,
|
||||
uuid: uuid
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
key,
|
||||
uuid,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
private class MyCentralControllerHostApiCodecReader: FlutterStandardReader {
|
||||
override func readValue(ofType type: UInt8) -> Any? {
|
||||
switch type {
|
||||
case 128:
|
||||
return MyCentralControllerArgs.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 MyGattServiceArgs.fromList(self.readValue() as! [Any?])
|
||||
default:
|
||||
return super.readValue(ofType: type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MyCentralControllerHostApiCodecWriter: FlutterStandardWriter {
|
||||
override func writeValue(_ value: Any) {
|
||||
if let value = value as? MyCentralControllerArgs {
|
||||
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 if let value = value as? MyGattServiceArgs {
|
||||
super.writeByte(131)
|
||||
super.writeValue(value.toList())
|
||||
} else {
|
||||
super.writeValue(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MyCentralControllerHostApiCodecReaderWriter: FlutterStandardReaderWriter {
|
||||
override func reader(with data: Data) -> FlutterStandardReader {
|
||||
return MyCentralControllerHostApiCodecReader(data: data)
|
||||
}
|
||||
|
||||
override func writer(with data: NSMutableData) -> FlutterStandardWriter {
|
||||
return MyCentralControllerHostApiCodecWriter(data: data)
|
||||
}
|
||||
}
|
||||
|
||||
class MyCentralControllerHostApiCodec: FlutterStandardMessageCodec {
|
||||
static let shared = MyCentralControllerHostApiCodec(readerWriter: MyCentralControllerHostApiCodecReaderWriter())
|
||||
}
|
||||
|
||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||
protocol MyCentralControllerHostApi {
|
||||
func setUp(completion: @escaping (Result<MyCentralControllerArgs, Error>) -> Void)
|
||||
func tearDown() throws
|
||||
func startDiscovery() throws
|
||||
func stopDiscovery() throws
|
||||
func connect(myPeripheralKey: Int64, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func disconnect(myPeripheralKey: Int64, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func discoverGATT(myPeripheralKey: Int64, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func getServices(myPeripheralKey: Int64) throws -> [MyGattServiceArgs]
|
||||
func getCharacteristics(myServiceKey: Int64) throws -> [MyGattCharacteristicArgs]
|
||||
func getDescriptors(myCharacteristicKey: Int64) throws -> [MyGattDescriptorArgs]
|
||||
func readCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void)
|
||||
func writeCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, value: FlutterStandardTypedData, myTypeNumber: Int64, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func notifyCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, state: Bool, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func readDescriptor(myPeripheralKey: Int64, myCharacteristicKey: Int64, myDescriptorKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void)
|
||||
func writeDescriptor(myPeripheralKey: Int64, myCharacteristicKey: Int64, myDescriptorKey: Int64, value: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
}
|
||||
|
||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||
class MyCentralControllerHostApiSetup {
|
||||
/// The codec used by MyCentralControllerHostApi.
|
||||
static var codec: FlutterStandardMessageCodec { MyCentralControllerHostApiCodec.shared }
|
||||
/// Sets up an instance of `MyCentralControllerHostApi` to handle messages through the `binaryMessenger`.
|
||||
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: MyCentralControllerHostApi?) {
|
||||
let setUpChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.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))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setUpChannel.setMessageHandler(nil)
|
||||
}
|
||||
let tearDownChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.tearDown", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
tearDownChannel.setMessageHandler { _, reply in
|
||||
do {
|
||||
try api.tearDown()
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tearDownChannel.setMessageHandler(nil)
|
||||
}
|
||||
let startDiscoveryChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.startDiscovery", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
startDiscoveryChannel.setMessageHandler { _, reply in
|
||||
do {
|
||||
try api.startDiscovery()
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
startDiscoveryChannel.setMessageHandler(nil)
|
||||
}
|
||||
let stopDiscoveryChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.stopDiscovery", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
stopDiscoveryChannel.setMessageHandler { _, reply in
|
||||
do {
|
||||
try api.stopDiscovery()
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
stopDiscoveryChannel.setMessageHandler(nil)
|
||||
}
|
||||
let connectChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.connect", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
connectChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
api.connect(myPeripheralKey: myPeripheralKeyArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
connectChannel.setMessageHandler(nil)
|
||||
}
|
||||
let disconnectChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.disconnect", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
disconnectChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
api.disconnect(myPeripheralKey: myPeripheralKeyArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
disconnectChannel.setMessageHandler(nil)
|
||||
}
|
||||
let discoverGATTChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.discoverGATT", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
discoverGATTChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
api.discoverGATT(myPeripheralKey: myPeripheralKeyArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
discoverGATTChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getServicesChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.getServices", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getServicesChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
do {
|
||||
let result = try api.getServices(myPeripheralKey: myPeripheralKeyArg)
|
||||
reply(wrapResult(result))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getServicesChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getCharacteristicsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.getCharacteristics", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getCharacteristicsChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myServiceKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
do {
|
||||
let result = try api.getCharacteristics(myServiceKey: myServiceKeyArg)
|
||||
reply(wrapResult(result))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getCharacteristicsChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getDescriptorsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.getDescriptors", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getDescriptorsChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myCharacteristicKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
do {
|
||||
let result = try api.getDescriptors(myCharacteristicKey: myCharacteristicKeyArg)
|
||||
reply(wrapResult(result))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getDescriptorsChannel.setMessageHandler(nil)
|
||||
}
|
||||
let readCharacteristicChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.readCharacteristic", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
readCharacteristicChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let myServiceKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let myCharacteristicKeyArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32)
|
||||
api.readCharacteristic(myPeripheralKey: myPeripheralKeyArg, myServiceKey: myServiceKeyArg, myCharacteristicKey: myCharacteristicKeyArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
readCharacteristicChannel.setMessageHandler(nil)
|
||||
}
|
||||
let writeCharacteristicChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.writeCharacteristic", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
writeCharacteristicChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let myServiceKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let myCharacteristicKeyArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32)
|
||||
let valueArg = args[3] as! FlutterStandardTypedData
|
||||
let myTypeNumberArg = args[4] is Int64 ? args[4] as! Int64 : Int64(args[4] as! Int32)
|
||||
api.writeCharacteristic(myPeripheralKey: myPeripheralKeyArg, myServiceKey: myServiceKeyArg, myCharacteristicKey: myCharacteristicKeyArg, value: valueArg, myTypeNumber: myTypeNumberArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
writeCharacteristicChannel.setMessageHandler(nil)
|
||||
}
|
||||
let notifyCharacteristicChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.notifyCharacteristic", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
notifyCharacteristicChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let myServiceKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let myCharacteristicKeyArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32)
|
||||
let stateArg = args[3] as! Bool
|
||||
api.notifyCharacteristic(myPeripheralKey: myPeripheralKeyArg, myServiceKey: myServiceKeyArg, myCharacteristicKey: myCharacteristicKeyArg, state: stateArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
notifyCharacteristicChannel.setMessageHandler(nil)
|
||||
}
|
||||
let readDescriptorChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.readDescriptor", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
readDescriptorChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let myCharacteristicKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let myDescriptorKeyArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32)
|
||||
api.readDescriptor(myPeripheralKey: myPeripheralKeyArg, myCharacteristicKey: myCharacteristicKeyArg, myDescriptorKey: myDescriptorKeyArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
readDescriptorChannel.setMessageHandler(nil)
|
||||
}
|
||||
let writeDescriptorChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.writeDescriptor", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
writeDescriptorChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let myPeripheralKeyArg = args[0] is Int64 ? args[0] as! Int64 : Int64(args[0] as! Int32)
|
||||
let myCharacteristicKeyArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32)
|
||||
let myDescriptorKeyArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32)
|
||||
let valueArg = args[3] as! FlutterStandardTypedData
|
||||
api.writeDescriptor(myPeripheralKey: myPeripheralKeyArg, myCharacteristicKey: myCharacteristicKeyArg, myDescriptorKey: myDescriptorKeyArg, value: valueArg) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
writeDescriptorChannel.setMessageHandler(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
private class MyCentralControllerFlutterApiCodecReader: FlutterStandardReader {
|
||||
override func readValue(ofType type: UInt8) -> Any? {
|
||||
switch type {
|
||||
case 128:
|
||||
return MyAdvertisementArgs.fromList(self.readValue() as! [Any?])
|
||||
case 129:
|
||||
return MyPeripheralArgs.fromList(self.readValue() as! [Any?])
|
||||
default:
|
||||
return super.readValue(ofType: type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MyCentralControllerFlutterApiCodecWriter: FlutterStandardWriter {
|
||||
override func writeValue(_ value: Any) {
|
||||
if let value = value as? MyAdvertisementArgs {
|
||||
super.writeByte(128)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? MyPeripheralArgs {
|
||||
super.writeByte(129)
|
||||
super.writeValue(value.toList())
|
||||
} else {
|
||||
super.writeValue(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MyCentralControllerFlutterApiCodecReaderWriter: FlutterStandardReaderWriter {
|
||||
override func reader(with data: Data) -> FlutterStandardReader {
|
||||
return MyCentralControllerFlutterApiCodecReader(data: data)
|
||||
}
|
||||
|
||||
override func writer(with data: NSMutableData) -> FlutterStandardWriter {
|
||||
return MyCentralControllerFlutterApiCodecWriter(data: data)
|
||||
}
|
||||
}
|
||||
|
||||
class MyCentralControllerFlutterApiCodec: FlutterStandardMessageCodec {
|
||||
static let shared = MyCentralControllerFlutterApiCodec(readerWriter: MyCentralControllerFlutterApiCodecReaderWriter())
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents Flutter messages that can be called from Swift.
|
||||
class MyCentralControllerFlutterApi {
|
||||
private let binaryMessenger: FlutterBinaryMessenger
|
||||
init(binaryMessenger: FlutterBinaryMessenger){
|
||||
self.binaryMessenger = binaryMessenger
|
||||
}
|
||||
var codec: FlutterStandardMessageCodec {
|
||||
return MyCentralControllerFlutterApiCodec.shared
|
||||
}
|
||||
func onStateChanged(myStateNumber myStateNumberArg: Int64, completion: @escaping () -> Void) {
|
||||
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onStateChanged", binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([myStateNumberArg] as [Any?]) { _ in
|
||||
completion()
|
||||
}
|
||||
}
|
||||
func onDiscovered(myPeripheralArgs myPeripheralArgsArg: MyPeripheralArgs, rssi rssiArg: Int64, myAdvertisementArgs myAdvertisementArgsArg: MyAdvertisementArgs, completion: @escaping () -> Void) {
|
||||
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onDiscovered", binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([myPeripheralArgsArg, rssiArg, myAdvertisementArgsArg] as [Any?]) { _ in
|
||||
completion()
|
||||
}
|
||||
}
|
||||
func onPeripheralStateChanged(myPeripheralKey myPeripheralKeyArg: Int64, state stateArg: Bool, completion: @escaping () -> Void) {
|
||||
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onPeripheralStateChanged", binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([myPeripheralKeyArg, stateArg] as [Any?]) { _ in
|
||||
completion()
|
||||
}
|
||||
}
|
||||
func onCharacteristicValueChanged(myCharacteristicKey myCharacteristicKeyArg: Int64, value valueArg: FlutterStandardTypedData, completion: @escaping () -> Void) {
|
||||
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onCharacteristicValueChanged", binaryMessenger: binaryMessenger, codec: codec)
|
||||
channel.sendMessage([myCharacteristicKeyArg, valueArg] as [Any?]) { _ in
|
||||
completion()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,722 @@
|
||||
//
|
||||
// MyCentralController.swift
|
||||
// bluetooth_low_energy_ios
|
||||
//
|
||||
// Created by 闫守旺 on 2023/8/13.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreBluetooth
|
||||
#if os(iOS)
|
||||
import Flutter
|
||||
#elseif os(macOS)
|
||||
import FlutterMacOS
|
||||
#else
|
||||
#error("Unsupported platform.")
|
||||
#endif
|
||||
|
||||
class MyCentralController: MyCentralControllerHostApi {
|
||||
init(_ binaryMessenger: FlutterBinaryMessenger) {
|
||||
myApi = MyCentralControllerFlutterApi(binaryMessenger: binaryMessenger)
|
||||
}
|
||||
|
||||
private let myApi: MyCentralControllerFlutterApi
|
||||
private lazy var myCentralManagerDelegate = MyCentralManagerDelegate(self)
|
||||
private lazy var myPeripheralDelegate = MyPeripheralDelegate(self)
|
||||
private let centralManager = CBCentralManager()
|
||||
|
||||
private var cachedPeripherals = [Int: CBPeripheral]()
|
||||
private var cachedServices = [Int: [Int: CBService]]()
|
||||
private var cachedCharacteristics = [Int: [Int: CBCharacteristic]]()
|
||||
private var cachedDescriptors = [Int: [Int: CBDescriptor]]()
|
||||
|
||||
var setUpCompletion: ((Result<MyCentralControllerArgs, Error>) -> Void)?
|
||||
var connectCompletions = [Int: (Result<Void, Error>) -> Void]()
|
||||
var disconnectCompletions = [Int: (Result<Void, Error>) -> Void]()
|
||||
var discoverGattCompletions = [Int: (Result<Void, Error>) -> Void]()
|
||||
var unfinishedServices = [Int: [CBService]]()
|
||||
var unfinishedCharacteristics = [Int: [CBCharacteristic]]()
|
||||
var readCharacteristicCompletions = [Int: (Result<FlutterStandardTypedData, Error>) -> Void]()
|
||||
var writeCharacteristicCompletions = [Int: (Result<Void, Error>) -> Void]()
|
||||
var notifyCharacteristicCompletions = [Int: (Result<Void, Error>) -> Void]()
|
||||
var readDescriptorCompletions = [Int: (Result<FlutterStandardTypedData, Error>) -> Void]()
|
||||
var writeDescriptorCompletions = [Int: (Result<Void, Error>) -> Void]()
|
||||
|
||||
func setUp(completion: @escaping (Result<MyCentralControllerArgs, Error>) -> Void) {
|
||||
do {
|
||||
let unfinishedCompletion = setUpCompletion
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
centralManager.delegate = myCentralManagerDelegate
|
||||
if centralManager.state == .unknown {
|
||||
setUpCompletion = completion
|
||||
} else {
|
||||
let myStateArgs = centralManager.state.toMyArgs()
|
||||
let myStateNumber = Int64(myStateArgs.rawValue)
|
||||
let myArgs = MyCentralControllerArgs(myStateNumber: myStateNumber)
|
||||
completion(.success(myArgs))
|
||||
}
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func tearDown() throws {
|
||||
centralManager.delegate = nil
|
||||
if(centralManager.isScanning) {
|
||||
centralManager.stopScan()
|
||||
}
|
||||
for peripheral in cachedPeripherals.values {
|
||||
peripheral.delegate = nil
|
||||
if peripheral.state != .disconnected {
|
||||
centralManager.cancelPeripheralConnection(peripheral)
|
||||
}
|
||||
}
|
||||
cachedPeripherals.removeAll()
|
||||
cachedServices.removeAll()
|
||||
cachedCharacteristics.removeAll()
|
||||
cachedDescriptors.removeAll()
|
||||
}
|
||||
|
||||
func startDiscovery() throws {
|
||||
let options = [CBCentralManagerScanOptionAllowDuplicatesKey: true]
|
||||
centralManager.scanForPeripherals(withServices: nil, options: options)
|
||||
}
|
||||
|
||||
func stopDiscovery() throws {
|
||||
centralManager.stopScan()
|
||||
}
|
||||
|
||||
func connect(myPeripheralKey: Int64, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
let unfinishedCompletion = connectCompletions[peripheralKey]
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
centralManager.connect(peripheral)
|
||||
connectCompletions[peripheralKey] = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func disconnect(myPeripheralKey: Int64, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
let unfinishedCompletion = disconnectCompletions[peripheralKey]
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
centralManager.cancelPeripheralConnection(peripheral)
|
||||
disconnectCompletions[peripheralKey] = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func discoverGATT(myPeripheralKey: Int64, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
let unfinishedCompletion = discoverGattCompletions[peripheralKey]
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
peripheral.discoverServices(nil)
|
||||
discoverGattCompletions[peripheralKey] = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func getServices(myPeripheralKey: Int64) throws -> [MyGattServiceArgs] {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let services = cachedServices[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
return services.map { (key, service) in
|
||||
return service.toMyArgs()
|
||||
}
|
||||
}
|
||||
|
||||
func getCharacteristics(myServiceKey: Int64) throws -> [MyGattCharacteristicArgs] {
|
||||
let serviceKey = Int(myServiceKey)
|
||||
guard let characteristics = cachedCharacteristics[serviceKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
return characteristics.map { (key, characteristic) in
|
||||
return characteristic.toMyArgs()
|
||||
}
|
||||
}
|
||||
|
||||
func getDescriptors(myCharacteristicKey: Int64) throws -> [MyGattDescriptorArgs] {
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
guard let descriptors = cachedDescriptors[characteristicKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
return descriptors.map { (key, descriptor) in
|
||||
return descriptor.toMyArgs()
|
||||
}
|
||||
}
|
||||
|
||||
func readCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let serviceKey = Int(myServiceKey)
|
||||
guard let characteristics = cachedCharacteristics[serviceKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
guard let characteristic = characteristics[characteristicKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let unfinishedCompletion = readCharacteristicCompletions[characteristicKey]
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
peripheral.readValue(for: characteristic)
|
||||
readCharacteristicCompletions[characteristicKey] = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func writeCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, value: FlutterStandardTypedData, myTypeNumber: Int64, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let serviceKey = Int(myServiceKey)
|
||||
guard let characteristics = cachedCharacteristics[serviceKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
guard let characteristic = characteristics[characteristicKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let data = value.data
|
||||
let myTypeRawValue = Int(myTypeNumber)
|
||||
guard let myTypeArgs = MyGattCharacteristicWriteTypeArgs(rawValue: myTypeRawValue) else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let type = myTypeArgs.toType()
|
||||
let unfinishedCompletion = writeCharacteristicCompletions[characteristicKey]
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
peripheral.writeValue(data, for: characteristic, type: type)
|
||||
writeCharacteristicCompletions[characteristicKey] = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func notifyCharacteristic(myPeripheralKey: Int64, myServiceKey: Int64, myCharacteristicKey: Int64, state: Bool, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let serviceKey = Int(myServiceKey)
|
||||
guard let characteristics = cachedCharacteristics[serviceKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
guard let characteristic = characteristics[characteristicKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let unfinishedCompletion = notifyCharacteristicCompletions[characteristicKey]
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
peripheral.setNotifyValue(state, for: characteristic)
|
||||
notifyCharacteristicCompletions[characteristicKey] = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func readDescriptor(myPeripheralKey: Int64, myCharacteristicKey: Int64, myDescriptorKey: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
guard let descriptors = cachedDescriptors[characteristicKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let descriptorKey = Int(myDescriptorKey)
|
||||
guard let descriptor = descriptors[descriptorKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let unfinishedCompletion = readDescriptorCompletions[descriptorKey]
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
peripheral.readValue(for: descriptor)
|
||||
readDescriptorCompletions[descriptorKey] = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func writeDescriptor(myPeripheralKey: Int64, myCharacteristicKey: Int64, myDescriptorKey: Int64, value: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
do {
|
||||
let peripheralKey = Int(myPeripheralKey)
|
||||
guard let peripheral = cachedPeripherals[peripheralKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let characteristicKey = Int(myCharacteristicKey)
|
||||
guard let descriptors = cachedDescriptors[characteristicKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let descriptorKey = Int(myDescriptorKey)
|
||||
guard let descriptor = descriptors[descriptorKey] else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let data = value.data
|
||||
let unfinishedCompletion = writeDescriptorCompletions[descriptorKey]
|
||||
if unfinishedCompletion != nil {
|
||||
throw MyError.illegalState
|
||||
}
|
||||
peripheral.writeValue(data, for: descriptor)
|
||||
writeDescriptorCompletions[descriptorKey] = completion
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
func didUpdateState(_ state: CBManagerState) {
|
||||
let completion = setUpCompletion
|
||||
if state != .unknown && completion != nil {
|
||||
let myStateArgs = state.toMyArgs()
|
||||
let myStateNumber = Int64(myStateArgs.rawValue)
|
||||
let myArgs = MyCentralControllerArgs(myStateNumber: myStateNumber)
|
||||
completion!(.success(myArgs))
|
||||
setUpCompletion = nil
|
||||
}
|
||||
let myStateArgs = state.toMyArgs()
|
||||
let myStateNumber = Int64(myStateArgs.rawValue)
|
||||
myApi.onStateChanged(myStateNumber: myStateNumber) {}
|
||||
}
|
||||
|
||||
|
||||
func didDiscover(_ peripheral: CBPeripheral, _ advertisementData: [String : Any], _ rssiNumber: NSNumber) {
|
||||
let peripheralKey = peripheral.hash
|
||||
if cachedPeripherals[peripheralKey] == nil {
|
||||
peripheral.delegate = myPeripheralDelegate
|
||||
cachedPeripherals[peripheralKey] = peripheral
|
||||
}
|
||||
let myPeripheralArgs = peripheral.toMyArgs()
|
||||
let rssi = rssiNumber.int64Value
|
||||
let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String
|
||||
let rawManufacturerSpecificData = advertisementData[CBAdvertisementDataManufacturerDataKey] as? Data
|
||||
var manufacturerSpecificData = [Int64: FlutterStandardTypedData]()
|
||||
if rawManufacturerSpecificData != nil {
|
||||
do {
|
||||
guard let data = rawManufacturerSpecificData else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
guard data.count >= 2 else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
let key = Int64(data[0]) | (Int64(data[1]) << 8)
|
||||
let bytes = data.count > 2 ? data[2...data.count-1] : Data()
|
||||
let value = FlutterStandardTypedData(bytes: bytes)
|
||||
manufacturerSpecificData[key] = value
|
||||
} catch {
|
||||
manufacturerSpecificData = [:]
|
||||
}
|
||||
}
|
||||
let rawServiceUUIDs = advertisementData[CBAdvertisementDataServiceUUIDsKey] as? [CBUUID] ?? []
|
||||
let serviceUUIDs = rawServiceUUIDs.map { uuid in uuid.uuidString }
|
||||
let rawServiceData = advertisementData[CBAdvertisementDataServiceDataKey] as? [CBUUID: Data] ?? [:]
|
||||
let elements = rawServiceData.map { (uuid, data) in
|
||||
let key = uuid.uuidString
|
||||
let value = FlutterStandardTypedData(bytes: data)
|
||||
return (key, value)
|
||||
}
|
||||
let serviceData = [String?: FlutterStandardTypedData?](uniqueKeysWithValues: elements)
|
||||
let myAdvertisementArgs = MyAdvertisementArgs(name: name, manufacturerSpecificData: manufacturerSpecificData, serviceUUIDs: serviceUUIDs, serviceData: serviceData)
|
||||
myApi.onDiscovered(myPeripheralArgs: myPeripheralArgs, rssi: rssi, myAdvertisementArgs: myAdvertisementArgs) {}
|
||||
}
|
||||
|
||||
func didConnect(_ peripheral: CBPeripheral) {
|
||||
let peripheralKey = peripheral.hash
|
||||
let myPeripheralKey = Int64(peripheralKey)
|
||||
myApi.onPeripheralStateChanged(myPeripheralKey: myPeripheralKey, state: true) {}
|
||||
guard let completion = connectCompletions.removeValue(forKey: peripheralKey) else {
|
||||
return
|
||||
}
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
func didFailToConnect(_ peripheral: CBPeripheral, _ error: Error?) {
|
||||
let peripheralKey = peripheral.hash
|
||||
guard let completion = connectCompletions.removeValue(forKey: peripheralKey) else {
|
||||
return
|
||||
}
|
||||
completion(.failure(error ?? MyError.unknown))
|
||||
}
|
||||
|
||||
func didDisconnectPeripheral(_ peripheral: CBPeripheral, _ error: Error?) {
|
||||
let peripheralKey = peripheral.hash
|
||||
let myPeripheralKey = Int64(peripheralKey)
|
||||
let discoverGattCompletion = discoverGattCompletions.removeValue(forKey: peripheralKey)
|
||||
if discoverGattCompletion != nil {
|
||||
didDiscoverGATT(peripheral, error ?? MyError.unknown)
|
||||
}
|
||||
let services = cachedServices[peripheralKey] ?? [:]
|
||||
for service in services {
|
||||
let characteristics = cachedCharacteristics[service.key] ?? [:]
|
||||
for characteristic in characteristics {
|
||||
let readCharacteristicCompletion = readCharacteristicCompletions.removeValue(forKey: characteristic.key)
|
||||
let writeCharacteristicCompletion = writeCharacteristicCompletions.removeValue(forKey: characteristic.key)
|
||||
if readCharacteristicCompletion != nil {
|
||||
readCharacteristicCompletion!(.failure(MyError.illegalState))
|
||||
}
|
||||
if writeCharacteristicCompletion != nil {
|
||||
writeCharacteristicCompletion!(.failure(MyError.illegalState))
|
||||
}
|
||||
let descriptors = cachedDescriptors[characteristic.key] ?? [:]
|
||||
for descriptor in descriptors {
|
||||
let readDescriptorCompletion = readDescriptorCompletions.removeValue(forKey: descriptor.key)
|
||||
let writeDescriptorCompletion = writeDescriptorCompletions.removeValue(forKey: descriptor.key)
|
||||
if readDescriptorCompletion != nil {
|
||||
readDescriptorCompletion!(.failure(MyError.illegalState))
|
||||
}
|
||||
if writeDescriptorCompletion != nil {
|
||||
writeDescriptorCompletion!(.failure(MyError.illegalState))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
myApi.onPeripheralStateChanged(myPeripheralKey: myPeripheralKey, state: false) {}
|
||||
guard let completion = disconnectCompletions.removeValue(forKey: peripheralKey) else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
completion(.success(()))
|
||||
} else {
|
||||
completion(.failure(error!))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func didDiscoverServices(_ peripheral: CBPeripheral, _ error: Error?) {
|
||||
let peripheralKey = peripheral.hash
|
||||
if error == nil {
|
||||
var services = peripheral.services ?? []
|
||||
if services.isEmpty {
|
||||
didDiscoverGATT(peripheral, error)
|
||||
} else {
|
||||
let service = services.removeFirst()
|
||||
unfinishedServices[peripheralKey] = services
|
||||
peripheral.discoverCharacteristics(nil, for: service)
|
||||
}
|
||||
} else {
|
||||
didDiscoverGATT(peripheral, error)
|
||||
}
|
||||
}
|
||||
|
||||
func didDiscoverCharacteristics(_ peripheral: CBPeripheral, _ service: CBService, _ error: Error?) {
|
||||
let peripheralKey = peripheral.hash
|
||||
if error == nil {
|
||||
var characteristics = service.characteristics ?? []
|
||||
if characteristics.isEmpty {
|
||||
var services = unfinishedServices.removeValue(forKey: peripheralKey) ?? []
|
||||
if services.isEmpty {
|
||||
didDiscoverGATT(peripheral, error)
|
||||
} else {
|
||||
let service = services.removeFirst()
|
||||
unfinishedServices[peripheralKey] = services
|
||||
peripheral.discoverCharacteristics(nil, for: service)
|
||||
}
|
||||
} else {
|
||||
let characteristic = characteristics.removeFirst()
|
||||
unfinishedCharacteristics[peripheralKey] = characteristics
|
||||
peripheral.discoverDescriptors(for: characteristic)
|
||||
}
|
||||
} else {
|
||||
didDiscoverGATT(peripheral, error)
|
||||
}
|
||||
}
|
||||
|
||||
func didDiscoverDescriptors(_ peripheral: CBPeripheral, _ characteristic: CBCharacteristic, _ error: Error?) {
|
||||
let peripheralKey = peripheral.hash
|
||||
if error == nil {
|
||||
var characteristics = unfinishedCharacteristics.removeValue(forKey: peripheralKey) ?? []
|
||||
if (characteristics.isEmpty) {
|
||||
var services = unfinishedServices.removeValue(forKey: peripheralKey) ?? []
|
||||
if services.isEmpty {
|
||||
didDiscoverGATT(peripheral, error)
|
||||
} else {
|
||||
let service = services.removeFirst()
|
||||
unfinishedServices[peripheralKey] = services
|
||||
peripheral.discoverCharacteristics(nil, for: service)
|
||||
}
|
||||
} else {
|
||||
let characteristic = characteristics.removeFirst()
|
||||
unfinishedCharacteristics[peripheralKey] = characteristics
|
||||
peripheral.discoverDescriptors(for: characteristic)
|
||||
}
|
||||
} else {
|
||||
didDiscoverGATT(peripheral, error)
|
||||
}
|
||||
}
|
||||
|
||||
private func didDiscoverGATT(_ peripheral: CBPeripheral, _ error: Error?) {
|
||||
let peripheralKey = peripheral.hash
|
||||
unfinishedServices.removeValue(forKey: peripheralKey)
|
||||
unfinishedCharacteristics.removeValue(forKey: peripheralKey)
|
||||
guard let completion = discoverGattCompletions.removeValue(forKey: peripheralKey) else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
let services = peripheral.services ?? []
|
||||
var cachedServices = [Int: CBService]()
|
||||
for service in services {
|
||||
let serviceKey = service.hash
|
||||
cachedServices[serviceKey] = service
|
||||
let characteristics = service.characteristics ?? []
|
||||
var cachedCharacteristics = [Int: CBCharacteristic]()
|
||||
for characteristic in characteristics {
|
||||
let characteristicKey = characteristic.hash
|
||||
cachedCharacteristics[characteristicKey] = characteristic
|
||||
let descriptors = characteristic.descriptors ?? []
|
||||
var cachedDescriptors = [Int: CBDescriptor]()
|
||||
for descriptor in descriptors {
|
||||
let descriptorKey = descriptor.hash
|
||||
cachedDescriptors[descriptorKey] = descriptor
|
||||
}
|
||||
self.cachedDescriptors[characteristicKey] = cachedDescriptors
|
||||
}
|
||||
self.cachedCharacteristics[serviceKey] = cachedCharacteristics
|
||||
}
|
||||
self.cachedServices[peripheralKey] = cachedServices
|
||||
completion(.success(()))
|
||||
} else {
|
||||
completion(.failure(error!))
|
||||
}
|
||||
}
|
||||
|
||||
func didUpdateCharacteristicValue(_ characteristic: CBCharacteristic, _ error: Error?) {
|
||||
let characteristicKey = characteristic.hash
|
||||
guard let completion = readCharacteristicCompletions.removeValue(forKey: characteristicKey) else {
|
||||
let myCharacteristicKey = Int64(characteristicKey)
|
||||
let rawValue = characteristic.value ?? Data()
|
||||
let value = FlutterStandardTypedData(bytes: rawValue)
|
||||
myApi.onCharacteristicValueChanged(myCharacteristicKey: myCharacteristicKey, value: value) {}
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
let rawValue = characteristic.value ?? Data()
|
||||
let value = FlutterStandardTypedData(bytes: rawValue)
|
||||
completion(.success(value))
|
||||
} else {
|
||||
completion(.failure(error!))
|
||||
}
|
||||
}
|
||||
|
||||
func didWriteCharacteristicValue(_ characteristic: CBCharacteristic, _ error: Error?) {
|
||||
let characteristicKey = characteristic.hash
|
||||
guard let completion = writeCharacteristicCompletions.removeValue(forKey: characteristicKey) else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
completion(.success(()))
|
||||
} else {
|
||||
completion(.failure(error!))
|
||||
}
|
||||
}
|
||||
|
||||
func didUpdateNotificationState(_ characteristic: CBCharacteristic, _ error: Error?) {
|
||||
let characteristicKey = characteristic.hash
|
||||
guard let completion = notifyCharacteristicCompletions.removeValue(forKey: characteristicKey) else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
completion(.success(()))
|
||||
} else {
|
||||
completion(.failure(error!))
|
||||
}
|
||||
}
|
||||
|
||||
func didUpdateDescriptorValue(_ descriptor: CBDescriptor, _ error: Error?) {
|
||||
let descriptorKey = descriptor.hash
|
||||
guard let completion = readDescriptorCompletions.removeValue(forKey: descriptorKey) else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
// TODO: Need to confirm wheather the corresponding descriptor type and value is correct.
|
||||
let value: FlutterStandardTypedData
|
||||
let rawValue = descriptor.value
|
||||
do {
|
||||
switch descriptor.uuid.uuidString {
|
||||
case CBUUIDCharacteristicExtendedPropertiesString:
|
||||
fallthrough
|
||||
case CBUUIDClientCharacteristicConfigurationString:
|
||||
fallthrough
|
||||
case CBUUIDServerCharacteristicConfigurationString:
|
||||
guard let rawNumber = rawValue as? NSNumber else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
value = FlutterStandardTypedData(bytes: rawNumber.data)
|
||||
case CBUUIDCharacteristicUserDescriptionString:
|
||||
fallthrough
|
||||
case CBUUIDCharacteristicAggregateFormatString:
|
||||
guard let rawString = rawValue as? String else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
value = FlutterStandardTypedData(bytes: rawString.data)
|
||||
case CBUUIDCharacteristicFormatString:
|
||||
guard let rawData = rawValue as? Data else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
value = FlutterStandardTypedData(bytes: rawData)
|
||||
case CBUUIDL2CAPPSMCharacteristicString:
|
||||
guard let rawU16 = rawValue as? UInt16 else {
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
value = FlutterStandardTypedData(bytes: rawU16.data)
|
||||
default:
|
||||
throw MyError.illegalArgument
|
||||
}
|
||||
} catch {
|
||||
value = FlutterStandardTypedData()
|
||||
}
|
||||
completion(.success((value)))
|
||||
} else {
|
||||
completion(.failure(error!))
|
||||
}
|
||||
}
|
||||
|
||||
func didWriteDescriptorValue(_ descriptor: CBDescriptor, _ error: Error?) {
|
||||
let descriptorKey = descriptor.hash
|
||||
guard let completion = writeDescriptorCompletions.removeValue(forKey: descriptorKey) else {
|
||||
return
|
||||
}
|
||||
if error == nil {
|
||||
completion(.success(()))
|
||||
} else {
|
||||
completion(.failure(error!))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension CBManagerState {
|
||||
func toMyArgs() -> MyCentralStateArgs {
|
||||
switch self {
|
||||
case .unauthorized:
|
||||
return .unauthorized
|
||||
case .poweredOff:
|
||||
return .poweredOff
|
||||
case .poweredOn:
|
||||
return .poweredOn
|
||||
default:
|
||||
return .unsupported
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension CBPeripheral {
|
||||
func toMyArgs() -> MyPeripheralArgs {
|
||||
let key = Int64(hash)
|
||||
let uuid = identifier.uuidString
|
||||
return MyPeripheralArgs(key: key, uuid: uuid)
|
||||
}
|
||||
}
|
||||
|
||||
extension CBService {
|
||||
func toMyArgs() -> MyGattServiceArgs {
|
||||
let key = Int64(hash)
|
||||
let uuid = uuid.uuidString
|
||||
return MyGattServiceArgs(key: key, uuid: uuid)
|
||||
}
|
||||
}
|
||||
|
||||
extension CBCharacteristic {
|
||||
func toMyArgs() -> MyGattCharacteristicArgs {
|
||||
let key = Int64(hash)
|
||||
let uuid = uuid.uuidString
|
||||
let myPropertyArgses = properties.toMyArgses()
|
||||
let myPropertyNumbers = myPropertyArgses.map { myPropertyArgs in Int64(myPropertyArgs.rawValue) }
|
||||
return MyGattCharacteristicArgs(key: key, uuid: uuid, myPropertyNumbers: myPropertyNumbers)
|
||||
}
|
||||
}
|
||||
|
||||
extension CBDescriptor {
|
||||
func toMyArgs() -> MyGattDescriptorArgs {
|
||||
let key = Int64(hash)
|
||||
let uuid = uuid.uuidString
|
||||
return MyGattDescriptorArgs(key: key, uuid: uuid)
|
||||
}
|
||||
}
|
||||
|
||||
extension CBCharacteristicProperties {
|
||||
func toMyArgses() -> [MyGattCharacteristicPropertyArgs] {
|
||||
var myPropertyArgs = [MyGattCharacteristicPropertyArgs]()
|
||||
if contains(.read) {
|
||||
myPropertyArgs.append(.read)
|
||||
}
|
||||
if contains(.write) {
|
||||
myPropertyArgs.append(.write)
|
||||
}
|
||||
if contains(.writeWithoutResponse) {
|
||||
myPropertyArgs.append(.writeWithoutResponse)
|
||||
}
|
||||
if contains(.notify) {
|
||||
myPropertyArgs.append(.notify)
|
||||
}
|
||||
if contains(.indicate) {
|
||||
myPropertyArgs.append(.indicate)
|
||||
}
|
||||
return myPropertyArgs
|
||||
}
|
||||
}
|
||||
|
||||
extension MyGattCharacteristicWriteTypeArgs {
|
||||
func toType() -> CBCharacteristicWriteType {
|
||||
switch self {
|
||||
case .withResponse:
|
||||
return .withResponse
|
||||
case .withoutResponse:
|
||||
return .withoutResponse
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension NSNumber {
|
||||
var data: Data {
|
||||
var source = self
|
||||
return Data(bytes: &source, count: MemoryLayout<NSNumber>.size)
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
var data: Data {
|
||||
return data(using: String.Encoding.utf8)!
|
||||
}
|
||||
}
|
||||
|
||||
extension UInt16 {
|
||||
var data: Data {
|
||||
var source = self
|
||||
return Data(bytes: &source, count: MemoryLayout<UInt16>.size)
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
//
|
||||
// MyCentralManagerDelegate.swift
|
||||
// bluetooth_low_energy_ios
|
||||
//
|
||||
// Created by 闫守旺 on 2023/8/13.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreBluetooth
|
||||
|
||||
class MyCentralManagerDelegate: NSObject, CBCentralManagerDelegate {
|
||||
private let myCentralController: MyCentralController
|
||||
|
||||
init(_ myCentralController: MyCentralController) {
|
||||
self.myCentralController = myCentralController
|
||||
}
|
||||
|
||||
func centralManagerDidUpdateState(_ central: CBCentralManager) {
|
||||
let state = central.state
|
||||
myCentralController.didUpdateState(state)
|
||||
}
|
||||
|
||||
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
|
||||
myCentralController.didDiscover(peripheral, advertisementData, RSSI)
|
||||
}
|
||||
|
||||
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
|
||||
myCentralController.didConnect(peripheral)
|
||||
}
|
||||
|
||||
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
|
||||
myCentralController.didFailToConnect(peripheral, error)
|
||||
}
|
||||
|
||||
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
|
||||
myCentralController.didDisconnectPeripheral(peripheral, error)
|
||||
}
|
||||
}
|
14
bluetooth_low_energy_darwin/darwin/Classes/MyError.swift
Normal file
14
bluetooth_low_energy_darwin/darwin/Classes/MyError.swift
Normal file
@ -0,0 +1,14 @@
|
||||
//
|
||||
// MyError.swift
|
||||
// bluetooth_low_energy_ios
|
||||
//
|
||||
// Created by 闫守旺 on 2023/8/13.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum MyError: Error {
|
||||
case illegalArgument
|
||||
case illegalState
|
||||
case unknown
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
//
|
||||
// MyPeripheralDelegate.swift
|
||||
// bluetooth_low_energy_ios
|
||||
//
|
||||
// Created by 闫守旺 on 2023/8/13.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreBluetooth
|
||||
|
||||
class MyPeripheralDelegate: NSObject, CBPeripheralDelegate {
|
||||
private let myCentralController: MyCentralController
|
||||
|
||||
init(_ myCentralController: MyCentralController) {
|
||||
self.myCentralController = myCentralController
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
|
||||
myCentralController.didDiscoverServices(peripheral, error)
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
|
||||
myCentralController.didDiscoverCharacteristics(peripheral, service, error)
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didDiscoverDescriptorsFor characteristic: CBCharacteristic, error: Error?) {
|
||||
myCentralController.didDiscoverDescriptors(peripheral, characteristic, error)
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
|
||||
myCentralController.didUpdateCharacteristicValue(characteristic, error)
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
|
||||
myCentralController.didWriteCharacteristicValue(characteristic, error)
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
|
||||
myCentralController.didUpdateNotificationState(characteristic, error)
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor descriptor: CBDescriptor, error: Error?) {
|
||||
myCentralController.didUpdateDescriptorValue(descriptor, error)
|
||||
}
|
||||
|
||||
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor descriptor: CBDescriptor, error: Error?) {
|
||||
myCentralController.didWriteDescriptorValue(descriptor, error)
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
#
|
||||
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
|
||||
# Run `pod lib lint bluetooth_low_energy_darwin.podspec` to validate before publishing.
|
||||
#
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'bluetooth_low_energy_darwin'
|
||||
s.version = '2.0.2'
|
||||
s.summary = 'iOS and macOS implementation of the bluetooth_low_energy plugin.'
|
||||
s.description = <<-DESC
|
||||
iOS and macOS implementation of the bluetooth_low_energy plugin.
|
||||
DESC
|
||||
s.homepage = 'https://github.com/yanshouwang/bluetooth_low_energy'
|
||||
s.license = { :file => '../LICENSE' }
|
||||
s.author = { 'yanshouwang' => 'yanshouwang@outlook.com' }
|
||||
|
||||
s.source = { :path => '.' }
|
||||
s.source_files = 'Classes/**/*'
|
||||
|
||||
s.ios.dependency 'Flutter'
|
||||
s.ios.deployment_target = '11.0'
|
||||
|
||||
s.osx.dependency 'FlutterMacOS'
|
||||
s.osx.deployment_target = '10.11'
|
||||
|
||||
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
|
||||
s.swift_version = '5.0'
|
||||
end
|
@ -0,0 +1,9 @@
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
|
||||
import 'src/my_central_controller.dart';
|
||||
|
||||
abstract class BluetoothLowEnergyDarwin {
|
||||
static void registerWith() {
|
||||
CentralController.instance = MyCentralController();
|
||||
}
|
||||
}
|
736
bluetooth_low_energy_darwin/lib/src/my_api.g.dart
Normal file
736
bluetooth_low_energy_darwin/lib/src/my_api.g.dart
Normal file
@ -0,0 +1,736 @@
|
||||
// Autogenerated from Pigeon (v10.1.6), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
|
||||
|
||||
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
enum MyCentralStateArgs {
|
||||
unknown,
|
||||
unsupported,
|
||||
unauthorized,
|
||||
poweredOff,
|
||||
poweredOn,
|
||||
}
|
||||
|
||||
enum MyGattCharacteristicPropertyArgs {
|
||||
read,
|
||||
write,
|
||||
writeWithoutResponse,
|
||||
notify,
|
||||
indicate,
|
||||
}
|
||||
|
||||
enum MyGattCharacteristicWriteTypeArgs {
|
||||
withResponse,
|
||||
withoutResponse,
|
||||
}
|
||||
|
||||
class MyCentralControllerArgs {
|
||||
MyCentralControllerArgs({
|
||||
required this.myStateNumber,
|
||||
});
|
||||
|
||||
int myStateNumber;
|
||||
|
||||
Object encode() {
|
||||
return <Object?>[
|
||||
myStateNumber,
|
||||
];
|
||||
}
|
||||
|
||||
static MyCentralControllerArgs decode(Object result) {
|
||||
result as List<Object?>;
|
||||
return MyCentralControllerArgs(
|
||||
myStateNumber: result[0]! as int,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyPeripheralArgs {
|
||||
MyPeripheralArgs({
|
||||
required this.key,
|
||||
required this.uuid,
|
||||
});
|
||||
|
||||
int key;
|
||||
|
||||
String uuid;
|
||||
|
||||
Object encode() {
|
||||
return <Object?>[
|
||||
key,
|
||||
uuid,
|
||||
];
|
||||
}
|
||||
|
||||
static MyPeripheralArgs decode(Object result) {
|
||||
result as List<Object?>;
|
||||
return MyPeripheralArgs(
|
||||
key: result[0]! as int,
|
||||
uuid: result[1]! as String,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyAdvertisementArgs {
|
||||
MyAdvertisementArgs({
|
||||
this.name,
|
||||
required this.manufacturerSpecificData,
|
||||
required this.serviceUUIDs,
|
||||
required this.serviceData,
|
||||
});
|
||||
|
||||
String? name;
|
||||
|
||||
Map<int?, Uint8List?> manufacturerSpecificData;
|
||||
|
||||
List<String?> serviceUUIDs;
|
||||
|
||||
Map<String?, Uint8List?> serviceData;
|
||||
|
||||
Object encode() {
|
||||
return <Object?>[
|
||||
name,
|
||||
manufacturerSpecificData,
|
||||
serviceUUIDs,
|
||||
serviceData,
|
||||
];
|
||||
}
|
||||
|
||||
static MyAdvertisementArgs decode(Object result) {
|
||||
result as List<Object?>;
|
||||
return MyAdvertisementArgs(
|
||||
name: result[0] as String?,
|
||||
manufacturerSpecificData: (result[1] as Map<Object?, Object?>?)!.cast<int?, Uint8List?>(),
|
||||
serviceUUIDs: (result[2] as List<Object?>?)!.cast<String?>(),
|
||||
serviceData: (result[3] as Map<Object?, Object?>?)!.cast<String?, Uint8List?>(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyGattServiceArgs {
|
||||
MyGattServiceArgs({
|
||||
required this.key,
|
||||
required this.uuid,
|
||||
});
|
||||
|
||||
int key;
|
||||
|
||||
String uuid;
|
||||
|
||||
Object encode() {
|
||||
return <Object?>[
|
||||
key,
|
||||
uuid,
|
||||
];
|
||||
}
|
||||
|
||||
static MyGattServiceArgs decode(Object result) {
|
||||
result as List<Object?>;
|
||||
return MyGattServiceArgs(
|
||||
key: result[0]! as int,
|
||||
uuid: result[1]! as String,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyGattCharacteristicArgs {
|
||||
MyGattCharacteristicArgs({
|
||||
required this.key,
|
||||
required this.uuid,
|
||||
required this.myPropertyNumbers,
|
||||
});
|
||||
|
||||
int key;
|
||||
|
||||
String uuid;
|
||||
|
||||
List<int?> myPropertyNumbers;
|
||||
|
||||
Object encode() {
|
||||
return <Object?>[
|
||||
key,
|
||||
uuid,
|
||||
myPropertyNumbers,
|
||||
];
|
||||
}
|
||||
|
||||
static MyGattCharacteristicArgs decode(Object result) {
|
||||
result as List<Object?>;
|
||||
return MyGattCharacteristicArgs(
|
||||
key: result[0]! as int,
|
||||
uuid: result[1]! as String,
|
||||
myPropertyNumbers: (result[2] as List<Object?>?)!.cast<int?>(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyGattDescriptorArgs {
|
||||
MyGattDescriptorArgs({
|
||||
required this.key,
|
||||
required this.uuid,
|
||||
});
|
||||
|
||||
int key;
|
||||
|
||||
String uuid;
|
||||
|
||||
Object encode() {
|
||||
return <Object?>[
|
||||
key,
|
||||
uuid,
|
||||
];
|
||||
}
|
||||
|
||||
static MyGattDescriptorArgs decode(Object result) {
|
||||
result as List<Object?>;
|
||||
return MyGattDescriptorArgs(
|
||||
key: result[0]! as int,
|
||||
uuid: result[1]! as String,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _MyCentralControllerHostApiCodec extends StandardMessageCodec {
|
||||
const _MyCentralControllerHostApiCodec();
|
||||
@override
|
||||
void writeValue(WriteBuffer buffer, Object? value) {
|
||||
if (value is MyCentralControllerArgs) {
|
||||
buffer.putUint8(128);
|
||||
writeValue(buffer, value.encode());
|
||||
} else if (value is MyGattCharacteristicArgs) {
|
||||
buffer.putUint8(129);
|
||||
writeValue(buffer, value.encode());
|
||||
} else if (value is MyGattDescriptorArgs) {
|
||||
buffer.putUint8(130);
|
||||
writeValue(buffer, value.encode());
|
||||
} else if (value is MyGattServiceArgs) {
|
||||
buffer.putUint8(131);
|
||||
writeValue(buffer, value.encode());
|
||||
} else {
|
||||
super.writeValue(buffer, value);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Object? readValueOfType(int type, ReadBuffer buffer) {
|
||||
switch (type) {
|
||||
case 128:
|
||||
return MyCentralControllerArgs.decode(readValue(buffer)!);
|
||||
case 129:
|
||||
return MyGattCharacteristicArgs.decode(readValue(buffer)!);
|
||||
case 130:
|
||||
return MyGattDescriptorArgs.decode(readValue(buffer)!);
|
||||
case 131:
|
||||
return MyGattServiceArgs.decode(readValue(buffer)!);
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MyCentralControllerHostApi {
|
||||
/// Constructor for [MyCentralControllerHostApi]. The [binaryMessenger] named argument is
|
||||
/// available for dependency injection. If it is left null, the default
|
||||
/// BinaryMessenger will be used which routes to the host platform.
|
||||
MyCentralControllerHostApi({BinaryMessenger? binaryMessenger})
|
||||
: _binaryMessenger = binaryMessenger;
|
||||
final BinaryMessenger? _binaryMessenger;
|
||||
|
||||
static const MessageCodec<Object?> codec = _MyCentralControllerHostApiCodec();
|
||||
|
||||
Future<MyCentralControllerArgs> setUp() async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.setUp', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(null) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else if (replyList[0] == null) {
|
||||
throw PlatformException(
|
||||
code: 'null-error',
|
||||
message: 'Host platform returned null value for non-null return value.',
|
||||
);
|
||||
} else {
|
||||
return (replyList[0] as MyCentralControllerArgs?)!;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> tearDown() async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.tearDown', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(null) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> startDiscovery() async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.startDiscovery', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(null) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stopDiscovery() async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.stopDiscovery', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(null) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> connect(int arg_myPeripheralKey) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.connect', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> disconnect(int arg_myPeripheralKey) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.disconnect', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> discoverGATT(int arg_myPeripheralKey) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.discoverGATT', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<MyGattServiceArgs?>> getServices(int arg_myPeripheralKey) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.getServices', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else if (replyList[0] == null) {
|
||||
throw PlatformException(
|
||||
code: 'null-error',
|
||||
message: 'Host platform returned null value for non-null return value.',
|
||||
);
|
||||
} else {
|
||||
return (replyList[0] as List<Object?>?)!.cast<MyGattServiceArgs?>();
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<MyGattCharacteristicArgs?>> getCharacteristics(int arg_myServiceKey) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.getCharacteristics', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myServiceKey]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else if (replyList[0] == null) {
|
||||
throw PlatformException(
|
||||
code: 'null-error',
|
||||
message: 'Host platform returned null value for non-null return value.',
|
||||
);
|
||||
} else {
|
||||
return (replyList[0] as List<Object?>?)!.cast<MyGattCharacteristicArgs?>();
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<MyGattDescriptorArgs?>> getDescriptors(int arg_myCharacteristicKey) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.getDescriptors', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myCharacteristicKey]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else if (replyList[0] == null) {
|
||||
throw PlatformException(
|
||||
code: 'null-error',
|
||||
message: 'Host platform returned null value for non-null return value.',
|
||||
);
|
||||
} else {
|
||||
return (replyList[0] as List<Object?>?)!.cast<MyGattDescriptorArgs?>();
|
||||
}
|
||||
}
|
||||
|
||||
Future<Uint8List> readCharacteristic(int arg_myPeripheralKey, int arg_myServiceKey, int arg_myCharacteristicKey) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.readCharacteristic', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myServiceKey, arg_myCharacteristicKey]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else if (replyList[0] == null) {
|
||||
throw PlatformException(
|
||||
code: 'null-error',
|
||||
message: 'Host platform returned null value for non-null return value.',
|
||||
);
|
||||
} else {
|
||||
return (replyList[0] as Uint8List?)!;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> writeCharacteristic(int arg_myPeripheralKey, int arg_myServiceKey, int arg_myCharacteristicKey, Uint8List arg_value, int arg_myTypeNumber) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.writeCharacteristic', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myServiceKey, arg_myCharacteristicKey, arg_value, arg_myTypeNumber]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> notifyCharacteristic(int arg_myPeripheralKey, int arg_myServiceKey, int arg_myCharacteristicKey, bool arg_state) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.notifyCharacteristic', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myServiceKey, arg_myCharacteristicKey, arg_state]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Uint8List> readDescriptor(int arg_myPeripheralKey, int arg_myCharacteristicKey, int arg_myDescriptorKey) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.readDescriptor', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myCharacteristicKey, arg_myDescriptorKey]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else if (replyList[0] == null) {
|
||||
throw PlatformException(
|
||||
code: 'null-error',
|
||||
message: 'Host platform returned null value for non-null return value.',
|
||||
);
|
||||
} else {
|
||||
return (replyList[0] as Uint8List?)!;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> writeDescriptor(int arg_myPeripheralKey, int arg_myCharacteristicKey, int arg_myDescriptorKey, Uint8List arg_value) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerHostApi.writeDescriptor', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final List<Object?>? replyList =
|
||||
await channel.send(<Object?>[arg_myPeripheralKey, arg_myCharacteristicKey, arg_myDescriptorKey, arg_value]) as List<Object?>?;
|
||||
if (replyList == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
);
|
||||
} else if (replyList.length > 1) {
|
||||
throw PlatformException(
|
||||
code: replyList[0]! as String,
|
||||
message: replyList[1] as String?,
|
||||
details: replyList[2],
|
||||
);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _MyCentralControllerFlutterApiCodec extends StandardMessageCodec {
|
||||
const _MyCentralControllerFlutterApiCodec();
|
||||
@override
|
||||
void writeValue(WriteBuffer buffer, Object? value) {
|
||||
if (value is MyAdvertisementArgs) {
|
||||
buffer.putUint8(128);
|
||||
writeValue(buffer, value.encode());
|
||||
} else if (value is MyPeripheralArgs) {
|
||||
buffer.putUint8(129);
|
||||
writeValue(buffer, value.encode());
|
||||
} else {
|
||||
super.writeValue(buffer, value);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Object? readValueOfType(int type, ReadBuffer buffer) {
|
||||
switch (type) {
|
||||
case 128:
|
||||
return MyAdvertisementArgs.decode(readValue(buffer)!);
|
||||
case 129:
|
||||
return MyPeripheralArgs.decode(readValue(buffer)!);
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class MyCentralControllerFlutterApi {
|
||||
static const MessageCodec<Object?> codec = _MyCentralControllerFlutterApiCodec();
|
||||
|
||||
void onStateChanged(int myStateNumber);
|
||||
|
||||
void onDiscovered(MyPeripheralArgs myPeripheralArgs, int rssi, MyAdvertisementArgs myAdvertisementArgs);
|
||||
|
||||
void onPeripheralStateChanged(int myPeripheralKey, bool state);
|
||||
|
||||
void onCharacteristicValueChanged(int myCharacteristicKey, Uint8List value);
|
||||
|
||||
static void setup(MyCentralControllerFlutterApi? api, {BinaryMessenger? binaryMessenger}) {
|
||||
{
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onStateChanged', codec,
|
||||
binaryMessenger: binaryMessenger);
|
||||
if (api == null) {
|
||||
channel.setMessageHandler(null);
|
||||
} else {
|
||||
channel.setMessageHandler((Object? message) async {
|
||||
assert(message != null,
|
||||
'Argument for dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onStateChanged was null.');
|
||||
final List<Object?> args = (message as List<Object?>?)!;
|
||||
final int? arg_myStateNumber = (args[0] as int?);
|
||||
assert(arg_myStateNumber != null,
|
||||
'Argument for dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onStateChanged was null, expected non-null int.');
|
||||
api.onStateChanged(arg_myStateNumber!);
|
||||
return;
|
||||
});
|
||||
}
|
||||
}
|
||||
{
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onDiscovered', codec,
|
||||
binaryMessenger: binaryMessenger);
|
||||
if (api == null) {
|
||||
channel.setMessageHandler(null);
|
||||
} else {
|
||||
channel.setMessageHandler((Object? message) async {
|
||||
assert(message != null,
|
||||
'Argument for dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onDiscovered was null.');
|
||||
final List<Object?> args = (message as List<Object?>?)!;
|
||||
final MyPeripheralArgs? arg_myPeripheralArgs = (args[0] as MyPeripheralArgs?);
|
||||
assert(arg_myPeripheralArgs != null,
|
||||
'Argument for dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onDiscovered was null, expected non-null MyPeripheralArgs.');
|
||||
final int? arg_rssi = (args[1] as int?);
|
||||
assert(arg_rssi != null,
|
||||
'Argument for dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onDiscovered was null, expected non-null int.');
|
||||
final MyAdvertisementArgs? arg_myAdvertisementArgs = (args[2] as MyAdvertisementArgs?);
|
||||
assert(arg_myAdvertisementArgs != null,
|
||||
'Argument for dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onDiscovered was null, expected non-null MyAdvertisementArgs.');
|
||||
api.onDiscovered(arg_myPeripheralArgs!, arg_rssi!, arg_myAdvertisementArgs!);
|
||||
return;
|
||||
});
|
||||
}
|
||||
}
|
||||
{
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onPeripheralStateChanged', codec,
|
||||
binaryMessenger: binaryMessenger);
|
||||
if (api == null) {
|
||||
channel.setMessageHandler(null);
|
||||
} else {
|
||||
channel.setMessageHandler((Object? message) async {
|
||||
assert(message != null,
|
||||
'Argument for dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onPeripheralStateChanged was null.');
|
||||
final List<Object?> args = (message as List<Object?>?)!;
|
||||
final int? arg_myPeripheralKey = (args[0] as int?);
|
||||
assert(arg_myPeripheralKey != null,
|
||||
'Argument for dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onPeripheralStateChanged was null, expected non-null int.');
|
||||
final bool? arg_state = (args[1] as bool?);
|
||||
assert(arg_state != null,
|
||||
'Argument for dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onPeripheralStateChanged was null, expected non-null bool.');
|
||||
api.onPeripheralStateChanged(arg_myPeripheralKey!, arg_state!);
|
||||
return;
|
||||
});
|
||||
}
|
||||
}
|
||||
{
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onCharacteristicValueChanged', codec,
|
||||
binaryMessenger: binaryMessenger);
|
||||
if (api == null) {
|
||||
channel.setMessageHandler(null);
|
||||
} else {
|
||||
channel.setMessageHandler((Object? message) async {
|
||||
assert(message != null,
|
||||
'Argument for dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onCharacteristicValueChanged was null.');
|
||||
final List<Object?> args = (message as List<Object?>?)!;
|
||||
final int? arg_myCharacteristicKey = (args[0] as int?);
|
||||
assert(arg_myCharacteristicKey != null,
|
||||
'Argument for dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onCharacteristicValueChanged was null, expected non-null int.');
|
||||
final Uint8List? arg_value = (args[1] as Uint8List?);
|
||||
assert(arg_value != null,
|
||||
'Argument for dev.flutter.pigeon.bluetooth_low_energy_darwin.MyCentralControllerFlutterApi.onCharacteristicValueChanged was null, expected non-null Uint8List.');
|
||||
api.onCharacteristicValueChanged(arg_myCharacteristicKey!, arg_value!);
|
||||
return;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
354
bluetooth_low_energy_darwin/lib/src/my_central_controller.dart
Normal file
354
bluetooth_low_energy_darwin/lib/src/my_central_controller.dart
Normal file
@ -0,0 +1,354 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
|
||||
import 'my_api.g.dart';
|
||||
import 'my_gatt_characteristic.dart';
|
||||
import 'my_gatt_descriptor.dart';
|
||||
import 'my_gatt_service.dart';
|
||||
import 'my_peripheral.dart';
|
||||
|
||||
class MyCentralController extends CentralController
|
||||
implements MyCentralControllerFlutterApi {
|
||||
MyCentralController()
|
||||
: _myApi = MyCentralControllerHostApi(),
|
||||
_stateChangedController = StreamController.broadcast(),
|
||||
_discoveredController = StreamController.broadcast(),
|
||||
_peripheralStateChangedController = StreamController.broadcast(),
|
||||
_characteristicValueChangedController = StreamController.broadcast(),
|
||||
_myPeripherals = {},
|
||||
_myServices = {},
|
||||
_myCharacteristics = {},
|
||||
_myDescriptors = {},
|
||||
_state = CentralState.unknown;
|
||||
|
||||
final MyCentralControllerHostApi _myApi;
|
||||
final StreamController<CentralStateChangedEventArgs> _stateChangedController;
|
||||
final StreamController<CentralDiscoveredEventArgs> _discoveredController;
|
||||
final StreamController<PeripheralStateChangedEventArgs>
|
||||
_peripheralStateChangedController;
|
||||
final StreamController<GattCharacteristicValueChangedEventArgs>
|
||||
_characteristicValueChangedController;
|
||||
final Map<int, MyPeripheral> _myPeripherals;
|
||||
final Map<int, MyGattService> _myServices;
|
||||
final Map<int, MyGattCharacteristic> _myCharacteristics;
|
||||
final Map<int, MyGattDescriptor> _myDescriptors;
|
||||
|
||||
CentralState _state;
|
||||
@override
|
||||
CentralState get state => _state;
|
||||
|
||||
@override
|
||||
Stream<CentralStateChangedEventArgs> get stateChanged =>
|
||||
_stateChangedController.stream;
|
||||
@override
|
||||
Stream<CentralDiscoveredEventArgs> get discovered =>
|
||||
_discoveredController.stream;
|
||||
@override
|
||||
Stream<PeripheralStateChangedEventArgs> get peripheralStateChanged =>
|
||||
_peripheralStateChangedController.stream;
|
||||
@override
|
||||
Stream<GattCharacteristicValueChangedEventArgs>
|
||||
get characteristicValueChanged =>
|
||||
_characteristicValueChangedController.stream;
|
||||
|
||||
Future<void> _throwWithState(CentralState state) async {
|
||||
if (this.state == state) {
|
||||
throw BluetoothLowEnergyError('$state is unexpected.');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _throwWithoutState(CentralState state) async {
|
||||
if (this.state != state) {
|
||||
throw BluetoothLowEnergyError(
|
||||
'$state is expected, but current state is ${this.state}.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setUp() async {
|
||||
await _throwWithoutState(CentralState.unknown);
|
||||
final args = await _myApi.setUp();
|
||||
final myStateArgs = MyCentralStateArgs.values[args.myStateNumber];
|
||||
_state = myStateArgs.toState();
|
||||
MyCentralControllerFlutterApi.setup(this);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> tearDown() async {
|
||||
await _throwWithState(CentralState.unknown);
|
||||
await _myApi.tearDown();
|
||||
MyCentralControllerFlutterApi.setup(null);
|
||||
_myPeripherals.clear();
|
||||
_myServices.clear();
|
||||
_myCharacteristics.clear();
|
||||
_myDescriptors.clear();
|
||||
_state = CentralState.unknown;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> startDiscovery() async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
await _myApi.startDiscovery();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stopDiscovery() async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
await _myApi.stopDiscovery();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> connect(Peripheral peripheral) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myPeripheral = peripheral as MyPeripheral;
|
||||
await _myApi.connect(myPeripheral.hashCode);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> disconnect(Peripheral peripheral) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myPeripheral = peripheral as MyPeripheral;
|
||||
await _myApi.disconnect(myPeripheral.hashCode);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> discoverGATT(Peripheral peripheral) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myPeripheral = peripheral as MyPeripheral;
|
||||
await _myApi.discoverGATT(myPeripheral.hashCode);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<GattService>> getServices(Peripheral peripheral) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myPeripheral = peripheral as MyPeripheral;
|
||||
final myServiceArgses = await _myApi.getServices(myPeripheral.hashCode);
|
||||
return myServiceArgses.cast<MyGattServiceArgs>().map(
|
||||
(myServiceArgs) {
|
||||
final myService = MyGattService.fromMyArgs(
|
||||
myPeripheral,
|
||||
myServiceArgs,
|
||||
);
|
||||
_myServices[myService.hashCode] = myService;
|
||||
return myService;
|
||||
},
|
||||
).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<GattCharacteristic>> getCharacteristics(
|
||||
GattService service,
|
||||
) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myService = service as MyGattService;
|
||||
final myCharactersiticArgses = await _myApi.getCharacteristics(
|
||||
myService.hashCode,
|
||||
);
|
||||
return myCharactersiticArgses.cast<MyGattCharacteristicArgs>().map(
|
||||
(myCharacteristicArgs) {
|
||||
final myCharacteristic = MyGattCharacteristic.fromMyArgs(
|
||||
myService,
|
||||
myCharacteristicArgs,
|
||||
);
|
||||
_myCharacteristics[myCharacteristic.hashCode] = myCharacteristic;
|
||||
return myCharacteristic;
|
||||
},
|
||||
).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<GattDescriptor>> getDescriptors(
|
||||
GattCharacteristic characteristic,
|
||||
) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myCharacteristic = characteristic as MyGattCharacteristic;
|
||||
final myDescriptorArgses = await _myApi.getDescriptors(
|
||||
myCharacteristic.hashCode,
|
||||
);
|
||||
return myDescriptorArgses.cast<MyGattDescriptorArgs>().map(
|
||||
(myDescriptorArgs) {
|
||||
final myDescriptor = MyGattDescriptor.fromMyArgs(
|
||||
myCharacteristic,
|
||||
myDescriptorArgs,
|
||||
);
|
||||
_myDescriptors[myDescriptor.hashCode] = myDescriptor;
|
||||
return myDescriptor;
|
||||
},
|
||||
).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> readCharacteristic(
|
||||
GattCharacteristic characteristic,
|
||||
) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myCharacteristic = characteristic as MyGattCharacteristic;
|
||||
final myService = myCharacteristic.myService;
|
||||
final myPeripheral = myService.myPeripheral;
|
||||
final value = await _myApi.readCharacteristic(
|
||||
myPeripheral.hashCode,
|
||||
myService.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
);
|
||||
return value;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeCharacteristic(
|
||||
GattCharacteristic characteristic, {
|
||||
required Uint8List value,
|
||||
required GattCharacteristicWriteType type,
|
||||
}) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myCharacteristic = characteristic as MyGattCharacteristic;
|
||||
final myService = myCharacteristic.myService;
|
||||
final myPeripheral = myService.myPeripheral;
|
||||
final typeArgs = type.toMyArgs();
|
||||
final typeNumber = typeArgs.index;
|
||||
await _myApi.writeCharacteristic(
|
||||
myPeripheral.hashCode,
|
||||
myService.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
value,
|
||||
typeNumber,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> notifyCharacteristic(
|
||||
GattCharacteristic characteristic, {
|
||||
required bool state,
|
||||
}) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myCharacteristic = characteristic as MyGattCharacteristic;
|
||||
final myService = myCharacteristic.myService;
|
||||
final myPeripheral = myService.myPeripheral;
|
||||
await _myApi.notifyCharacteristic(
|
||||
myPeripheral.hashCode,
|
||||
myService.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
state,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> readDescriptor(GattDescriptor descriptor) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myDescriptor = descriptor as MyGattDescriptor;
|
||||
final myCharacteristic = myDescriptor.myCharacteristic;
|
||||
final myService = myCharacteristic.myService;
|
||||
final myPeripheral = myService.myPeripheral;
|
||||
final value = await _myApi.readDescriptor(
|
||||
myPeripheral.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
myDescriptor.hashCode,
|
||||
);
|
||||
return value;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> writeDescriptor(
|
||||
GattDescriptor descriptor, {
|
||||
required Uint8List value,
|
||||
}) async {
|
||||
await _throwWithoutState(CentralState.poweredOn);
|
||||
final myDescriptor = descriptor as MyGattDescriptor;
|
||||
final myCharacteristic = myDescriptor.myCharacteristic;
|
||||
final myService = myCharacteristic.myService;
|
||||
final myPeripheral = myService.myPeripheral;
|
||||
await _myApi.writeDescriptor(
|
||||
myPeripheral.hashCode,
|
||||
myCharacteristic.hashCode,
|
||||
myDescriptor.hashCode,
|
||||
value,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onStateChanged(int myStateNumber) {
|
||||
final myStateArgs = MyCentralStateArgs.values[myStateNumber];
|
||||
final state = myStateArgs.toState();
|
||||
if (_state == state) {
|
||||
return;
|
||||
}
|
||||
_state = state;
|
||||
final eventArgs = CentralStateChangedEventArgs(state);
|
||||
_stateChangedController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onDiscovered(
|
||||
MyPeripheralArgs myPeripheralArgs,
|
||||
int rssi,
|
||||
MyAdvertisementArgs myAdvertisementArgs,
|
||||
) {
|
||||
final myPeripheral = MyPeripheral.fromMyArgs(myPeripheralArgs);
|
||||
_myPeripherals[myPeripheral.hashCode] = myPeripheral;
|
||||
final advertisement = myAdvertisementArgs.toAdvertisement();
|
||||
final eventArgs = CentralDiscoveredEventArgs(
|
||||
myPeripheral,
|
||||
rssi,
|
||||
advertisement,
|
||||
);
|
||||
_discoveredController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onPeripheralStateChanged(int myPeripheralKey, bool state) {
|
||||
final myPeripheral = _myPeripherals[myPeripheralKey];
|
||||
if (myPeripheral == null) {
|
||||
return;
|
||||
}
|
||||
final eventArgs = PeripheralStateChangedEventArgs(myPeripheral, state);
|
||||
_peripheralStateChangedController.add(eventArgs);
|
||||
}
|
||||
|
||||
@override
|
||||
void onCharacteristicValueChanged(int myCharacteristicKey, Uint8List value) {
|
||||
final myCharacteristic =
|
||||
_myCharacteristics[myCharacteristicKey] as MyGattCharacteristic;
|
||||
final eventArgs = GattCharacteristicValueChangedEventArgs(
|
||||
myCharacteristic,
|
||||
value,
|
||||
);
|
||||
_characteristicValueChangedController.add(eventArgs);
|
||||
}
|
||||
}
|
||||
|
||||
extension on MyAdvertisementArgs {
|
||||
Advertisement toAdvertisement() {
|
||||
final serviceUUIDs = this
|
||||
.serviceUUIDs
|
||||
.cast<String>()
|
||||
.map((uuid) => UUID.fromString(uuid))
|
||||
.toList();
|
||||
final serviceData = this.serviceData.cast<String, Uint8List>().map(
|
||||
(uuid, data) {
|
||||
final key = UUID.fromString(uuid);
|
||||
final value = data;
|
||||
return MapEntry(key, value);
|
||||
},
|
||||
);
|
||||
return Advertisement(
|
||||
name: name,
|
||||
manufacturerSpecificData: manufacturerSpecificData.cast<int, Uint8List>(),
|
||||
serviceUUIDs: serviceUUIDs,
|
||||
serviceData: serviceData,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
extension on MyCentralStateArgs {
|
||||
CentralState toState() {
|
||||
return CentralState.values[index];
|
||||
}
|
||||
}
|
||||
|
||||
extension on GattCharacteristicWriteType {
|
||||
MyGattCharacteristicWriteTypeArgs toMyArgs() {
|
||||
return MyGattCharacteristicWriteTypeArgs.values[index];
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
|
||||
import 'my_api.g.dart';
|
||||
import 'my_gatt_service.dart';
|
||||
import 'my_object.dart';
|
||||
|
||||
class MyGattCharacteristic extends MyObject implements GattCharacteristic {
|
||||
final MyGattService myService;
|
||||
@override
|
||||
final UUID uuid;
|
||||
@override
|
||||
final List<GattCharacteristicProperty> properties;
|
||||
|
||||
MyGattCharacteristic(
|
||||
super.hashCode,
|
||||
this.myService,
|
||||
this.uuid,
|
||||
this.properties,
|
||||
);
|
||||
|
||||
factory MyGattCharacteristic.fromMyArgs(
|
||||
MyGattService myService,
|
||||
MyGattCharacteristicArgs myArgs,
|
||||
) {
|
||||
final hashCode = myArgs.key;
|
||||
final uuid = UUID.fromString(myArgs.uuid);
|
||||
final properties = myArgs.myPropertyNumbers.cast<int>().map(
|
||||
(myPropertyNumber) {
|
||||
final myPropertyArgs =
|
||||
MyGattCharacteristicPropertyArgs.values[myPropertyNumber];
|
||||
return myPropertyArgs.toProperty();
|
||||
},
|
||||
).toList();
|
||||
return MyGattCharacteristic(hashCode, myService, uuid, properties);
|
||||
}
|
||||
}
|
||||
|
||||
extension on MyGattCharacteristicPropertyArgs {
|
||||
GattCharacteristicProperty toProperty() {
|
||||
return GattCharacteristicProperty.values[index];
|
||||
}
|
||||
}
|
22
bluetooth_low_energy_darwin/lib/src/my_gatt_descriptor.dart
Normal file
22
bluetooth_low_energy_darwin/lib/src/my_gatt_descriptor.dart
Normal file
@ -0,0 +1,22 @@
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
|
||||
import 'my_api.g.dart';
|
||||
import 'my_gatt_characteristic.dart';
|
||||
import 'my_object.dart';
|
||||
|
||||
class MyGattDescriptor extends MyObject implements GattDescriptor {
|
||||
final MyGattCharacteristic myCharacteristic;
|
||||
@override
|
||||
final UUID uuid;
|
||||
|
||||
MyGattDescriptor(super.hashCode, this.myCharacteristic, this.uuid);
|
||||
|
||||
factory MyGattDescriptor.fromMyArgs(
|
||||
MyGattCharacteristic myCharacteristic,
|
||||
MyGattDescriptorArgs myArgs,
|
||||
) {
|
||||
final hashCode = myArgs.key;
|
||||
final uuid = UUID.fromString(myArgs.uuid);
|
||||
return MyGattDescriptor(hashCode, myCharacteristic, uuid);
|
||||
}
|
||||
}
|
22
bluetooth_low_energy_darwin/lib/src/my_gatt_service.dart
Normal file
22
bluetooth_low_energy_darwin/lib/src/my_gatt_service.dart
Normal file
@ -0,0 +1,22 @@
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
|
||||
import 'my_api.g.dart';
|
||||
import 'my_object.dart';
|
||||
import 'my_peripheral.dart';
|
||||
|
||||
class MyGattService extends MyObject implements GattService {
|
||||
final MyPeripheral myPeripheral;
|
||||
@override
|
||||
final UUID uuid;
|
||||
|
||||
MyGattService(super.hashCode, this.myPeripheral, this.uuid);
|
||||
|
||||
factory MyGattService.fromMyArgs(
|
||||
MyPeripheral myPeripheral,
|
||||
MyGattServiceArgs myArgs,
|
||||
) {
|
||||
final hashCode = myArgs.key;
|
||||
final uuid = UUID.fromString(myArgs.uuid);
|
||||
return MyGattService(hashCode, myPeripheral, uuid);
|
||||
}
|
||||
}
|
11
bluetooth_low_energy_darwin/lib/src/my_object.dart
Normal file
11
bluetooth_low_energy_darwin/lib/src/my_object.dart
Normal file
@ -0,0 +1,11 @@
|
||||
abstract class MyObject {
|
||||
@override
|
||||
final int hashCode;
|
||||
|
||||
MyObject(this.hashCode);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is MyObject && other.hashCode == hashCode;
|
||||
}
|
||||
}
|
17
bluetooth_low_energy_darwin/lib/src/my_peripheral.dart
Normal file
17
bluetooth_low_energy_darwin/lib/src/my_peripheral.dart
Normal file
@ -0,0 +1,17 @@
|
||||
import 'package:bluetooth_low_energy_platform_interface/bluetooth_low_energy_platform_interface.dart';
|
||||
|
||||
import 'my_api.g.dart';
|
||||
import 'my_object.dart';
|
||||
|
||||
class MyPeripheral extends MyObject implements Peripheral {
|
||||
@override
|
||||
final UUID uuid;
|
||||
|
||||
MyPeripheral(super.hashCode, this.uuid);
|
||||
|
||||
factory MyPeripheral.fromMyArgs(MyPeripheralArgs myArgs) {
|
||||
final hashCode = myArgs.key;
|
||||
final uuid = UUID.fromString(myArgs.uuid);
|
||||
return MyPeripheral(hashCode, uuid);
|
||||
}
|
||||
}
|
151
bluetooth_low_energy_darwin/my_api.dart
Normal file
151
bluetooth_low_energy_darwin/my_api.dart
Normal file
@ -0,0 +1,151 @@
|
||||
import 'package:pigeon/pigeon.dart';
|
||||
|
||||
@ConfigurePigeon(
|
||||
PigeonOptions(
|
||||
dartOut: 'lib/src/my_api.g.dart',
|
||||
dartOptions: DartOptions(),
|
||||
swiftOut: 'darwin/Classes/MyApi.g.swift',
|
||||
swiftOptions: SwiftOptions(),
|
||||
),
|
||||
)
|
||||
@HostApi()
|
||||
abstract class MyCentralControllerHostApi {
|
||||
@async
|
||||
MyCentralControllerArgs setUp();
|
||||
void tearDown();
|
||||
void startDiscovery();
|
||||
void stopDiscovery();
|
||||
@async
|
||||
void connect(int myPeripheralKey);
|
||||
@async
|
||||
void disconnect(int myPeripheralKey);
|
||||
@async
|
||||
void discoverGATT(int myPeripheralKey);
|
||||
List<MyGattServiceArgs> getServices(int myPeripheralKey);
|
||||
List<MyGattCharacteristicArgs> getCharacteristics(int myServiceKey);
|
||||
List<MyGattDescriptorArgs> getDescriptors(int myCharacteristicKey);
|
||||
@async
|
||||
Uint8List readCharacteristic(
|
||||
int myPeripheralKey,
|
||||
int myServiceKey,
|
||||
int myCharacteristicKey,
|
||||
);
|
||||
@async
|
||||
void writeCharacteristic(
|
||||
int myPeripheralKey,
|
||||
int myServiceKey,
|
||||
int myCharacteristicKey,
|
||||
Uint8List value,
|
||||
int myTypeNumber,
|
||||
);
|
||||
@async
|
||||
void notifyCharacteristic(
|
||||
int myPeripheralKey,
|
||||
int myServiceKey,
|
||||
int myCharacteristicKey,
|
||||
bool state,
|
||||
);
|
||||
@async
|
||||
Uint8List readDescriptor(
|
||||
int myPeripheralKey,
|
||||
int myCharacteristicKey,
|
||||
int myDescriptorKey,
|
||||
);
|
||||
@async
|
||||
void writeDescriptor(
|
||||
int myPeripheralKey,
|
||||
int myCharacteristicKey,
|
||||
int myDescriptorKey,
|
||||
Uint8List value,
|
||||
);
|
||||
}
|
||||
|
||||
@FlutterApi()
|
||||
abstract class MyCentralControllerFlutterApi {
|
||||
void onStateChanged(int myStateNumber);
|
||||
void onDiscovered(
|
||||
MyPeripheralArgs myPeripheralArgs,
|
||||
int rssi,
|
||||
MyAdvertisementArgs myAdvertisementArgs,
|
||||
);
|
||||
void onPeripheralStateChanged(int myPeripheralKey, bool state);
|
||||
void onCharacteristicValueChanged(int myCharacteristicKey, Uint8List value);
|
||||
}
|
||||
|
||||
class MyCentralControllerArgs {
|
||||
final int myStateNumber;
|
||||
|
||||
MyCentralControllerArgs(this.myStateNumber);
|
||||
}
|
||||
|
||||
class MyPeripheralArgs {
|
||||
final int key;
|
||||
final String uuid;
|
||||
|
||||
MyPeripheralArgs(this.key, this.uuid);
|
||||
}
|
||||
|
||||
class MyAdvertisementArgs {
|
||||
final String? name;
|
||||
final Map<int?, Uint8List?> manufacturerSpecificData;
|
||||
final List<String?> serviceUUIDs;
|
||||
final Map<String?, Uint8List?> serviceData;
|
||||
|
||||
MyAdvertisementArgs(
|
||||
this.name,
|
||||
this.manufacturerSpecificData,
|
||||
this.serviceUUIDs,
|
||||
this.serviceData,
|
||||
);
|
||||
}
|
||||
|
||||
class MyGattServiceArgs {
|
||||
final int key;
|
||||
final String uuid;
|
||||
|
||||
MyGattServiceArgs(this.key, this.uuid);
|
||||
}
|
||||
|
||||
class MyGattCharacteristicArgs {
|
||||
final int key;
|
||||
final String uuid;
|
||||
final List<int?> myPropertyNumbers;
|
||||
|
||||
MyGattCharacteristicArgs(
|
||||
this.key,
|
||||
this.uuid,
|
||||
this.myPropertyNumbers,
|
||||
);
|
||||
}
|
||||
|
||||
class MyGattDescriptorArgs {
|
||||
final int key;
|
||||
final String uuid;
|
||||
|
||||
MyGattDescriptorArgs(this.key, this.uuid);
|
||||
}
|
||||
|
||||
enum MyCentralStateArgs {
|
||||
unknown,
|
||||
unsupported,
|
||||
unauthorized,
|
||||
poweredOff,
|
||||
poweredOn,
|
||||
}
|
||||
|
||||
enum MyGattCharacteristicPropertyArgs {
|
||||
read,
|
||||
write,
|
||||
writeWithoutResponse,
|
||||
notify,
|
||||
indicate,
|
||||
}
|
||||
|
||||
enum MyGattCharacteristicWriteTypeArgs {
|
||||
// Write with response
|
||||
withResponse,
|
||||
// Write without response
|
||||
withoutResponse,
|
||||
// Write with response and waiting for confirmation
|
||||
// reliable,
|
||||
}
|
31
bluetooth_low_energy_darwin/pubspec.yaml
Normal file
31
bluetooth_low_energy_darwin/pubspec.yaml
Normal file
@ -0,0 +1,31 @@
|
||||
name: bluetooth_low_energy_darwin
|
||||
description: iOS and macOS implementation of the bluetooth_low_energy plugin.
|
||||
version: 2.0.2
|
||||
homepage: https://github.com/yanshouwang/bluetooth_low_energy
|
||||
|
||||
environment:
|
||||
sdk: ">=3.0.0 <4.0.0"
|
||||
flutter: ">=3.3.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
bluetooth_low_energy_platform_interface: ^2.0.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^2.0.0
|
||||
pigeon: ^10.1.6
|
||||
|
||||
flutter:
|
||||
plugin:
|
||||
platforms:
|
||||
ios:
|
||||
pluginClass: BluetoothLowEnergyDarwin
|
||||
sharedDarwinSource: true
|
||||
dartPluginClass: BluetoothLowEnergyDarwin
|
||||
macos:
|
||||
pluginClass: BluetoothLowEnergyDarwin
|
||||
sharedDarwinSource: true
|
||||
dartPluginClass: BluetoothLowEnergyDarwin
|
Reference in New Issue
Block a user