import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:get_storage/get_storage.dart'; import 'package:get/get.dart'; import 'package:ble_service/ble_service.dart'; import 'package:agent_service/agent_service.dart'; import '../models/user_Info.dart' as userInfo; import '/data/models/appconfig_model.dart'; import '../../data/models/appconfig.dart'; import '../../core/translations/app_translations.dart'; import '../../core/utils/logger.dart'; import 'bluetooth_manager.dart'; import 'language_manager.dart'; import 'network/dio_manager.dart'; // 重新导出BLE连接状态常量,让外部可以通过BleManager访问 export 'package:ble_service/ble_service.dart' show BleConnectionState; /// 命令类型常量(与原生层保持一致) class BleCommands { static const int GET_VERSION = 0x01; static const int GET_PRODUCT_ID = 0x02; static const int GET_PRODUCT_COLOR = 0x03; static const int GET_BATTERY_INFO = 0x04; static const int CONTROL_CODEC = 0x05; static const int GET_WAKEUP_VERSION = 0x08; static const int GET_VOICE_WAKEUP_STATUS = 0x14; static const int SET_VOICE_WAKEUP_STATUS = 0x15; } /// 判断编解码控制指令是否成功 /// /// 根据 rawData 第二字节是否为非 0 来判断: /// - 成功:第二字节不为 0 /// - 失败或无法解析:返回 false bool _isCodecControlSuccess(Map data) { final dynamic raw = data['rawData']; if (raw == null) return false; int? secondByte; if (raw is List) { if (raw.length >= 2) { final s = raw[1]; if (s is int) { secondByte = s; } else if (s is num) { secondByte = s.toInt(); } else if (s is String) { final t = s.trim(); if (t.startsWith('0x') || t.startsWith('0X')) { secondByte = int.tryParse(t.substring(2), radix: 16); } else { secondByte = int.tryParse(t); } } } } else if (raw is String) { final normalized = raw.trim().replaceAll('[', '').replaceAll(']', ''); final parts = normalized.split(RegExp(r'[,\s]+')).where((e) => e.isNotEmpty).toList(); if (parts.length >= 2) { final t = parts[1].trim(); if (t.startsWith('0x') || t.startsWith('0X')) { secondByte = int.tryParse(t.substring(2), radix: 16); } else { secondByte = int.tryParse(t); } } } else if (raw is Map) { final dynamic s = raw['second'] ?? raw['status2'] ?? raw['result']; if (s is int) { secondByte = s; } else if (s is num) { secondByte = s.toInt(); } else if (s is String) { final t = s.trim(); if (t.startsWith('0x') || t.startsWith('0X')) { secondByte = int.tryParse(t.substring(2), radix: 16); } else { secondByte = int.tryParse(t); } } } else { // 无法解析的类型 return false; } return secondByte != null && secondByte != 0; } /// 蓝牙设备信息缓存模型 class DeviceInfo { final String address; final String name; // 整体电池电量 final int batteryLevel; // 详细电池信息 final int leftEarBattery; final int rightEarBattery; final int caseBattery; // 充电状态 final bool leftEarCharging; final bool rightEarCharging; final bool caseCharging; final String firmwareVersion; final String firmwareProductId; final String firmwareProductColor; final DateTime lastUpdated; //唤醒词版本 final String wakeupLeftVersion; final String wakeupRightVersion; DeviceInfo({ required this.address, required this.name, this.batteryLevel = 0, this.leftEarBattery = 0, this.rightEarBattery = 0, this.caseBattery = 0, this.leftEarCharging = false, this.rightEarCharging = false, this.caseCharging = false, this.firmwareVersion = '', this.firmwareProductId = '', this.firmwareProductColor = '', DateTime? lastUpdated, this.wakeupLeftVersion = '', this.wakeupRightVersion = '', }) : lastUpdated = lastUpdated ?? DateTime.now(); /// 创建更新后的设备信息副本 DeviceInfo copyWith({ String? address, String? name, int? batteryLevel, int? leftEarBattery, int? rightEarBattery, int? caseBattery, bool? leftEarCharging, bool? rightEarCharging, bool? caseCharging, String? firmwareVersion, String? firmwareProductId, String? firmwareProductColor, String? wakeupLeftVersion, String? wakeupRightVersion, }) { return DeviceInfo( address: address ?? this.address, name: name ?? this.name, batteryLevel: batteryLevel ?? this.batteryLevel, leftEarBattery: leftEarBattery ?? this.leftEarBattery, rightEarBattery: rightEarBattery ?? this.rightEarBattery, caseBattery: caseBattery ?? this.caseBattery, leftEarCharging: leftEarCharging ?? this.leftEarCharging, rightEarCharging: rightEarCharging ?? this.rightEarCharging, caseCharging: caseCharging ?? this.caseCharging, firmwareVersion: firmwareVersion ?? this.firmwareVersion, firmwareProductId: firmwareProductId ?? this.firmwareProductId, firmwareProductColor: firmwareProductColor ?? this.firmwareProductColor, lastUpdated: DateTime.now(), wakeupLeftVersion: wakeupLeftVersion ?? this.wakeupLeftVersion, wakeupRightVersion: wakeupRightVersion ?? this.wakeupRightVersion, ); } @override String toString() { return 'DeviceInfo(address: $address, name: $name, ' 'battery: $batteryLevel%, L: $leftEarBattery%, R: $rightEarBattery%, Case: $caseBattery%, ' 'charging: L:$leftEarCharging, R:$rightEarCharging, C:$caseCharging, ' 'version: $firmwareVersion, ' 'wakeupLeftVersion: $wakeupLeftVersion, ' 'wakeupRightVersion: $wakeupRightVersion)'; } } /// BLE管理器 - 专门处理BLE设备连接和信息管理 class BleManager extends GetxService { static BleManager get to => Get.find(); // BLE服务实例 final BleService _bleService = BleService(); // 经典蓝牙实例 // 当前连接的设备信息 String? currentDeviceAddress; String? _currentDeviceName; // BLE连接状态 final _connectionState = BleConnectionState.disconnected.obs; int get connectionState => _connectionState.value; // 公开的连接状态流,供外部监听 RxInt get connectionStateRx => _connectionState; // 连接状态监听 final _isCall = false.obs; final _isConnected = false.obs; bool get isConnected => _isConnected.value; bool get isCall => _isCall.value; // 设备信息缓存 final deviceInfo = Rx(null); // 使用 Rx 包装 //添加编码器状态跟踪 final _isCodecActive = false.obs; bool get isCodecActive => _isCodecActive.value; RxBool get isCodecActiveRx => _isCodecActive; bool _awaitingCodecOpen = false; //是否正在等待编码器打开的成功应答 bool _awaitingCodecClose = false; //是否正在等待编码器关闭的成功应答 // 语音唤醒状态 final _voiceWakeupEnabled = true.obs; // 唤醒开关状态,默认开启 bool get voiceWakeupEnabled => _voiceWakeupEnabled.value; RxBool get voiceWakeupEnabledRx => _voiceWakeupEnabled; final _voiceWakeupSupported = false.obs; // 耳机是否支持语音唤醒功能 bool get voiceWakeupSupported => _voiceWakeupSupported.value; RxBool get voiceWakeupSupportedRx => _voiceWakeupSupported; // 订阅 StreamSubscription? _statusSubscription; StreamSubscription? _dataSubscription; final GetStorage _storage = GetStorage(); final _wakeupVoiceUpgradeProgress = 0.obs; // 唤醒语音升级进度 RxInt get wakeupVoiceUpgradeProgress => _wakeupVoiceUpgradeProgress; final _wakeupVoiceUpgradeStatus = 0.obs; // 唤醒语音升级状态 0: 未升级 1: 升级中 2: 升级成功 3: 升级失败 RxInt get wakeupVoiceUpgradeStatus => _wakeupVoiceUpgradeStatus; /// 初始化 @override void onInit() { super.onInit(); Logger.info('BLE管理器初始化'); // 设置BLE事件监听 _setupBleListener(); } /// 释放资源 @override void onClose() { _statusSubscription?.cancel(); _dataSubscription?.cancel(); super.onClose(); } /// 设置BLE事件监听 void _setupBleListener() { //Logger.info('lxm--_setupBleListener被调用,开始设置BLE事件监听'); _statusSubscription?.cancel(); _dataSubscription?.cancel(); try { Logger.info('lxm--开始监听BLE状态更新流'); // 监听BLE状态更新 _statusSubscription = _bleService.onStatusUpdated.listen( (event) { Logger.info('lxm--收到BLE状态更新事件: $event'); if (event is Map) { Logger.info('lxm--事件是Map类型,开始处理'); // 处理连接状态更新 if (event['type'] == 'connectionStateChanged') { Logger.info('lxm--处理连接状态变化事件'); final state = event['state'] as int; final oldState = _connectionState.value; _connectionState.value = state; Logger.d('BleManager', '🔄 BLE状态更新: $oldState → $state'); Logger.d('BleManager', '📡 通知监听器状态变化: ${_connectionState.value}'); // 连接状态转换 if (state == BleConnectionState.connected) { Logger.info('lxm--BLE设备已连接'); _isConnected.value = true; // 设备信息(含唤醒状态)由 HomeController.fetchDeviceInfo() 统一查询 } else if (state == BleConnectionState.disconnected || state == BleConnectionState.error) { Logger.info('lxm--BLE设备已断开或发生错误'); _isConnected.value = false; _awaitingCodecOpen = false; _awaitingCodecClose = false; _isCodecActive.value = false; _voiceWakeupSupported.value = false; _voiceWakeupEnabled.value = true; Logger.info('[VoiceWakeup] 断开连接,重置 supported=false, enabled=true'); Logger.info('lxm--断开连接时重置设备信息为0'); _updateDeviceInfoIfNeeded( batteryLevel: 0, leftEarBattery: 0, rightEarBattery: 0, caseBattery: 0, leftEarCharging: false, rightEarCharging: false, caseCharging: false, firmwareVersion: '', firmwareProductId: '', firmwareProductColor: '', wakeupLeftVersion: '', wakeupRightVersion: '', ); // 断开连接时不清除设备信息,保留最后的电量信息 // 只有在需要完全清除设备时才重置信息 } } if (event['type'] == 'wakeupVoiceUpgradeProgress') { // 唤醒语音升级进度 Logger.info('lxm--处理唤醒语音升级进度事件: $event'); _wakeupVoiceUpgradeProgress.value = event['progress'] as int? ?? 0; _wakeupVoiceUpgradeStatus.value = 1; // 升级中 Logger.info( 'lxm--唤醒语音升级进度: ${_wakeupVoiceUpgradeProgress.value}%'); } if (event['type'] == 'wakeupVoiceUpgradeSuccess') { // 唤醒语音升级状态 Logger.info('lxm--处理唤醒语音升级状态事件: $event'); _wakeupVoiceUpgradeStatus.value = 2; // 升级成功 Logger.info('lxm--唤醒语音升级状态: ${_wakeupVoiceUpgradeStatus.value}'); } if (event['type'] == 'wakeupVoiceUpgradeFailure') { // 唤醒语音升级状态 Logger.info('lxm--处理唤醒语音升级状态事件: $event'); _wakeupVoiceUpgradeStatus.value = 3; // 升级失败 Logger.info('lxm--唤醒语音升级状态: ${_wakeupVoiceUpgradeStatus.value}'); } Logger.info('lxm--准备调用_processDeviceInfo处理设备信息'); // 处理设备信息 _processDeviceInfo(event); } else { Logger.info('lxm--事件不是Map类型: ${event.runtimeType}'); } }, onError: (error) { Logger.error('lxm--BLE状态事件流错误: $error'); }, ); Logger.info('lxm--BLE状态监听器设置完成'); // 监听BLE数据流 } catch (e) { Logger.error('lxm--设置BLE事件监听器失败: ${e.toString()}'); } } /// 处理来自原生层的设备信息 void _processDeviceInfo(Map event) { try { Logger.info('lxm--_processDeviceInfo被调用'); Logger.info('lxm--接收到的事件数据: $event'); // 检查是否是设备信息响应 if (event.containsKey('command') && event.containsKey('success')) { Logger.info('lxm--事件包含command和success字段'); final bool success = event['success'] as bool; Logger.info('lxm--命令执行成功状态: $success'); if (!success) { Logger.warning('lxm--设备命令执行失败: ${event['command']}'); return; } // 根据命令类型处理不同信息 final command = event['command']; Logger.info('lxm--命令类型: $command (${command.runtimeType})'); if (command is int) { Logger.info('lxm--基于命令ID处理: $command'); // 基于命令ID处理 _processDeviceInfoByCommandId(command, event); } else if (command is String) { Logger.info('lxm--基于命令名称处理: $command'); // 基于命令名称处理 _processDeviceInfoByCommandName(command, event); } else { Logger.warning('lxm--未知的命令类型: ${command.runtimeType}'); } } else { Logger.info('lxm--事件不包含command或success字段,跳过处理'); Logger.info('lxm--事件包含的键: ${event.keys.toList()}'); } } catch (e) { Logger.error('lxm--处理设备信息异常: ${e.toString()}'); Logger.error('lxm--异常堆栈: ${StackTrace.current}'); } } /// 根据命令ID处理设备信息 void _processDeviceInfoByCommandId( int commandId, Map data) { Logger.info('lxm--_processDeviceInfoByCommandId被调用,命令ID: $commandId'); Logger.info('lxm--命令数据: $data'); switch (commandId) { case BleCommands.GET_VERSION: Logger.info('lxm--处理版本信息命令'); _updateVersionInfoFromData(data); break; case BleCommands.GET_PRODUCT_ID: Logger.info('lxm--处理产品ID命令'); _updateProductIdFromData(data); break; case BleCommands.GET_PRODUCT_COLOR: Logger.info('lxm--处理产品颜色命令(暂未实现)'); break; case BleCommands.GET_BATTERY_INFO: Logger.info('lxm--处理电池信息命令,准备调用_updateBatteryInfoFromData'); _updateBatteryInfoFromData(data); Logger.info('lxm--电池信息处理完成'); break; case BleCommands.CONTROL_CODEC: Logger.info('lxm--处理编解码控制命令'); // 处理通话状态 print(" CONTROL_CODEC: $commandId,$data"); final bool codecSuccess = _isCodecControlSuccess(data); if (_awaitingCodecOpen) { //如果正在等待打开编解码器 _isCodecActive.value = codecSuccess; // 只在等待打开时更新状态 _awaitingCodecOpen = false; } else if (_awaitingCodecClose) { if (codecSuccess) { _isCodecActive.value = false; } _awaitingCodecClose = false; } if (codecSuccess) { print("lxm--编解码控制成功 (rawData 第二字节非 0)"); Logger.info('lxm--编解码控制成功 (rawData 第二字节非 0)'); } else { print("lxm--编解码控制失败 (rawData 为 [162, 0] 或无法解析)"); Logger.warning('lxm--编解码控制失败 (rawData 为 [162, 0] 或无法解析)'); } break; case BleCommands.GET_WAKEUP_VERSION: Logger.info('lxm--处理唤醒语音版本命令'); _updateWakeupVersionFromData(data); break; case BleCommands.GET_VOICE_WAKEUP_STATUS: Logger.info('[VoiceWakeup] 收到查询响应(0x14), data: $data'); _updateVoiceWakeupStatusFromData(data); break; case BleCommands.SET_VOICE_WAKEUP_STATUS: Logger.info('[VoiceWakeup] 收到设置响应(0x15), data: $data'); _updateVoiceWakeupSetResultFromData(data); break; default: Logger.warning('lxm--未处理的命令ID: $commandId,数据: $data'); print(" 未处理的命令ID: $commandId,$data"); } } /// 根据命令名称处理设备信息 void _processDeviceInfoByCommandName( String commandName, Map data) { switch (commandName) { case 'batteryInfo': _updateBatteryInfoFromData(data); break; case 'versionInfo': _updateVersionInfoFromData(data); break; case 'productId': _updateProductIdFromData(data); break; case 'productColor': break; case 'Error': print(" Error: $commandName,$data"); break; default: print(" 未处理的命令名称: $commandName,$data"); Logger.info('未处理的命令名称: $commandName'); } } /// 更新电池信息 void _updateBatteryInfoFromData(Map data) { try { Logger.info('lxm--_updateBatteryInfoFromData被调用'); Logger.info('lxm--接收到的原始数据: $data'); // 确保数据中包含电池信息 if (!data.containsKey('leftEarBattery') || !data.containsKey('rightEarBattery') || !data.containsKey('caseBattery')) { Logger.warning('lxm--电池信息数据不完整,缺少必要字段'); Logger.warning('lxm--数据包含的键: ${data.keys.toList()}'); return; } Logger.info('lxm--原始电池数据解析:'); Logger.info( 'lxm-- leftEarBattery原始值: ${data['leftEarBattery']} (类型: ${data['leftEarBattery'].runtimeType})'); Logger.info( 'lxm-- rightEarBattery原始值: ${data['rightEarBattery']} (类型: ${data['rightEarBattery'].runtimeType})'); Logger.info( 'lxm-- caseBattery原始值: ${data['caseBattery']} (类型: ${data['caseBattery'].runtimeType})'); Logger.info( 'lxm-- leftEarCharging原始值: ${data['leftEarCharging']} (类型: ${data['leftEarCharging'].runtimeType})'); Logger.info( 'lxm-- rightEarCharging原始值: ${data['rightEarCharging']} (类型: ${data['rightEarCharging'].runtimeType})'); Logger.info( 'lxm-- caseCharging原始值: ${data['caseCharging']} (类型: ${data['caseCharging'].runtimeType})'); Logger.info( 'lxm-- batteryLevel原始值: ${data['batteryLevel']} (类型: ${data['batteryLevel']?.runtimeType})'); // 提取电池信息 final int leftBattery = (data['leftEarBattery'] as int? ?? 0) == 127 ? -1 // 特殊值127转换为-1 : (data['leftEarBattery'] as int? ?? 0) > 100 ? 0 // 大于100的值重置为0 : (data['leftEarBattery'] as int? ?? 0); // 正常值 final int rightBattery = (data['rightEarBattery'] as int? ?? 0) == 127 ? -1 // 特殊值127转换为-1 : (data['rightEarBattery'] as int? ?? 0) > 100 ? 0 // 大于100的值重置为0 : (data['rightEarBattery'] as int? ?? 0); // 正常值 final int caseBattery = (data['caseBattery'] as int? ?? 0) == 127 ? -1 // 特殊值127转换为-1 : (data['caseBattery'] as int? ?? 0) > 100 ? 0 // 大于100的值重置为0 : (data['caseBattery'] as int? ?? 0); // 正常值 final bool leftCharging = data['leftEarCharging'] as bool? ?? false; final bool rightCharging = data['rightEarCharging'] as bool? ?? false; final bool caseCharging = data['caseCharging'] as bool? ?? false; // 获取整体电量(原生层使用左耳电量作为主要指示) final int overallBattery = data['batteryLevel'] as int? ?? leftBattery; Logger.info('lxm--处理后的电池数据:'); Logger.info('lxm-- leftBattery: $leftBattery'); Logger.info('lxm-- rightBattery: $rightBattery'); Logger.info('lxm-- caseBattery: $caseBattery'); Logger.info('lxm-- leftCharging: $leftCharging'); Logger.info('lxm-- rightCharging: $rightCharging'); Logger.info('lxm-- caseCharging: $caseCharging'); Logger.info('lxm-- overallBattery: $overallBattery'); Logger.info('lxm--准备调用_updateDeviceInfoIfNeeded'); // 更新设备信息 _updateDeviceInfoIfNeeded( batteryLevel: overallBattery, leftEarBattery: leftBattery, rightEarBattery: rightBattery, caseBattery: caseBattery, leftEarCharging: leftCharging, rightEarCharging: rightCharging, caseCharging: caseCharging, ); Logger.info( 'lxm--设备电池信息已更新: 电量=$overallBattery%, 左耳=$leftBattery%, 右耳=$rightBattery%, 充电仓=$caseBattery%'); } catch (e) { Logger.error('lxm--更新电池信息失败: ${e.toString()}'); Logger.error('lxm--错误堆栈: ${StackTrace.current}'); } } /// 更新版本信息 void _updateVersionInfoFromData(Map data) { try { // 确保数据中包含版本信息 if (!data.containsKey('version')) { Logger.warning('版本信息数据不完整'); return; } // 提取版本信息 final String version = data['version'] as String? ?? ''; // 更新设备信息 _updateDeviceInfoIfNeeded( firmwareVersion: version, ); Logger.info('设备版本信息已更新: 版本=$version'); } catch (e) { Logger.error('更新版本信息失败: ${e.toString()}'); } } /// 更新设备id void _updateProductIdFromData(Map data) { try { // 确保数据中包含版本信息 if (!data.containsKey('productId')) { Logger.warning('版本信息数据不完整'); return; } // 提取版本信息 final String productId = data['productId'] as String? ?? ''; // 更新设备信息 _updateDeviceInfoIfNeeded( firmwareProductId: productId, ); Logger.info('设备设备id已更新: 设备id=$productId'); } catch (e) { Logger.error('更新设备id失败: ${e.toString()}'); } } /// 更新唤醒语音版本信息 void _updateWakeupVersionFromData(Map data) { try { // 确保数据中包含版本信息 if (!data.containsKey('leftVersionDec') || !data.containsKey('rightVersionDec')) { Logger.warning('唤醒语音版本信息数据不完整'); return; } // 提取版本信息 final String wakeupLeftVersion = data['leftVersionDec'] as String? ?? ''; final String wakeupRightVersion = data['rightVersionDec'] as String? ?? ''; // 更新设备信息 _updateDeviceInfoIfNeeded( wakeupLeftVersion: wakeupLeftVersion, wakeupRightVersion: wakeupRightVersion, ); Logger.info('设备唤醒语音版本信息已更新: 左=$wakeupLeftVersion, 右=$wakeupRightVersion'); } catch (e) { Logger.error('更新唤醒语音版本信息失败: ${e.toString()}'); } } /// 更新语音唤醒状态(0x14 查询响应) void _updateVoiceWakeupStatusFromData(Map data) { try { if (!data.containsKey('voiceWakeupEnabled')) { Logger.warning('[VoiceWakeup] 查询响应数据不完整,缺少 voiceWakeupEnabled'); return; } final bool enabled = data['voiceWakeupEnabled'] as bool? ?? true; _voiceWakeupEnabled.value = enabled; _voiceWakeupSupported.value = true; Logger.info('[VoiceWakeup] 查询成功 → supported=true, enabled=${enabled ? "开启" : "关闭"}'); } catch (e) { Logger.error('[VoiceWakeup] 解析查询响应异常: ${e.toString()}'); } } /// 处理设置语音唤醒的响应(0x15 设置响应) void _updateVoiceWakeupSetResultFromData(Map data) { try { final bool setSuccess = data['voiceWakeupSetSuccess'] as bool? ?? false; if (setSuccess) { Logger.info('[VoiceWakeup] 设置成功 → enabled=${_voiceWakeupEnabled.value ? "开启" : "关闭"}'); } else { Logger.warning('[VoiceWakeup] 设置失败 → supported=false,开关置灰'); _voiceWakeupSupported.value = false; } } catch (e) { Logger.error('[VoiceWakeup] 解析设置响应异常: ${e.toString()}'); } } /// 查询语音唤醒状态 Future queryVoiceWakeupStatus() async { Logger.info('[VoiceWakeup] 发送查询命令(0x14)...'); final result = await _bleService.getVoiceWakeupStatus(); if (!result) { _voiceWakeupSupported.value = false; Logger.warning('[VoiceWakeup] 查询命令发送失败 → supported=false,设备可能不支持'); } else { Logger.info('[VoiceWakeup] 查询命令发送成功,等待设备响应...'); } return result; } /// 设置语音唤醒状态 Future setVoiceWakeupStatus(bool enabled) async { Logger.info('[VoiceWakeup] 发送设置命令(0x15), enabled=${enabled ? "开启" : "关闭"}...'); _voiceWakeupEnabled.value = enabled; // 乐观更新 final result = await _bleService.setVoiceWakeupStatus(enabled); if (!result) { _voiceWakeupSupported.value = false; Logger.warning('[VoiceWakeup] 设置命令发送失败 → supported=false,开关置灰'); } else { Logger.info('[VoiceWakeup] 设置命令发送成功,等待设备响应...'); } return result; } /// 更新设备信息(如果已存在设备) void _updateDeviceInfoIfNeeded({ int? batteryLevel, int? leftEarBattery, int? rightEarBattery, int? caseBattery, bool? leftEarCharging, bool? rightEarCharging, bool? caseCharging, String? firmwareVersion, String? firmwareProductId, String? firmwareProductColor, String? wakeupLeftVersion, String? wakeupRightVersion, }) { Logger.info('lxm--_updateDeviceInfoIfNeeded被调用'); Logger.info( 'lxm--传入参数: batteryLevel=$batteryLevel, leftEarBattery=$leftEarBattery, rightEarBattery=$rightEarBattery, caseBattery=$caseBattery'); Logger.info( 'lxm--充电状态: leftEarCharging=$leftEarCharging, rightEarCharging=$rightEarCharging, caseCharging=$caseCharging'); Logger.info('lxm--当前deviceInfo.value是否为null: ${deviceInfo.value == null}'); // 如果设备信息已存在,则更新 if (deviceInfo.value != null) { Logger.info('lxm--设备信息已存在,进行更新操作'); Logger.info('lxm--更新前的设备信息: ${deviceInfo.value}'); deviceInfo.value = deviceInfo.value!.copyWith( batteryLevel: batteryLevel ?? deviceInfo.value?.batteryLevel, leftEarBattery: _getValidBatteryValue( leftEarBattery, deviceInfo.value?.leftEarBattery), rightEarBattery: _getValidBatteryValue( rightEarBattery, deviceInfo.value?.rightEarBattery), caseBattery: caseBattery ?? deviceInfo.value?.caseBattery, leftEarCharging: leftEarCharging ?? deviceInfo.value!.leftEarCharging, rightEarCharging: rightEarCharging ?? deviceInfo.value!.rightEarCharging, caseCharging: caseCharging ?? deviceInfo.value!.caseCharging, firmwareVersion: firmwareVersion ?? deviceInfo.value!.firmwareVersion, firmwareProductId: firmwareProductId ?? deviceInfo.value!.firmwareProductId, firmwareProductColor: firmwareProductColor ?? deviceInfo.value!.firmwareProductColor, wakeupLeftVersion: wakeupLeftVersion ?? deviceInfo.value!.wakeupLeftVersion, wakeupRightVersion: wakeupRightVersion ?? deviceInfo.value!.wakeupRightVersion, ); Logger.info('lxm--更新后的设备信息: ${deviceInfo.value}'); } // 创建设备信息 // 如果设备信息不存在,但有地址和名称,则创建新的设备信息 else if (deviceInfo.value == null && _isConnected.value && (firmwareVersion != null || batteryLevel != null)) { Logger.info('lxm--设备信息不存在,创建新的设备信息对象'); // 使用保存的设备信息创建新的DeviceInfo对象 String deviceAddress = currentDeviceAddress ?? ""; String deviceName = _currentDeviceName ?? ""; Logger.info('lxm--创建新的设备信息对象: address=$deviceAddress, name=$deviceName'); deviceInfo.value = DeviceInfo( address: deviceAddress, name: deviceName, batteryLevel: batteryLevel ?? 0, leftEarBattery: leftEarBattery ?? 0, rightEarBattery: rightEarBattery ?? 0, caseBattery: caseBattery ?? 0, leftEarCharging: leftEarCharging ?? false, rightEarCharging: rightEarCharging ?? false, caseCharging: caseCharging ?? false, firmwareVersion: firmwareVersion ?? '', firmwareProductId: firmwareProductId ?? '', firmwareProductColor: firmwareProductColor ?? '', wakeupLeftVersion: wakeupLeftVersion ?? '', wakeupRightVersion: wakeupRightVersion ?? '', ); Logger.info('lxm--新创建的设备信息: ${deviceInfo.value}'); } else { Logger.info( 'lxm--不满足更新条件: deviceInfo.value == null: ${deviceInfo.value == null}, _isConnected.value: ${_isConnected.value}, firmwareVersion: $firmwareVersion, batteryLevel: $batteryLevel'); } } // 新增智能电池值选择方法 int? _getValidBatteryValue(int? newValue, int? currentValue) { // 如果新值为null,使用当前值 if (newValue == null) return currentValue; // 如果当前值为null或0,使用新值(即使新值为0) if (currentValue == null || currentValue == 0) return newValue; // 如果新值为0但当前值不为0,保持当前值(避免有效数据被0覆盖) if (newValue == 0 && currentValue > 0) { Logger.warning('检测到电池数据异常(新值为0),保持当前值: $currentValue'); return currentValue; } // 其他情况使用新值 return newValue; } /// 清除设备信息(用于完全断开连接或切换设备时) void clearDeviceInfo() { Logger.info('清除设备信息'); deviceInfo.value = null; currentDeviceAddress = null; _currentDeviceName = null; } /// 连接成功后获取设备信息 Future fetchDeviceInfo() async { Logger.info('开始获取BLE设备详细信息'); try { // 确保设备信息对象存在 if (deviceInfo.value == null && _isConnected.value) { // 创建初始设备信息对象 String deviceAddress = currentDeviceAddress ?? ""; String deviceName = _currentDeviceName ?? ""; Logger.info('初始化设备信息对象: address=$deviceAddress, name=$deviceName'); deviceInfo.value = DeviceInfo( address: deviceAddress, name: deviceName, batteryLevel: 0, leftEarBattery: 0, rightEarBattery: 0, caseBattery: 0, leftEarCharging: false, rightEarCharging: false, caseCharging: false, firmwareVersion: '', firmwareProductId: '', firmwareProductColor: '', wakeupLeftVersion: '', wakeupRightVersion: '', ); } // 并行获取所有设备信息,不使用延迟 final results = await Future.wait([ _bleService.getBatteryInfo(), _bleService.getDeviceVersion(), _bleService.getProductId(), _bleService.getVoiceWakeupStatus(), ]); Logger.info( '设备信息获取结果: 电池=${results[0]}, 版本=${results[1]}, 产品ID=${results[2]}, 唤醒状态=${results[3]}'); if (!results[0]) { Logger.warning('电池信息获取指令发送失败'); } if (!results[1]) { Logger.warning('版本信息获取指令发送失败'); } if (!results[2]) { Logger.warning('产品ID获取指令发送失败'); } if (!results[3]) { Logger.warning('语音唤醒状态获取指令发送失败'); _voiceWakeupSupported.value = false; } } catch (e) { Logger.error('获取BLE设备信息失败: ${e.toString()}'); } } /// 检查BLE连接状态 Future getConnectionState() async { try { final isConnected = await _bleService.isConnected(); _connectionState.value = isConnected ? BleConnectionState.connected : BleConnectionState.disconnected; _isConnected.value = isConnected; return _connectionState.value; } catch (e) { Logger.error('获取BLE连接状态失败: ${e.toString()}'); return BleConnectionState.error; } } String getDeviceName() { if (deviceInfo.value != null) { return deviceInfo.value!.name; } return ""; } // 加载TTS偏好设置 Future _loadTtsInterrupe() async { try { if (!_storage.hasData("agent_tts_interrupt")) { // 获取设备类型以确定检查策略 String deviceName = getDeviceName(); DBProduct? product = AppConfig.getproduct(deviceName); if (deviceName != "" && product != null) { // Logger.d('AgentController', // 'liwe----------product $deviceName ${product.toJson()}'); return !product.iscontinuouschat!; } else { return false; } } else { return _storage.read('agent_tts_interrupt') ?? false; } } catch (e) { return false; } } /// 启动BLE服务 Future startAgentService() async { try { // 从.env文件直接读取环境变量 var serverurl = DioManager().baseUrl; var jsonString = _storage.read("logintoken"); final azureSpeechKey = AppConfig.env('AZURE_SPEECH_KEY') ?? ''; final azureSpeechRegion = AppConfig.env('AZURE_SPEECH_REGION') ?? 'eastasia'; final openaiApiKey = AppConfig.env('OPENAI_API_KEY') ?? ''; final openaiBaseUrl = AppConfig.env('OPENAI_BASE_URL') ?? 'https://api.openai.com/v1'; final openaiModel = AppConfig.env('OPENAI_MODEL') ?? 'gpt-3.5-turbo'; final openaiModelMedia = AppConfig.env('OPENAI_API_VISION_MODEL') ?? 'doubao-1-5-vision-pro-32k-250115'; final openaiagentid = AppConfig.env('OPENAI_AGENT_ID') ?? 'personal_assistant'; final systemPrompt = AppConfig.agentsystemPrompt(openaiagentid); var musicServiceType = AppConfig.env('APP_ANDROID_MUSICSERVICE_TYPE') ?? 'AUTO'; if (Platform.isIOS) { musicServiceType = AppConfig.env('APP_IOS_MUSICSERVICE_TYPE') ?? 'AUTO'; } final navigationMode = AppConfig.env('APP_NAVIGATION_MODE') ?? 'external_auto'; final xunfeiAppId = AppConfig.env('XUNFEI_ASR_APP_ID') ?? ''; final xunfeiAccessKeyId = AppConfig.env('XUNFEI_ASR_ACCESS_KEY_ID') ?? ''; final xunfeiAccessKeySecret = AppConfig.env('XUNFEI_ASR_ACCESS_KEY_SECRET') ?? ''; // 从Flutter资源包中加载.mcp.json final jsonData = AppConfig.mcpConfig(); Logger.info('启动BLE服务,musicServiceType: $musicServiceType'); final isTtsInterruptEnabled = await _loadTtsInterrupe(); final vipExpiryTime = userInfo.User.instance.vipexptime; Logger.info('liwei------ vipexptime 1: $vipExpiryTime'); // 根据APP语言动态配置语音识别语言 List supportedLanguages = []; try { final storage = GetStorage(); final languageManager = Get.find(); // 从存储中读取用户设置的语言 String? savedLanguage = storage.read('language'); if (savedLanguage != null && savedLanguage != 'system') { // 用户设置了特定语言 final parts = savedLanguage.split('_'); if (parts.length == 2) { final lang = parts[0].toLowerCase(); final country = parts[1].toUpperCase(); if (lang == 'zh' && (country == 'HK' || country == 'TW' || country == 'CN')) { supportedLanguages.add('zh-$country'); } else if (lang == 'tl' && country == 'PH') { // 菲律宾语特殊处理,映射为azure语言码 supportedLanguages.add('fil-PH'); } else { supportedLanguages.add('$lang-$country'); } } } else { // 跟随系统语言或未设置 final appLocale = Get.locale ?? AppTranslations.deviceLocale(); if (appLocale != null) { final lang = appLocale.languageCode.toLowerCase(); final country = appLocale.countryCode; if (lang.toLowerCase() == 'zh' && country != null && country.isNotEmpty && (country.toUpperCase() == 'HK' || country.toUpperCase() == 'TW' || country.toUpperCase() == 'CN')) { supportedLanguages.add('zh-${country.toUpperCase()}'); } else { if (country != null && country.isNotEmpty) { final normalizedCountry = country.toUpperCase(); if (lang == 'tl' && normalizedCountry == 'PH') { supportedLanguages.add('fil-PH'); } else { supportedLanguages.add('$lang-$normalizedCountry'); } } else { final asrCode = languageManager.getAsrCodeByShortCode(lang); if (asrCode != null) { supportedLanguages.add(asrCode); } else { supportedLanguages.add('en-US'); } } } } } // 最终兜底 if (supportedLanguages.isEmpty) { supportedLanguages.add('en-US'); } // Logger.info('动态配置语音识别语言: ${supportedLanguages.join(', ')}'); } catch (e) { Logger.error('获取APP语言配置失败,使用默认语言: $e'); supportedLanguages = ['zh-CN', 'en-US']; } final config = { // 语音代理配置参数 'azureSpeechKey': azureSpeechKey, 'azureSpeechRegion': azureSpeechRegion, 'xunfeiAppId': xunfeiAppId, 'xunfeiAccessKeyId': xunfeiAccessKeyId, 'xunfeiAccessKeySecret': xunfeiAccessKeySecret, 'openaiApiKey': openaiApiKey, 'openaiBaseUrl': openaiBaseUrl, 'openaiModel': openaiModel, 'openaivisionModel': openaiModelMedia, 'systemPrompt': systemPrompt, 'mcpServer': jsonEncode(jsonData), 'volcanoAppId': '2316081933', 'volcanoToken': 'mcJTh6OelBqU_L78lgGd77Nyrc_-5-En', 'serverurl': serverurl, 'usertoken': jsonString, 'supportedLanguages': supportedLanguages, 'musicServiceType': musicServiceType, "navigationMode": navigationMode, "isttsinterrupt": isTtsInterruptEnabled ? "true" : "false", "vipexptime": vipExpiryTime, //会员过期时间 "callingToolText": "callingTool".tr, "insufficientIntegralText": "insufficientIntegral".tr, }; Logger.info('启动BLE服务,配置参数键名: ${config.keys.toList()}'); if (xunfeiAppId.isEmpty || xunfeiAccessKeyId.isEmpty || xunfeiAccessKeySecret.isEmpty) { Logger.warning('XUNFEI_ASR_* 未完整配置,ASR 将不会切到讯飞'); } if (azureSpeechKey.isEmpty || openaiApiKey.isEmpty) { Logger.warning('缺少必要的API密钥,请检查.env文件配置'); // 检查.env中相关密钥是否存在 if (azureSpeechKey.isEmpty) { Logger.warning('AZURE_SPEECH_KEY未配置在.env文件中'); } if (openaiApiKey.isEmpty) { Logger.warning('OPENAI_API_KEY未配置在.env文件中'); } } Logger.info('lxm--准备调用AgentService.startAgentService启动BLE服务'); final result = await AgentService.startAgentService(config); Logger.info('lxm--AgentService.startAgentService调用结果: $result'); if (result) { Logger.info('lxm--BLE服务启动成功'); // 添加延迟以等待设备连接 Logger.info('lxm--等待2秒让设备连接'); //await Future.delayed(const Duration(seconds: 2)); // 检查连接状态 Logger.info('lxm--检查设备连接状态'); final isConnected = await _bleService.isConnected(); Logger.info('lxm--设备连接状态检查结果: $isConnected'); if (isConnected) { Logger.info('lxm--设备已连接,更新连接状态'); _isConnected.value = true; _connectionState.value = BleConnectionState.connected; // 如果设备信息存在,则获取详细信息 Logger.info('lxm--准备获取设备详细信息'); if (deviceInfo.value != null) { // 获取详细设备信息 // fetchDeviceInfo(); } } } else { Logger.error('BLE服务启动失败'); } return result; } catch (e) { Logger.error('启动BLE服务失败: ${e.toString()}'); return false; } } /// 停止BLE服务 Future stopAgentService() async { try { final result = await AgentService.stopAgentService(); if (result) { Logger.info('BLE服务停止成功'); _isConnected.value = false; _connectionState.value = BleConnectionState.disconnected; // 停止服务时清除设备信息 clearDeviceInfo(); } else { Logger.error('BLE服务停止失败'); } return result; } catch (e) { Logger.error('停止BLE服务失败: ${e.toString()}'); return false; } } /// 获取电池电量 Future getBatteryLevel() async { try { return await _bleService.getBatteryLevel(); } catch (e) { Logger.error('获取电池电量失败: ${e.toString()}'); return 0; } } /// 主动获取电池信息 Future fetchBatteryInfo() async { try { //Logger.info('lxm--fetchBatteryInfo被调用,准备向设备发送获取电池信息指令'); final result = await _bleService.getBatteryInfo(); //Logger.info('lxm--getBatteryInfo指令发送结果: $result'); return result; } catch (e) { //Logger.error('lxm--获取电池信息失败: ${e.toString()}'); return false; } } /// 主动产品id Future getProductId() async { try { return await _bleService.getProductId(); } catch (e) { Logger.error('获取设备版本失败: ${e.toString()}'); return false; } } /// 主动获取设备版本信息 Future fetchDeviceVersion() async { try { return await _bleService.getDeviceVersion(); } catch (e) { Logger.error('获取设备版本失败: ${e.toString()}'); return false; } } /// 打开编码器 Future openEncoder() async { try { return await _bleService.openEncoder(); } catch (e) { Logger.error('打开编码器失败: ${e.toString()}'); return false; } } /// 打开解码器 Future openDecoder() async { try { _awaitingCodecOpen = true; _awaitingCodecClose = false; _isCodecActive.value = false; return await _bleService.openDecoder(); } catch (e) { Logger.error('打开解码器失败: ${e.toString()}'); _awaitingCodecOpen = false; return false; } } /// 打开A2DP解码器 Future openA2DPDecoder() async { try { _awaitingCodecOpen = true; _awaitingCodecClose = false; _isCodecActive.value = false; return await _bleService.openA2DPDecoder(); } catch (e) { Logger.error('打开解码器失败: ${e.toString()}'); _awaitingCodecOpen = false; return false; } } /// 打开解码器 Future openCallRecordDecoder() async { try { return await _bleService.openCallRecordDecoder(); } catch (e) { Logger.error('打开解码器失败: ${e.toString()}'); return false; } } /// 关闭编解码器 Future closeCodec() async { try { _awaitingCodecOpen = false; _awaitingCodecClose = true; _isCodecActive.value = false; return await _bleService.closeCodec(); } catch (e) { Logger.error('关闭编解码器失败: ${e.toString()}'); _awaitingCodecClose = false; return false; } } /// 播放A2DP Future playA2DP() async { try { return await _bleService.playA2DP(); } catch (e) { Logger.error('播放A2DP失败: ${e.toString()}'); return false; } } // ==================== 配对相关方法 ==================== /// 检查设备是否支持Companion Device Manager Future isCompanionSupported() async { try { return await _bleService.isCompanionSupported(); } catch (e) { Logger.error('检查Companion支持失败: ${e.toString()}'); return false; } } /// 获取已配对的MAC地址 Future getPairedMacAddress() async { try { return await _bleService.getPairedMacAddress(); } catch (e) { Logger.error('获取已配对MAC地址失败: ${e.toString()}'); return null; } } /// 检查BLE连接状态 Future isBleConnected() async { try { return await _bleService.isBleConnected(); } catch (e) { Logger.error('检查BLE连接状态失败: ${e.toString()}'); return false; } } /// 设置是否是ota模式 Future setEnterOta(bool enterOta) async { try { await _bleService.setEnterOta(enterOta); } catch (e) { Logger.error('设置是否是ota模式失败: ${e.toString()}'); } } /// 断开连接 Future disconnect() async { try { await _bleService.disconnect(); } catch (e) { Logger.error('断开连接失败: ${e.toString()}'); } } /// 验证设备是否可以配对 Future startScan(List uuids) async { try { await _bleService.startScan(uuids); } catch (e) { Logger.error('开始扫描设备: ${e.toString()}'); } } /// 验证设备是否可以配对 Future stopScan() async { try { await _bleService.stopScan(); } catch (e) { Logger.error('停止扫描设备: ${e.toString()}'); } } Future?> getDeviceInfo(String deviceName) async { try { final result = _bleService.getDeviceInfo(deviceName); return result; } catch (e) { Logger.error('获取设备信息: ${e.toString()}'); return null; } } Future>?> getDeviceList(String deviceName) async { try { final result = _bleService.getDeviceList(deviceName); return result; } catch (e) { Logger.error('获取设备信息: ${e.toString()}'); return null; } } /// 验证设备是否可以配对 Future verifyDeviceCanPair(String macAddress) async { try { return true; } catch (e) { Logger.error('验证设备配对失败: ${e.toString()}'); return false; } } /// 启动设备关联 Future startDeviceAssociation({ required String deviceNamePattern, required String macAddress, }) async { try { return await _bleService.startDeviceAssociation( deviceNamePattern: deviceNamePattern, macAddress: macAddress, ); } catch (e) { Logger.error('启动设备关联失败: ${e.toString()}'); return false; } } /// 启动设备关联 Future connect() async { try { await _bleService.connect(); } catch (e) { Logger.error('连接设备失败: ${e.toString()}'); } } /// 注册后台扫描 Future registerBackgroundScan({ String? macAddress, List? uuids, }) async { try { // 在注册新设备前先清除旧设备信息 if (macAddress != null && macAddress != currentDeviceAddress) { clearDeviceInfo(); // 清除上一个设备的信息 } // 保存设备地址信息 if (macAddress != null) { currentDeviceAddress = macAddress; // 从蓝牙管理器获取设备名称 final bluetoothManager = Get.find(); _currentDeviceName = bluetoothManager.currentDevice?.name ?? ""; Logger.info( '保存设备信息: address=$currentDeviceAddress, name=$_currentDeviceName'); } return await _bleService.registerBackgroundScan( macAddress: macAddress, uuids: uuids, ); } catch (e) { Logger.error('注册后台扫描失败: ${e.toString()}'); return false; } } /// 注销后台扫描 Future unregisterBackgroundScan() async { try { return await _bleService.unregisterBackgroundScan(); } catch (e) { Logger.error('注销后台扫描失败: ${e.toString()}'); return false; } } /// 清除BLE配对设备 Future clearPairedDevices() async { try { return await _bleService.clearAssociations(); } catch (e) { Logger.error('清除BLE配对设备失败: ${e.toString()}'); return false; } } /// 注册服务 static Future init() async { if (!Get.isRegistered()) { Get.put(BleManager(), permanent: true); } return Future.value(Get.find()); } /// 请求蓝牙权限 Future requestBluetoothPermission() async { try { return await _bleService.requestBluetoothPermission(); } catch (e) { Logger.error('请求蓝牙权限失败: ${e.toString()}'); return false; } } /// 开始唤醒词升级 Future startWakeupVoicesUpgrade(List wakeupVoiceBytes) async { try { return await _bleService.startWakeupVoicesUpgrade(wakeupVoiceBytes); } catch (e) { Logger.error('开始唤醒词升级失败: ${e.toString()}'); return false; } } }