466 lines
16 KiB
Dart
Raw Normal View History

2024-11-28 14:57:49 +08:00
import 'dart:convert';
import 'package:star_lock/app_settings/app_settings.dart';
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/entity/heartbeat_response.dart';
import 'package:star_lock/talk/startChart/entity/login_response.dart';
import 'package:star_lock/talk/startChart/proto/ble_message.pb.dart';
import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart';
import 'package:star_lock/talk/startChart/proto/gateway_transfer.pb.dart';
import 'package:star_lock/talk/startChart/proto/generic.pb.dart';
import 'package:star_lock/talk/startChart/proto/remote_unlock.pb.dart';
import 'package:star_lock/talk/startChart/proto/talk_accept.pbserver.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_push.pbserver.dart';
import 'package:star_lock/talk/startChart/proto/talk_receiver_transfer.pb.dart';
import 'package:star_lock/talk/startChart/proto/talk_reject.pb.dart';
import 'package:star_lock/talk/startChart/proto/talk_request.pb.dart';
2024-11-28 14:57:49 +08:00
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表示
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
}
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) {
2024-11-28 14:57:49 +08:00
bytes.addAll(utf8.encode(Payload!));
} else {
// 如果不是字符串则需要外部转为字节数组,这里直接添加
bytes.addAll(Payload);
2024-11-28 14:57:49 +08:00
}
// 转16进制字符串
final bytesToHexString = bytesToHex(bytes);
return bytesToHexString;
}
static ScpMessage deserialize(List<int> bytes) {
final message = ScpMessage();
int offset = 0;
// 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!);
// print('sublist:$sublist');
offset += message.PayloadLength!;
message.Payload = _handlePayLoad(
payloadType: message.PayloadType ?? 0,
messageType: message.MessageType ?? 0,
byte: sublist,
offset: offset,
PayloadLength: message.PayloadLength,
);
} else {
throw FormatException("Invalid Payload or PayloadLength");
}
return message;
}
2024-11-28 14:57:49 +08:00
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;
}
// 根据不同payloadType序列化对应的payload结构体
static dynamic _handlePayLoad({
required int payloadType,
required int messageType,
required List<int> byte,
int? offset,
int? PayloadLength,
}) {
try {
switch (payloadType) {
case PayloadTypeConstant.goOnline:
// 上线
LoginResponse loginResp = LoginResponse.fromBytes(byte);
return loginResp;
case PayloadTypeConstant.heartbeat:
// 心跳
HeartbeatResponse heartbeatResponse =
HeartbeatResponse.fromBytes(byte);
return heartbeatResponse;
case PayloadTypeConstant.echoTest:
// 回声测试
String payload = utf8.decode(byte);
return payload;
case PayloadTypeConstant.gatewayReset:
// 初始化网关
if (messageType == MessageTypeConstant.Resp) {
final GatewayResetResp gatewayResetResp =
GatewayResetResp.fromBuffer(byte);
return gatewayResetResp;
} else if (messageType == MessageTypeConstant.Req) {
final GatewayResetReq gatewayResetReq =
GatewayResetReq.fromBuffer(byte);
return gatewayResetReq;
} else {
String payload = utf8.decode(byte);
return payload;
}
case PayloadTypeConstant.callRequest:
if (messageType == MessageTypeConstant.Resp) {
final GenericResp genericResp = GenericResp.fromBuffer(byte);
return genericResp;
} else if (messageType == MessageTypeConstant.Req) {
final TalkReq talkReq = TalkReq.fromBuffer(byte);
return talkReq;
} else {
String payload = utf8.decode(byte);
return payload;
}
case PayloadTypeConstant.talkAccept:
if (messageType == MessageTypeConstant.Resp) {
final GenericResp genericResp = GenericResp.fromBuffer(byte);
return genericResp;
} else if (messageType == MessageTypeConstant.Req) {
final TalkAcceptReq talkAccept = TalkAcceptReq.fromBuffer(byte);
return talkAccept;
} else {
String payload = utf8.decode(byte);
return payload;
}
case PayloadTypeConstant.gatewayTransfer:
if (messageType == MessageTypeConstant.Resp) {
final GenericResp genericResp = GenericResp.fromBuffer(byte);
return genericResp;
} else if (messageType == MessageTypeConstant.Req) {
final GatewayTransferReq gatewayTransferReq =
GatewayTransferReq.fromBuffer(byte);
return gatewayTransferReq;
} else {
String payload = utf8.decode(byte);
return payload;
}
case PayloadTypeConstant.blePassthrough:
final BleResp bleResp = BleResp.fromBuffer(byte);
return bleResp;
case PayloadTypeConstant.remoteUnlock:
if (messageType == MessageTypeConstant.Resp) {
final GenericResp genericResp = GenericResp.fromBuffer(byte);
return genericResp;
} else if (messageType == MessageTypeConstant.Req) {
final RemoteUnlockResp remoteUnlockResp =
RemoteUnlockResp.fromBuffer(byte);
return remoteUnlockResp;
} else {
String payload = utf8.decode(byte);
return payload;
}
case PayloadTypeConstant.talkReceiverTransfer:
if (messageType == MessageTypeConstant.Resp) {
final GenericResp genericResp = GenericResp.fromBuffer(byte);
return genericResp;
} else if (messageType == MessageTypeConstant.Req) {
final TalkReceiverTransfer talkReceiverTransfer =
TalkReceiverTransfer.fromBuffer(byte);
return talkReceiverTransfer;
} else {
String payload = utf8.decode(byte);
return payload;
}
case PayloadTypeConstant.talkPush:
if (messageType == MessageTypeConstant.Resp) {
final GenericResp genericResp = GenericResp.fromBuffer(byte);
return genericResp;
} else if (messageType == MessageTypeConstant.Req) {
final TalkPush talkPush = TalkPush.fromBuffer(byte);
return talkPush;
} else {
String payload = utf8.decode(byte);
return payload;
}
case PayloadTypeConstant.talkReject:
if (messageType == MessageTypeConstant.Resp) {
final GenericResp genericResp = GenericResp.fromBuffer(byte);
return genericResp;
} else if (messageType == MessageTypeConstant.Req) {
final TalkReject talkReject = TalkReject.fromBuffer(byte);
return talkReject;
} else {
String payload = utf8.decode(byte);
return payload;
}
case PayloadTypeConstant.talkPing:
if (messageType == MessageTypeConstant.Resp) {
final GenericResp genericResp = GenericResp.fromBuffer(byte);
return genericResp;
} else if (messageType == MessageTypeConstant.Req) {
final TalkPing talkPing = TalkPing.fromBuffer(byte);
return talkPing;
} else {
String payload = utf8.decode(byte);
return payload;
}
case PayloadTypeConstant.talkExpect:
if (messageType == MessageTypeConstant.Resp) {
final GenericResp genericResp = GenericResp.fromBuffer(byte);
return genericResp;
} else if (messageType == MessageTypeConstant.Req) {
final TalkExpect talkExpect = TalkExpect.fromBuffer(byte);
return talkExpect;
} else {
String payload = utf8.decode(byte);
return payload;
}
case PayloadTypeConstant.talkData:
if (messageType == MessageTypeConstant.Resp) {
final GenericResp genericResp = GenericResp.fromBuffer(byte);
return genericResp;
} else if (messageType == MessageTypeConstant.RealTimeData) {
final TalkData talkData = TalkData.fromBuffer(byte);
return talkData;
} else {
String payload = utf8.decode(byte);
return payload;
}
case PayloadTypeConstant.talkHangup:
if (messageType == MessageTypeConstant.Resp) {
final GenericResp genericResp = GenericResp.fromBuffer(byte);
return genericResp;
} else if (messageType == MessageTypeConstant.RealTimeData) {
final TalkHangup talkHangup = TalkHangup.fromBuffer(byte);
return talkHangup;
} else {
String payload = utf8.decode(byte);
return payload;
}
default:
print('❌未知的payloadType类型,按照字符串解析');
String payload = utf8.decode(byte);
return payload;
}
} catch (e) {
_log(text: '❌反序列化udp数据时遇到错误----》$e');
String payload = utf8.decode(byte);
return payload;
}
}
static void _log({required String text}) {
AppLog.log('=====${text}');
}
2024-11-28 14:57:49 +08:00
}