import 'dart:convert'; 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/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'; import 'package:star_lock/talk/startChart/proto/talk_accept.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_expect.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_hangup.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_ping.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_reject.pb.dart'; import 'package:star_lock/talk/startChart/proto/talk_request.pb.dart'; class MessageCommand { /// 客户端去中继上线命令 static List goOnlineRelay({ required String FromPeerId, required String ToPeerId, }) { String serializedBytesString = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, MessageId: 1, SpTotal: 0, SpIndex: 0, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: 'hello', PayloadCRC: 55230, PayloadLength: 5, PayloadType: PayloadTypeConstant.goOnline, ).serialize(); return _hexToBytes(serializedBytesString); } // 回声测试消息 static List echoMessage({ required String ToPeerId, required String FromPeerId, }) { String payload = 'hello'; ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, MessageId: 1, SpTotal: 0, SpIndex: 0, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, PayloadCRC: calculationCrc(_stringToUint8List(payload)), PayloadLength: payload.length, PayloadType: PayloadTypeConstant.echoTest, ); String serializedBytesString = message.serialize(); return _hexToBytes(serializedBytesString); } // 心跳消息 static List heartbeatMessage({ required String FromPeerId, required String ToPeerId, }) { String payload = 'hello'; ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, MessageId: 1, SpTotal: 0, SpIndex: 0, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, PayloadCRC: calculationCrc(_stringToUint8List(payload)), PayloadLength: payload.length, PayloadType: PayloadTypeConstant.heartbeat, ); String serializedBytesString = message.serialize(); return _hexToBytes(serializedBytesString); } // 网关初始化 static List gatewayResetMessage({ required int gatewayId, required String FromPeerId, required String ToPeerId, required int time, }) { // 构建荷载 final gatewayResetReq = GatewayResetReq( iD: gatewayId, time: time, ); // 构建荷载长度 final payload = gatewayResetReq.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, MessageId: 1, SpTotal: 0, SpIndex: 0, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, PayloadCRC: calculationCrc(payload), PayloadLength: payload.length, PayloadType: PayloadTypeConstant.gatewayReset, ); String serializedBytesString = message.serialize(); return _hexToBytes(serializedBytesString); } // 同意接听消息 static List talkAcceptMessage({ required String FromPeerId, required String ToPeerId, }) { final talkAcceptReq = TalkAcceptReq(); final payload = talkAcceptReq.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, MessageId: 1, SpTotal: 0, SpIndex: 0, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, PayloadCRC: calculationCrc(payload), PayloadLength: payload.length, PayloadType: PayloadTypeConstant.talkAccept, ); String serializedBytesString = message.serialize(); return _hexToBytes(serializedBytesString); } // 发送对话请求消息 static List talkRequestMessage({ required String FromPeerId, required String ToPeerId, }) { final talkReq = TalkReq(); final payload = talkReq.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, MessageId: 1, SpTotal: 0, SpIndex: 0, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, PayloadCRC: calculationCrc(payload), PayloadLength: payload.length, PayloadType: PayloadTypeConstant.callRequest, ); String serializedBytesString = message.serialize(); return _hexToBytes(serializedBytesString); } // 拒绝接听消息 static List talkRejectMessage({ required String FromPeerId, required String ToPeerId, }) { final talkReject = TalkReject(); final payload = talkReject.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, MessageId: 1, SpTotal: 0, SpIndex: 0, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, PayloadCRC: calculationCrc(payload), PayloadLength: payload.length, PayloadType: PayloadTypeConstant.talkReject, ); String serializedBytesString = message.serialize(); return _hexToBytes(serializedBytesString); } // 呼叫保持消息 static List talkPingMessage({ required String FromPeerId, required String ToPeerId, }) { final talkPing = TalkPing(); final payload = talkPing.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, MessageId: 1, SpTotal: 0, SpIndex: 0, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, PayloadCRC: calculationCrc(payload), PayloadLength: payload.length, PayloadType: PayloadTypeConstant.talkPing, ); String serializedBytesString = message.serialize(); return _hexToBytes(serializedBytesString); } // 通话中挂断 static List talkHangupMessage({ required String FromPeerId, required String ToPeerId, }) { final talkHangup = TalkHangup(); final payload = talkHangup.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, MessageId: 1, SpTotal: 0, SpIndex: 0, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, PayloadCRC: calculationCrc(payload), PayloadLength: payload.length, PayloadType: PayloadTypeConstant.talkHangup, ); String serializedBytesString = message.serialize(); return _hexToBytes(serializedBytesString); } // 音视频数据 static List talkDataMessage({ required String FromPeerId, required String ToPeerId, required TalkData talkData, }) { final payload = talkData.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.RealTimeData, MessageId: 1, SpTotal: 0, SpIndex: 0, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, PayloadCRC: calculationCrc(payload), PayloadLength: payload.length, PayloadType: PayloadTypeConstant.talkData, ); String serializedBytesString = message.serialize(); return _hexToBytes(serializedBytesString); } // 预期接收消息 static List talkExpectMessage({ required String FromPeerId, required String ToPeerId, required TalkExpect talkExpect, }) { final payload = talkExpect.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Req, MessageId: 1, SpTotal: 0, SpIndex: 0, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, PayloadCRC: calculationCrc(payload), PayloadLength: payload.length, PayloadType: PayloadTypeConstant.talkExpect, ); String serializedBytesString = message.serialize(); return _hexToBytes(serializedBytesString); } // GenericRespSuccess 消息 static List genericRespSuccessMessage({ required String FromPeerId, required String ToPeerId, required int PayloadType, }) { final genericResp = GenericResp(); genericResp.message = 'ok'; genericResp.code = 0; final payload = genericResp.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Resp, MessageId: 1, SpTotal: 0, SpIndex: 0, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, PayloadCRC: calculationCrc(payload), PayloadLength: payload.length, PayloadType: PayloadType, ); String serializedBytesString = message.serialize(); return _hexToBytes(serializedBytesString); } // GenericRespError 消息 static List genericRespErrorMessage({ required String FromPeerId, required String ToPeerId, required int PayloadType, }) { final genericResp = GenericResp(); genericResp.message = 'error'; genericResp.code = -1; final payload = genericResp.writeToBuffer(); ScpMessage message = ScpMessage( ProtocolFlag: ProtocolFlagConstant.scp01, MessageType: MessageTypeConstant.Resp, MessageId: 1, SpTotal: 0, SpIndex: 0, FromPeerId: FromPeerId, ToPeerId: ToPeerId, Payload: payload, PayloadCRC: calculationCrc(payload), PayloadLength: payload.length, PayloadType: PayloadType, ); String serializedBytesString = message.serialize(); return _hexToBytes(serializedBytesString); } // 辅助方法:将16进制字符串转换为字节列表 static List _hexToBytes(String hex) { final bytes = []; for (int i = 0; i < hex.length; i += 2) { bytes.add(int.parse(hex.substring(i, i + 2), radix: 16)); } return bytes; } static int calculationCrc(Uint8List uint8Payload) { // 使用自定义 CRC32 算法 final int crc32Value = _crc32Uint16(uint8Payload); return crc32Value; } // 将字符串转换为 Uint8List static Uint8List _stringToUint8List(String input) { return Uint8List.fromList(utf8.encode(input)); } // 自定义 CRC32 实现 static int _crc32Uint16(Uint8List data) { const int polynomial = 0xD5828281; // 创建 CRC32 表 final List table = List.generate(256, (i) { int crc = i; for (int j = 0; j < 8; j++) { if ((crc & 1) != 0) { crc = (crc >> 1) ^ polynomial; } else { crc >>= 1; } } return crc; }); // 计算 CRC32 校验值 int crc = 0xFFFFFFFF; for (final int byte in data) { crc = (crc >> 8) ^ table[(crc ^ byte) & 0xFF]; } crc ^= 0xFFFFFFFF; // 返回 CRC32 的低 16 位 return crc & 0xFFFF; } }