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

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])
}
}