zsh_root
2025-12-10 8d662de2fd262b3a485f16e197cb4d0ca2a61cdf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package jiexi;
import java.util.Arrays;
public class Dell55AA01Parser {
    // 常量定义
    private static final String EXPECTED_HEADER = "55AA01"; // 协议头
    private static final int MIN_LENGTH = 42; // 最小长度(21字节*2字符)
    private static final ThreadLocal<ParseResult> RESULT_CACHE = 
            ThreadLocal.withInitial(ParseResult::new);
 
    // 解析结果类
    public static class ParseResult {
        public int sequenceNum;   // 序列号
        public String tagId;      // 标签ID(4字节小端序)
        public String anchorId;   // 锚点ID(4字节小端序)
        public int distance;      // 距离(毫米)
        public int power;         // 电量(0-100)
        public int buttonPressed; // 按钮状态
        public boolean buttonPressed2;
        public void reset() {
            sequenceNum = 0;
            tagId = "";
            anchorId = "";
            distance = 0;
            power = 0;
            buttonPressed = 0;
            buttonPressed2=false;
        }
    }
 
    /**
     * 解析55AA01协议数据
     * @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 || cleanedMessage.length < MIN_LENGTH) {
            return null;
        }
 
        // 协议头校验 (55AA01)
        if (!new String(cleanedMessage, 0, 6).equals(EXPECTED_HEADER)) {
            return null;
        }
 
        ParseResult result = RESULT_CACHE.get();
        result.reset();
 
        try {
            if (cleanedMessage.length < 30) { // 确保有足够长度访问charAt(28)
                return null;
            }
 
            // 解析序列号 (位置8-9)
            result.sequenceNum = HexUtils.fastHexToByte(cleanedMessage[8], cleanedMessage[9]);
 
            // 解析标签ID (位置10-13, 小端序)
            result.tagId = new String(new char[]{
                    cleanedMessage[12], cleanedMessage[13], // 高位
                    cleanedMessage[10], cleanedMessage[11]  // 低位
            });
 
            // 解析锚点ID (位置14-17, 小端序)
            result.anchorId = new String(new char[]{
                    cleanedMessage[16], cleanedMessage[17], // 高位
                    cleanedMessage[14], cleanedMessage[15]  // 低位
            });
 
            // 解析距离 (位置18-25, 4字节小端整数)
            int b0 = HexUtils.fastHexToByte(cleanedMessage[18], cleanedMessage[19]); // 最低位
            int b1 = HexUtils.fastHexToByte(cleanedMessage[20], cleanedMessage[21]);
            int b2 = HexUtils.fastHexToByte(cleanedMessage[22], cleanedMessage[23]);
            int b3 = HexUtils.fastHexToByte(cleanedMessage[24], cleanedMessage[25]); // 最高位
            int raw = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
            result.distance = raw; // 保持原始整数值
 
            // 解析电量 (位置26-27)
            result.power = HexUtils.fastHexToByte(cleanedMessage[26], cleanedMessage[27]);
 
            // 解析按钮状态 (位置28-29)
            result.buttonPressed = HexUtils.fastHexToByte(cleanedMessage[28], cleanedMessage[29]);
            result.buttonPressed2 =result.buttonPressed==1;         
 
        } catch (IndexOutOfBoundsException | NumberFormatException e) {
            System.err.println("Parsing error in packet from " + ip + ":" + port);
            return null;
        }
 
        return result;
    }
 
    private static char[] cleanMessage(String message) {
        char[] cleaned = new char[message.length()];
        int j = 0;
        for (char c : message.toCharArray()) {
            if (Character.isDigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) {
                cleaned[j++] = Character.toUpperCase(c);
            }
        }
        if (j == 0) return null;
        return Arrays.copyOf(cleaned, j);
    }
    
}