import Foundation import CoreBluetooth import os.log /// BLE服务类 - 单例实现 actor BleService { // MARK: - 单例实现 static let shared = BleService() // MARK: - 常量 /// 用于状态恢复的唯一标识符 private let restoreIdentifier = "com.yunqiinnovation.ble_service.restore" private init() { // 初始化连接状态 connectionState = BleConst.STATE_DISCONNECTED // 将通知处理移到非actor方法中 setupNotifications() } deinit { // 移除通知观察者 for observer in notificationObservers { NotificationCenter.default.removeObserver(observer) } } // MARK: - 属性 /// 中央管理器 private var centralManager: CBCentralManager? /// 当前连接的外设 private var peripheral: CBPeripheral? /// 主服务特征 private var writeCharacteristic: CBCharacteristic? private var notifyCharacteristic: CBCharacteristic? private var audioCharacteristic: CBCharacteristic? /// 连接状态 private(set) var connectionState: Int { didSet { if oldValue != connectionState { Task { await notifyConnectionStateChanged(state: connectionState) } } } } /// 是否正在扫描 private(set) var isScanning = false /// 扫描结果缓存 private var scanResults = [CBPeripheral: [String: Any]]() /// 扫描超时任务 private var scanTimeoutTask: Task? /// 是否已初始化 private var isInitialized = false /// 回调代理列表 - 使用actor保证线程安全 private var delegates = [BleDelegate]() /// 日志 private let logger = OSLog(subsystem: "com.yunqiinnovation.ble_service", category: "BleService") /// 通知观察者 private var notificationObservers = [NSObjectProtocol]() // MARK: - 通知设置 /// 设置应用生命周期通知 private nonisolated func setupNotifications() { // 使用nonisolated函数以避免actor隔离问题 let becomeActiveObserver = NotificationCenter.default.addObserver( forName: UIApplication.didBecomeActiveNotification, object: nil, queue: .main ) { [weak self] _ in guard let self = self else { return } Task { await self.handleAppDidBecomeActive() } } let enterBackgroundObserver = NotificationCenter.default.addObserver( forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: .main ) { [weak self] _ in guard let self = self else { return } Task { await self.handleAppDidEnterBackground() } } // 存储观察者以便后续移除 notificationObservers = [becomeActiveObserver, enterBackgroundObserver] } // MARK: - 公共方法 /// 初始化BLE服务 /// - Returns: 是否初始化成功 func initialize() -> Bool { if isInitialized { return true } do { // 初始化中央管理器 - 配置状态恢复选项 let options: [String: Any] = [ CBCentralManagerOptionRestoreIdentifierKey: restoreIdentifier, CBCentralManagerOptionShowPowerAlertKey: true ] centralManager = CBCentralManager( delegate: CBManagerHandler.shared, queue: nil, options: options ) CBManagerHandler.shared.bleService = self isInitialized = true os_log("BLE服务初始化成功", log: logger, type: .info) return true } catch { os_log("BLE服务初始化失败: %{public}@", log: logger, type: .error, error.localizedDescription) return false } } /// 添加回调代理 /// - Parameter delegate: 要添加的代理 /// - Returns: 是否添加成功 func addDelegate(_ delegate: BleDelegate) -> Bool { if !delegates.contains(where: { $0 === delegate }) { delegates.append(delegate) os_log("已添加BLE回调, 当前回调数: %d", log: logger, type: .debug, delegates.count) return true } return false } /// 移除回调代理 /// - Parameter delegate: 要移除的代理 /// - Returns: 是否移除成功 func removeDelegate(_ delegate: BleDelegate) -> Bool { if let index = delegates.firstIndex(where: { $0 === delegate }) { delegates.remove(at: index) os_log("已移除BLE回调, 当前回调数: %d", log: logger, type: .debug, delegates.count) return true } return false } /// 清除所有回调代理 func clearDelegates() { delegates.removeAll() os_log("已清除所有BLE回调", log: logger, type: .debug) } /// 检查是否已连接 /// - Returns: 是否已连接 func isConnected() -> Bool { return connectionState == BleConst.STATE_CONNECTED } // MARK: - 扫描方法 /// 开始主动扫描BLE设备 /// - Parameter timeout: 扫描超时时间(秒) /// - Returns: 是否成功开始扫描 func startScan(timeout: TimeInterval = 15.0) -> Bool { if !isInitialized { os_log("BLE服务未初始化", log: logger, type: .error) return false } if isScanning { return false } guard let manager = centralManager, manager.state == .poweredOn else { os_log("蓝牙未开启", log: logger, type: .error) return false } os_log("开始主动扫描BLE设备...", log: logger, type: .info) unregisterBackgroundScan() // 避免双重扫描 scanResults.removeAll() // 扫描选项 - 允许重复结果,以获取最新的RSSI值 let options: [String: Any] = [ CBCentralManagerScanOptionAllowDuplicatesKey: true ] // 设置过滤服务UUID let scanFilters = [ // 如果需要过滤,添加CBUUID // CBUUID(string: BleConst.PRIMARY_SERVICE_UUID.uuidString) ] // 使用过滤器开始扫描 manager.scanForPeripherals( withServices: scanFilters.isEmpty ? nil : scanFilters, options: options ) isScanning = true // 设置扫描超时 scanTimeoutTask?.cancel() scanTimeoutTask = Task { [weak self] in guard let self = self else { return } do { try await Task.sleep(nanoseconds: UInt64(timeout * 1_000_000_000)) if !Task.isCancelled { await self.stopScan() } } catch { // 任务被取消,忽略错误 } } return true } /// 停止主动扫描 /// - Returns: 是否成功停止扫描 func stopScan() -> Bool { if !isScanning { return false } os_log("停止主动扫描", log: logger, type: .info) centralManager?.stopScan() scanTimeoutTask?.cancel() scanTimeoutTask = nil isScanning = false // 重新注册后台扫描,保证唤醒能力 registerBackgroundScan() return true } /// 注册后台扫描 /// - Returns: 是否成功注册 func registerBackgroundScan() -> Bool { // iOS中无法直接实现与Android相同的后台扫描唤醒功能 os_log("iOS不支持直接的后台扫描唤醒,将使用状态保存和恢复功能", log: logger, type: .info) return true } /// 注销后台扫描 /// - Returns: 是否成功注销 func unregisterBackgroundScan() -> Bool { // iOS没有直接的后台扫描注销机制 os_log("iOS不支持直接的后台扫描注销", log: logger, type: .info) return true } // MARK: - 连接方法 /// 连接到指定地址的BLE设备 /// - Parameter address: 设备UUID字符串 func connect(address: String) async { if connectionState == BleConst.STATE_CONNECTED { os_log("已经连接中,忽略连接请求", log: logger, type: .warning) return } guard let central = centralManager, central.state == .poweredOn else { updateConnectionState(BleConst.STATE_ERROR) return } // 关闭现有连接 disconnectGatt() // 查找对应的外设 if let uuid = UUID(uuidString: address), let targetPeripheral = scanResults.keys.first(where: { $0.identifier == uuid }) { // 如果在扫描结果中找到,直接连接 os_log("从扫描结果中找到目标设备,开始连接...", log: logger, type: .debug) await connectToPeripheral(targetPeripheral) } else { // 如果没有找到,尝试从已知设备中恢复 os_log("尝试使用UUID恢复设备连接: %{public}@", log: logger, type: .debug, address) if let uuid = UUID(uuidString: address) { let peripherals = central.retrievePeripherals(withIdentifiers: [uuid]) if let targetPeripheral = peripherals.first { await connectToPeripheral(targetPeripheral) } else { os_log("未找到指定UUID的设备: %{public}@", log: logger, type: .error, address) updateConnectionState(BleConst.STATE_ERROR) } } else { os_log("无效的UUID格式: %{public}@", log: logger, type: .error, address) updateConnectionState(BleConst.STATE_ERROR) } } } /// 连接到指定外设 /// - Parameter peripheral: 要连接的外设 private func connectToPeripheral(_ peripheral: CBPeripheral) async { self.peripheral = peripheral peripheral.delegate = CBPeripheralHandler.shared CBPeripheralHandler.shared.bleService = self updateConnectionState(BleConst.STATE_CONNECTING) centralManager?.connect(peripheral, options: nil) } /// 断开当前连接 func disconnect() async { guard let peripheral = peripheral, let central = centralManager else { return } updateConnectionState(BleConst.STATE_DISCONNECTING) central.cancelPeripheralConnection(peripheral) } /// 安全关闭GATT连接 private func disconnectGatt() { if let peripheral = peripheral, let central = centralManager { central.cancelPeripheralConnection(peripheral) } peripheral = nil writeCharacteristic = nil notifyCharacteristic = nil audioCharacteristic = nil } /// 更新连接状态并通知回调 private func updateConnectionState(_ state: Int) { connectionState = state } // MARK: - 设备通信方法 /// 获取设备版本号 /// - Returns: 是否成功发送请求 func getDeviceVersion() -> Bool { return sendCommand(BleConst.CMD_GET_VERSION) } ///获取产品ID /// - Returns: 是否成功发送请求 func getProductId() -> Bool { return sendCommand(BleConst.CMD_GET_PRODUCT_ID) } /// 获取电池信息 /// - Returns: 是否成功发送请求 func getBatteryInfo() -> Bool { return sendCommand(BleConst.CMD_GET_BATTERY_INFO) } /// 打开编码器 /// - Returns: 是否成功发送请求 func openEncoder() -> Bool { return sendCodecControl(BleConst.CODEC_CONTROL_ENCODE_ON) } /// 打开解码器 /// - Returns: 是否成功发送请求 func openDecoder() -> Bool { return sendCodecControl(BleConst.CODEC_CONTROL_DECODE_ON) } /// 打开解码器 /// - Returns: 是否成功发送请求 func openA2DPDecoder() -> Bool { return sendCodecControl(BleConst.CODEC_CONTROL_A2DP_PLAY) } /// 关闭编解码器 /// - Returns: 是否成功发送请求 func closeCodec() -> Bool { return sendCodecControl(BleConst.CODEC_CONTROL_CLOSE) } /// 播放A2DP /// - Returns: 是否成功发送请求 func playA2DP() -> Bool { return sendCodecControl(BleConst.CODEC_CONTROL_A2DP_PLAY) } /// 发送编解码控制指令 /// - Parameter control: 控制值 /// - Returns: 是否成功发送 private func sendCodecControl(_ control: UInt8) -> Bool { let data = Data([BleConst.APP_REQUEST_HEADER, BleConst.CMD_CONTROL_CODEC, control]) return writeData(data) } /// 发送命令 /// - Parameter command: 命令字 /// - Returns: 是否成功发送 private func sendCommand(_ command: UInt8) -> Bool { let data = Data([BleConst.APP_REQUEST_HEADER, command]) return writeData(data) } /// 写入数据 /// - Parameter data: 要写入的数据 /// - Returns: 是否成功写入 private func writeData(_ data: Data) -> Bool { guard let peripheral = peripheral, let characteristic = writeCharacteristic, connectionState == BleConst.STATE_CONNECTED else { os_log("无法写入数据,设备未连接或特征未找到", log: logger, type: .error) return false } let hexString = data.map { String(format: "0x%02X", $0) }.joined(separator: " ") os_log("写入数据: %{public}@", log: logger, type: .debug, hexString) peripheral.writeValue(data, for: characteristic, type: .withoutResponse) return true } // MARK: - 数据处理方法 /// 处理音频数据 /// - Parameter data: 音频数据 func processAudioData(_ data: Data) async { os_log("收到音频数据: %d字节", log: logger, type: .debug, data.count) await notifyAudioDataReceived(data: data) } /// 处理设备响应 /// - Parameter data: 设备响应数据 func processDeviceResponse(_ data: Data) async { guard data.count >= 2 else { return } let cmd = data[1] os_log("收到设备响应: CMD=0x%02X", log: logger, type: .debug, cmd) switch cmd { case BleConst.CMD_GET_VERSION: if data.count >= 3 { // 解析版本号 let version = String(format: "%d.%d.%d", data[2], data.count > 3 ? data[3] : 0, data.count > 4 ? data[4] : 0) let infoData: [String: Any] = ["version": version] await notifyDeviceInfoReceived(infoType: Int(cmd), infoData: infoData) } case BleConst.CMD_GET_BATTERY_INFO: if data.count >= 3 { // 解析电池电量 let batteryLevel = Int(data[2]) let infoData: [String: Any] = ["level": batteryLevel] await notifyDeviceInfoReceived(infoType: Int(cmd), infoData: infoData) } default: os_log("未处理的响应命令: 0x%02X", log: logger, type: .debug, cmd) } } /// 处理设备通知 /// - Parameter data: 设备通知数据 func processDeviceNotification(_ data: Data) async { guard data.count >= 2 else { return } let notifyType = data[1] os_log("收到设备通知: Type=0x%02X", log: logger, type: .debug, notifyType) switch notifyType { case BleConst.CMD_WAKE_UP: // 设备唤醒信号 await notifyWakeupSignalReceived() default: os_log("未处理的通知类型: 0x%02X", log: logger, type: .debug, notifyType) } } // MARK: - 应用状态处理 /// 处理应用进入活跃状态 private func handleAppDidBecomeActive() async { os_log("应用进入活跃状态", log: logger, type: .debug) // 重新初始化蓝牙管理器,如果需要 if centralManager == nil { _ = initialize() } } /// 处理应用进入后台 private func handleAppDidEnterBackground() async { os_log("应用进入后台", log: logger, type: .debug) // 在iOS中,后台蓝牙操作有一定限制,这里可以做一些清理工作 } // MARK: - 回调通知方法 /// 通知扫描结果 /// - Parameter devices: 设备列表 func notifyScanResult(devices: [[String: Any]]) async { let currentDelegates = delegates for delegate in currentDelegates { await MainActor.run { delegate.onScanResult(devices: devices) } } } /// 通知连接状态变化 /// - Parameter state: 连接状态 func notifyConnectionStateChanged(state: Int) async { let currentDelegates = delegates for delegate in currentDelegates { await MainActor.run { delegate.onConnectionStateChanged(state: state) } } } /// 通知音频数据接收 /// - Parameter data: 音频数据 func notifyAudioDataReceived(data: Data) async { let currentDelegates = delegates for delegate in currentDelegates { await MainActor.run { delegate.onAudioDataReceived(data: data) } } } /// 通知唤醒信号接收 func notifyWakeupSignalReceived() async { let currentDelegates = delegates for delegate in currentDelegates { await MainActor.run { delegate.onWakeupSignalReceived() } } } /// 通知设备信息接收 /// - Parameters: /// - infoType: 信息类型 /// - infoData: 信息数据 func notifyDeviceInfoReceived(infoType: Int, infoData: [String: Any]) async { let currentDelegates = delegates for delegate in currentDelegates { await MainActor.run { delegate.onDeviceInfoReceived(infoType: infoType, infoData: infoData) } } } /// 处理扫描到的设备 func handleDiscoveredPeripheral(_ peripheral: CBPeripheral, advertisementData: [String: Any], rssi: NSNumber) async { // 打印外设信息 os_log("扫描到设备: 名称=%{public}@, ID=%{public}@, RSSI=%d", log: logger, type: .debug, peripheral.name ?? "未知", peripheral.identifier.uuidString, rssi.intValue) // 提取服务UUID var uuids: [String] = [] if let serviceUUIDs = advertisementData[CBAdvertisementDataServiceUUIDsKey] as? [CBUUID] { uuids = serviceUUIDs.map { $0.uuidString } } // 创建设备信息字典 let deviceInfo: [String: Any] = [ "id": peripheral.identifier.uuidString, "name": peripheral.name ?? "未知", "rssi": rssi.intValue, "uuids": uuids ] // 更新扫描缓存 scanResults[peripheral] = deviceInfo // 通知扫描结果 await notifyScanResult(devices: [deviceInfo]) } /// 处理连接结果 func handleConnectionResult(peripheral: CBPeripheral, success: Bool, error: Error?) async { if success { os_log("已连接到设备: %{public}@", log: logger, type: .info, peripheral.identifier.uuidString) updateConnectionState(BleConst.STATE_CONNECTED) // 开始服务发现 peripheral.discoverServices([BleConst.PRIMARY_SERVICE_UUID, BleConst.AUDIO_SERVICE_UUID]) } else { os_log("连接设备失败: %{public}@", log: logger, type: .error, error?.localizedDescription ?? "未知错误") updateConnectionState(BleConst.STATE_ERROR) // 清理资源 self.peripheral = nil } } /// 处理断开连接 func handleDisconnection(peripheral: CBPeripheral, error: Error?) async { if let error = error { os_log("设备连接断开(错误): %{public}@", log: logger, type: .error, error.localizedDescription) updateConnectionState(BleConst.STATE_ERROR) } else { os_log("设备连接断开(正常)", log: logger, type: .info) updateConnectionState(BleConst.STATE_DISCONNECTED) } // 清理资源 if self.peripheral?.identifier == peripheral.identifier { self.peripheral = nil self.writeCharacteristic = nil self.notifyCharacteristic = nil self.audioCharacteristic = nil } } /// 处理发现服务 func handleDiscoveredServices(peripheral: CBPeripheral, error: Error?) async { if let error = error { os_log("发现服务失败: %{public}@", log: logger, type: .error, error.localizedDescription) updateConnectionState(BleConst.STATE_ERROR) return } guard let services = peripheral.services else { os_log("没有发现任何服务", log: logger, type: .error) updateConnectionState(BleConst.STATE_ERROR) return } // 发现所有服务的特征 for service in services { os_log("发现服务: %{public}@", log: logger, type: .debug, service.uuid.uuidString) peripheral.discoverCharacteristics(nil, for: service) } } /// 处理发现的特征 func handleDiscoveredCharacteristics(for service: CBService, peripheral: CBPeripheral, error: Error?) async { if let error = error { os_log("发现特征失败: %{public}@", log: logger, type: .error, error.localizedDescription) return } guard let characteristics = service.characteristics else { os_log("服务没有任何特征: %{public}@", log: logger, type: .warning, service.uuid.uuidString) return } // 根据UUID识别和保存特征 for characteristic in characteristics { os_log("发现特征: %{public}@", log: logger, type: .debug, characteristic.uuid.uuidString) // 主服务特征 if service.uuid == BleConst.PRIMARY_SERVICE_UUID { if characteristic.uuid == BleConst.WRITE_CHAR_UUID { writeCharacteristic = characteristic os_log("找到写入特征", log: logger, type: .debug) } else if characteristic.uuid == BleConst.NOTIFY_CHAR_UUID { notifyCharacteristic = characteristic os_log("找到通知特征", log: logger, type: .debug) // 设置通知 await setupNotification(for: characteristic, peripheral: peripheral) } } // 音频服务特征 if service.uuid == BleConst.AUDIO_SERVICE_UUID { if characteristic.uuid == BleConst.RECEIVE_AUDIO_CHAR_UUID { audioCharacteristic = characteristic os_log("找到音频特征", log: logger, type: .debug) // 设置通知 await setupNotification(for: characteristic, peripheral: peripheral) } } } // 检查是否找到所有必要的特征 if writeCharacteristic == nil || notifyCharacteristic == nil { os_log("未找到所有必要的特征", log: logger, type: .error) updateConnectionState(BleConst.STATE_ERROR) } } /// 设置特征的通知 /// - Parameters: /// - characteristic: 特征 /// - peripheral: 外设 private func setupNotification(for characteristic: CBCharacteristic, peripheral: CBPeripheral) async { if characteristic.properties.contains(.notify) { peripheral.setNotifyValue(true, for: characteristic) } } /// 处理特征值更新 func handleValueUpdate(for characteristic: CBCharacteristic, peripheral: CBPeripheral, error: Error?) async { if let error = error { os_log("特征值更新失败: %{public}@", log: logger, type: .error, error.localizedDescription) return } guard let data = characteristic.value else { os_log("特征没有值", log: logger, type: .warning) return } let hexString = data.map { String(format: "%02X", $0) }.joined(separator: " ") os_log("收到特征数据: %{public}@ - %{public}@", log: logger, type: .debug, characteristic.uuid.uuidString, hexString) // 根据特征UUID处理不同类型的数据 if characteristic.uuid == BleConst.RECEIVE_AUDIO_CHAR_UUID { // 音频数据处理 await processAudioData(data) } else if characteristic.uuid == BleConst.NOTIFY_CHAR_UUID { // 通知特征处理 if !data.isEmpty { switch data[0] { case BleConst.DEVICE_RESPONSE_HEADER: // 设备响应 await processDeviceResponse(data) case BleConst.DEVICE_NOTIFY_HEADER: // 设备通知 await processDeviceNotification(data) default: os_log("未知数据类型: %d", log: logger, type: .debug, data[0]) } } } } // MARK: - 状态恢复处理 /// 处理蓝牙状态恢复 func handleStateRestoration(dict: [String: Any]) async { os_log("正在恢复蓝牙状态...", log: logger, type: .info) // 1. 恢复之前连接的外设 if let peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey] as? [CBPeripheral] { os_log("恢复 %d 个已连接的外设", log: logger, type: .debug, peripherals.count) for peripheral in peripherals { self.peripheral = peripheral peripheral.delegate = CBPeripheralHandler.shared CBPeripheralHandler.shared.bleService = self // 根据外设当前状态采取不同操作 if peripheral.state == .connected { os_log("外设 %{public}@ 已连接", log: logger, type: .debug, peripheral.identifier.uuidString) updateConnectionState(BleConst.STATE_CONNECTED) // 重新发现服务 peripheral.discoverServices([BleConst.PRIMARY_SERVICE_UUID, BleConst.AUDIO_SERVICE_UUID]) } else if peripheral.state == .connecting { os_log("外设 %{public}@ 正在连接中", log: logger, type: .debug, peripheral.identifier.uuidString) updateConnectionState(BleConst.STATE_CONNECTING) } else { os_log("外设 %{public}@ 状态异常: %d", log: logger, type: .debug, peripheral.identifier.uuidString, peripheral.state.rawValue) // 尝试重新连接 updateConnectionState(BleConst.STATE_CONNECTING) centralManager?.connect(peripheral, options: nil) } } } // 2. 恢复扫描状态 if let scanServices = dict[CBCentralManagerRestoredStateScanServicesKey] as? [CBUUID] { os_log("恢复扫描任务,服务UUID数: %d", log: logger, type: .debug, scanServices.count) let scanOptions = dict[CBCentralManagerRestoredStateScanOptionsKey] as? [String: Any] ?? [ CBCentralManagerScanOptionAllowDuplicatesKey: true ] // 重新启动扫描任务 centralManager?.scanForPeripherals( withServices: scanServices.isEmpty ? nil : scanServices, options: scanOptions ) isScanning = true // 设置新的扫描超时(默认15秒) scanTimeoutTask?.cancel() scanTimeoutTask = Task { [weak self] in guard let self = self else { return } do { try await Task.sleep(nanoseconds: UInt64(15.0 * 1_000_000_000)) if !Task.isCancelled { await self.stopScan() } } catch { // 任务被取消,忽略错误 } } } // 通知外部:BLE状态已恢复 await notifyStateRestored() } /// 通知状态恢复 private func notifyStateRestored() async { let currentDelegates = delegates for delegate in currentDelegates { if let stateDelegate = delegate as? BleStateRestorationDelegate { await MainActor.run { stateDelegate.onBleStateRestored() } } } } } // MARK: - 中央管理器委托处理器 class CBManagerHandler: NSObject, CBCentralManagerDelegate { static let shared = CBManagerHandler() weak var bleService: BleService? func centralManagerDidUpdateState(_ central: CBCentralManager) { Task { guard let service = bleService else { return } switch central.state { case .poweredOn: await MainActor.run { os_log("蓝牙已开启", log: OSLog(subsystem: "com.yunqiinnovation.ble_service", category: "BleService"), type: .info) } case .poweredOff: await MainActor.run { os_log("蓝牙已关闭", log: OSLog(subsystem: "com.yunqiinnovation.ble_service", category: "BleService"), type: .warning) } await service.updateConnectionState(BleConst.STATE_DISCONNECTED) case .unauthorized, .unsupported: await MainActor.run { os_log("蓝牙不可用: %d", log: OSLog(subsystem: "com.yunqiinnovation.ble_service", category: "BleService"), type: .error, central.state.rawValue) } await service.updateConnectionState(BleConst.STATE_ERROR) default: await MainActor.run { os_log("蓝牙状态变化: %d", log: OSLog(subsystem: "com.yunqiinnovation.ble_service", category: "BleService"), type: .debug, central.state.rawValue) } } } } func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { Task { await bleService?.handleDiscoveredPeripheral(peripheral, advertisementData: advertisementData, rssi: RSSI) } } func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { Task { await bleService?.handleConnectionResult(peripheral: peripheral, success: true, error: nil) } } func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) { Task { await bleService?.handleConnectionResult(peripheral: peripheral, success: false, error: error) } } func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) { Task { await bleService?.handleDisconnection(peripheral: peripheral, error: error) } } /// 状态恢复处理 func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any]) { os_log("蓝牙状态恢复被触发", log: OSLog(subsystem: "com.yunqiinnovation.ble_service", category: "BleService"), type: .info) // 打印恢复信息 if let peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey] as? [CBPeripheral] { os_log("恢复外设数量: %d", log: OSLog(subsystem: "com.yunqiinnovation.ble_service", category: "BleService"), type: .debug, peripherals.count) for (i, peripheral) in peripherals.enumerated() { os_log("恢复外设[%d]: %{public}@", log: OSLog(subsystem: "com.yunqiinnovation.ble_service", category: "BleService"), type: .debug, i, peripheral.identifier.uuidString) } } if let services = dict[CBCentralManagerRestoredStateScanServicesKey] as? [CBUUID] { os_log("恢复扫描服务数量: %d", log: OSLog(subsystem: "com.yunqiinnovation.ble_service", category: "BleService"), type: .debug, services.count) } // 异步处理状态恢复 Task { if let service = bleService { await service.handleStateRestoration(dict: dict) } } } } // MARK: - 外设委托处理器 class CBPeripheralHandler: NSObject, CBPeripheralDelegate { static let shared = CBPeripheralHandler() weak var bleService: BleService? func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { Task { await bleService?.handleDiscoveredServices(peripheral: peripheral, error: error) } } func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { Task { await bleService?.handleDiscoveredCharacteristics(for: service, peripheral: peripheral, error: error) } } func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { Task { await bleService?.handleValueUpdate(for: characteristic, peripheral: peripheral, error: error) } } func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) { if let error = error { os_log("写入特征值失败: %{public}@", log: OSLog(subsystem: "com.yunqiinnovation.ble_service", category: "BleService"), type: .error, error.localizedDescription) } else { os_log("写入特征值成功", log: OSLog(subsystem: "com.yunqiinnovation.ble_service", category: "BleService"), type: .debug) } } func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) { if let error = error { os_log("设置通知状态失败: %{public}@", log: OSLog(subsystem: "com.yunqiinnovation.ble_service", category: "BleService"), type: .error, error.localizedDescription) } else { os_log("设置通知状态成功: %{public}@", log: OSLog(subsystem: "com.yunqiinnovation.ble_service", category: "BleService"), type: .debug, characteristic.uuid.uuidString) } } } // MARK: - BLE状态恢复代理 /// 蓝牙状态恢复代理 protocol BleStateRestorationDelegate: AnyObject { /// 当蓝牙状态被系统恢复时调用 func onBleStateRestored() } // MARK: - BLE代理 /// 蓝牙事件代理 protocol BleDelegate: AnyObject { /// 扫描结果回调 func onScanResult(devices: [[String: Any]]) /// 连接状态变化回调 func onConnectionStateChanged(state: Int) /// 音频数据接收回调 func onAudioDataReceived(data: Data) /// 唤醒信号接收回调 func onWakeupSignalReceived() /// 设备信息接收回调 func onDeviceInfoReceived(infoType: Int, infoData: [String: Any]) }