zsh_root
2025-12-10 8d662de2fd262b3a485f16e197cb4d0ca2a61cdf
src/jiexi/Dell55AA51Parser.java
@@ -3,27 +3,27 @@
import java.util.Arrays;
public class Dell55AA51Parser {
    // 预期包头
    // 预期包头
    private static final String EXPECTED_HEADER = "55AA51";
    private static final ThreadLocal<ParseResult> RESULT_CACHE = 
            ThreadLocal.withInitial(ParseResult::new);
    // 解析结果类
    // 解析结果类
    public static class ParseResult {
        public int dataLength;          // 数据长度(十进制)
        public String baseStationId;    // 基站ID(2字节,低位在前)
        public String tagId;            // 标签ID(2字节,低位在前)
        public int packetSequence;      // 包序(十进制)
        public int distance;            // 测距距离(十进制)
        public int horizontalAngle;     // 水平角度(十进制)
        public int verticalAngle;       // 俯仰角度(十进制,有符号)
        public int signalStrength;      // 信号强度(十进制)
        public int angleConfidence;     // 角度置信度(十进制)
        public int tagBattery;          // 标签电量(十进制)
        public int deviceStatus;        // 设备状态
        public int airPressure;         // 气压值(十进制)
        public String reserved;         // 保留字段
        public String checksum;         // 校验和
        public int dataLength;          // 数据长度(十进制)
        public String baseStationId;    // 基站ID(2字节,低位在前)
        public String tagId;            // 标签ID(2字节,低位在前)
        public int packetSequence;      // 包序(十进制)
        public int distance;            // 测距距离(十进制)
        public int horizontalAngle;     // 水平角度(十进制)
        public int verticalAngle;       // 俯仰角度(十进制,有符号)
        public int signalStrength;      // 信号强度(十进制)
        public int angleConfidence;     // 角度置信度(十进制)
        public int tagBattery;          // 标签电量(十进制)
        public int deviceStatus;        // 设备状态
        public int airPressure;         // 气压值(十进制)
        public String reserved;         // 保留字段
        public String checksum;         // 校验和
        
        public void reset() {
            dataLength = 0;
@@ -64,23 +64,23 @@
    }
    /**
     * 解析55AA51数据包
     * @param message 原始十六进制字符串
     * @return 解析结果(解析失败返回null)
     * 解析55AA51数据包
     * @param message 原始十六进制字符串
     * @return 解析结果(解析失败返回null)
     */
    public static ParseResult parse(String message, String ip, int port) {
        if (message == null || message.isEmpty()) {
            return null;
        }
        // 清理消息:移除非十六进制字符
        // 清理消息:移除非十六进制字符
        char[] cleanedMessage = cleanMessage(message);
        if (cleanedMessage == null) {
            return null;
        }
        // 检查包头 (55AA51)
        // 检查包头 (55AA51)
        if (cleanedMessage.length < 6 || 
            !new String(cleanedMessage, 0, 6).equals(EXPECTED_HEADER)) {
            return null;
@@ -90,14 +90,14 @@
        result.reset();
        try {
            // 解析数据长度 (位置6-7),转换为十进制
            // 解析数据长度 (位置6-7),转换为十进制
            result.dataLength = HexUtils.fastHexToByte(cleanedMessage[6], cleanedMessage[7]);
            
            // 计算期望的消息长度
            int expectedCharLength = 6 + // 包头(3字节)
                                    2 + // 数据长度(1字节)
                                    result.dataLength * 2 + // 数据内容
                                    4; // 校验和(2字节)
            // 计算期望的消息长度
            int expectedCharLength = 6 + // 包头(3字节)
                                    2 + // 数据长度(1字节)
                                    result.dataLength * 2 + // 数据内容
                                    4; // 校验和(2字节)
            if (cleanedMessage.length != expectedCharLength) {
                System.err.println("Data length mismatch: expected " + expectedCharLength + 
@@ -105,64 +105,64 @@
                return null;
            }
            // 解析基站ID (位置8-11,2字节,低位在前)
            // 解析基站ID (位置8-11,2字节,低位在前)
            int baseIdLow = HexUtils.fastHexToByte(cleanedMessage[8], cleanedMessage[9]);
            int baseIdHigh = HexUtils.fastHexToByte(cleanedMessage[10], cleanedMessage[11]);
            int baseIdValue = (baseIdHigh << 8) | baseIdLow;
            result.baseStationId = String.valueOf(baseIdValue); // 转换为十进制字符串
            result.baseStationId = String.valueOf(baseIdValue); // 转换为十进制字符串
            // 解析标签ID (位置12-15,2字节,低位在前)
            // 解析标签ID (位置12-15,2字节,低位在前)
            int tagIdLow = HexUtils.fastHexToByte(cleanedMessage[12], cleanedMessage[13]);
            int tagIdHigh = HexUtils.fastHexToByte(cleanedMessage[14], cleanedMessage[15]);
            int tagIdValue = (tagIdHigh << 8) | tagIdLow;
            result.tagId = String.valueOf(tagIdValue); // 转换为十进制字符串
            result.tagId = String.valueOf(tagIdValue); // 转换为十进制字符串
            // 解析包序 (位置16-17),转换为十进制
            // 解析包序 (位置16-17),转换为十进制
            result.packetSequence = HexUtils.fastHexToByte(cleanedMessage[16], cleanedMessage[17]);
            // 解析测距距离 (位置18-21,2字节,低位在前),转换为十进制
            // 解析测距距离 (位置18-21,2字节,低位在前),转换为十进制
            int distLow = HexUtils.fastHexToByte(cleanedMessage[18], cleanedMessage[19]);
            int distHigh = HexUtils.fastHexToByte(cleanedMessage[20], cleanedMessage[21]);
            result.distance = (distHigh << 8) | distLow;
            // 解析水平角度 (位置22-25,2字节,低位在前),转换为十进制
            // 解析水平角度 (位置22-25,2字节,低位在前),转换为十进制
            int hAngleLow = HexUtils.fastHexToByte(cleanedMessage[22], cleanedMessage[23]);
            int hAngleHigh = HexUtils.fastHexToByte(cleanedMessage[24], cleanedMessage[25]);
            result.horizontalAngle = (hAngleHigh << 8) | hAngleLow;
            // 解析俯仰角度 (位置26-29,2字节,低位在前),转换为十进制
            // 注意:这是有符号数,范围-180到180度
            // 解析俯仰角度 (位置26-29,2字节,低位在前),转换为十进制
            // 注意:这是有符号数,范围-180到180度
            int vAngleLow = HexUtils.fastHexToByte(cleanedMessage[26], cleanedMessage[27]);
            int vAngleHigh = HexUtils.fastHexToByte(cleanedMessage[28], cleanedMessage[29]);
            short vAngleShort = (short) ((vAngleHigh << 8) | vAngleLow);
            result.verticalAngle = vAngleShort;
            // 解析信号强度 (位置30-31),转换为十进制
            // 解析信号强度 (位置30-31),转换为十进制
            result.signalStrength = HexUtils.fastHexToByte(cleanedMessage[30], cleanedMessage[31]);
            // 解析角度置信度 (位置32-33),转换为十进制
            // 解析角度置信度 (位置32-33),转换为十进制
            result.angleConfidence = HexUtils.fastHexToByte(cleanedMessage[32], cleanedMessage[33]);
            // 解析标签电量 (位置34-35),转换为十进制
            // 解析标签电量 (位置34-35),转换为十进制
            result.tagBattery = HexUtils.fastHexToByte(cleanedMessage[34], cleanedMessage[35]);
            // 解析设备状态 (位置36-39,2字节,低位在前)
            // 解析设备状态 (位置36-39,2字节,低位在前)
            int statusLow = HexUtils.fastHexToByte(cleanedMessage[36], cleanedMessage[37]);
            int statusHigh = HexUtils.fastHexToByte(cleanedMessage[38], cleanedMessage[39]);
            result.deviceStatus = (statusHigh << 8) | statusLow;
            // 解析气压值 (位置40-43,2字节,低位在前),转换为十进制
            // 解析气压值 (位置40-43,2字节,低位在前),转换为十进制
            int pressureLow = HexUtils.fastHexToByte(cleanedMessage[40], cleanedMessage[41]);
            int pressureHigh = HexUtils.fastHexToByte(cleanedMessage[42], cleanedMessage[43]);
            result.airPressure = (pressureHigh << 8) | pressureLow;
            // 解析保留字段 (位置44-51,4字节)
            // 解析保留字段 (位置44-51,4字节)
            result.reserved = new String(cleanedMessage, 44, 8);
            // 解析校验和 (最后4个字符)
            // 解析校验和 (最后4个字符)
            result.checksum = new String(cleanedMessage, cleanedMessage.length - 4, 4);
            // 验证校验和
            // 验证校验和
            byte[] packetBytes = hexStringToByteArray(new String(cleanedMessage));
            if (!verifyChecksum(packetBytes)) {
                System.err.println("Checksum verification failed for packet from " + ip + ":" + port);
@@ -179,7 +179,7 @@
    }
    /**
     * 将十六进制字符串转换为字节数组
     * 将十六进制字符串转换为字节数组
     */
    private static byte[] hexStringToByteArray(String s) {
        int len = s.length();
@@ -192,21 +192,21 @@
    }
    /**
     * 验证数据包校验和
     * 从数据类型字段开始到保留字段结束,校验和为双字节补码
     * 验证数据包校验和
     * 从数据类型字段开始到保留字段结束,校验和为双字节补码
     */
    private static boolean verifyChecksum(byte[] packet) {
        int len = packet.length;
        if (len < 4) return false;
        int sum = 0;
        // 从数据类型字段开始到保留字段结束 (跳过包头2字节)
        // 从数据类型字段开始到保留字段结束 (跳过包头2字节)
        for (int i = 3; i < len - 2; i++) {
            sum += packet[i] & 0xFF;
        }
        sum = ~sum & 0xFFFF; // 取反并保留16位
        sum = ~sum & 0xFFFF; // 取反并保留16位
        // 获取接收到的校验和 (低位在前)
        // 获取接收到的校验和 (低位在前)
        int receivedChecksum = ((packet[len - 2] & 0xFF) << 8) | (packet[len - 1] & 0xFF);
        return sum == receivedChecksum;