app-starlock/lib/talk/starChart/entity/scp_message.dart

411 lines
12 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/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';
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}';
}
// 辅助函数:定长字符串编码
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;
}
}
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字节)
if (FromPeerId != null) {
bytes.addAll(utf8.encode(FromPeerId!));
}
// FromPeerId (44字节定长)
// bytes.addAll(encodeFixedLengthString(FromPeerId, 44));
// ToPeerId (字符串长度固定为44字节)
if (ToPeerId != null) {
bytes.addAll(utf8.encode(ToPeerId!));
}
// ToPeerId (44字节定长)
// bytes.addAll(encodeFixedLengthString(ToPeerId, 44));
// 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();
final length = bytes.length;
int offset = 0;
// 提前检查字节数组长度是否足够
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)
message.ProtocolFlag = utf8.decode(bytes.sublist(offset, offset + 4));
offset += 4;
// MessageType (1 byte)
message.MessageType = bytes[offset];
offset += 1;
// MessageId (2 bytes, little-endian)
message.MessageId = byteData.getUint16(offset, Endian.little);
offset += 2;
// SpTotal (1 byte)
message.SpTotal = bytes[offset];
offset += 1;
// SpIndex (1 byte)
message.SpIndex = bytes[offset];
offset += 1;
// FromPeerId (44 bytes)
message.FromPeerId =
utf8.decode(bytes.sublist(offset, offset + 44)).trimRight();
offset += 44;
// ToPeerId (44 bytes)
message.ToPeerId =
utf8.decode(bytes.sublist(offset, offset + 44)).trimRight();
offset += 44;
// PayloadType (2 bytes, little-endian)
message.PayloadType = byteData.getUint16(offset, Endian.little);
offset += 2;
// PayloadCRC (2 bytes, little-endian)
message.PayloadCRC = byteData.getUint16(offset, Endian.little);
offset += 2;
// PayloadLength (4 bytes, little-endian)
message.PayloadLength = byteData.getUint32(offset, Endian.little);
offset += 4;
// 检查 Payload 长度是否有效
if (message.PayloadLength == null ||
length - offset < message.PayloadLength!) {
throw FormatException("Invalid Payload or PayloadLength");
}
// 处理 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;
}
// 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;
} 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}');
}
}