import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; import 'package:audioplayers/audioplayers.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:get/get.dart'; import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/talk/other/audio_player_manager.dart'; import 'package:star_lock/talk/starChart/constant/payload_type_constant.dart'; import 'package:star_lock/talk/starChart/constant/udp_constant.dart'; import 'package:star_lock/talk/starChart/entity/scp_message.dart'; import 'package:star_lock/talk/starChart/handle/other/h264_frame_handler.dart'; import 'package:star_lock/talk/starChart/handle/other/talk_data_repository.dart'; import 'package:star_lock/talk/starChart/handle/other/talke_data_over_time_timer_manager.dart'; import 'package:star_lock/talk/starChart/handle/other/talke_ping_over_time_timer_manager.dart'; import 'package:star_lock/talk/starChart/handle/other/talke_request_over_time_timer_manager.dart'; import 'package:star_lock/talk/starChart/proto/generic.pb.dart'; import 'package:star_lock/talk/starChart/proto/talk_data.pb.dart'; import 'package:star_lock/talk/starChart/star_chart_manage.dart'; import 'package:star_lock/talk/starChart/status/star_chart_talk_status.dart'; class ScpMessageBaseHandle { /// 使用单例 TimerManager /// 超时处理 final TalkeRequestOverTimeTimerManager talkeRequestOverTimeTimerManager = TalkeRequestOverTimeTimerManager(); final TalkePingOverTimeTimerManager talkePingOverTimeTimerManager = TalkePingOverTimeTimerManager(); final TalkDataOverTimeTimerManager talkDataOverTimeTimerManager = TalkDataOverTimeTimerManager(); final startChartManage = StartChartManage(); /// 分包缓冲区 // 存储每个 messageId 对应的分包数据 static Map>> _packetBuffer = {}; final Map _packetTimers = {}; final Duration _timeoutDuration = Duration(seconds: 3); // 分包组包最大超时时间 // 通话数据流的单例流数据处理类 final TalkDataRepository talkDataRepository = TalkDataRepository.instance; // 获取 StartChartTalkStatus 的唯一实例 final StartChartTalkStatus talkStatus = StartChartTalkStatus.instance; final audioManager = AudioPlayerManager(); // 处理出完整帧数据后的回调 final H264FrameHandler frameHandler = H264FrameHandler(onCompleteFrame: (frameData) { // 处理完整的帧数据 TalkDataRepository.instance.addTalkData( TalkData(contentType: TalkData_ContentTypeE.H264, content: frameData), ); }); // 回复成功消息 void replySuccessMessage(ScpMessage scpMessage) { startChartManage.sendGenericRespSuccessMessage( ToPeerId: scpMessage.FromPeerId!, FromPeerId: scpMessage.ToPeerId!, PayloadType: scpMessage.PayloadType!, messageId: scpMessage.MessageId!, ); } // 回复失败消息 void replyErrorMessage(ScpMessage scpMessage) { startChartManage.sendGenericRespErrorMessage( ToPeerId: scpMessage.FromPeerId!, FromPeerId: scpMessage.ToPeerId!, PayloadType: scpMessage.PayloadType!, messageId: scpMessage.MessageId!, ); } bool checkGenericRespSuccess(GenericResp genericResp) { if (genericResp == null) return false; final code = genericResp.code; final message = genericResp.message; return (code == UdpConstant.genericRespSuccessCode || code == null) && message.toLowerCase() == UdpConstant.genericRespSuccessMsg.toLowerCase(); } void log({required String text}) { AppLog.log('==========${text}'); } // 播放铃声 void playRingtone() async { //test:使用自定义铃声 await audioManager.playRingtone(); } // 停止播放铃声 void stopRingtone() async { await audioManager.stopRingtone(); } /// 处理分包逻辑 /// 如果没有收到所有包则返回null dynamic handleFragmentedPayload({ required int messageId, required int spTotal, required int spIndex, required List byte, required int payloadType, }) { // 初始化分包列表 // 使用更高效的key生成方式 final key = '${messageId}_$payloadType'; // 打印每个包的信息 // AppLog.log( // '📦 收到分包 - MessageId: $messageId, 总包数: $spTotal, 当前包序号: $spIndex'); // 检查分包索引是否在合法范围内 if (spIndex < 1 || spIndex > spTotal) { AppLog.log( '❌ 分包序号异常 - MessageId: $messageId, 总包数: $spTotal, 无效包序号: $spIndex'); return null; } // 检查分包索引是否在合法范围内(提前检查可以避免后续无效操作) if (spIndex < 1 || spIndex > spTotal) return null; // 初始化分包列表(使用固定长度列表提高性能) var packets = _packetBuffer[key]; if (packets == null) { // 预分配固定大小的列表,避免动态扩容 packets = List>.filled(spTotal, const [], growable: false); _packetBuffer[key] = packets; _startTimer(key); // AppLog.log('📝 新建分包缓存 - MessageId: $messageId, 预期总包数: $spTotal'); } // 存储当前分包 packets[spIndex - 1] = byte; // 优化检查逻辑,使用循环替代every var isComplete = true; var totalLength = 0; for (var i = 0; i < packets.length; i++) { if (packets[i].isEmpty) { isComplete = false; } else { totalLength += packets[i].length; } } if (isComplete) { // 预分配确切大小的buffer,避免扩容 final buffer = Uint8List(totalLength); var offset = 0; // 直接复制数据,避免使用expand for (var packet in packets) { buffer.setRange(offset, offset + packet.length, packet); offset += packet.length; } // 清理资源 _clearPacketData(key); // 构造TalkData if (payloadType == PayloadTypeConstant.talkData) { final talkData = TalkData(); talkData.mergeFromBuffer(buffer); return talkData; } } return null; // if (!_packetBuffer.containsKey(key)) { // _packetBuffer[key] = List.filled(spTotal, []); // _startTimer(key); // } // // // 检查分包索引是否在合法范围内 // if (spIndex < 1 || spIndex > spTotal) { // // print( // // 'Invalid spTotal: $spTotal spIndex: $spIndex for messageId: $messageId'); // return null; // } // // // 存储当前分包 // _packetBuffer[key]![spIndex - 1] = byte; // // // 检查是否接收到所有分包 // if (_packetBuffer[key]!.every((packet) => packet.isNotEmpty)) { // // 重组所有分包 // Uint8List completePayload = Uint8List.fromList( // _packetBuffer[key]!.expand((packet) => packet).toList()); // // 清除已重组和超时的分包数据 // _clearPacketData(key); // // // 使用重组的包构造成TalkData // if (payloadType == PayloadTypeConstant.talkData) { // final talkData = TalkData(); // talkData.mergeFromBuffer(completePayload); // return talkData; // } // } else { // // 如果分包尚未接收完全,返回 null 或其他指示符 // return null; // } } // 启动定时器 void _startTimer(String key) { _packetTimers[key]?.cancel(); _packetTimers[key] = Timer(_timeoutDuration, () { _clearPacketData(key); }); } // 清除分包数据和定时器 void _clearPacketData(String key) { _packetBuffer.remove(key); _packetTimers.remove(key)?.cancel(); } // 处理通话请求未处理超时 void _handleTalkeRequestOverTime() {} void _handleTalkePingOverTime() {} void _handleTalkDataOverTime() {} }