import 'dart:convert'; import 'dart:typed_data'; import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart'; import 'package:star_lock/talk/startChart/handle/scp_message_handler_factory.dart'; class ScpMessage { ScpMessage({ this.ProtocolFlag, this.MessageType, this.MessageId, this.SpTotal, this.SpIndex, this.FromPeerId, this.ToPeerId, this.PayloadType, this.PayloadCRC, this.PayloadLength, this.Payload, }); String? ProtocolFlag; int? MessageType; int? MessageId; int? SpTotal; int? SpIndex; String? FromPeerId; String? ToPeerId; int? PayloadType; int? PayloadCRC; int? PayloadLength; dynamic Payload; // Payload可以是任何类型,这里用dynamic表示 ScpMessage.fromJson(dynamic json) { ProtocolFlag = json['ProtocolFlag']; MessageType = json['MessageType']; MessageId = json['MessageId']; SpTotal = json['SpTotal']; SpIndex = json['SpIndex']; FromPeerId = json['FromPeerId']; ToPeerId = json['ToPeerId']; PayloadType = json['PayloadType']; PayloadCRC = json['PayloadCRC']; PayloadLength = json['PayloadLength']; Payload = json['Payload']; } Map toJson() { return { 'ProtocolFlag': ProtocolFlag, 'MessageType': MessageType, 'MessageId': MessageId, 'SpTotal': SpTotal, 'SpIndex': SpIndex, 'FromPeerId': FromPeerId, 'ToPeerId': ToPeerId, 'PayloadType': PayloadType, 'PayloadCRC': PayloadCRC, 'PayloadLength': PayloadLength, 'Payload': Payload, }; } @override String toString() { return 'ScpMessage{ProtocolFlag: $ProtocolFlag, MessageType: $MessageType, MessageId: $MessageId, SpTotal: $SpTotal, SpIndex: $SpIndex, FromPeerId: $FromPeerId, ToPeerId: $ToPeerId, PayloadType: $PayloadType, PayloadCRC: $PayloadCRC, PayloadLength: $PayloadLength, Payload: $Payload}'; } String serialize() { final bytes = []; // ProtocolFlag (4 bytes) if (ProtocolFlag != null) { bytes.addAll(utf8.encode(ProtocolFlag!)); } // MessageType (1 byte) if (MessageType != null) { bytes.add(MessageType!); } // MessageId (2 bytes) if (MessageId != null) { final highByteMessageId = (MessageId! >> 8) & 0xFF; final lowByteMessageId = MessageId! & 0xFF; bytes.add(lowByteMessageId); // 交换位置 bytes.add(highByteMessageId); // 交换位置 } // SpTotal (1 byte) if (SpTotal != null) { bytes.add(SpTotal!); } // SpIndex (1 byte) if (SpIndex != null) { bytes.add(SpIndex!); } // FromPeerId (字符串,记录长度) if (FromPeerId != null) { bytes.addAll(utf8.encode(FromPeerId!)); } // ToPeerId (字符串,假设长度固定为32字节) if (ToPeerId != null) { bytes.addAll(utf8.encode(ToPeerId!)); } // PayloadType (2 bytes) if (PayloadType != null) { final highBytePayloadType = (PayloadType! >> 8) & 0xFF; final lowBytePayloadType = PayloadType! & 0xFF; bytes.add(lowBytePayloadType); // 交换位置 bytes.add(highBytePayloadType); // 交换位置 } // 计算 PayloadCRC (2 bytes) if (PayloadCRC != null) { final highBytePayloadCRC = (PayloadCRC! >> 8) & 0xFF; final lowBytePayloadCRC = PayloadCRC! & 0xFF; bytes.add(lowBytePayloadCRC); // 交换位置 bytes.add(highBytePayloadCRC); // 交换位置 } // PayloadLength (4 bytes) if (PayloadLength != null) { bytes.add(PayloadLength! & 0xFF); bytes.add((PayloadLength! >> 8) & 0xFF); bytes.add((PayloadLength! >> 16) & 0xFF); bytes.add((PayloadLength! >> 24) & 0xFF); } // Payload (字符串,转换为字节) if (Payload != null && Payload is String) { bytes.addAll(utf8.encode(Payload!)); } else if (Payload != null) { // 如果不是字符串则需要外部转为字节数组,这里直接添加 bytes.addAll(Payload); } // 转16进制字符串 final bytesToHexString = bytesToHex(bytes); return bytesToHexString; } static ScpMessage deserialize(Uint8List bytes) { final message = ScpMessage(); int offset = 0; // Convert byte array to hex string with zero padding and without spaces // String hexString = // bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(); // // // Log the hex string // _log(text: '原始字节数组: $hexString'); // ProtocolFlag (4 bytes) if (bytes.length - offset >= 4) { message.ProtocolFlag = utf8.decode(bytes.sublist(offset, offset + 4)); offset += 4; } else { throw FormatException("Invalid ProtocolFlag length"); } // MessageType (1 byte) if (bytes.length - offset >= 1) { message.MessageType = bytes[offset]; offset += 1; } else { throw FormatException("Invalid MessageType length"); } // MessageId (2 bytes, little-endian) if (bytes.length - offset >= 2) { message.MessageId = (bytes[offset + 1] << 8) | bytes[offset]; offset += 2; } else { throw FormatException("Invalid MessageId length"); } // SpTotal (1 byte) if (bytes.length - offset >= 1) { message.SpTotal = bytes[offset]; offset += 1; } else { throw FormatException("Invalid SpTotal length"); } // SpIndex (1 byte) if (bytes.length - offset >= 1) { message.SpIndex = bytes[offset]; offset += 1; } else { throw FormatException("Invalid SpIndex length"); } // FromPeerId (字符串,长度固定为44字节) if (bytes.length - offset >= 44) { message.FromPeerId = utf8.decode(bytes.sublist(offset, offset + 44)).trimRight(); offset += 44; } else { throw FormatException("Invalid FromPeerId length"); } // ToPeerId (字符串,长度固定为44字节) if (bytes.length - offset >= 44) { message.ToPeerId = utf8.decode(bytes.sublist(offset, offset + 44)).trimRight(); offset += 44; } else { throw FormatException("Invalid ToPeerId length"); } // PayloadType (2 bytes, little-endian) if (bytes.length - offset >= 2) { message.PayloadType = (bytes[offset + 1] << 8) | bytes[offset]; offset += 2; } else { throw FormatException("Invalid PayloadType length"); } // PayloadCRC (2 bytes, little-endian) if (bytes.length - offset >= 2) { message.PayloadCRC = (bytes[offset + 1] << 8) | bytes[offset]; offset += 2; } else { throw FormatException("Invalid PayloadCRC length"); } // PayloadLength (4 bytes, little-endian) if (bytes.length - offset >= 4) { message.PayloadLength = (bytes[offset] | (bytes[offset + 1] << 8) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 24)); // 修正为 little-endian offset += 4; } else { throw FormatException("Invalid PayloadLength length"); } // 处理其他类型的Payload if (message.PayloadLength != null && bytes.length - offset >= message.PayloadLength!) { final Uint8List sublist = bytes.sublist(offset, offset + message.PayloadLength!); offset += message.PayloadLength!; message.Payload = _handlePayLoad( payloadType: message.PayloadType ?? 0, messageType: message.MessageType ?? 0, byte: sublist, offset: offset, PayloadLength: message.PayloadLength, spIndex: message.SpIndex, spTotal: message.SpTotal, messageId: message.MessageId, ); } else { throw FormatException("Invalid Payload or PayloadLength"); } return message; } // 根据不同payloadType序列化对应的payload结构体 static dynamic _handlePayLoad({ required int payloadType, required int messageType, required Uint8List byte, int? offset, int? PayloadLength, int? spTotal, int? spIndex, int? messageId, }) { try { // 构造工厂 final ScpMessageHandler handler = ScpMessageHandlerFactory.createHandler(payloadType); // 处理荷载信息并返回 return handler.deserializePayload( payloadType: payloadType, messageType: messageType, byte: byte, offset: offset, PayloadLength: PayloadLength, spTotal: spTotal, spIndex: spIndex, messageId: messageId, ); } catch (e, stackTrace) { // 打印异常信息 _log(text: '❌反序列化udp数据时遇到错误----》$e'); // 打印堆栈跟踪信息 _log(text: '堆栈跟踪:\n$stackTrace'); return ''; } } static String bytesToHex(List bytes) { return bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(''); } // 辅助函数:将16进制字符串转换为字节数组 static List hexToBytes(String hexString) { final bytes = []; for (int i = 0; i < hexString.length; i += 2) { final hexByte = hexString.substring(i, i + 2); bytes.add(int.parse(hexByte, radix: 16)); } return bytes; } static void _log({required String text}) { AppLog.log('=====${text}'); } }