320 lines
9.1 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<String, dynamic> 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 = <int>[];
// 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<int> bytes) {
return bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join('');
}
// 辅助函数将16进制字符串转换为字节数组
static List<int> hexToBytes(String hexString) {
final bytes = <int>[];
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}');
}
}