469 lines
16 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 'package:crc32_checksum/crc32_checksum.dart';
import 'package:crypto/crypto.dart';
import 'package:get/get.dart';
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';
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 {
// 如果不是字符串则需要外部转为字节数组,这里直接添加
bytes.addAll(Payload);
}
// 转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;
}
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}');
}
}