package com.jsowell.netty.domain; import com.jsowell.common.YouDianUtils; import com.jsowell.common.util.BytesUtil; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import java.nio.charset.StandardCharsets; import java.util.Arrays; @Slf4j @Data @NoArgsConstructor @AllArgsConstructor @Builder public class EBikeMessage { private String header; // 包头 (3字节) private int length; // 长度 (2字节) private int physicalId; // 物理ID (4字节) private int messageId; // 消息ID (2字节) private String command; // 命令 (1字节) private byte[] data; // 数据 (n字节) private int checksum; // 校验 (2字节) @Override public String toString() { return new ToStringBuilder(this, ToStringStyle.JSON_STYLE) .append("header", header) .append("length", length) .append("physicalId", physicalId) .append("messageId", messageId) .append("command", command) .append("data", data) .append("checksum", checksum) .toString(); } public static EBikeMessage parseMessage(byte[] messageBytes) { if (messageBytes == null || messageBytes.length < 14 || messageBytes.length > 256) { throw new IllegalArgumentException("Invalid message bytes"); } EBikeMessage message = new EBikeMessage(); try { // 读取包头 byte[] headerBytes = Arrays.copyOfRange(messageBytes, 0, 3); String header = new String(headerBytes, StandardCharsets.UTF_8); message.setHeader(header); // 读取长度 byte[] lengthBytes = Arrays.copyOfRange(messageBytes, 3, 5); int length = BytesUtil.bytesToIntLittle(lengthBytes); message.setLength(length); // 验证长度 if (length != (messageBytes.length - 5)) { throw new IllegalArgumentException("Invalid message length"); } // 读取物理ID byte[] physicalIdBytes = Arrays.copyOfRange(messageBytes, 5, 9); int physicalId = BytesUtil.bytesToIntLittle(physicalIdBytes); message.setPhysicalId(physicalId); // 读取消息ID byte[] messageIdBytes = Arrays.copyOfRange(messageBytes, 9, 11); int messageId = BytesUtil.bytesToIntLittle(messageIdBytes); message.setMessageId(messageId); // 读取命令 byte commandByte = messageBytes[11]; String command = BytesUtil.bcd2StrLittle(new byte[]{commandByte}); message.setCommand(command); // 读取数据 byte[] dataBytes = Arrays.copyOfRange(messageBytes, 12, messageBytes.length - 2); message.setData(dataBytes); String data = BytesUtil.bcd2StrLittle(dataBytes); // 读取校验 byte[] checksumBytes = Arrays.copyOfRange(messageBytes, messageBytes.length - 2, messageBytes.length); int checksum = BytesUtil.bytesToIntLittle(checksumBytes); message.setChecksum(checksum); // 校验码验证 if (!YouDianUtils.validateChecksum(messageBytes)) { throw new IllegalArgumentException("Checksum validation failed"); } log.info("报文:{}, parseMessage:{}", BytesUtil.binary(messageBytes, 16), message.toString()); return message; } catch (Exception e) { log.error("Error parsing message", e); throw e; } } }