411 lines
12 KiB
Dart
Raw Permalink Normal View History

2024-11-28 14:57:49 +08:00
import 'dart:convert';
import 'dart:typed_data';
2024-11-28 14:57:49 +08:00
import 'package:star_lock/app_settings/app_settings.dart';
2025-01-23 14:30:31 +08:00
import 'package:star_lock/talk/starChart/exception/start_chart_message_exception.dart';
import 'package:star_lock/talk/starChart/handle/impl/udp_heart_beat_handler.dart';
import 'package:star_lock/talk/starChart/handle/scp_message_handle.dart';
import 'package:star_lock/talk/starChart/handle/scp_message_handler_factory.dart';
2024-11-28 14:57:49 +08:00
class ScpMessage {
2024-11-28 14:57:49 +08:00
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表示
2024-11-28 14:57:49 +08:00
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}';
2024-11-28 14:57:49 +08:00
}
// 辅助函数:定长字符串编码
List<int> encodeFixedLengthString(String? str, int length) {
final bytes = utf8.encode(str ?? '');
if (bytes.length > length) {
return bytes.sublist(0, length);
} else if (bytes.length < length) {
return bytes + List.filled(length - bytes.length, 0);
} else {
return bytes;
}
}
2024-11-28 14:57:49 +08:00
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 (字符串长度固定为44字节)
2024-11-28 14:57:49 +08:00
if (FromPeerId != null) {
bytes.addAll(utf8.encode(FromPeerId!));
}
// FromPeerId (44字节定长)
// bytes.addAll(encodeFixedLengthString(FromPeerId, 44));
2024-11-28 14:57:49 +08:00
// ToPeerId (字符串长度固定为44字节)
2024-11-28 14:57:49 +08:00
if (ToPeerId != null) {
bytes.addAll(utf8.encode(ToPeerId!));
}
// ToPeerId (44字节定长)
// bytes.addAll(encodeFixedLengthString(ToPeerId, 44));
2024-11-28 14:57:49 +08:00
// 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) {
2024-11-28 14:57:49 +08:00
bytes.addAll(utf8.encode(Payload!));
} else if (Payload != null) {
// 如果不是字符串则需要外部转为字节数组,这里直接添加
bytes.addAll(Payload);
2024-11-28 14:57:49 +08:00
}
// 转16进制字符串
final bytesToHexString = bytesToHex(bytes);
return bytesToHexString;
}
static ScpMessage deserialize(Uint8List bytes) {
final message = ScpMessage();
2025-01-20 16:21:41 +08:00
final length = bytes.length;
int offset = 0;
2025-01-20 16:21:41 +08:00
// 提前检查字节数组长度是否足够
if (length < 4 + 1 + 2 + 1 + 1 + 44 + 44 + 2 + 2 + 4) {
throw FormatException("Invalid message length");
}
// 使用 ByteData 读取多字节数据
final byteData = ByteData.sublistView(bytes);
// ProtocolFlag (4 bytes)
2025-01-20 16:21:41 +08:00
message.ProtocolFlag = utf8.decode(bytes.sublist(offset, offset + 4));
offset += 4;
// MessageType (1 byte)
2025-01-20 16:21:41 +08:00
message.MessageType = bytes[offset];
offset += 1;
// MessageId (2 bytes, little-endian)
2025-01-20 16:21:41 +08:00
message.MessageId = byteData.getUint16(offset, Endian.little);
offset += 2;
// SpTotal (1 byte)
2025-01-20 16:21:41 +08:00
message.SpTotal = bytes[offset];
offset += 1;
// SpIndex (1 byte)
2025-01-20 16:21:41 +08:00
message.SpIndex = bytes[offset];
offset += 1;
2025-01-20 16:21:41 +08:00
// FromPeerId (44 bytes)
message.FromPeerId =
utf8.decode(bytes.sublist(offset, offset + 44)).trimRight();
offset += 44;
2025-01-20 16:21:41 +08:00
// ToPeerId (44 bytes)
message.ToPeerId =
utf8.decode(bytes.sublist(offset, offset + 44)).trimRight();
offset += 44;
// PayloadType (2 bytes, little-endian)
2025-01-20 16:21:41 +08:00
message.PayloadType = byteData.getUint16(offset, Endian.little);
offset += 2;
// PayloadCRC (2 bytes, little-endian)
2025-01-20 16:21:41 +08:00
message.PayloadCRC = byteData.getUint16(offset, Endian.little);
offset += 2;
// PayloadLength (4 bytes, little-endian)
2025-01-20 16:21:41 +08:00
message.PayloadLength = byteData.getUint32(offset, Endian.little);
offset += 4;
2025-01-20 16:21:41 +08:00
// 检查 Payload 长度是否有效
if (message.PayloadLength == null ||
length - offset < message.PayloadLength!) {
throw FormatException("Invalid Payload or PayloadLength");
}
2025-01-20 16:21:41 +08:00
// 处理 Payload
final payloadBytes = bytes.sublist(offset, offset + message.PayloadLength!);
offset += message.PayloadLength!;
message.Payload = _handlePayLoad(
payloadType: message.PayloadType ?? 0,
messageType: message.MessageType ?? 0,
byte: payloadBytes,
offset: offset,
PayloadLength: message.PayloadLength,
spIndex: message.SpIndex,
spTotal: message.SpTotal,
messageId: message.MessageId,
);
return message;
}
2025-01-20 16:21:41 +08:00
// static ScpMessage deserialize(Uint8List bytes) {
// final message = ScpMessage();
// int offset = 0;
//
// // String hexString =
// // bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join();
// // // _log(text: 'result bytes hex: ${hexString}');
// // _log(
// // text:
// // '\n result bytes hex: ${hexString} \n payload hex: ${hexString.substring(210)}');
//
// // 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 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 List<int> byte,
int? offset,
int? PayloadLength,
int? spTotal,
int? spIndex,
int? messageId,
}) {
try {
// 构造工厂
final ScpMessageHandler handler =
ScpMessageHandlerFactory.createHandler(payloadType);
// 处理荷载信息并返回
final payload = handler.deserializePayload(
payloadType: payloadType,
messageType: messageType,
byte: byte,
offset: offset,
PayloadLength: PayloadLength,
spTotal: spTotal,
spIndex: spIndex,
messageId: messageId,
);
return payload;
2024-12-23 15:21:48 +08:00
} catch (e, stackTrace) {
throw StartChartMessageException('❌反序列化udp数据时遇到错误----》$e \n$stackTrace');
}
}
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}');
}
2024-11-28 14:57:49 +08:00
}