|
|
@ -15,6 +15,7 @@ import '../../core/utils/logger.dart'; |
|
|
import 'bluetooth_manager.dart'; |
|
|
import 'bluetooth_manager.dart'; |
|
|
import 'language_manager.dart'; |
|
|
import 'language_manager.dart'; |
|
|
import 'network/dio_manager.dart'; |
|
|
import 'network/dio_manager.dart'; |
|
|
|
|
|
import '../../routes/app_routes.dart'; |
|
|
|
|
|
|
|
|
// 重新导出BLE连接状态常量,让外部可以通过BleManager访问 |
|
|
// 重新导出BLE连接状态常量,让外部可以通过BleManager访问 |
|
|
export 'package:ble_service/ble_service.dart' show BleConnectionState; |
|
|
export 'package:ble_service/ble_service.dart' show BleConnectionState; |
|
|
@ -29,6 +30,10 @@ class BleCommands { |
|
|
static const int GET_WAKEUP_VERSION = 0x08; |
|
|
static const int GET_WAKEUP_VERSION = 0x08; |
|
|
static const int GET_VOICE_WAKEUP_STATUS = 0x14; |
|
|
static const int GET_VOICE_WAKEUP_STATUS = 0x14; |
|
|
static const int SET_VOICE_WAKEUP_STATUS = 0x15; |
|
|
static const int SET_VOICE_WAKEUP_STATUS = 0x15; |
|
|
|
|
|
/// 设备上报开启通话翻译 0x16 (帧头0xCC, cmdLen=0x01, status=0xFF) |
|
|
|
|
|
static const int CALL_TRANSLATION_ON = 0x16; |
|
|
|
|
|
/// 设备上报关闭通话翻译 0x17 (帧头0xCC, cmdLen=0x01, status=0xFF) |
|
|
|
|
|
static const int CALL_TRANSLATION_OFF = 0x17; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// 判断编解码控制指令是否成功 |
|
|
/// 判断编解码控制指令是否成功 |
|
|
@ -239,6 +244,14 @@ class BleManager extends GetxService { |
|
|
0.obs; // 唤醒语音升级状态 0: 未升级 1: 升级中 2: 升级成功 3: 升级失败 |
|
|
0.obs; // 唤醒语音升级状态 0: 未升级 1: 升级中 2: 升级成功 3: 升级失败 |
|
|
RxInt get wakeupVoiceUpgradeStatus => _wakeupVoiceUpgradeStatus; |
|
|
RxInt get wakeupVoiceUpgradeStatus => _wakeupVoiceUpgradeStatus; |
|
|
|
|
|
|
|
|
|
|
|
/// 设备上报通话翻译开关信号流 |
|
|
|
|
|
/// true = 设备上报开启通话翻译 (0x16),false = 设备上报关闭通话翻译 (0x17) |
|
|
|
|
|
/// 外部(如 TranslationController)可监听该流,收到信号后启动/停止通话翻译功能。 |
|
|
|
|
|
final StreamController<bool> _callTranslationRequestController = |
|
|
|
|
|
StreamController<bool>.broadcast(); |
|
|
|
|
|
Stream<bool> get onCallTranslationRequest => |
|
|
|
|
|
_callTranslationRequestController.stream; |
|
|
|
|
|
|
|
|
/// 初始化 |
|
|
/// 初始化 |
|
|
@override |
|
|
@override |
|
|
void onInit() { |
|
|
void onInit() { |
|
|
@ -254,6 +267,7 @@ class BleManager extends GetxService { |
|
|
void onClose() { |
|
|
void onClose() { |
|
|
_statusSubscription?.cancel(); |
|
|
_statusSubscription?.cancel(); |
|
|
_dataSubscription?.cancel(); |
|
|
_dataSubscription?.cancel(); |
|
|
|
|
|
_callTranslationRequestController.close(); |
|
|
super.onClose(); |
|
|
super.onClose(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -392,11 +406,51 @@ class BleManager extends GetxService { |
|
|
case BleCommands.SET_VOICE_WAKEUP_STATUS: |
|
|
case BleCommands.SET_VOICE_WAKEUP_STATUS: |
|
|
_updateVoiceWakeupSetResultFromData(data); |
|
|
_updateVoiceWakeupSetResultFromData(data); |
|
|
break; |
|
|
break; |
|
|
|
|
|
case BleCommands.CALL_TRANSLATION_ON: |
|
|
|
|
|
_handleCallTranslationRequest(true, data); |
|
|
|
|
|
break; |
|
|
|
|
|
case BleCommands.CALL_TRANSLATION_OFF: |
|
|
|
|
|
_handleCallTranslationRequest(false, data); |
|
|
|
|
|
break; |
|
|
default: |
|
|
default: |
|
|
Logger.w('BleManager', '未处理的命令ID: $commandId'); |
|
|
Logger.w('BleManager', '未处理的命令ID: $commandId'); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 处理设备上报的通话翻译开关指令 (0x16 / 0x17) |
|
|
|
|
|
/// - [enable] true=开启通话翻译, false=关闭 |
|
|
|
|
|
/// 行为: |
|
|
|
|
|
/// 1. 打印 [CALL_TRANS_CMD] 日志; |
|
|
|
|
|
/// 2. 向 [onCallTranslationRequest] 流广播信号(TranslationController 监听并启停); |
|
|
|
|
|
/// 3. 未在翻译页时,自动导航到 Routes.translation 并以 call 模式 + autoStart 进入。 |
|
|
|
|
|
void _handleCallTranslationRequest( |
|
|
|
|
|
bool enable, Map<dynamic, dynamic> data) { |
|
|
|
|
|
final status = data['status']; |
|
|
|
|
|
Logger.i('BleManager', |
|
|
|
|
|
'[CALL_TRANS_CMD] 收到设备上报${enable ? "开启" : "关闭"}通话翻译 cmd=0x${(enable ? BleCommands.CALL_TRANSLATION_ON : BleCommands.CALL_TRANSLATION_OFF).toRadixString(16)} status=$status'); |
|
|
|
|
|
|
|
|
|
|
|
// 广播给监听者(如 TranslationController 已在 call 模式可直接启/停) |
|
|
|
|
|
if (!_callTranslationRequestController.isClosed) { |
|
|
|
|
|
_callTranslationRequestController.add(enable); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 开启:若当前不在翻译页,则导航并请求自动开始 |
|
|
|
|
|
if (enable) { |
|
|
|
|
|
final currentRoute = Get.currentRoute; |
|
|
|
|
|
if (currentRoute != Routes.translation) { |
|
|
|
|
|
Logger.i('BleManager', |
|
|
|
|
|
'[CALL_TRANS_CMD] 当前路由=$currentRoute,导航到翻译页(call 模式, autoStart=true)'); |
|
|
|
|
|
Get.toNamed( |
|
|
|
|
|
Routes.translation, |
|
|
|
|
|
arguments: {'translationId': 'call', 'autoStart': true}, |
|
|
|
|
|
); |
|
|
|
|
|
} else { |
|
|
|
|
|
Logger.i('BleManager', |
|
|
|
|
|
'[CALL_TRANS_CMD] 已在翻译页,由 TranslationController 监听信号自行启动'); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/// 根据命令名称处理设备信息 |
|
|
/// 根据命令名称处理设备信息 |
|
|
void _processDeviceInfoByCommandName( |
|
|
void _processDeviceInfoByCommandName( |
|
|
String commandName, Map<dynamic, dynamic> data) { |
|
|
String commandName, Map<dynamic, dynamic> data) { |
|
|
@ -1125,9 +1179,14 @@ class BleManager extends GetxService { |
|
|
_awaitingCodecOpen = true; |
|
|
_awaitingCodecOpen = true; |
|
|
_awaitingCodecClose = false; |
|
|
_awaitingCodecClose = false; |
|
|
_isCodecActive.value = false; |
|
|
_isCodecActive.value = false; |
|
|
return await _bleService.openA2DPDecoder(); |
|
|
Logger.i('CALL_TRANS_CMD', |
|
|
|
|
|
'准备发送通话翻译指令 cmd=0x05 sub=0xA2(A2DP_PLAY) → openA2DPDecoder'); |
|
|
|
|
|
final ok = await _bleService.openA2DPDecoder(); |
|
|
|
|
|
Logger.i('CALL_TRANS_CMD', |
|
|
|
|
|
'通话翻译指令下发结果: ${ok ? "成功" : "失败"} (等待设备回包确认)'); |
|
|
|
|
|
return ok; |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
Logger.error('打开解码器失败: ${e.toString()}'); |
|
|
Logger.e('CALL_TRANS_CMD', '通话翻译指令异常: ${e.toString()}'); |
|
|
_awaitingCodecOpen = false; |
|
|
_awaitingCodecOpen = false; |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|