You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
6.4 KiB
197 lines
6.4 KiB
import Foundation
|
|
import ExternalAccessory
|
|
import CoreBluetooth
|
|
|
|
/// 蓝牙事件类型
|
|
enum BluetoothEventType {
|
|
case stateChanged
|
|
case deviceConnected
|
|
case deviceDisconnected
|
|
}
|
|
|
|
/// 蓝牙状态枚举
|
|
enum BluetoothState: String {
|
|
case unknown = "unknown"
|
|
case off = "off"
|
|
case on = "on"
|
|
case turningOn = "turningOn"
|
|
case turningOff = "turningOff"
|
|
}
|
|
|
|
/// 经典蓝牙助手类,负责iOS上的蓝牙设备管理
|
|
class ClassicBluetoothHelper: NSObject {
|
|
private let TAG = "ClassicBluetoothHelper"
|
|
|
|
// 状态监控相关
|
|
private var isMonitoring = false
|
|
private var stateCallback: ((BluetoothEventType, [String: Any]) -> Void)?
|
|
|
|
// 用于监控蓝牙系统状态
|
|
private var centralManager: CBCentralManager?
|
|
|
|
// 通知观察者
|
|
private var accessoryConnectionObserver: NSObjectProtocol?
|
|
private var accessoryDisconnectionObserver: NSObjectProtocol?
|
|
|
|
override init() {
|
|
super.init()
|
|
centralManager = CBCentralManager(delegate: nil, queue: nil, options: [CBCentralManagerOptionShowPowerAlertKey: false])
|
|
}
|
|
|
|
deinit {
|
|
stopBluetoothStateMonitoring()
|
|
}
|
|
|
|
/// 检查蓝牙是否启用
|
|
func isBluetoothEnabled() -> Bool {
|
|
guard let centralManager = centralManager else { return false }
|
|
return centralManager.state == .poweredOn
|
|
}
|
|
|
|
/// 获取已连接的蓝牙设备
|
|
/// - Parameter completion: 完成回调
|
|
func getConnectedDevices(completion: @escaping ([[String: String]], Error?) -> Void) {
|
|
// 获取所有已连接的外部配件
|
|
let accessoryManager = EAAccessoryManager.shared()
|
|
let connectedAccessories = accessoryManager.connectedAccessories
|
|
|
|
// 将配件转换为设备信息数组
|
|
let devices = connectedAccessories.map { accessory -> [String: String] in
|
|
return [
|
|
"name": accessory.name,
|
|
"address": accessory.serialNumber // iOS使用序列号作为唯一标识
|
|
]
|
|
}
|
|
|
|
// 返回结果
|
|
completion(devices, nil)
|
|
}
|
|
|
|
/// 开始监听蓝牙状态变化
|
|
/// - Parameter callback: 状态变化回调
|
|
func startBluetoothStateMonitoring(callback: @escaping (BluetoothEventType, [String: Any]) -> Void) {
|
|
self.stateCallback = callback
|
|
|
|
if !isMonitoring {
|
|
isMonitoring = true
|
|
|
|
// 设置蓝牙中央管理器代理
|
|
centralManager?.delegate = self
|
|
|
|
// 注册蓝牙配件连接/断开通知
|
|
let notificationCenter = NotificationCenter.default
|
|
|
|
// 观察配件连接
|
|
accessoryConnectionObserver = notificationCenter.addObserver(
|
|
forName: NSNotification.Name.EAAccessoryDidConnect,
|
|
object: nil,
|
|
queue: nil
|
|
) { [weak self] notification in
|
|
guard let self = self,
|
|
let accessory = notification.userInfo?[EAAccessoryKey] as? EAAccessory else {
|
|
return
|
|
}
|
|
|
|
let device: [String: String] = [
|
|
"name": accessory.name,
|
|
"address": accessory.serialNumber
|
|
]
|
|
|
|
self.stateCallback?(.deviceConnected, ["device": device])
|
|
}
|
|
|
|
// 观察配件断开
|
|
accessoryDisconnectionObserver = notificationCenter.addObserver(
|
|
forName: NSNotification.Name.EAAccessoryDidDisconnect,
|
|
object: nil,
|
|
queue: nil
|
|
) { [weak self] notification in
|
|
guard let self = self,
|
|
let accessory = notification.userInfo?[EAAccessoryKey] as? EAAccessory else {
|
|
return
|
|
}
|
|
|
|
let device: [String: String] = [
|
|
"name": accessory.name,
|
|
"address": accessory.serialNumber
|
|
]
|
|
|
|
self.stateCallback?(.deviceDisconnected, ["device": device])
|
|
}
|
|
|
|
// 开始监视配件变化
|
|
EAAccessoryManager.shared().registerForLocalNotifications()
|
|
}
|
|
}
|
|
|
|
/// 停止监听蓝牙状态变化
|
|
func stopBluetoothStateMonitoring() {
|
|
if isMonitoring {
|
|
isMonitoring = false
|
|
|
|
// 移除蓝牙中央管理器代理
|
|
centralManager?.delegate = nil
|
|
|
|
// 注销配件通知观察者
|
|
if let observer = accessoryConnectionObserver {
|
|
NotificationCenter.default.removeObserver(observer)
|
|
accessoryConnectionObserver = nil
|
|
}
|
|
|
|
if let observer = accessoryDisconnectionObserver {
|
|
NotificationCenter.default.removeObserver(observer)
|
|
accessoryDisconnectionObserver = nil
|
|
}
|
|
|
|
// 停止监视配件变化
|
|
EAAccessoryManager.shared().unregisterForLocalNotifications()
|
|
}
|
|
|
|
// 清除回调
|
|
stateCallback = nil
|
|
}
|
|
|
|
/// 报告当前蓝牙状态
|
|
func reportCurrentBluetoothState() {
|
|
guard let centralManager = centralManager else { return }
|
|
|
|
let state: BluetoothState
|
|
|
|
switch centralManager.state {
|
|
case .poweredOn:
|
|
state = .on
|
|
case .poweredOff:
|
|
state = .off
|
|
case .resetting:
|
|
state = .turningOff // 最接近的近似值
|
|
case .unauthorized, .unsupported:
|
|
state = .off // 功能上等同于关闭
|
|
default:
|
|
state = .unknown
|
|
}
|
|
|
|
stateCallback?(.stateChanged, ["state": state.rawValue])
|
|
}
|
|
}
|
|
|
|
// MARK: - CBCentralManagerDelegate
|
|
extension ClassicBluetoothHelper: CBCentralManagerDelegate {
|
|
func centralManagerDidUpdateState(_ central: CBCentralManager) {
|
|
let state: BluetoothState
|
|
|
|
switch central.state {
|
|
case .poweredOn:
|
|
state = .on
|
|
case .poweredOff:
|
|
state = .off
|
|
case .resetting:
|
|
state = .turningOff
|
|
case .unauthorized, .unsupported:
|
|
state = .off
|
|
default:
|
|
state = .unknown
|
|
}
|
|
|
|
stateCallback?(.stateChanged, ["state": state.rawValue])
|
|
}
|
|
}
|