app-starlock/lib/talk/startChart/handle/scp_message_base_handle.dart

144 lines
4.5 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.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/startChart/constant/payload_type_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/handle/other/overtime_timer_manger.dart';
import 'package:star_lock/talk/startChart/handle/other/talk_data_repository.dart';
import 'package:star_lock/talk/startChart/proto/generic.pb.dart';
import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart';
import 'package:star_lock/talk/startChart/start_chart_manage.dart';
import 'package:star_lock/talk/startChart/start_chart_talk_status.dart';
class ScpMessageBaseHandle {
final startChartManage = StartChartManage();
/// 分包缓冲区
// 存储每个 messageId 对应的分包数据
static Map<String, List<List<int>>> _packetBuffer = {};
final Map<String, Timer> _packetTimers = {};
final Duration _timeoutDuration = Duration(seconds: 10); // 分包组包最大超时时间
// 通话数据流的单例流数据处理类
final TalkDataRepository talkDataRepository = TalkDataRepository.instance;
final audioManager = AudioPlayerManager();
// 通话保持超时监听定时器管理
final talkePingOverTimeTimerManager = OverTimeTimerManager(
timeoutInSeconds: 5,
);
// 通话数据超时定时器
final talkDataOverTimeTimerManager = OverTimeTimerManager(
timeoutInSeconds: 3,
);
// 回复成功消息
void replySuccessMessage(ScpMessage scpMessage) {
startChartManage.sendGenericRespSuccessMessage(
ToPeerId: scpMessage.FromPeerId!,
FromPeerId: scpMessage.ToPeerId!,
PayloadType: scpMessage.PayloadType!,
);
}
// 获取 StartChartTalkStatus 的唯一实例
StartChartTalkStatus talkStatus = StartChartTalkStatus.instance;
bool checkGenericRespSuccess(GenericResp genericResp) {
if (genericResp == null) return false;
final code = genericResp.code;
final message = genericResp.message;
return code == UdpConstant.genericRespSuccessCode &&
message == UdpConstant.genericRespSuccessMsg;
}
void log({required String text}) {
AppLog.log('==========${text}');
}
// 播放铃声
void playRingtone() async {
await audioManager.playRingtone();
}
// 停止播放铃声
void stopRingtone() async {
await audioManager.stopRingtone();
}
/// 处理分包逻辑
/// 如果没有收到所有包则返回null
dynamic handleFragmentedPayload({
required int messageId,
required int spTotal,
required int spIndex,
required List<int> byte,
required int payloadType,
}) {
// 初始化分包列表
String key = '$messageId-$payloadType';
if (!_packetBuffer.containsKey(messageId)) {
_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)) {
// 重组所有分包
List<int> completePayload =
_packetBuffer[key]!.expand((packet) => packet).toList();
// 清除已重组和超时的分包数据
_clearPacketData(key);
// 解析完整的 payload
if (payloadType == PayloadTypeConstant.talkData) {
final TalkData talkData = TalkData();
talkData.mergeFromBuffer(completePayload);
return talkData;
} else if (payloadType == PayloadTypeConstant.echoTest) {
return completePayload;
} else {
String payload = utf8.decode(completePayload);
return payload;
}
} 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();
}
}