import 'dart:async'; import 'package:deep_voice/data/models/appconfig.dart'; import 'package:get/get.dart'; import 'package:ble_service/ble_service.dart'; import 'package:deep_voice/core/utils/logger.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:get_storage/get_storage.dart'; import 'package:deep_voice/data/models/appconfig_model.dart'; import 'dart:convert'; import 'package:flutter/services.dart' show rootBundle; import 'package:agent_service/agent_service.dart'; import 'package:classic_bluetooth/classic_bluetooth.dart'; /// 命令类型常量(与原生层保持一致) 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; } /// 蓝牙设备信息缓存模型 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; 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, }) : 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, }) { 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(), ); } @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)'; } } /// BLE管理器 - 专门处理BLE设备连接和信息管理 class BleManager extends GetxService { static BleManager get to => Get.find(); // BLE服务实例 final BleService _bleService = BleService(); // 经典蓝牙实例 // BLE连接状态 final _connectionState = BleConnectionState.disconnected.obs; int get connectionState => _connectionState.value; // 连接状态监听 final _isConnected = false.obs; bool get isConnected => _isConnected.value; // 设备信息缓存 final deviceInfo = Rx(null); // 使用 Rx 包装 // 订阅 StreamSubscription? _statusSubscription; StreamSubscription? _dataSubscription; final GetStorage _storage = GetStorage(); /// 初始化 @override void onInit() { super.onInit(); Logger.info('BLE管理器初始化'); // 设置BLE事件监听 _setupBleListener(); } /// 释放资源 @override void onClose() { _statusSubscription?.cancel(); _dataSubscription?.cancel(); super.onClose(); } /// 设置BLE事件监听 void _setupBleListener() { _statusSubscription?.cancel(); _dataSubscription?.cancel(); try { // 监听BLE状态更新 _statusSubscription = _bleService.onStatusUpdated.listen( (event) { Logger.info('接收到BLE状态更新: $event'); if (event is Map) { // 处理连接状态更新 if (event['type'] == 'connectionStateChanged') { final state = event['state'] as int; _connectionState.value = state; // 连接状态转换 if (state == BleConnectionState.connected) { Logger.info('BLE设备已连接'); _isConnected.value = true; // 在连接成功后延迟 300 毫秒获取设备信息(可根据需要调整时间) Future.delayed(const Duration(milliseconds: 300), () { // 可选:检查是否仍处于连接状态 if (_isConnected.value) { // fetchDeviceInfo(); } }); } else if (state == BleConnectionState.disconnected || state == BleConnectionState.error) { Logger.info('BLE设备已断开或发生错误'); _isConnected.value = false; } } // 处理设备信息 _processDeviceInfo(event); } }, onError: (error) { Logger.error('BLE状态事件流错误: $error'); }, ); // 监听BLE数据流 _dataSubscription = _bleService.onDataReceived.listen( (data) { Logger.info('接收到BLE数据: $data'); // 在这里处理来自设备的数据 }, onError: (error) { Logger.error('BLE数据流错误: $error'); }, ); } catch (e) { Logger.error('设置BLE事件监听器失败: ${e.toString()}'); } } /// 处理来自原生层的设备信息 void _processDeviceInfo(Map event) { try { // 检查是否是设备信息响应 if (event.containsKey('command') && event.containsKey('success')) { final bool success = event['success'] as bool; if (!success) { Logger.warning('设备命令执行失败: ${event['command']}'); return; } // 根据命令类型处理不同信息 final command = event['command']; if (command is int) { // 基于命令ID处理 _processDeviceInfoByCommandId(command, event); } else if (command is String) { // 基于命令名称处理 _processDeviceInfoByCommandName(command, event); } } } catch (e) { Logger.error('处理设备信息异常: ${e.toString()}'); } } /// 根据命令ID处理设备信息 void _processDeviceInfoByCommandId( int commandId, Map data) { switch (commandId) { case BleCommands.GET_VERSION: _updateVersionInfoFromData(data); break; case BleCommands.GET_PRODUCT_ID: _updateProductIdFromData(data); break; case BleCommands.GET_PRODUCT_COLOR: break; case BleCommands.GET_BATTERY_INFO: _updateBatteryInfoFromData(data); break; default: Logger.info('未处理的命令ID: $commandId'); } } /// 根据命令名称处理设备信息 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; default: Logger.info('未处理的命令名称: $commandName'); } } /// 更新电池信息 void _updateBatteryInfoFromData(Map data) { try { // 确保数据中包含电池信息 if (!data.containsKey('leftEarBattery') || !data.containsKey('rightEarBattery') || !data.containsKey('caseBattery')) { Logger.warning('电池信息数据不完整'); return; } // 提取电池信息 final int leftBattery = data['leftEarBattery'] as int? ?? 0; final int rightBattery = data['rightEarBattery'] as int? ?? 0; final int caseBattery = 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; // 更新设备信息 _updateDeviceInfoIfNeeded( batteryLevel: overallBattery, leftEarBattery: leftBattery, rightEarBattery: rightBattery, caseBattery: caseBattery, leftEarCharging: leftCharging, rightEarCharging: rightCharging, caseCharging: caseCharging, ); Logger.info( '设备电池信息已更新: 电量=$overallBattery%, 左耳=$leftBattery%, 右耳=$rightBattery%, 充电仓=$caseBattery%'); } catch (e) { Logger.error('更新电池信息失败: ${e.toString()}'); } } /// 更新版本信息 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 _updateDeviceInfoIfNeeded({ int? batteryLevel, int? leftEarBattery, int? rightEarBattery, int? caseBattery, bool? leftEarCharging, bool? rightEarCharging, bool? caseCharging, String? firmwareVersion, String? firmwareProductId, String? firmwareProductColor, }) { // 如果设备信息已存在,则更新 if (deviceInfo.value != null) { deviceInfo.value = deviceInfo.value!.copyWith( batteryLevel: batteryLevel ?? deviceInfo.value?.batteryLevel, leftEarBattery: leftEarBattery ?? deviceInfo.value?.leftEarBattery, rightEarBattery: 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, ); } // 创建设备信息 // 如果设备信息不存在,但有地址和名称,则创建新的设备信息 else if (deviceInfo.value == null && _isConnected.value && (firmwareVersion != null || batteryLevel != null)) { // 提示尝试创建设备信息但缺少必要信息 Logger.warning('尝试更新设备信息,但设备基本信息不存在'); deviceInfo.value = DeviceInfo( address: "", // 应确保从连接信息中获取真实值 name: "", 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 ?? '', ); } } /// 连接成功后获取设备信息 Future fetchDeviceInfo() async { Logger.info('开始获取BLE设备详细信息'); try { // 获取电池信息 final batteryResult = await _bleService.getBatteryInfo(); if (batteryResult) { Logger.info('电池信息获取指令已发送'); } else { Logger.warning('电池信息获取指令发送失败'); } // 获取设备版本信息 final versionResult = await _bleService.getDeviceVersion(); if (versionResult) { Logger.info('版本信息获取指令已发送'); } else { Logger.warning('版本信息获取指令发送失败'); } // 获取产品id final productIdResult = await _bleService.getProductId(); if (productIdResult) { Logger.info('产品id获取指令已发送'); } else { Logger.warning('产品id获取指令发送失败'); } } 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; } } /// 启动BLE服务 Future startAgentService() async { try { // 从.env文件直接读取环境变量 // final azureSpeechKey = dotenv.env['AZURE_SPEECH_KEY'] ?? ''; // final azureSpeechRegion = dotenv.env['AZURE_SPEECH_REGION'] ?? 'eastasia'; // final openaiApiKey = dotenv.env['OPENAI_API_KEY'] ?? ''; // final openaiBaseUrl = // dotenv.env['OPENAI_BASE_URL'] ?? 'https://api.openai.com/v1'; // final openaiModel = dotenv.env['OPENAI_MODEL'] ?? 'gpt-3.5-turbo'; // 从Flutter资源包中加载.mcp.json // final mcpConfig = await rootBundle.loadString('.mcp.json'); // 验证JSON格式 // final jsonData = jsonDecode(mcpConfig); 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 openaiagentid = AppConfig.env('OPENAI_AGENT_ID') ?? 'personal_assistant'; final systemPrompt = AppConfig.agentsystemPrompt(openaiagentid); // 从Flutter资源包中加载.mcp.json final jsonData = AppConfig.mcpConfig(); final config = { // 语音代理配置参数 'azureSpeechKey': azureSpeechKey, 'azureSpeechRegion': azureSpeechRegion, 'openaiApiKey': openaiApiKey, 'openaiBaseUrl': openaiBaseUrl, 'openaiModel': openaiModel, 'systemPrompt': systemPrompt, 'mcpServer': jsonEncode(jsonData), 'volcanoAppId': '2316081933', 'volcanoToken': 'mcJTh6OelBqU_L78lgGd77Nyrc_-5-En', }; // 记录日志(不记录敏感信息) Logger.info('启动BLE服务,配置参数键名: ${config}'); 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文件中'); } } final result = await AgentService.startAgentService(config); if (result) { Logger.info('BLE服务启动成功'); // 添加延迟以等待设备连接 await Future.delayed(const Duration(seconds: 2)); // 检查连接状态 final isConnected = await _bleService.isConnected(); if (isConnected) { _isConnected.value = true; _connectionState.value = BleConnectionState.connected; // 如果设备信息存在,则获取详细信息 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; } 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 { return await _bleService.getBatteryInfo(); } catch (e) { Logger.error('获取电池信息失败: ${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 { return await _bleService.openDecoder(); } catch (e) { Logger.error('打开解码器失败: ${e.toString()}'); return false; } } /// 打开解码器 Future openA2DPDecoder() async { try { return await _bleService.openA2DPDecoder(); } catch (e) { Logger.error('打开解码器失败: ${e.toString()}'); return false; } } /// 关闭编解码器 Future closeCodec() async { try { return await _bleService.closeCodec(); } catch (e) { Logger.error('关闭编解码器失败: ${e.toString()}'); return false; } } /// 播放A2DP Future playA2DP() async { try { return await _bleService.playA2DP(); } catch (e) { Logger.error('播放A2DP失败: ${e.toString()}'); return false; } } /// 注册服务 static Future init() async { if (!Get.isRegistered()) { Get.put(BleManager(), permanent: true); } return Future.value(Get.find()); } }