* 调整接口 * 临时提交 * 重构 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>
304 lines
9.5 KiB
Swift
304 lines
9.5 KiB
Swift
//
|
|
// MyApi.swift
|
|
// bluetooth_low_energy_darwin
|
|
//
|
|
// Created by 闫守旺 on 2023/9/28.
|
|
//
|
|
|
|
import Foundation
|
|
import CoreBluetooth
|
|
|
|
#if os(iOS)
|
|
import Flutter
|
|
#elseif os(macOS)
|
|
import FlutterMacOS
|
|
#else
|
|
#error("Unsupported platform.")
|
|
#endif
|
|
|
|
// ToObj
|
|
extension [MyGATTCharacteristicPropertyArgs] {
|
|
func toProperties() -> CBCharacteristicProperties {
|
|
var properties: CBCharacteristicProperties = []
|
|
for args in self {
|
|
switch args {
|
|
case .read:
|
|
properties.insert(.read)
|
|
case .write:
|
|
properties.insert(.write)
|
|
case .writeWithoutResponse:
|
|
properties.insert(.writeWithoutResponse)
|
|
case .notify:
|
|
properties.insert(.notify)
|
|
case .indicate:
|
|
properties.insert(.indicate)
|
|
}
|
|
}
|
|
return properties
|
|
}
|
|
}
|
|
|
|
extension [MyGATTCharacteristicPermissionArgs] {
|
|
func toPermissions() -> CBAttributePermissions {
|
|
var permissions: CBAttributePermissions = []
|
|
for args in self {
|
|
switch args {
|
|
case .read:
|
|
permissions.insert(.readable)
|
|
case .readEncrypted:
|
|
permissions.insert(.readEncryptionRequired)
|
|
case .write:
|
|
permissions.insert(.writeable)
|
|
case .writeEncrypted:
|
|
permissions.insert(.writeEncryptionRequired)
|
|
}
|
|
}
|
|
return permissions
|
|
}
|
|
}
|
|
|
|
extension MyGATTCharacteristicWriteTypeArgs {
|
|
func toWriteType() -> CBCharacteristicWriteType {
|
|
switch self {
|
|
case .withResponse:
|
|
return .withResponse
|
|
case .withoutResponse:
|
|
return .withoutResponse
|
|
}
|
|
}
|
|
}
|
|
|
|
extension MyATTErrorArgs {
|
|
func toError() -> CBATTError.Code {
|
|
switch self {
|
|
case .success:
|
|
return .success
|
|
case .invalidHandle:
|
|
return .invalidHandle
|
|
case .readNotPermitted:
|
|
return .readNotPermitted
|
|
case .writeNotPermitted:
|
|
return .writeNotPermitted
|
|
case .invalidPDU:
|
|
return .invalidPdu
|
|
case .insufficientAuthentication:
|
|
return .insufficientAuthentication
|
|
case .requestNotSupported:
|
|
return .requestNotSupported
|
|
case .invalidOffset:
|
|
return .invalidOffset
|
|
case .insufficientAuthorization:
|
|
return .insufficientAuthorization
|
|
case .prepareQueueFull:
|
|
return .prepareQueueFull
|
|
case .attributeNotFound:
|
|
return .attributeNotFound
|
|
case .attributeNotLong:
|
|
return .attributeNotLong
|
|
case .insufficientEncryptionKeySize:
|
|
return .insufficientEncryptionKeySize
|
|
case .invalidAttributeValueLength:
|
|
return .invalidAttributeValueLength
|
|
case .unlikelyError:
|
|
return .unlikelyError
|
|
case .insufficientEncryption:
|
|
return .insufficientEncryption
|
|
case .unsupportedGroupType:
|
|
return .unsupportedGroupType
|
|
case .insufficientResources:
|
|
return .insufficientResources
|
|
}
|
|
}
|
|
}
|
|
|
|
extension MyAdvertisementArgs {
|
|
func toAdvertisement() -> [String : Any] {
|
|
// CoreBluetooth only support `CBAdvertisementDataLocalNameKey` and `CBAdvertisementDataServiceUUIDsKey`
|
|
// see https://developer.apple.com/documentation/corebluetooth/cbperipheralmanager/1393252-startadvertising
|
|
var advertisement = [String: Any]()
|
|
if nameArgs != nil {
|
|
let name = nameArgs!
|
|
advertisement[CBAdvertisementDataLocalNameKey] = name
|
|
}
|
|
if !serviceUUIDsArgs.isEmpty {
|
|
let serviceUUIDs = serviceUUIDsArgs.map { serviceUUIDArgs in serviceUUIDArgs!.toCBUUID() }
|
|
advertisement[CBAdvertisementDataServiceUUIDsKey] = serviceUUIDs
|
|
}
|
|
return advertisement
|
|
}
|
|
}
|
|
|
|
extension MyMutableGATTDescriptorArgs {
|
|
func toDescriptor() -> CBMutableDescriptor {
|
|
let type = uuidArgs.toCBUUID()
|
|
let value = valueArgs?.data
|
|
return CBMutableDescriptor(type: type, value: value)
|
|
}
|
|
}
|
|
|
|
extension MyMutableGATTCharacteristicArgs {
|
|
func toCharacteristic() -> CBMutableCharacteristic {
|
|
let type = uuidArgs.toCBUUID()
|
|
let propertiesArgs = propertyNumbersArgs.map { propertyNumberArgs in
|
|
let propertyNumber = propertyNumberArgs!.toInt()
|
|
return MyGATTCharacteristicPropertyArgs(rawValue: propertyNumber)!
|
|
}
|
|
let properties = propertiesArgs.toProperties()
|
|
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 MyMutableGATTServiceArgs {
|
|
func toService() -> CBMutableService {
|
|
let type = uuidArgs.toCBUUID()
|
|
let primary = isPrimaryArgs
|
|
return CBMutableService(type: type, primary: primary)
|
|
}
|
|
}
|
|
|
|
extension Int64 {
|
|
func toInt() -> Int {
|
|
return Int(self)
|
|
}
|
|
}
|
|
|
|
extension String {
|
|
func toCBUUID() -> CBUUID {
|
|
return CBUUID(string: self)
|
|
}
|
|
}
|
|
|
|
// ToArgs
|
|
extension CBManagerState {
|
|
func toArgs() -> MyBluetoothLowEnergyStateArgs {
|
|
switch self {
|
|
case .resetting:
|
|
return .resetting
|
|
case .unsupported:
|
|
return .unsupported
|
|
case .unauthorized:
|
|
return .unauthorized
|
|
case .poweredOff:
|
|
return .poweredOff
|
|
case .poweredOn:
|
|
return .poweredOn
|
|
default:
|
|
return .unknown
|
|
}
|
|
}
|
|
}
|
|
|
|
extension [String: Any] {
|
|
func toAdvertisementArgs() -> MyAdvertisementArgs {
|
|
let nameArgs = self[CBAdvertisementDataLocalNameKey] as? String
|
|
let serviceUUIDs = self[CBAdvertisementDataServiceUUIDsKey] as? [CBUUID] ?? []
|
|
let serviceUUIDsArgs = serviceUUIDs.map { uuid in uuid.uuidString }
|
|
let serviceData = self[CBAdvertisementDataServiceDataKey] as? [CBUUID: Data] ?? [:]
|
|
let serviceDataArgsKeyWithValues = serviceData.map { (uuid, data) in
|
|
let uuidArgs = uuid.uuidString
|
|
let dataArgs = FlutterStandardTypedData(bytes: data)
|
|
return (uuidArgs, dataArgs)
|
|
}
|
|
let serviceDataArgs = [String?: FlutterStandardTypedData?](uniqueKeysWithValues: serviceDataArgsKeyWithValues)
|
|
let manufacturerData = self[CBAdvertisementDataManufacturerDataKey] as? Data
|
|
let manufacturerSpecificDataArgs = manufacturerData == nil ? nil : FlutterStandardTypedData(bytes: manufacturerData!)
|
|
return MyAdvertisementArgs(nameArgs: nameArgs, serviceUUIDsArgs: serviceUUIDsArgs, serviceDataArgs: serviceDataArgs, manufacturerSpecificDataArgs: manufacturerSpecificDataArgs)
|
|
}
|
|
}
|
|
|
|
extension CBCentral {
|
|
func toArgs() -> MyCentralArgs {
|
|
let uuidArgs = identifier.toArgs()
|
|
return MyCentralArgs(uuidArgs: uuidArgs)
|
|
}
|
|
}
|
|
|
|
extension CBPeripheral {
|
|
func toArgs() -> MyPeripheralArgs {
|
|
let uuidArgs = identifier.toArgs()
|
|
return MyPeripheralArgs(uuidArgs: uuidArgs)
|
|
}
|
|
}
|
|
|
|
extension CBDescriptor {
|
|
func toArgs() -> MyGATTDescriptorArgs {
|
|
let hashCodeArgs = hash.toInt64()
|
|
let uuidArgs = uuid.toArgs()
|
|
return MyGATTDescriptorArgs(hashCodeArgs: hashCodeArgs, uuidArgs: uuidArgs)
|
|
}
|
|
}
|
|
|
|
extension CBCharacteristic {
|
|
func toArgs() -> MyGATTCharacteristicArgs {
|
|
let hashCodeArgs = hash.toInt64()
|
|
let uuidArgs = uuid.toArgs()
|
|
let propertyNumbersArgs = properties.toArgs().map { args in args.rawValue.toInt64() }
|
|
let descriptorsArgs = descriptors?.map { descriptor in descriptor.toArgs() } ?? []
|
|
return MyGATTCharacteristicArgs(hashCodeArgs: hashCodeArgs, uuidArgs: uuidArgs, propertyNumbersArgs: propertyNumbersArgs, descriptorsArgs: descriptorsArgs)
|
|
}
|
|
}
|
|
|
|
extension CBCharacteristicProperties {
|
|
func toArgs() -> [MyGATTCharacteristicPropertyArgs] {
|
|
var args = [MyGATTCharacteristicPropertyArgs]()
|
|
if contains(.read) {
|
|
args.append(.read)
|
|
}
|
|
if contains(.write) {
|
|
args.append(.write)
|
|
}
|
|
if contains(.writeWithoutResponse) {
|
|
args.append(.writeWithoutResponse)
|
|
}
|
|
if contains(.notify) {
|
|
args.append(.notify)
|
|
}
|
|
if contains(.indicate) {
|
|
args.append(.indicate)
|
|
}
|
|
return args
|
|
}
|
|
}
|
|
|
|
extension CBService {
|
|
func toArgs() -> MyGATTServiceArgs {
|
|
let hashCodeArgs = hash.toInt64()
|
|
let uuidArgs = uuid.toArgs()
|
|
let isPrimaryArgs = isPrimary
|
|
let includedServicesArgs = includedServices?.map { includedService in includedService.toArgs() } ?? []
|
|
let characteristicsArgs = characteristics?.map { characteristic in characteristic.toArgs() } ?? []
|
|
return MyGATTServiceArgs(hashCodeArgs: hashCodeArgs, uuidArgs: uuidArgs, isPrimaryArgs: isPrimaryArgs, includedServicesArgs: includedServicesArgs, characteristicsArgs: characteristicsArgs)
|
|
}
|
|
}
|
|
|
|
extension Int {
|
|
func toInt64() -> Int64 {
|
|
return Int64(self)
|
|
}
|
|
}
|
|
|
|
extension UUID {
|
|
func toArgs() -> String {
|
|
return uuidString.lowercased()
|
|
}
|
|
}
|
|
|
|
extension CBUUID {
|
|
func toArgs() -> String {
|
|
return uuidString.lowercased()
|
|
}
|
|
}
|
|
|
|
extension UInt16 {
|
|
var data: Data {
|
|
var bytes = self
|
|
return Data(bytes: &bytes, count: MemoryLayout<UInt16>.size)
|
|
}
|
|
}
|