From a029c4b4e04a94de514bfd75aa55ba9fec32e6de Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 24 Dec 2024 15:38:36 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E6=9B=B4=E6=96=B0=E7=BB=84=E5=8C=85?= =?UTF-8?q?=E7=BC=93=E5=86=B2=E5=8C=BA=E7=9A=84key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../star_chart_h264/star_chart_logic.dart | 18 +++++----- .../star_chart_h264/star_chart_page.dart | 2 +- .../star_chart_h264/star_chart_state.dart | 2 +- .../startChart/command/message_command.dart | 11 +++--- .../startChart/constant/udp_constant.dart | 3 ++ .../handle/impl/udp_talk_accept_handler.dart | 8 ++--- .../handle/impl/udp_talk_data_handler.dart | 9 +---- .../handle/impl/udp_talk_request_handler.dart | 3 ++ .../handle/other/overtime_timer_manger.dart | 5 +-- .../handle/scp_message_base_handle.dart | 36 ++++++++++--------- lib/talk/startChart/start_chart_manage.dart | 1 + 11 files changed, 51 insertions(+), 47 deletions(-) diff --git a/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_logic.dart b/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_logic.dart index 5b41c798..7cc18cbc 100644 --- a/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_logic.dart +++ b/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_logic.dart @@ -25,12 +25,6 @@ class StarChartLogic extends BaseGetXController { @override void onReady() { super.onReady(); - // 初始化音频播放设备,采样率为 44100 Hz,单声道 - FlutterPcmSound.setup(sampleRate: 44100, channelCount: 1, ); - - // 设置音频数据的供给阈值,假设我们使用一秒钟的供给阈值 - int feedThreshold = 44100 * 1; // 44100 个样本,相当于一秒钟的数据量 - FlutterPcmSound.setFeedThreshold(feedThreshold); _getTalkStatusRefreshUIAction(); _startListenTalkData(); } @@ -75,8 +69,16 @@ class StarChartLogic extends BaseGetXController { } /// 播放音频数据 - Future _playG711Data(List audioData) async { - final PcmArrayInt16 fromList = PcmArrayInt16.fromList(audioData); + Future _playG711Data(List pcmData) async { + // 将 PCM 数据转换为 PcmArrayInt16 + final PcmArrayInt16 fromList = PcmArrayInt16.fromList(pcmData); + + // 初始化音频播放设备,确保采样率和声道数与 PCM 数据匹配 + await FlutterPcmSound.setup(sampleRate: 8000, channelCount: 1); + + // 设置音频数据的供给阈值 + FlutterPcmSound.setFeedThreshold(8000 ~/ 2); // 根据需要调整 + // final PcmArrayInt16 fromList = PcmArrayInt16.fromList(audioData); await FlutterPcmSound.feed(fromList); FlutterPcmSound.play(); diff --git a/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_page.dart b/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_page.dart index b0678082..f8669c97 100644 --- a/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_page.dart +++ b/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_page.dart @@ -316,7 +316,7 @@ class _StarChartPageState extends State { void dispose() { super.dispose(); logic.stopProcessing(); - state.getTVDataRefreshUIEvent!.cancel(); + // state.getTVDataRefreshUIEvent!.cancel(); } Widget _buildTalkView({required bool isMpeg4}) { diff --git a/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_state.dart b/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_state.dart index c0aa5e69..25512f62 100644 --- a/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_state.dart +++ b/lib/main/lockDetail/monitoring/star_chart_h264/star_chart_state.dart @@ -14,7 +14,7 @@ class StarChartState { RxBool isOpenVoice = false.obs; int udpSendDataFrameNumber = 0; // 帧序号 // var isSenderAudioData = false.obs;// 是否要发送音频数据 - StreamSubscription? getTVDataRefreshUIEvent; //收到视频流数据 + // StreamSubscription? getTVDataRefreshUIEvent; //收到视频流数据 RxBool shouldUpdateUI = false.obs; //是否需要更新UI Future userMobileIP = NetworkInfo().getWifiIP(); diff --git a/lib/talk/startChart/command/message_command.dart b/lib/talk/startChart/command/message_command.dart index 8f3ea1d5..00093af7 100644 --- a/lib/talk/startChart/command/message_command.dart +++ b/lib/talk/startChart/command/message_command.dart @@ -4,6 +4,7 @@ import 'dart:typed_data'; import 'package:star_lock/talk/startChart/constant/message_type_constant.dart'; import 'package:star_lock/talk/startChart/constant/payload_type_constant.dart'; import 'package:star_lock/talk/startChart/constant/protocol_flag_constant.dart'; +import 'package:star_lock/talk/startChart/constant/udp_constant.dart'; import 'package:star_lock/talk/startChart/entity/scp_message.dart'; import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart'; import 'package:star_lock/talk/startChart/proto/generic.pb.dart'; @@ -17,6 +18,7 @@ import 'package:star_lock/talk/startChart/proto/talk_request.pb.dart'; class MessageCommand { // 全局字典,用于存储每个 ToPeerId 对应的当前 messageId + // 单个会话的messageId需要递增 static Map _messageIdMap = {}; static int _maxIntValue = 9223372036854775807; // Dart 中 int 的最大值 @@ -322,8 +324,8 @@ class MessageCommand { int? MessageId, }) { final genericResp = GenericResp(); - genericResp.message = 'ok'; - genericResp.code = 0; + genericResp.message = UdpConstant.genericRespSuccessMsg; + genericResp.code = UdpConstant.genericRespSuccessCode; final payload = genericResp.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, @@ -348,10 +350,11 @@ class MessageCommand { required String ToPeerId, required int PayloadType, int? MessageId, + String? errorMessageText, }) { final genericResp = GenericResp(); - genericResp.message = 'error'; - genericResp.code = -1; + genericResp.message = errorMessageText ?? UdpConstant.genericRespErrorMsg; + genericResp.code = UdpConstant.genericRespErrorCode; final payload = genericResp.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, diff --git a/lib/talk/startChart/constant/udp_constant.dart b/lib/talk/startChart/constant/udp_constant.dart index 39c6e524..f696ac92 100644 --- a/lib/talk/startChart/constant/udp_constant.dart +++ b/lib/talk/startChart/constant/udp_constant.dart @@ -2,4 +2,7 @@ class UdpConstant{ // generic成功响应 static const int genericRespSuccessCode = 0; static const String genericRespSuccessMsg = 'ok'; + // generic失败响应 + static const int genericRespErrorCode = -1; + static const String genericRespErrorMsg = 'error'; } \ No newline at end of file diff --git a/lib/talk/startChart/handle/impl/udp_talk_accept_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_accept_handler.dart index 295e2c02..40bfaea3 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_accept_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_accept_handler.dart @@ -31,12 +31,12 @@ class UdpTalkAcceptHandler extends ScpMessageBaseHandle // 收到同意接听回复 final GenericResp genericResp = scpMessage.Payload; if (checkGenericRespSuccess(genericResp)) { - // 延迟一秒启动定时器判断 + // 启动发送预期数据请求 + _handleStartSendTalkExpectDataRequest(); Future.delayed(Duration(seconds: 1), () { + print('启动定时器判断'); // 启动通话保持定时器 _handleStartTalkPing(); - // 启动发送预期数据请求 - _handleStartSendTalkExpectDataRequest(); // 启动通话数据检查的定时器 _handleCheckTalkDataTimer(); }); @@ -78,7 +78,7 @@ class UdpTalkAcceptHandler extends ScpMessageBaseHandle } } - // 启动通话保持 + // 启动通话保持,判断x秒内是否收到通话保持 void _handleStartTalkPing() { // 启动通话保持 startChartManage.startTalkPingMessageTimer(); diff --git a/lib/talk/startChart/handle/impl/udp_talk_data_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_data_handler.dart index 98767822..856b84ce 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_data_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_data_handler.dart @@ -85,11 +85,7 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle int? spTotal, int? spIndex, int? messageId}) { - if (messageType == MessageTypeConstant.Resp) { - final GenericResp genericResp = GenericResp(); - genericResp.mergeFromBuffer(byte); - return genericResp; - } else if (messageType == MessageTypeConstant.RealTimeData) { + if (messageType == MessageTypeConstant.RealTimeData) { // 回声测试 if (spTotal != null && spTotal > 1 && @@ -109,9 +105,6 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle talkData.mergeFromBuffer(byte); return talkData; } - } else { - String payload = utf8.decode(byte); - return payload; } } } diff --git a/lib/talk/startChart/handle/impl/udp_talk_request_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_request_handler.dart index 02588870..f8f66c23 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_request_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_request_handler.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:typed_data'; +import 'package:flutter/services.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:get/get.dart'; @@ -65,6 +66,8 @@ class UdpTalkRequestHandler extends ScpMessageBaseHandle Routers.starChartPage, arguments: {'lockId': '111'}, ); + // 触发轻微震动反馈 + HapticFeedback.lightImpact(); } // 收到来电请求时进行本地通知 diff --git a/lib/talk/startChart/handle/other/overtime_timer_manger.dart b/lib/talk/startChart/handle/other/overtime_timer_manger.dart index c813dcaf..16add8ad 100644 --- a/lib/talk/startChart/handle/other/overtime_timer_manger.dart +++ b/lib/talk/startChart/handle/other/overtime_timer_manger.dart @@ -12,9 +12,6 @@ class OverTimeTimerManager { // 超时时间(以秒为单位),是 final 的,因此必须在构造函数中初始化 final int timeoutInSeconds; - // 默认超时时间(以秒为单位) - static const int defaultTimeoutInSeconds = 5; - // 超时回调函数 TimeoutCallback? _onTimeout; @@ -24,7 +21,7 @@ class OverTimeTimerManager { _timer = Timer(Duration(seconds: timeoutInSeconds), () { // 超时回调方法 _onTimeout?.call(); - // 清楚定时器 + // 清除定时器 _cancelTimer(); }); } diff --git a/lib/talk/startChart/handle/scp_message_base_handle.dart b/lib/talk/startChart/handle/scp_message_base_handle.dart index 430578bf..5db47166 100644 --- a/lib/talk/startChart/handle/scp_message_base_handle.dart +++ b/lib/talk/startChart/handle/scp_message_base_handle.dart @@ -22,8 +22,8 @@ class ScpMessageBaseHandle { /// 分包缓冲区 // 存储每个 messageId 对应的分包数据 - static Map>> _packetBuffer = {}; - final Map _packetTimers = {}; + static Map>> _packetBuffer = {}; + final Map _packetTimers = {}; final Duration _timeoutDuration = Duration(seconds: 10); // 分包组包最大超时时间 // 通话数据流的单例流数据处理类 @@ -85,28 +85,30 @@ class ScpMessageBaseHandle { required int payloadType, }) { // 初始化分包列表 + String key = '$messageId-$payloadType'; if (!_packetBuffer.containsKey(messageId)) { - _packetBuffer[messageId] = List.filled(spTotal, []); - _startTimer(messageId); + _packetBuffer[key] = List.filled(spTotal, []); + _startTimer(key); } // 检查分包索引是否在合法范围内 if (spIndex < 1 || spIndex > spTotal) { - print('Invalid spIndex: $spIndex for messageId: $messageId'); + print( + 'Invalid spTotal: $spTotal spIndex: $spIndex for messageId: $messageId'); return null; } // 存储当前分包 - _packetBuffer[messageId]![spIndex - 1] = byte; + _packetBuffer[key]![spIndex - 1] = byte; // 检查是否接收到所有分包 - if (_packetBuffer[messageId]!.every((packet) => packet.isNotEmpty)) { + if (_packetBuffer[key]!.every((packet) => packet.isNotEmpty)) { // 重组所有分包 List completePayload = - _packetBuffer[messageId]!.expand((packet) => packet).toList(); + _packetBuffer[key]!.expand((packet) => packet).toList(); - // 清除已重组的分包数据 - _clearPacketData(messageId); + // 清除已重组和超时的分包数据 + _clearPacketData(key); // 解析完整的 payload if (payloadType == PayloadTypeConstant.talkData) { @@ -126,16 +128,16 @@ class ScpMessageBaseHandle { } // 启动定时器 - void _startTimer(int messageId) { - _packetTimers[messageId]?.cancel(); - _packetTimers[messageId] = Timer(_timeoutDuration, () { - _clearPacketData(messageId); + void _startTimer(String key) { + _packetTimers[key]?.cancel(); + _packetTimers[key] = Timer(_timeoutDuration, () { + _clearPacketData(key); }); } // 清除分包数据和定时器 - void _clearPacketData(int messageId) { - _packetBuffer.remove(messageId); - _packetTimers.remove(messageId)?.cancel(); + void _clearPacketData(String key) { + _packetBuffer.remove(key); + _packetTimers.remove(key)?.cancel(); } } diff --git a/lib/talk/startChart/start_chart_manage.dart b/lib/talk/startChart/start_chart_manage.dart index 0b3d22d4..22ff1c64 100644 --- a/lib/talk/startChart/start_chart_manage.dart +++ b/lib/talk/startChart/start_chart_manage.dart @@ -296,6 +296,7 @@ class StartChartManage { // 取到分包数据 List packet = payload.sublist(start, end); + // 分包数据不递增messageID final messageId = MessageCommand.getNextMessageId(toPeerId, increment: false); // 组装分包数据