* 调整接口

* 临时提交

* 重构 Android 平台代码

* 临时提交

* 临时提交

* Android 6.0.0-dev.0

* 临时提交

* 实现 Windows 接口

* windows-6.0.0-dev.0

* Darwin 6.0.0-dev.0

* 临时提交

* 1

* 临时提交

* 调整接口

* windows-6.0.0-dev.1

* 临时提交

* interface-6.0.0-dev.7

* interface-6.0.0-dev.8

* 临时提交

* windows-6.0.0-dev.2

* 删除多余脚本

* interface-6.0.0-dev.9

* 临时提交

* 临时提交

* interface-6.0.0-dev.10

* android-6.0.0-dev.1

* windows-6.0.0-dev.3

* 临时提交

* interface-6.0.0-dev.11

* windows-6.0.0-dev.4

* 更新 pubspec.lock

* 1

* interface-6.0.0-dev.12

* interface-6.0.0-dev.13

* interface-6.0.0-dev.14

* 临时提交

* interface-6.0.0-dev.15

* 临时提交

* interface-6.0.0-dev.16

* android-6.0.0-dev.2

* 临时提交

* windows-6.0.0-dev.5

* 临时提交

* 临时提交

* windows-6.0.0-dev.6

* 优化注释和代码样式

* 优化代码

* 临时提交

* 实现 Dart 接口

* darwin-6.0.0-dev.0

* linux-6.0.0-dev.0

* 修复已知问题

* 修复问题

* 6.0.0-dev.0

* 修改包名

* 更新版本

* 移除原生部分

* 临时提交

* 修复问题

* 更新 pigeon 19.0.0

* 更新 README,添加迁移文档

* linux-6.0.0-dev.1

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

* 修复 googletest 版本警告问题

* Use centralArgs instead of addressArgs

* interface-6.0.0-dev.18

* android-6.0.0-dev.4

* linux-6.0.0-dev.2

* windows-6.0.0-dev.8

* darwin-6.0.0-dev.2

* 6.0.0-dev.1

* Update LICENSE

* clang-format

* Combine ADV_IND and SCAN_RES

* TEMP commit: update exampe

* Adjust advertisement combine logic

* Implement `MyPeripheralMananger` on Windows

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

* fetch nuget using other technique

* move FetchContent to right location in CMakeLists.txt

* also added hash for googletest

---------

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

* Fix errors.

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

* Sort code

* Fix known errors

* interface-6.0.0-dev.19

* windows-6.0.0-dev.9

* Optimize example

* android-6.0.0-dev.5

* Optimize the Adverrtisement BottomSheet.

* linux-6.0.0-dev.3

* Update dependency

* Fix example errors.

* Temp commit.

* darwin-6.0.0-dev.3

* 6.0.0-dev.2

* Update README.md

* 6.0.0

* darwin-6.0.0-dev.4

* android-6.0.0-dev.6

* 6.0.0-dev.3

* Update docs.

* interface-6.0.0

* android-6.0.0

* darwin-6.0.0

* linux-6.0.0

* windows-6.0.0

* 6.0.0

* Update dependency

---------

Co-authored-by: Kevin De Keyser <dekeyser.kevin97@gmail.com>
Co-authored-by: Kevin De Keyser <kevin@dekeyser.ch>
This commit is contained in:
渐渐被你吸引
2024-06-04 00:44:39 +08:00
committed by GitHub
parent 71de531ceb
commit 108b6a804f
380 changed files with 23782 additions and 14127 deletions

View File

@ -0,0 +1,38 @@
.idea/
.vagrant/
.sconsign.dblite
.svn/
.DS_Store
*.swp
profile
DerivedData/
build/
GeneratedPluginRegistrant.h
GeneratedPluginRegistrant.m
.generated/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
/Flutter/Generated.xcconfig
/Flutter/ephemeral/
/Flutter/flutter_export_environment.sh

View File

@ -8,7 +8,7 @@ import FlutterMacOS
#error("Unsupported platform.")
#endif
public class BluetoothLowEnergyDarwin: NSObject, FlutterPlugin {
public class BluetoothLowEnergyDarwinPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
#if os(iOS)
let messenger = registrar.messenger()
@ -19,7 +19,7 @@ public class BluetoothLowEnergyDarwin: NSObject, FlutterPlugin {
#endif
let centralManager = MyCentralManager(messenger: messenger)
let peripheralManager = MyPeripheralManager(messenger: messenger)
MyCentralManagerHostApiSetup.setUp(binaryMessenger: messenger, api: centralManager)
MyPeripheralManagerHostApiSetup.setUp(binaryMessenger: messenger, api: peripheralManager)
MyCentralManagerHostAPISetup.setUp(binaryMessenger: messenger, api: centralManager)
MyPeripheralManagerHostAPISetup.setUp(binaryMessenger: messenger, api: peripheralManager)
}
}

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@ import FlutterMacOS
#endif
// ToObj
extension [MyGattCharacteristicPropertyArgs] {
extension [MyGATTCharacteristicPropertyArgs] {
func toProperties() -> CBCharacteristicProperties {
var properties: CBCharacteristicProperties = []
for args in self {
@ -36,24 +36,28 @@ extension [MyGattCharacteristicPropertyArgs] {
}
return properties
}
}
extension [MyGATTCharacteristicPermissionArgs] {
func toPermissions() -> CBAttributePermissions {
var permissions: CBAttributePermissions = []
for args in self {
switch args {
case .read:
permissions.insert(.readable)
case .write, .writeWithoutResponse:
case .readEncrypted:
permissions.insert(.readEncryptionRequired)
case .write:
permissions.insert(.writeable)
default:
continue
case .writeEncrypted:
permissions.insert(.writeEncryptionRequired)
}
}
return permissions
}
}
extension MyGattCharacteristicWriteTypeArgs {
extension MyGATTCharacteristicWriteTypeArgs {
func toWriteType() -> CBCharacteristicWriteType {
switch self {
case .withResponse:
@ -64,7 +68,7 @@ extension MyGattCharacteristicWriteTypeArgs {
}
}
extension MyGattErrorArgs {
extension MyATTErrorArgs {
func toError() -> CBATTError.Code {
switch self {
case .success:
@ -116,22 +120,15 @@ extension MyAdvertisementArgs {
let name = nameArgs!
advertisement[CBAdvertisementDataLocalNameKey] = name
}
if serviceUUIDsArgs.count > 0 {
var serviceUUIDs = [CBUUID]()
for args in serviceUUIDsArgs {
guard let uuidArgs = args else {
continue
}
let uuid = uuidArgs.toCBUUID()
serviceUUIDs.append(uuid)
}
if !serviceUUIDsArgs.isEmpty {
let serviceUUIDs = serviceUUIDsArgs.map { serviceUUIDArgs in serviceUUIDArgs!.toCBUUID() }
advertisement[CBAdvertisementDataServiceUUIDsKey] = serviceUUIDs
}
return advertisement
}
}
extension MyGattDescriptorArgs {
extension MyMutableGATTDescriptorArgs {
func toDescriptor() -> CBMutableDescriptor {
let type = uuidArgs.toCBUUID()
let value = valueArgs?.data
@ -139,30 +136,28 @@ extension MyGattDescriptorArgs {
}
}
extension MyGattCharacteristicArgs {
extension MyMutableGATTCharacteristicArgs {
func toCharacteristic() -> CBMutableCharacteristic {
let type = uuidArgs.toCBUUID()
var propertiesArgs = [MyGattCharacteristicPropertyArgs]()
for args in propertyNumbersArgs {
guard let propertyNumberArgs = args else {
continue
}
let propertyNumber = propertyNumberArgs.toInt()
guard let propertyArgs = MyGattCharacteristicPropertyArgs(rawValue: propertyNumber) else {
continue
}
propertiesArgs.append(propertyArgs)
let propertiesArgs = propertyNumbersArgs.map { propertyNumberArgs in
let propertyNumber = propertyNumberArgs!.toInt()
return MyGATTCharacteristicPropertyArgs(rawValue: propertyNumber)!
}
let properties = propertiesArgs.toProperties()
let permissions = propertiesArgs.toPermissions()
return CBMutableCharacteristic(type: type, properties: properties, value: nil, permissions: permissions)
let value = valueArgs?.data
let permissionsArgs = permissionNumbersArgs.map { permissionNumberArgs in
let permissionNumber = permissionNumberArgs!.toInt()
return MyGATTCharacteristicPermissionArgs(rawValue: permissionNumber)!
}
let permissions = permissionsArgs.toPermissions()
return CBMutableCharacteristic(type: type, properties: properties, value: value, permissions: permissions)
}
}
extension MyGattServiceArgs {
extension MyMutableGATTServiceArgs {
func toService() -> CBMutableService {
let type = uuidArgs.toCBUUID()
let primary = true
let primary = isPrimaryArgs
return CBMutableService(type: type, primary: primary)
}
}
@ -199,19 +194,6 @@ extension CBManagerState {
}
}
extension Data {
func toManufacturerSpecificDataArgs() -> MyManufacturerSpecificDataArgs? {
if count > 2 {
let idArgs = Int64(self[0]) | (Int64(self[1]) << 8)
let data = self[2...count - 1]
let dataArgs = FlutterStandardTypedData(bytes: data)
return MyManufacturerSpecificDataArgs(idArgs: idArgs, dataArgs: dataArgs)
} else {
return nil
}
}
}
extension [String: Any] {
func toAdvertisementArgs() -> MyAdvertisementArgs {
let nameArgs = self[CBAdvertisementDataLocalNameKey] as? String
@ -224,8 +206,8 @@ extension [String: Any] {
return (uuidArgs, dataArgs)
}
let serviceDataArgs = [String?: FlutterStandardTypedData?](uniqueKeysWithValues: serviceDataArgsKeyWithValues)
let manufacturerSpecificData = self[CBAdvertisementDataManufacturerDataKey] as? Data
let manufacturerSpecificDataArgs = manufacturerSpecificData?.toManufacturerSpecificDataArgs()
let manufacturerData = self[CBAdvertisementDataManufacturerDataKey] as? Data
let manufacturerSpecificDataArgs = manufacturerData == nil ? nil : FlutterStandardTypedData(bytes: manufacturerData!)
return MyAdvertisementArgs(nameArgs: nameArgs, serviceUUIDsArgs: serviceUUIDsArgs, serviceDataArgs: serviceDataArgs, manufacturerSpecificDataArgs: manufacturerSpecificDataArgs)
}
}
@ -245,26 +227,26 @@ extension CBPeripheral {
}
extension CBDescriptor {
func toArgs() -> MyGattDescriptorArgs {
func toArgs() -> MyGATTDescriptorArgs {
let hashCodeArgs = hash.toInt64()
let uuidArgs = uuid.toArgs()
return MyGattDescriptorArgs(hashCodeArgs: hashCodeArgs, uuidArgs: uuidArgs)
return MyGATTDescriptorArgs(hashCodeArgs: hashCodeArgs, uuidArgs: uuidArgs)
}
}
extension CBCharacteristic {
func toArgs() -> MyGattCharacteristicArgs {
func toArgs() -> MyGATTCharacteristicArgs {
let hashCodeArgs = hash.toInt64()
let uuidArgs = uuid.toArgs()
let propertyNumbersArgs = properties.toArgs().map { args in args.rawValue.toInt64() }
let descriptorsArgs = descriptors?.map { descriptor in descriptor.toArgs() } ?? []
return MyGattCharacteristicArgs(hashCodeArgs: hashCodeArgs, uuidArgs: uuidArgs, propertyNumbersArgs: propertyNumbersArgs, descriptorsArgs: descriptorsArgs)
return MyGATTCharacteristicArgs(hashCodeArgs: hashCodeArgs, uuidArgs: uuidArgs, propertyNumbersArgs: propertyNumbersArgs, descriptorsArgs: descriptorsArgs)
}
}
extension CBCharacteristicProperties {
func toArgs() -> [MyGattCharacteristicPropertyArgs] {
var args = [MyGattCharacteristicPropertyArgs]()
func toArgs() -> [MyGATTCharacteristicPropertyArgs] {
var args = [MyGATTCharacteristicPropertyArgs]()
if contains(.read) {
args.append(.read)
}
@ -285,11 +267,13 @@ extension CBCharacteristicProperties {
}
extension CBService {
func toArgs() -> MyGattServiceArgs {
func toArgs() -> MyGATTServiceArgs {
let hashCodeArgs = hash.toInt64()
let uuidArgs = uuid.toArgs()
let isPrimaryArgs = isPrimary
let includedServicesArgs = includedServices?.map { includedService in includedService.toArgs() } ?? []
let characteristicsArgs = characteristics?.map { characteristic in characteristic.toArgs() } ?? []
return MyGattServiceArgs(hashCodeArgs: hashCodeArgs, uuidArgs: uuidArgs, characteristicsArgs: characteristicsArgs)
return MyGATTServiceArgs(hashCodeArgs: hashCodeArgs, uuidArgs: uuidArgs, isPrimaryArgs: isPrimaryArgs, includedServicesArgs: includedServicesArgs, characteristicsArgs: characteristicsArgs)
}
}
@ -311,24 +295,9 @@ extension CBUUID {
}
}
// This extension of Error is required to do use FlutterError in any Swift code.
extension FlutterError: Error {}
extension String {
var data: Data { data(using: String.Encoding.utf8)! }
}
extension NSNumber {
var data: Data {
var source = self
// TODO: resolve warning: Forming 'UnsafeRawPointer' to a variable of type 'NSNumber'; this is likely incorrect because 'NSNumber' may contain an object reference.
return Data(bytes: &source, count: MemoryLayout<NSNumber>.size)
}
}
extension UInt16 {
var data: Data {
var source = self
return Data(bytes: &source, count: MemoryLayout<UInt16>.size)
var bytes = self
return Data(bytes: &bytes, count: MemoryLayout<UInt16>.size)
}
}

File diff suppressed because it is too large Load Diff

View File

@ -16,76 +16,142 @@ import FlutterMacOS
#error("Unsupported platform.")
#endif
class MyCentralManager: MyCentralManagerHostApi {
private let _api: MyCentralManagerFlutterApi
private let _centralManager: CBCentralManager
class MyCentralManager: MyCentralManagerHostAPI {
private let mAPI: MyCentralManagerFlutterAPI
private let mCentralManager: CBCentralManager
private lazy var _centralManagerDelegate = MyCentralManagerDelegate(centralManager: self)
private lazy var _peripheralDelegate = MyPeripheralDelegate(centralManager: self)
private lazy var mCentralManagerDelegate = MyCentralManagerDelegate(centralManager: self)
private lazy var peripheralDelegate = MyPeripheralDelegate(centralManager: self)
private var _peripherals: [String: CBPeripheral]
private var _services: [String: [Int64: CBService]]
private var _characteristics: [String: [Int64: CBCharacteristic]]
private var _descriptors: [String: [Int64: CBDescriptor]]
private var mPeripherals: [String: CBPeripheral]
private var mServices: [String: [Int64: CBService]]
private var mCharacteristics: [String: [Int64: CBCharacteristic]]
private var mDescriptors: [String: [Int64: CBDescriptor]]
private var _connectCompletions: [String: (Result<Void, Error>) -> Void]
private var _disconnectCompletions: [String: (Result<Void, Error>) -> Void]
private var _readRssiCompletions: [String: (Result<Int64, Error>) -> Void]
private var _discoverServicesCompletions: [String: (Result<[MyGattServiceArgs], Error>) -> Void]
private var _discoverCharacteristicsCompletions: [String: [Int64: (Result<[MyGattCharacteristicArgs], Error>) -> Void]]
private var _discoverDescriptorsCompletions: [String: [Int64: (Result<[MyGattDescriptorArgs], Error>) -> Void]]
private var _readCharacteristicCompletions: [String: [Int64: (Result<FlutterStandardTypedData, Error>) -> Void]]
private var _writeCharacteristicCompletions: [String: [Int64: (Result<Void, Error>) -> Void]]
private var _setCharacteristicNotifyStateCompletions: [String: [Int64: (Result<Void, Error>) -> Void]]
private var _readDescriptorCompletions: [String: [Int64: (Result<FlutterStandardTypedData, Error>) -> Void]]
private var _writeDescriptorCompletions: [String: [Int64: (Result<Void, Error>) -> Void]]
private var mConnectCompletions: [String: (Result<Void, Error>) -> Void]
private var mDisconnectCompletions: [String: (Result<Void, Error>) -> Void]
private var mReadRSSICompletions: [String: (Result<Int64, Error>) -> Void]
private var mDiscoverServicesCompletions: [String: (Result<[MyGATTServiceArgs], Error>) -> Void]
private var mDiscoverIncludedServicesCompletions: [String: [Int64: (Result<[MyGATTServiceArgs], Error>) -> Void]]
private var mDiscoverCharacteristicsCompletions: [String: [Int64: (Result<[MyGATTCharacteristicArgs], Error>) -> Void]]
private var mDiscoverDescriptorsCompletions: [String: [Int64: (Result<[MyGATTDescriptorArgs], Error>) -> Void]]
private var mReadCharacteristicCompletions: [String: [Int64: (Result<FlutterStandardTypedData, Error>) -> Void]]
private var mWriteCharacteristicCompletions: [String: [Int64: (Result<Void, Error>) -> Void]]
private var mSetCharacteristicNotifyStateCompletions: [String: [Int64: (Result<Void, Error>) -> Void]]
private var mReadDescriptorCompletions: [String: [Int64: (Result<FlutterStandardTypedData, Error>) -> Void]]
private var mWriteDescriptorCompletions: [String: [Int64: (Result<Void, Error>) -> Void]]
init(messenger: FlutterBinaryMessenger) {
_api = MyCentralManagerFlutterApi(binaryMessenger: messenger)
_centralManager = CBCentralManager()
mAPI = MyCentralManagerFlutterAPI(binaryMessenger: messenger)
mCentralManager = CBCentralManager()
_peripherals = [:]
_services = [:]
_characteristics = [:]
_descriptors = [:]
mPeripherals = [:]
mServices = [:]
mCharacteristics = [:]
mDescriptors = [:]
_connectCompletions = [:]
_disconnectCompletions = [:]
_readRssiCompletions = [:]
_discoverServicesCompletions = [:]
_discoverCharacteristicsCompletions = [:]
_discoverDescriptorsCompletions = [:]
_readCharacteristicCompletions = [:]
_writeCharacteristicCompletions = [:]
_setCharacteristicNotifyStateCompletions = [:]
_readDescriptorCompletions = [:]
_writeDescriptorCompletions = [:]
mConnectCompletions = [:]
mDisconnectCompletions = [:]
mReadRSSICompletions = [:]
mDiscoverServicesCompletions = [:]
mDiscoverIncludedServicesCompletions = [:]
mDiscoverCharacteristicsCompletions = [:]
mDiscoverDescriptorsCompletions = [:]
mReadCharacteristicCompletions = [:]
mWriteCharacteristicCompletions = [:]
mSetCharacteristicNotifyStateCompletions = [:]
mReadDescriptorCompletions = [:]
mWriteDescriptorCompletions = [:]
}
func setUp() throws {
_clearState()
if _centralManager.delegate == nil {
_centralManager.delegate = _centralManagerDelegate
func initialize() throws {
if(mCentralManager.isScanning) {
mCentralManager.stopScan()
}
didUpdateState(central: _centralManager)
for peripheral in mPeripherals.values {
if peripheral.state != .disconnected {
mCentralManager.cancelPeripheralConnection(peripheral)
}
}
mPeripherals.removeAll()
mServices.removeAll()
mCharacteristics.removeAll()
mDescriptors.removeAll()
mConnectCompletions.removeAll()
mDisconnectCompletions.removeAll()
mReadRSSICompletions.removeAll()
mDiscoverServicesCompletions.removeAll()
mDiscoverIncludedServicesCompletions.removeAll()
mDiscoverCharacteristicsCompletions.removeAll()
mDiscoverDescriptorsCompletions.removeAll()
mReadCharacteristicCompletions.removeAll()
mWriteCharacteristicCompletions.removeAll()
mSetCharacteristicNotifyStateCompletions.removeAll()
mReadDescriptorCompletions.removeAll()
mWriteDescriptorCompletions.removeAll()
mCentralManager.delegate = mCentralManagerDelegate
}
func startDiscovery() throws {
func getState() throws -> MyBluetoothLowEnergyStateArgs {
let state = mCentralManager.state
let stateArgs = state.toArgs()
return stateArgs
}
func showAppSettings(completion: @escaping (Result<Void, any Error>) -> Void) {
#if os(iOS)
do {
guard let url = URL(string: UIApplication.openSettingsURLString) else {
throw MyError.illegalArgument
}
UIApplication.shared.open(url) { success in
if (success) {
completion(.success(()))
} else {
completion(.failure(MyError.unknown))
}
}
} catch {
completion(.failure(error))
}
#else
completion(.failure(MyError.unsupported))
#endif
}
func startDiscovery(serviceUUIDsArgs: [String]) throws {
let serviceUUIDs = serviceUUIDsArgs.isEmpty ? nil : serviceUUIDsArgs.map { serviceUUIDArgs in serviceUUIDArgs.toCBUUID() }
let options = [CBCentralManagerScanOptionAllowDuplicatesKey: true]
_centralManager.scanForPeripherals(withServices: nil, options: options)
mCentralManager.scanForPeripherals(withServices: serviceUUIDs, options: options)
}
func stopDiscovery() throws {
_centralManager.stopScan()
mCentralManager.stopScan()
}
func retrieveConnectedPeripherals() throws -> [MyPeripheralArgs] {
let peripherals = mCentralManager.retrieveConnectedPeripherals(withServices: [])
let peripheralsArgs = peripherals.map { peripheral in
let peripheralArgs = peripheral.toArgs()
let uuidArgs = peripheralArgs.uuidArgs
if peripheral.delegate == nil {
peripheral.delegate = peripheralDelegate
}
self.mPeripherals[uuidArgs] = peripheral
return peripheralArgs
}
return peripheralsArgs
}
func connect(uuidArgs: String, completion: @escaping (Result<Void, Error>) -> Void) {
do {
guard let peripheral = _peripherals[uuidArgs] else {
throw MyError.illegalArgument
}
_centralManager.connect(peripheral)
_connectCompletions[uuidArgs] = completion
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
mCentralManager.connect(peripheral)
mConnectCompletions[uuidArgs] = completion
} catch {
completion(.failure(error))
}
@ -93,79 +159,70 @@ class MyCentralManager: MyCentralManagerHostApi {
func disconnect(uuidArgs: String, completion: @escaping (Result<Void, Error>) -> Void) {
do {
guard let peripheral = _peripherals[uuidArgs] else {
throw MyError.illegalArgument
}
_centralManager.cancelPeripheralConnection(peripheral)
_disconnectCompletions[uuidArgs] = completion
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
mCentralManager.cancelPeripheralConnection(peripheral)
mDisconnectCompletions[uuidArgs] = completion
} catch {
completion(.failure(error))
}
}
func getMaximumWriteValueLength(uuidArgs: String, typeNumberArgs: Int64) throws -> Int64 {
guard let peripheral = _peripherals[uuidArgs] else {
throw MyError.illegalArgument
}
let typeNumber = typeNumberArgs.toInt()
guard let typeArgs = MyGattCharacteristicWriteTypeArgs(rawValue: typeNumber) else {
throw MyError.illegalArgument
}
func getMaximumWriteLength(uuidArgs: String, typeArgs: MyGATTCharacteristicWriteTypeArgs) throws -> Int64 {
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let type = typeArgs.toWriteType()
let maximumWriteValueLength = peripheral.maximumWriteValueLength(for: type)
let maximumWriteValueLengthArgs = maximumWriteValueLength.toInt64()
return maximumWriteValueLengthArgs
let maximumWriteLength = peripheral.maximumWriteValueLength(for: type)
let maximumWriteLengthArgs = maximumWriteLength.toInt64()
return maximumWriteLengthArgs
}
func readRSSI(uuidArgs: String, completion: @escaping (Result<Int64, Error>) -> Void) {
do {
guard let peripheral = _peripherals[uuidArgs] else {
throw MyError.illegalArgument
}
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
peripheral.readRSSI()
_readRssiCompletions[uuidArgs] = completion
mReadRSSICompletions[uuidArgs] = completion
} catch {
completion(.failure(error))
}
}
func discoverServices(uuidArgs: String, completion: @escaping (Result<[MyGattServiceArgs], Error>) -> Void) {
func discoverServices(uuidArgs: String, completion: @escaping (Result<[MyGATTServiceArgs], Error>) -> Void) {
do {
guard let peripheral = _peripherals[uuidArgs] else {
throw MyError.illegalArgument
}
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
peripheral.discoverServices(nil)
_discoverServicesCompletions[uuidArgs] = completion
mDiscoverServicesCompletions[uuidArgs] = completion
} catch {
completion(.failure(error))
}
}
func discoverCharacteristics(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<[MyGattCharacteristicArgs], Error>) -> Void) {
func discoverIncludedServices(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<[MyGATTServiceArgs], Error>) -> Void) {
do {
guard let peripheral = _peripherals[uuidArgs] else {
throw MyError.illegalArgument
}
guard let service = _retrieveService(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs) else {
throw MyError.illegalArgument
}
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let service = try retrieveService(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs)
peripheral.discoverIncludedServices(nil, for: service)
mDiscoverIncludedServicesCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func discoverCharacteristics(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<[MyGATTCharacteristicArgs], Error>) -> Void) {
do {
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let service = try retrieveService(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs)
peripheral.discoverCharacteristics(nil, for: service)
_discoverCharacteristicsCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
mDiscoverCharacteristicsCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func discoverDescriptors(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<[MyGattDescriptorArgs], Error>) -> Void){
func discoverDescriptors(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<[MyGATTDescriptorArgs], Error>) -> Void){
do {
guard let peripheral = _peripherals[uuidArgs] else {
throw MyError.illegalArgument
}
guard let characteristic = _retrieveCharacteristic(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs) else {
throw MyError.illegalArgument
}
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let characteristic = try retrieveCharacteristic(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs)
peripheral.discoverDescriptors(for: characteristic)
_discoverDescriptorsCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
mDiscoverDescriptorsCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
} catch {
completion(.failure(error))
}
@ -173,36 +230,24 @@ class MyCentralManager: MyCentralManagerHostApi {
func readCharacteristic(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
do {
guard let peripheral = _peripherals[uuidArgs] else {
throw MyError.illegalArgument
}
guard let characteristic = _retrieveCharacteristic(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs) else {
throw MyError.illegalArgument
}
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let characteristic = try retrieveCharacteristic(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs)
peripheral.readValue(for: characteristic)
_readCharacteristicCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
mReadCharacteristicCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
} catch {
completion(.failure(error))
}
}
func writeCharacteristic(uuidArgs: String, hashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, typeNumberArgs: Int64, completion: @escaping (Result<Void, Error>) -> Void) {
func writeCharacteristic(uuidArgs: String, hashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, typeArgs: MyGATTCharacteristicWriteTypeArgs, completion: @escaping (Result<Void, Error>) -> Void) {
do {
guard let peripheral = _peripherals[uuidArgs] else {
throw MyError.illegalArgument
}
guard let characteristic = _retrieveCharacteristic(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs) else {
throw MyError.illegalArgument
}
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let characteristic = try retrieveCharacteristic(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs)
let data = valueArgs.data
let typeNumber = typeNumberArgs.toInt()
guard let typeArgs = MyGattCharacteristicWriteTypeArgs(rawValue: typeNumber) else {
throw MyError.illegalArgument
}
let type = typeArgs.toWriteType()
peripheral.writeValue(data, for: characteristic, type: type)
if type == .withResponse {
_writeCharacteristicCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
mWriteCharacteristicCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
} else {
completion(.success(()))
}
@ -213,15 +258,11 @@ class MyCentralManager: MyCentralManagerHostApi {
func setCharacteristicNotifyState(uuidArgs: String, hashCodeArgs: Int64, stateArgs: Bool, completion: @escaping (Result<Void, Error>) -> Void) {
do {
guard let peripheral = _peripherals[uuidArgs] else {
throw MyError.illegalArgument
}
guard let characteristic = _retrieveCharacteristic(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs) else {
throw MyError.illegalArgument
}
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let characteristic = try retrieveCharacteristic(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs)
let enabled = stateArgs
peripheral.setNotifyValue(enabled, for: characteristic)
_setCharacteristicNotifyStateCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
mSetCharacteristicNotifyStateCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
} catch {
completion(.failure(error))
}
@ -229,14 +270,10 @@ class MyCentralManager: MyCentralManagerHostApi {
func readDescriptor(uuidArgs: String, hashCodeArgs: Int64, completion: @escaping (Result<FlutterStandardTypedData, Error>) -> Void) {
do {
guard let peripheral = _peripherals[uuidArgs] else {
throw MyError.illegalArgument
}
guard let descriptor = _retrieveDescriptor(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs) else {
throw MyError.illegalArgument
}
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let descriptor = try retrieveDescriptor(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs)
peripheral.readValue(for: descriptor)
_readDescriptorCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
mReadDescriptorCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
} catch {
completion(.failure(error))
}
@ -244,15 +281,11 @@ class MyCentralManager: MyCentralManagerHostApi {
func writeDescriptor(uuidArgs: String, hashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, completion: @escaping (Result<Void, Error>) -> Void) {
do {
guard let peripheral = _peripherals[uuidArgs] else {
throw MyError.illegalArgument
}
guard let descriptor = _retrieveDescriptor(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs) else {
throw MyError.illegalArgument
}
let peripheral = try retrievePeripheral(uuidArgs: uuidArgs)
let descriptor = try retrieveDescriptor(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs)
let data = valueArgs.data
peripheral.writeValue(data, for: descriptor)
_writeDescriptorCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
mWriteDescriptorCompletions[uuidArgs, default: [:]][hashCodeArgs] = completion
} catch {
completion(.failure(error))
}
@ -261,8 +294,7 @@ class MyCentralManager: MyCentralManagerHostApi {
func didUpdateState(central: CBCentralManager) {
let state = central.state
let stateArgs = state.toArgs()
let stateNumberArgs = stateArgs.rawValue.toInt64()
_api.onStateChanged(stateNumberArgs: stateNumberArgs) {_ in }
mAPI.onStateChanged(stateArgs: stateArgs) { _ in }
}
func didDiscover(central: CBCentralManager, peripheral: CBPeripheral, advertisementData: [String : Any], rssi: NSNumber) {
@ -271,17 +303,18 @@ class MyCentralManager: MyCentralManagerHostApi {
let rssiArgs = rssi.int64Value
let advertisementArgs = advertisementData.toAdvertisementArgs()
if peripheral.delegate == nil {
peripheral.delegate = _peripheralDelegate
peripheral.delegate = peripheralDelegate
}
_peripherals[uuidArgs] = peripheral
_api.onDiscovered(peripheralArgs: peripheralArgs, rssiArgs: rssiArgs, advertisementArgs: advertisementArgs) {_ in }
mPeripherals[uuidArgs] = peripheral
mAPI.onDiscovered(peripheralArgs: peripheralArgs, rssiArgs: rssiArgs, advertisementArgs: advertisementArgs) {_ in }
}
func didConnect(central: CBCentralManager, peripheral: CBPeripheral) {
let uuidArgs = peripheral.identifier.toArgs()
let stateArgs = true
_api.onConnectionStateChanged(uuidArgs: uuidArgs, stateArgs: stateArgs) {_ in }
guard let completion = _connectCompletions.removeValue(forKey: uuidArgs) else {
let peripheralArgs = peripheral.toArgs()
let uuidArgs = peripheralArgs.uuidArgs
let stateArgs = MyConnectionStateArgs.connected
mAPI.onConnectionStateChanged(peripheralArgs: peripheralArgs, stateArgs: stateArgs) { _ in }
guard let completion = mConnectCompletions.removeValue(forKey: uuidArgs) else {
return
}
completion(.success(()))
@ -289,74 +322,82 @@ class MyCentralManager: MyCentralManagerHostApi {
func didFailToConnect(central: CBCentralManager, peripheral: CBPeripheral, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
guard let completion = _connectCompletions.removeValue(forKey: uuidArgs) else {
guard let completion = mConnectCompletions.removeValue(forKey: uuidArgs) else {
return
}
completion(.failure(error ?? MyError.unknown))
}
func didDisconnectPeripheral(central: CBCentralManager, peripheral: CBPeripheral, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
_services.removeValue(forKey: uuidArgs)
_characteristics.removeValue(forKey: uuidArgs)
_descriptors.removeValue(forKey: uuidArgs)
let peripheralArgs = peripheral.toArgs()
let uuidArgs = peripheralArgs.uuidArgs
mServices.removeValue(forKey: uuidArgs)
mCharacteristics.removeValue(forKey: uuidArgs)
mDescriptors.removeValue(forKey: uuidArgs)
let errorNotNil = error ?? MyError.unknown
let readRssiCompletion = _readRssiCompletions.removeValue(forKey: uuidArgs)
let readRssiCompletion = mReadRSSICompletions.removeValue(forKey: uuidArgs)
readRssiCompletion?(.failure(errorNotNil))
let discoverServicesCompletion = _discoverServicesCompletions.removeValue(forKey: uuidArgs)
let discoverServicesCompletion = mDiscoverServicesCompletions.removeValue(forKey: uuidArgs)
discoverServicesCompletion?(.failure(errorNotNil))
let discoverCharacteristicsCompletions = _discoverCharacteristicsCompletions.removeValue(forKey: uuidArgs)
let discoverIncludedServicesCompletions = self.mDiscoverIncludedServicesCompletions.removeValue(forKey: uuidArgs)
if discoverIncludedServicesCompletions != nil {
let completions = discoverIncludedServicesCompletions!.values
for completion in completions {
completion(.failure(errorNotNil))
}
}
let discoverCharacteristicsCompletions = self.mDiscoverCharacteristicsCompletions.removeValue(forKey: uuidArgs)
if discoverCharacteristicsCompletions != nil {
let completions = discoverCharacteristicsCompletions!.values
for completion in completions {
completion(.failure(errorNotNil))
}
}
let discoverDescriptorsCompletions = _discoverDescriptorsCompletions.removeValue(forKey: uuidArgs)
let discoverDescriptorsCompletions = self.mDiscoverDescriptorsCompletions.removeValue(forKey: uuidArgs)
if discoverDescriptorsCompletions != nil {
let completions = discoverDescriptorsCompletions!.values
for completion in completions {
completion(.failure(errorNotNil))
}
}
let readCharacteristicCompletions = _readCharacteristicCompletions.removeValue(forKey: uuidArgs)
let readCharacteristicCompletions = self.mReadCharacteristicCompletions.removeValue(forKey: uuidArgs)
if readCharacteristicCompletions != nil {
let completions = readCharacteristicCompletions!.values
for completion in completions {
completion(.failure(errorNotNil))
}
}
let writeCharacteristicCompletions = _writeCharacteristicCompletions.removeValue(forKey: uuidArgs)
let writeCharacteristicCompletions = self.mWriteCharacteristicCompletions.removeValue(forKey: uuidArgs)
if writeCharacteristicCompletions != nil {
let completions = writeCharacteristicCompletions!.values
for completion in completions {
completion(.failure(errorNotNil))
}
}
let notifyCharacteristicCompletions = _setCharacteristicNotifyStateCompletions.removeValue(forKey: uuidArgs)
let notifyCharacteristicCompletions = self.mSetCharacteristicNotifyStateCompletions.removeValue(forKey: uuidArgs)
if notifyCharacteristicCompletions != nil {
let completions = notifyCharacteristicCompletions!.values
for completioin in completions {
completioin(.failure(errorNotNil))
}
}
let readDescriptorCompletions = _readDescriptorCompletions.removeValue(forKey: uuidArgs)
let readDescriptorCompletions = self.mReadDescriptorCompletions.removeValue(forKey: uuidArgs)
if readDescriptorCompletions != nil {
let completions = readDescriptorCompletions!.values
for completioin in completions {
completioin(.failure(errorNotNil))
}
}
let writeDescriptorCompletions = _writeDescriptorCompletions.removeValue(forKey: uuidArgs)
let writeDescriptorCompletions = self.mWriteDescriptorCompletions.removeValue(forKey: uuidArgs)
if writeDescriptorCompletions != nil {
let completions = writeDescriptorCompletions!.values
for completion in completions {
completion(.failure(errorNotNil))
}
}
let stateArgs = false
_api.onConnectionStateChanged(uuidArgs: uuidArgs, stateArgs: stateArgs) {_ in }
guard let completion = _disconnectCompletions.removeValue(forKey: uuidArgs) else {
let stateArgs = MyConnectionStateArgs.disconnected
mAPI.onConnectionStateChanged(peripheralArgs: peripheralArgs, stateArgs: stateArgs) { _ in }
guard let completion = mDisconnectCompletions.removeValue(forKey: uuidArgs) else {
return
}
if error == nil {
@ -368,7 +409,7 @@ class MyCentralManager: MyCentralManagerHostApi {
func didReadRSSI(peripheral: CBPeripheral, rssi: NSNumber, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
guard let completion = _readRssiCompletions.removeValue(forKey: uuidArgs) else {
guard let completion = mReadRSSICompletions.removeValue(forKey: uuidArgs) else {
return
}
if error == nil {
@ -381,37 +422,57 @@ class MyCentralManager: MyCentralManagerHostApi {
func didDiscoverServices(peripheral: CBPeripheral, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
guard let completion = _discoverServicesCompletions.removeValue(forKey: uuidArgs) else {
guard let completion = mDiscoverServicesCompletions.removeValue(forKey: uuidArgs) else {
return
}
if error == nil {
let services = peripheral.services ?? []
let servicesArgs = services.map { service in service.toArgs() }
let values = services.flatMap { service in
let hashCodeArgs = service.hash.toInt64()
return [hashCodeArgs: service]
var servicesArgs = [MyGATTServiceArgs]()
for service in services {
let serviceArgs = service.toArgs()
self.mServices[uuidArgs, default: [:]][serviceArgs.hashCodeArgs] = service
servicesArgs.append(serviceArgs)
}
_services[uuidArgs] = Dictionary(uniqueKeysWithValues: values)
completion(.success(servicesArgs))
} else {
completion(.failure(error!))
}
}
func didDiscoverIncludedServices(peripheral: CBPeripheral, service: CBService, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
let hashCodeArgs = service.hash.toInt64()
guard let completion = mDiscoverIncludedServicesCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
return
}
if error == nil {
let includedServices = service.includedServices ?? []
var includedServicesArgs = [MyGATTServiceArgs]()
for includedService in includedServices {
let includedServiceArgs = includedService.toArgs()
self.mServices[uuidArgs, default: [:]][includedServiceArgs.hashCodeArgs] = includedService
includedServicesArgs.append(includedServiceArgs)
}
completion(.success(includedServicesArgs))
} else {
completion(.failure(error!))
}
}
func didDiscoverCharacteristics(peripheral: CBPeripheral, service: CBService, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
let hashCodeArgs = service.hash.toInt64()
guard let completion = _discoverCharacteristicsCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
guard let completion = mDiscoverCharacteristicsCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
return
}
if error == nil {
let characteristics = service.characteristics ?? []
let characteristicsArgs = characteristics.map { characteristic in characteristic.toArgs() }
let values = characteristics.flatMap { characteristic in
let hashCodeArgs = characteristic.hash.toInt64()
return [hashCodeArgs: characteristic]
var characteristicsArgs = [MyGATTCharacteristicArgs]()
for characteristic in characteristics {
let characteristicArgs = characteristic.toArgs()
self.mCharacteristics[uuidArgs, default: [:]][characteristicArgs.hashCodeArgs] = characteristic
characteristicsArgs.append(characteristicArgs)
}
_characteristics[uuidArgs, default: [:]].merge(values) { value1, value2 in value2 }
completion(.success(characteristicsArgs))
} else {
completion(.failure(error!))
@ -421,17 +482,17 @@ class MyCentralManager: MyCentralManagerHostApi {
func didDiscoverDescriptors(peripheral: CBPeripheral, characteristic: CBCharacteristic, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
let hashCodeArgs = characteristic.hash.toInt64()
guard let completion = _discoverDescriptorsCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
guard let completion = mDiscoverDescriptorsCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
return
}
if error == nil {
let descriptors = characteristic.descriptors ?? []
let descriptorsArgs = descriptors.map { descriptor in descriptor.toArgs() }
let values = descriptors.flatMap { descriptor in
let hashCodeArgs = descriptor.hash.toInt64()
return [hashCodeArgs: descriptor]
var descriptorsArgs = [MyGATTDescriptorArgs]()
for descriptor in descriptors {
let descriptorArgs = descriptor.toArgs()
self.mDescriptors[uuidArgs, default: [:]][descriptorArgs.hashCodeArgs] = descriptor
descriptorsArgs.append(descriptorArgs)
}
_descriptors[uuidArgs, default: [:]].merge(values) { value1, value2 in value2 }
completion(.success(descriptorsArgs))
} else {
completion(.failure(error!))
@ -439,12 +500,14 @@ class MyCentralManager: MyCentralManagerHostApi {
}
func didUpdateCharacteristicValue(peripheral: CBPeripheral, characteristic: CBCharacteristic, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
let hashCodeArgs = characteristic.hash.toInt64()
let peripheralArgs = peripheral.toArgs()
let uuidArgs = peripheralArgs.uuidArgs
let characteristicArgs = characteristic.toArgs()
let hashCodeArgs = characteristicArgs.hashCodeArgs
let value = characteristic.value ?? Data()
let valueArgs = FlutterStandardTypedData(bytes: value)
guard let completion = _readCharacteristicCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
_api.onCharacteristicNotified(uuidArgs: uuidArgs, hashCodeArgs: hashCodeArgs, valueArgs: valueArgs) {_ in }
guard let completion = mReadCharacteristicCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
mAPI.onCharacteristicNotified(peripheralArgs: peripheralArgs, characteristicArgs: characteristicArgs, valueArgs: valueArgs) { _ in }
return
}
if error == nil {
@ -457,7 +520,7 @@ class MyCentralManager: MyCentralManagerHostApi {
func didWriteCharacteristicValue(peripheral: CBPeripheral, characteristic: CBCharacteristic, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
let hashCodeArgs = characteristic.hash.toInt64()
guard let completion = _writeCharacteristicCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
guard let completion = mWriteCharacteristicCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
return
}
if error == nil {
@ -470,7 +533,7 @@ class MyCentralManager: MyCentralManagerHostApi {
func didUpdateCharacteristicNotificationState(peripheral: CBPeripheral, characteristic: CBCharacteristic, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
let hashCodeArgs = characteristic.hash.toInt64()
guard let completion = _setCharacteristicNotifyStateCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
guard let completion = mSetCharacteristicNotifyStateCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
return
}
if error == nil {
@ -483,45 +546,24 @@ class MyCentralManager: MyCentralManagerHostApi {
func didUpdateDescriptorValue(peripheral: CBPeripheral, descriptor: CBDescriptor, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
let hashCodeArgs = descriptor.hash.toInt64()
guard let completion = _readDescriptorCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
guard let completion = mReadDescriptorCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
return
}
if error == nil {
// TODO: confirm the corresponding descriptor types and values are correct.
let valueArgs: FlutterStandardTypedData
let value = descriptor.value
do {
switch descriptor.uuid.uuidString {
case CBUUIDCharacteristicExtendedPropertiesString:
fallthrough
case CBUUIDClientCharacteristicConfigurationString:
fallthrough
case CBUUIDServerCharacteristicConfigurationString:
guard let numberValue = value as? NSNumber else {
throw MyError.illegalArgument
}
valueArgs = FlutterStandardTypedData(bytes: numberValue.data)
case CBUUIDCharacteristicUserDescriptionString:
fallthrough
case CBUUIDCharacteristicAggregateFormatString:
guard let stringValue = value as? String else {
throw MyError.illegalArgument
}
valueArgs = FlutterStandardTypedData(bytes: stringValue.data)
case CBUUIDCharacteristicFormatString:
guard let bytes = value as? Data else {
throw MyError.illegalArgument
}
valueArgs = FlutterStandardTypedData(bytes: bytes)
case CBUUIDL2CAPPSMCharacteristicString:
guard let uint16Value = value as? UInt16 else {
throw MyError.illegalArgument
}
valueArgs = FlutterStandardTypedData(bytes: uint16Value.data)
default:
throw MyError.illegalArgument
}
} catch {
switch descriptor.value {
case let bytes as Data:
valueArgs = FlutterStandardTypedData(bytes: bytes)
case let value as String:
let bytes = value.data(using: .utf8) ?? Data()
valueArgs = FlutterStandardTypedData(bytes: bytes)
case let value as UInt16:
let bytes = value.data
valueArgs = FlutterStandardTypedData(bytes: bytes)
case let value as NSNumber:
let bytes = withUnsafeBytes(of: value) { elements in Data(elements) }
valueArgs = FlutterStandardTypedData(bytes: bytes)
default:
valueArgs = FlutterStandardTypedData()
}
completion(.success((valueArgs)))
@ -533,7 +575,7 @@ class MyCentralManager: MyCentralManagerHostApi {
func didWriteDescriptorValue(peripheral: CBPeripheral, descriptor: CBDescriptor, error: Error?) {
let uuidArgs = peripheral.identifier.toArgs()
let hashCodeArgs = descriptor.hash.toInt64()
guard let completion = _writeDescriptorCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
guard let completion = mWriteDescriptorCompletions[uuidArgs]?.removeValue(forKey: hashCodeArgs) else {
return
}
if error == nil {
@ -543,52 +585,40 @@ class MyCentralManager: MyCentralManagerHostApi {
}
}
private func _clearState() {
if(_centralManager.isScanning) {
_centralManager.stopScan()
private func retrievePeripheral(uuidArgs: String) throws -> CBPeripheral {
guard let peripheral = mPeripherals[uuidArgs] else {
throw MyError.illegalArgument
}
for peripheral in _peripherals.values {
if peripheral.state != .disconnected {
_centralManager.cancelPeripheralConnection(peripheral)
}
}
_peripherals.removeAll()
_services.removeAll()
_characteristics.removeAll()
_descriptors.removeAll()
_connectCompletions.removeAll()
_disconnectCompletions.removeAll()
_readRssiCompletions.removeAll()
_discoverServicesCompletions.removeAll()
_discoverCharacteristicsCompletions.removeAll()
_discoverDescriptorsCompletions.removeAll()
_readCharacteristicCompletions.removeAll()
_writeCharacteristicCompletions.removeAll()
_setCharacteristicNotifyStateCompletions.removeAll()
_readDescriptorCompletions.removeAll()
_writeDescriptorCompletions.removeAll()
return peripheral
}
private func _retrieveService(uuidArgs: String, hashCodeArgs: Int64) -> CBService? {
guard let services = _services[uuidArgs] else {
return nil
private func retrieveService(uuidArgs: String, hashCodeArgs: Int64) throws -> CBService {
guard let services = self.mServices[uuidArgs] else {
throw MyError.illegalArgument
}
return services[hashCodeArgs]
guard let service = services[hashCodeArgs] else {
throw MyError.illegalArgument
}
return service
}
private func _retrieveCharacteristic(uuidArgs: String, hashCodeArgs: Int64) -> CBCharacteristic? {
guard let characteristics = _characteristics[uuidArgs] else {
return nil
private func retrieveCharacteristic(uuidArgs: String, hashCodeArgs: Int64) throws -> CBCharacteristic {
guard let characteristics = self.mCharacteristics[uuidArgs] else {
throw MyError.illegalArgument
}
return characteristics[hashCodeArgs]
guard let characteristic = characteristics[hashCodeArgs] else {
throw MyError.illegalArgument
}
return characteristic
}
private func _retrieveDescriptor(uuidArgs: String, hashCodeArgs: Int64) -> CBDescriptor? {
guard let descriptors = _descriptors[uuidArgs] else {
return nil
private func retrieveDescriptor(uuidArgs: String, hashCodeArgs: Int64) throws -> CBDescriptor {
guard let descriptors = self.mDescriptors[uuidArgs] else {
throw MyError.illegalArgument
}
return descriptors[hashCodeArgs]
guard let descriptor = descriptors[hashCodeArgs] else {
throw MyError.illegalArgument
}
return descriptor
}
}

View File

@ -9,29 +9,29 @@ import Foundation
import CoreBluetooth
class MyCentralManagerDelegate: NSObject, CBCentralManagerDelegate {
private let _centralManager: MyCentralManager
private let mCentralManager: MyCentralManager
init(centralManager: MyCentralManager) {
_centralManager = centralManager
self.mCentralManager = centralManager
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
_centralManager.didUpdateState(central: central)
mCentralManager.didUpdateState(central: central)
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
_centralManager.didDiscover(central: central, peripheral: peripheral, advertisementData: advertisementData, rssi: RSSI)
mCentralManager.didDiscover(central: central, peripheral: peripheral, advertisementData: advertisementData, rssi: RSSI)
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
_centralManager.didConnect(central: central, peripheral: peripheral)
mCentralManager.didConnect(central: central, peripheral: peripheral)
}
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
_centralManager.didFailToConnect(central: central, peripheral: peripheral, error: error)
mCentralManager.didFailToConnect(central: central, peripheral: peripheral, error: error)
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
_centralManager.didDisconnectPeripheral(central: central, peripheral: peripheral, error: error)
mCentralManager.didDisconnectPeripheral(central: central, peripheral: peripheral, error: error)
}
}

View File

@ -7,8 +7,8 @@
import Foundation
// TODO:
enum MyError: Error {
case illegalArgument
case unknown
case unsupported
case illegalArgument
}

View File

@ -9,45 +9,49 @@ import Foundation
import CoreBluetooth
class MyPeripheralDelegate: NSObject, CBPeripheralDelegate {
private let _centralManager: MyCentralManager
private let mCentralManager: MyCentralManager
init(centralManager: MyCentralManager) {
_centralManager = centralManager
self.mCentralManager = centralManager
}
func peripheral(_ peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: Error?) {
_centralManager.didReadRSSI(peripheral: peripheral, rssi: RSSI, error: error)
mCentralManager.didReadRSSI(peripheral: peripheral, rssi: RSSI, error: error)
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
_centralManager.didDiscoverServices(peripheral: peripheral, error: error)
mCentralManager.didDiscoverServices(peripheral: peripheral, error: error)
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverIncludedServicesFor service: CBService, error: Error?) {
mCentralManager.didDiscoverIncludedServices(peripheral: peripheral, service: service, error: error)
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
_centralManager.didDiscoverCharacteristics(peripheral: peripheral, service: service, error: error)
mCentralManager.didDiscoverCharacteristics(peripheral: peripheral, service: service, error: error)
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverDescriptorsFor characteristic: CBCharacteristic, error: Error?) {
_centralManager.didDiscoverDescriptors(peripheral: peripheral, characteristic: characteristic, error: error)
mCentralManager.didDiscoverDescriptors(peripheral: peripheral, characteristic: characteristic, error: error)
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
_centralManager.didUpdateCharacteristicValue(peripheral: peripheral, characteristic: characteristic, error: error)
mCentralManager.didUpdateCharacteristicValue(peripheral: peripheral, characteristic: characteristic, error: error)
}
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
_centralManager.didWriteCharacteristicValue(peripheral: peripheral, characteristic: characteristic, error: error)
mCentralManager.didWriteCharacteristicValue(peripheral: peripheral, characteristic: characteristic, error: error)
}
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
_centralManager.didUpdateCharacteristicNotificationState(peripheral: peripheral, characteristic: characteristic, error: error)
mCentralManager.didUpdateCharacteristicNotificationState(peripheral: peripheral, characteristic: characteristic, error: error)
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor descriptor: CBDescriptor, error: Error?) {
_centralManager.didUpdateDescriptorValue(peripheral: peripheral, descriptor: descriptor, error: error)
mCentralManager.didUpdateDescriptorValue(peripheral: peripheral, descriptor: descriptor, error: error)
}
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor descriptor: CBDescriptor, error: Error?) {
_centralManager.didWriteDescriptorValue(peripheral: peripheral, descriptor: descriptor, error: error)
mCentralManager.didWriteDescriptorValue(peripheral: peripheral, descriptor: descriptor, error: error)
}
}

View File

@ -16,207 +16,180 @@ import FlutterMacOS
#error("Unsupported platform.")
#endif
class MyPeripheralManager: MyPeripheralManagerHostApi {
private let _api: MyPeripheralManagerFlutterApi
private let _peripheralManager: CBPeripheralManager
class MyPeripheralManager: MyPeripheralManagerHostAPI {
private let mAPI: MyPeripheralManagerFlutterAPI
private let mPeripheralManager: CBPeripheralManager
private lazy var _peripheralManagerDelegate = MyPeripheralManagerDelegate(peripheralManager: self)
private lazy var mPeripheralManagerDelegate = MyPeripheralManagerDelegate(peripheralManager: self)
private var _servicesArgs: [Int: MyGattServiceArgs]
private var _characteristicsArgs: [Int: MyGattCharacteristicArgs]
private var _descriptorsArgs: [Int: MyGattDescriptorArgs]
private var mServicesArgs: [Int: MyMutableGATTServiceArgs]
private var mCharacteristicsArgs: [Int: MyMutableGATTCharacteristicArgs]
private var mDescriptorsArgs: [Int: MyMutableGATTDescriptorArgs]
private var _centrals: [String: CBCentral]
private var _services: [Int64: CBMutableService]
private var _characteristics: [Int64: CBMutableCharacteristic]
private var _descriptors: [Int64: CBMutableDescriptor]
private var _requests: [Int64: CBATTRequest]
private var mCentrals: [String: CBCentral]
private var mServices: [Int64: CBMutableService]
private var mCharacteristics: [Int64: CBMutableCharacteristic]
private var mDescriptors: [Int64: CBMutableDescriptor]
private var mRequests: [Int64: CBATTRequest]
private var _addServiceCompletion: ((Result<Void, Error>) -> Void)?
private var _startAdvertisingCompletion: ((Result<Void, Error>) -> Void)?
private var _isReadyToUpdateSubscribersCallbacks: [() -> Void]
private var mAddServiceCompletion: ((Result<Void, Error>) -> Void)?
private var mStartAdvertisingCompletion: ((Result<Void, Error>) -> Void)?
init(messenger: FlutterBinaryMessenger) {
_api = MyPeripheralManagerFlutterApi(binaryMessenger: messenger)
_peripheralManager = CBPeripheralManager()
mAPI = MyPeripheralManagerFlutterAPI(binaryMessenger: messenger)
mPeripheralManager = CBPeripheralManager()
_servicesArgs = [:]
_characteristicsArgs = [:]
_descriptorsArgs = [:]
mServicesArgs = [:]
mCharacteristicsArgs = [:]
mDescriptorsArgs = [:]
_centrals = [:]
_services = [:]
_characteristics = [:]
_descriptors = [:]
_requests = [:]
mCentrals = [:]
mServices = [:]
mCharacteristics = [:]
mDescriptors = [:]
mRequests = [:]
_addServiceCompletion = nil
_startAdvertisingCompletion = nil
_isReadyToUpdateSubscribersCallbacks = []
mAddServiceCompletion = nil
mStartAdvertisingCompletion = nil
}
func setUp() throws {
_clearState()
if _peripheralManager.delegate == nil {
_peripheralManager.delegate = _peripheralManagerDelegate
func initialize() throws {
if(mPeripheralManager.isAdvertising) {
mPeripheralManager.stopAdvertising()
}
didUpdateState(peripheral: _peripheralManager)
}
func addService(serviceArgs: MyGattServiceArgs, completion: @escaping (Result<Void, Error>) -> Void) {
let service = serviceArgs.toService()
var characteristics = [CBMutableCharacteristic]()
let characteristicsArgs = serviceArgs.characteristicsArgs
for args in characteristicsArgs {
guard let characteristicArgs = args else {
continue
}
let characteristic = characteristicArgs.toCharacteristic()
characteristics.append(characteristic)
var descriptors = [CBMutableDescriptor]()
let descriptorsArgs = characteristicArgs.descriptorsArgs
for args in descriptorsArgs {
guard let descriptorArgs = args else {
continue
}
let descriptor = descriptorArgs.toDescriptor()
descriptors.append(descriptor)
let descriptorHashCodeArgs = descriptorArgs.hashCodeArgs
let descriptorHashCode = descriptor.hash
_descriptorsArgs[descriptorHashCode] = descriptorArgs
_descriptors[descriptorHashCodeArgs] = descriptor
}
characteristic.descriptors = descriptors
let characteristicHashCodeArgs = characteristicArgs.hashCodeArgs
let characteristicHashCode = characteristic.hash
_characteristicsArgs[characteristicHashCode] = characteristicArgs
_characteristics[characteristicHashCodeArgs] = characteristic
}
service.characteristics = characteristics
let serviceHashCodeArgs = serviceArgs.hashCodeArgs
let serviceHashCode = service.hash
_servicesArgs[serviceHashCode] = serviceArgs
_services[serviceHashCodeArgs] = service
_peripheralManager.add(service)
_addServiceCompletion = completion
}
func removeService(hashCodeArgs: Int64) throws {
guard let service = _services.removeValue(forKey: hashCodeArgs) else {
throw MyError.illegalArgument
}
_peripheralManager.remove(service)
let hashCode = service.hash
guard let serviceArgs = _servicesArgs.removeValue(forKey: hashCode) else {
throw MyError.illegalArgument
}
for args in serviceArgs.characteristicsArgs {
guard let characteristicArgs = args else {
continue
}
let characteristicHashCodeArgs = characteristicArgs.hashCodeArgs
guard let characteristic = _characteristics.removeValue(forKey: characteristicHashCodeArgs) else {
throw MyError.illegalArgument
}
let characteristicHashCode = characteristic.hash
_characteristicsArgs.removeValue(forKey: characteristicHashCode)
for args in characteristicArgs.descriptorsArgs {
guard let descriptorArgs = args else {
continue
}
let descriptorHashCodeArgs = descriptorArgs.hashCodeArgs
guard let descriptor = _descriptors.removeValue(forKey: descriptorHashCodeArgs) else {
throw MyError.illegalArgument
}
let descriptorHashCode = descriptor.hash
_descriptorsArgs.removeValue(forKey: descriptorHashCode)
}
}
}
func clearServices() throws {
_peripheralManager.removeAllServices()
_services.removeAll()
_characteristics.removeAll()
_descriptors.removeAll()
mServicesArgs.removeAll()
mCharacteristicsArgs.removeAll()
mDescriptorsArgs.removeAll()
_servicesArgs.removeAll()
_characteristicsArgs.removeAll()
_descriptors.removeAll()
mCentrals.removeAll()
mServices.removeAll()
mCharacteristics.removeAll()
mDescriptors.removeAll()
mRequests.removeAll()
mAddServiceCompletion = nil
mStartAdvertisingCompletion = nil
mPeripheralManager.delegate = mPeripheralManagerDelegate
}
func getState() throws -> MyBluetoothLowEnergyStateArgs {
let state = mPeripheralManager.state
let stateArgs = state.toArgs()
return stateArgs
}
func startAdvertising(advertisementArgs: MyAdvertisementArgs, completion: @escaping (Result<Void, Error>) -> Void) {
let advertisement = advertisementArgs.toAdvertisement()
_peripheralManager.startAdvertising(advertisement)
_startAdvertisingCompletion = completion
}
func stopAdvertising() throws {
_peripheralManager.stopAdvertising()
}
func getMaximumUpdateValueLength(uuidArgs: String) throws -> Int64 {
guard let central = _centrals[uuidArgs] else {
throw MyError.illegalArgument
}
let maximumUpdateValueLength = central.maximumUpdateValueLength
let maximumUpdateValueLengthArgs = maximumUpdateValueLength.toInt64()
return maximumUpdateValueLengthArgs
}
func respond(idArgs: Int64, errorNumberArgs: Int64, valueArgs: FlutterStandardTypedData?) throws {
guard let request = _requests.removeValue(forKey: idArgs) else {
throw MyError.illegalArgument
}
if valueArgs != nil {
request.value = valueArgs?.data
}
let errorArgsRawValue = errorNumberArgs.toInt()
guard let errorArgs = MyGattErrorArgs(rawValue: errorArgsRawValue) else {
throw MyError.illegalArgument
}
let result = errorArgs.toError()
_peripheralManager.respond(to: request, withResult: result)
}
func updateCharacteristic(hashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, uuidsArgs: [String]?, completion: @escaping (Result<Void, Error>) -> Void) {
func showAppSettings(completion: @escaping (Result<Void, any Error>) -> Void) {
#if os(iOS)
do {
let centrals = try uuidsArgs?.map { uuidArgs in
guard let central = _centrals[uuidArgs] else {
throw MyError.illegalArgument
}
return central
}
guard let characteristic = _characteristics[hashCodeArgs] else {
guard let url = URL(string: UIApplication.openSettingsURLString) else {
throw MyError.illegalArgument
}
let value = valueArgs.data
let updated = _peripheralManager.updateValue(value, for: characteristic, onSubscribedCentrals: centrals)
if updated {
completion(.success(()))
} else {
_isReadyToUpdateSubscribersCallbacks.append {
self.updateCharacteristic(hashCodeArgs: hashCodeArgs, valueArgs: valueArgs, uuidsArgs: uuidsArgs, completion: completion)
UIApplication.shared.open(url) { success in
if (success) {
completion(.success(()))
} else {
completion(.failure(MyError.unknown))
}
}
} catch {
completion(.failure(error))
}
#else
completion(.failure(MyError.unsupported))
#endif
}
func addService(serviceArgs: MyMutableGATTServiceArgs, completion: @escaping (Result<Void, Error>) -> Void) {
do {
let service = try addServiceArgs(serviceArgs)
mPeripheralManager.add(service)
mAddServiceCompletion = completion
} catch {
completion(.failure(error))
}
}
func removeService(hashCodeArgs: Int64) throws {
guard let service = mServices[hashCodeArgs] else {
throw MyError.illegalArgument
}
guard let serviceArgs = mServicesArgs[service.hash] else {
throw MyError.illegalArgument
}
mPeripheralManager.remove(service)
try removeServiceArgs(serviceArgs)
}
func removeAllServices() throws {
mPeripheralManager.removeAllServices()
mServices.removeAll()
mCharacteristics.removeAll()
mDescriptors.removeAll()
mServicesArgs.removeAll()
mCharacteristicsArgs.removeAll()
mDescriptors.removeAll()
}
func startAdvertising(advertisementArgs: MyAdvertisementArgs, completion: @escaping (Result<Void, Error>) -> Void) {
let advertisement = advertisementArgs.toAdvertisement()
mPeripheralManager.startAdvertising(advertisement)
mStartAdvertisingCompletion = completion
}
func stopAdvertising() throws {
mPeripheralManager.stopAdvertising()
}
func getMaximumNotifyLength(uuidArgs: String) throws -> Int64 {
guard let central = mCentrals[uuidArgs] else {
throw MyError.illegalArgument
}
let maximumNotifyLength = central.maximumUpdateValueLength
let maximumNotifyLengthArgs = maximumNotifyLength.toInt64()
return maximumNotifyLengthArgs
}
func respond(hashCodeArgs: Int64, valueArgs: FlutterStandardTypedData?, errorArgs: MyATTErrorArgs) throws {
guard let request = mRequests.removeValue(forKey: hashCodeArgs) else {
throw MyError.illegalArgument
}
if valueArgs != nil {
request.value = valueArgs!.data
}
let error = errorArgs.toError()
mPeripheralManager.respond(to: request, withResult: error)
}
func updateValue(hashCodeArgs: Int64, valueArgs: FlutterStandardTypedData, uuidsArgs: [String]?) throws -> Bool {
let centrals = try uuidsArgs?.map { uuidArgs in
guard let central = self.mCentrals[uuidArgs] else {
throw MyError.illegalArgument
}
return central
}
guard let characteristic = mCharacteristics[hashCodeArgs] else {
throw MyError.illegalArgument
}
let value = valueArgs.data
let updated = mPeripheralManager.updateValue(value, for: characteristic, onSubscribedCentrals: centrals)
return updated
}
func didUpdateState(peripheral: CBPeripheralManager) {
let state = peripheral.state
let stateArgs = state.toArgs()
let stateNumberArgs = stateArgs.rawValue.toInt64()
_api.onStateChanged(stateNumberArgs: stateNumberArgs) {_ in }
mAPI.onStateChanged(stateArgs: stateArgs) { _ in }
}
func didAdd(peripheral: CBPeripheralManager, service: CBService, error: Error?) {
guard let completion = _addServiceCompletion else {
guard let completion = mAddServiceCompletion else {
return
}
_addServiceCompletion = nil
mAddServiceCompletion = nil
if error == nil {
completion(.success(()))
} else {
@ -225,10 +198,10 @@ class MyPeripheralManager: MyPeripheralManagerHostApi {
}
func didStartAdvertising(peripheral: CBPeripheralManager, error: Error?) {
guard let completion = _startAdvertisingCompletion else {
guard let completion = mStartAdvertisingCompletion else {
return
}
_startAdvertisingCompletion = nil
mStartAdvertisingCompletion = nil
if error == nil {
completion(.success(()))
} else {
@ -237,107 +210,152 @@ class MyPeripheralManager: MyPeripheralManagerHostApi {
}
func didReceiveRead(peripheral: CBPeripheralManager, request: CBATTRequest) {
let hashCodeArgs = request.hash.toInt64()
let central = request.central
let centralArgs = central.toArgs()
_centrals[centralArgs.uuidArgs] = central
mCentrals[centralArgs.uuidArgs] = central
let characteristic = request.characteristic
let hashCode = characteristic.hash
guard let characteristicArgs = _characteristicsArgs[hashCode] else {
_peripheralManager.respond(to: request, withResult: .attributeNotFound)
guard let characteristicArgs = mCharacteristicsArgs[characteristic.hash] else {
mPeripheralManager.respond(to: request, withResult: .attributeNotFound)
return
}
let hashCodeArgs = characteristicArgs.hashCodeArgs
let idArgs = request.hash.toInt64()
let characteristicHashCodeArgs = characteristicArgs.hashCodeArgs
let value = request.value
let valueArgs = value == nil ? nil : FlutterStandardTypedData(bytes: value!)
let offsetArgs = request.offset.toInt64()
_requests[idArgs] = request
_api.onCharacteristicReadRequest(centralArgs: centralArgs, hashCodeArgs: hashCodeArgs, idArgs: idArgs, offsetArgs: offsetArgs) {_ in }
let requestArgs = MyATTRequestArgs(hashCodeArgs: hashCodeArgs, centralArgs: centralArgs, characteristicHashCodeArgs: characteristicHashCodeArgs, valueArgs: valueArgs, offsetArgs: offsetArgs)
mRequests[hashCodeArgs] = request
mAPI.didReceiveRead(requestArgs: requestArgs) { _ in }
}
func didReceiveWrite(peripheral: CBPeripheralManager, requests: [CBATTRequest]) {
// When you respond to a write request, note that the first parameter of the respond(to:with
// Result:) method expects a single CBATTRequest object, even though you received an array of
// them from the peripheralManager(_:didReceiveWrite:) method. To respond properly,
// pass in the first request of the requests array.
// see: https://developer.apple.com/documentation/corebluetooth/cbperipheralmanagerdelegate/1393315-peripheralmanager#discussion
var requestsArgs = [MyATTRequestArgs]()
for request in requests {
let hashCodeArgs = request.hash.toInt64()
let central = request.central
let centralArgs = central.toArgs()
mCentrals[centralArgs.uuidArgs] = central
let characteristic = request.characteristic
guard let characteristicArgs = mCharacteristicsArgs[characteristic.hash] else {
mPeripheralManager.respond(to: request, withResult: .attributeNotFound)
return
}
let characteristicHashCodeArgs = characteristicArgs.hashCodeArgs
let value = request.value
let valueArgs = value == nil ? nil : FlutterStandardTypedData(bytes: value!)
let offsetArgs = request.offset.toInt64()
let requestArgs = MyATTRequestArgs(hashCodeArgs: hashCodeArgs, centralArgs: centralArgs, characteristicHashCodeArgs: characteristicHashCodeArgs, valueArgs: valueArgs, offsetArgs: offsetArgs)
requestsArgs.append(requestArgs)
}
guard let request = requests.first else {
return
}
if requests.count > 1 {
// TODO:
let result = CBATTError.requestNotSupported
_peripheralManager.respond(to: request, withResult: result)
guard let requestArgs = requestsArgs.first else {
return
}
let central = request.central
let centralArgs = central.toArgs()
_centrals[centralArgs.uuidArgs] = central
let characteristic = request.characteristic
let hashCode = characteristic.hash
guard let characteristicArgs = _characteristicsArgs[hashCode] else {
_peripheralManager.respond(to: request, withResult: .attributeNotFound)
return
}
let hashCodeArgs = characteristicArgs.hashCodeArgs
let idArgs = request.hash.toInt64()
let offsetArgs = request.offset.toInt64()
guard let value = request.value else {
_peripheralManager.respond(to: request, withResult: .requestNotSupported)
return
}
let valueArgs = FlutterStandardTypedData(bytes: value)
_requests[idArgs] = request
_api.onCharacteristicWriteRequest(centralArgs: centralArgs, hashCodeArgs: hashCodeArgs, idArgs: idArgs, offsetArgs: offsetArgs, valueArgs: valueArgs) {_ in }
self.mRequests[requestArgs.hashCodeArgs] = request
mAPI.didReceiveWrite(requestsArgs: requestsArgs) { _ in }
}
func didSubscribeTo(peripheral: CBPeripheralManager, central: CBCentral, characteristic: CBCharacteristic) {
let centralArgs = central.toArgs()
_centrals[centralArgs.uuidArgs] = central
mCentrals[centralArgs.uuidArgs] = central
let hashCode = characteristic.hash
guard let characteristicArgs = _characteristicsArgs[hashCode] else {
guard let characteristicArgs = mCharacteristicsArgs[hashCode] else {
return
}
let hashCodeArgs = characteristicArgs.hashCodeArgs
let stateArgs = true
_api.onCharacteristicNotifyStateChanged(centralArgs: centralArgs, hashCodeArgs: hashCodeArgs, stateArgs: stateArgs) {_ in }
mAPI.onCharacteristicNotifyStateChanged(centralArgs: centralArgs, hashCodeArgs: hashCodeArgs, stateArgs: stateArgs) { _ in }
}
func didUnsubscribeFrom(peripheral: CBPeripheralManager, central: CBCentral, characteristic: CBCharacteristic) {
let centralArgs = central.toArgs()
_centrals[centralArgs.uuidArgs] = central
mCentrals[centralArgs.uuidArgs] = central
let hashCode = characteristic.hash
guard let characteristicArgs = _characteristicsArgs[hashCode] else {
guard let characteristicArgs = mCharacteristicsArgs[hashCode] else {
return
}
let hashCodeArgs = characteristicArgs.hashCodeArgs
let stateArgs = false
_api.onCharacteristicNotifyStateChanged(centralArgs: centralArgs, hashCodeArgs: hashCodeArgs, stateArgs: stateArgs) {_ in }
mAPI.onCharacteristicNotifyStateChanged(centralArgs: centralArgs, hashCodeArgs: hashCodeArgs, stateArgs: stateArgs) { _ in }
}
func isReadyToUpdateSubscribers(peripheral: CBPeripheralManager) {
let callbacks = _isReadyToUpdateSubscribersCallbacks
_isReadyToUpdateSubscribersCallbacks.removeAll()
for callback in callbacks {
callback()
}
mAPI.isReady() { _ in }
}
private func _clearState() {
if(_peripheralManager.isAdvertising) {
_peripheralManager.stopAdvertising()
private func addServiceArgs(_ serviceArgs: MyMutableGATTServiceArgs) throws -> CBMutableService {
let service = serviceArgs.toService()
mServicesArgs[service.hash] = serviceArgs
mServices[serviceArgs.hashCodeArgs] = service
var includedServices = [CBService]()
let includedServicesArgs = serviceArgs.includedServicesArgs
for args in includedServicesArgs {
guard let includedServiceArgs = args else {
throw MyError.illegalArgument
}
let includedService = try addServiceArgs(includedServiceArgs)
self.mServicesArgs[includedService.hash] = includedServiceArgs
self.mServices[includedServiceArgs.hashCodeArgs] = includedService
includedServices.append(includedService)
}
_servicesArgs.removeAll()
_characteristicsArgs.removeAll()
_descriptorsArgs.removeAll()
_centrals.removeAll()
_services.removeAll()
_characteristics.removeAll()
_descriptors.removeAll()
_requests.removeAll()
_addServiceCompletion = nil
_startAdvertisingCompletion = nil
_isReadyToUpdateSubscribersCallbacks.removeAll()
service.includedServices = includedServices
var characteristics = [CBMutableCharacteristic]()
let characteristicsArgs = serviceArgs.characteristicsArgs
for args in characteristicsArgs {
guard let characteristicArgs = args else {
throw MyError.illegalArgument
}
let characteristic = characteristicArgs.toCharacteristic()
self.mCharacteristicsArgs[characteristic.hash] = characteristicArgs
self.mCharacteristics[characteristicArgs.hashCodeArgs] = characteristic
characteristics.append(characteristic)
var descriptors = [CBMutableDescriptor]()
let descriptorsArgs = characteristicArgs.descriptorsArgs
for args in descriptorsArgs {
guard let descriptorArgs = args else {
continue
}
let descriptor = descriptorArgs.toDescriptor()
self.mDescriptorsArgs[descriptor.hash] = descriptorArgs
self.mDescriptors[descriptorArgs.hashCodeArgs] = descriptor
descriptors.append(descriptor)
}
characteristic.descriptors = descriptors
}
service.characteristics = characteristics
return service
}
private func removeServiceArgs(_ serviceArgs: MyMutableGATTServiceArgs) throws {
for args in serviceArgs.includedServicesArgs {
guard let includedServiceArgs = args else {
throw MyError.illegalArgument
}
try removeServiceArgs(includedServiceArgs)
}
for args in serviceArgs.characteristicsArgs {
guard let characteristicArgs = args else {
throw MyError.illegalArgument
}
for args in characteristicArgs.descriptorsArgs {
guard let descriptorArgs = args else {
throw MyError.illegalArgument
}
guard let descriptor = mDescriptors.removeValue(forKey: descriptorArgs.hashCodeArgs) else {
throw MyError.illegalArgument
}
mDescriptorsArgs.removeValue(forKey: descriptor.hash)
}
guard let characteristic = mCharacteristics.removeValue(forKey: characteristicArgs.hashCodeArgs) else {
throw MyError.illegalArgument
}
mCharacteristicsArgs.removeValue(forKey: characteristic.hash)
}
guard let service = mServices.removeValue(forKey: serviceArgs.hashCodeArgs) else {
throw MyError.illegalArgument
}
mServicesArgs.removeValue(forKey: service.hash)
}
}

View File

@ -9,41 +9,41 @@ import Foundation
import CoreBluetooth
class MyPeripheralManagerDelegate: NSObject, CBPeripheralManagerDelegate {
private let _peripheralManager: MyPeripheralManager
private let mPeripheralManager: MyPeripheralManager
init(peripheralManager: MyPeripheralManager) {
_peripheralManager = peripheralManager
self.mPeripheralManager = peripheralManager
}
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
_peripheralManager.didUpdateState(peripheral: peripheral)
mPeripheralManager.didUpdateState(peripheral: peripheral)
}
func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) {
_peripheralManager.didAdd(peripheral: peripheral, service: service, error: error)
mPeripheralManager.didAdd(peripheral: peripheral, service: service, error: error)
}
func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {
_peripheralManager.didStartAdvertising(peripheral: peripheral, error: error)
mPeripheralManager.didStartAdvertising(peripheral: peripheral, error: error)
}
func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveRead request: CBATTRequest) {
_peripheralManager.didReceiveRead(peripheral: peripheral, request: request)
mPeripheralManager.didReceiveRead(peripheral: peripheral, request: request)
}
func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) {
_peripheralManager.didReceiveWrite(peripheral: peripheral, requests: requests)
mPeripheralManager.didReceiveWrite(peripheral: peripheral, requests: requests)
}
func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didSubscribeTo characteristic: CBCharacteristic) {
_peripheralManager.didSubscribeTo(peripheral: peripheral, central: central, characteristic: characteristic)
mPeripheralManager.didSubscribeTo(peripheral: peripheral, central: central, characteristic: characteristic)
}
func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didUnsubscribeFrom characteristic: CBCharacteristic) {
_peripheralManager.didUnsubscribeFrom(peripheral: peripheral, central: central, characteristic: characteristic)
mPeripheralManager.didUnsubscribeFrom(peripheral: peripheral, central: central, characteristic: characteristic)
}
func peripheralManagerIsReady(toUpdateSubscribers peripheral: CBPeripheralManager) {
_peripheralManager.isReadyToUpdateSubscribers(peripheral: peripheral)
mPeripheralManager.isReadyToUpdateSubscribers(peripheral: peripheral)
}
}

View File

@ -4,24 +4,24 @@
#
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.version = '0.0.1'
s.summary = 'A new Flutter plugin project.'
s.description = <<-DESC
iOS and macOS implementation of the bluetooth_low_energy plugin.
A new Flutter plugin project.
DESC
s.homepage = 'https://github.com/yanshouwang/bluetooth_low_energy'
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'yanshouwang' => 'yanshouwang@outlook.com' }
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.ios.dependency 'Flutter'
s.ios.deployment_target = '11.0'
s.ios.deployment_target = '12.0'
s.osx.dependency 'FlutterMacOS'
s.osx.deployment_target = '10.11'
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
s.swift_version = '5.0'
end