fix:更新组包缓冲区的key
This commit is contained in:
parent
1108d4c665
commit
a029c4b4e0
@ -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<void> _playG711Data(List<int> audioData) async {
|
||||
final PcmArrayInt16 fromList = PcmArrayInt16.fromList(audioData);
|
||||
Future<void> _playG711Data(List<int> 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();
|
||||
|
||||
@ -316,7 +316,7 @@ class _StarChartPageState extends State<StarChartPage> {
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
logic.stopProcessing();
|
||||
state.getTVDataRefreshUIEvent!.cancel();
|
||||
// state.getTVDataRefreshUIEvent!.cancel();
|
||||
}
|
||||
|
||||
Widget _buildTalkView({required bool isMpeg4}) {
|
||||
|
||||
@ -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<String?> userMobileIP = NetworkInfo().getWifiIP();
|
||||
|
||||
@ -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<String, int> _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,
|
||||
|
||||
@ -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';
|
||||
}
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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: <String, String>{'lockId': '111'},
|
||||
);
|
||||
// 触发轻微震动反馈
|
||||
HapticFeedback.lightImpact();
|
||||
}
|
||||
|
||||
// 收到来电请求时进行本地通知
|
||||
|
||||
@ -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();
|
||||
});
|
||||
}
|
||||
|
||||
@ -22,8 +22,8 @@ class ScpMessageBaseHandle {
|
||||
|
||||
/// 分包缓冲区
|
||||
// 存储每个 messageId 对应的分包数据
|
||||
static Map<int, List<List<int>>> _packetBuffer = {};
|
||||
final Map<int, Timer> _packetTimers = {};
|
||||
static Map<String, List<List<int>>> _packetBuffer = {};
|
||||
final Map<String, Timer> _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<int> 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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -296,6 +296,7 @@ class StartChartManage {
|
||||
// 取到分包数据
|
||||
List<int> packet = payload.sublist(start, end);
|
||||
|
||||
// 分包数据不递增messageID
|
||||
final messageId =
|
||||
MessageCommand.getNextMessageId(toPeerId, increment: false);
|
||||
// 组装分包数据
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user