Pu Zhibing
2025-03-07 297512bc22b179b7038d96a1ff033eceaed38c4b
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
package com.ruoyi.dataInterchange.util.jtt809.common;
 
import io.netty.buffer.ByteBuf;
import lombok.extern.slf4j.Slf4j;
 
import java.nio.charset.Charset;
import java.util.Arrays;
 
/**
 * @author tucke
 */
@Slf4j
public class Jtt809Util {
 
    /**
     * 0x5B, 0x5A, 0x5D, 0x5E 转义处理
     */
    public static byte[] escape(byte[] bytes) {
        // 最极端情况,每个byte都需要转义,所以使用2倍长度
        byte[] result = new byte[bytes.length * 2];
        int i = 0;
        for (byte b : bytes) {
            switch (b) {
                case 0x5B:
                    result[i++] = 0x5A;
                    result[i++] = 0x01;
                    break;
                case 0x5A:
                    result[i++] = 0x5A;
                    result[i++] = 0x02;
                    break;
                case 0x5D:
                    result[i++] = 0x5E;
                    result[i++] = 0x01;
                    break;
                case 0x5E:
                    result[i++] = 0x5E;
                    result[i++] = 0x02;
                    break;
                default:
                    result[i++] = b;
            }
        }
        // 截取转义后的数据并返回
        return Arrays.copyOf(result, i);
    }
 
    /**
     * 0x5B, 0x5A, 0x5D, 0x5E 反转义处理
     */
    public static byte[] unescape(byte[] bytes) {
        if (bytes == null || bytes.length <= 1) {
            return bytes;
        }
        // 最极端情况,每个byte都不需要反转义,所以使用1倍长度
        byte[] result = new byte[bytes.length];
        int ii = 0;
        for (int i = 0; i < bytes.length; i++) {
            // 当前循环的 byte 数据
            byte curr = bytes[i];
            // 若最后一条 byte 数据还能进入循环,则它必定不满足反转义
            if (i == bytes.length - 1) {
                result[ii++] = curr;
                break;
            }
            // 下一条 byte 数据
            byte next = bytes[i + 1];
            if (curr == 0x5A) {
                // 将 0x5A 0x01 反转义为 0x5B,且下一条数据 0x01 不需要参与循环
                if (next == 0x01) {
                    result[ii++] = 0x5B;
                    i++;
                    continue;
                }
                // 0x5A 0x02 反转义结果就是 0x5A,且下一条数据 0x02 不需要参与循环
                if (next == 0x02) {
                    i++;
                }
            }
            if (curr == 0x5E) {
                // 将 0x5E 0x01 反转义为 0x5D,且下一条数据 0x01 不需要参与循环
                if (next == 0x01) {
                    result[ii++] = 0x5D;
                    i++;
                    continue;
                }
                // 0x5E 0x02 反转义结果就是 0x5E,且下一条数据 0x02 不需要参与循环
                if (next == 0x02) {
                    i++;
                }
            }
            result[ii++] = curr;
        }
        // 截取反转义后的数据并返回
        return Arrays.copyOf(result, ii);
    }
 
    /**
     * 消息校验
     */
    public static boolean validate(ByteBuf byteBuf) {
        int len = byteBuf.readableBytes();
        byte[] bytes = new byte[len - 2];
        byteBuf.getBytes(2, bytes);
        int calc = CRC16CCITT.crc16(bytes);
        int code = byteBuf.getUnsignedShort(len - 2);
        boolean result = calc == code;
        if (!result) {
            log.warn("CRC校验失败!计算结果为:{}, 传入值为:{}", calc, code);
        }
        return result;
    }
 
    /**
     * 加密
     */
    public static byte[] encrypt(int m1, int ia1, int ic1, long key, byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        if (key == 0) {
            key = 1;
        }
        for (int i = 0; i < bytes.length; i++) {
            key = ia1 * (key % m1) + ic1;
            bytes[i] ^= ((key >> 20) & 0xFF);
        }
        return bytes;
    }
 
    /**
     * 解密
     */
    public static byte[] decrypt(int m1, int ia1, int ic1, long key, byte[] bytes) {
        return encrypt(m1, ia1, ic1, key, bytes);
    }
 
    /**
     * 解析字符串
     *
     * @param complement 是否考虑右边补零的情况
     */
    public static String readString(ByteBuf byteBuf, int length, Charset charset, boolean complement) {
        // 是否考虑右补十六进制 0x00
        if (complement) {
            byte[] bytes = new byte[length];
            byteBuf.readBytes(bytes);
            int len = 0;
            for (int i = bytes.length; i > 0; i--) {
                if (bytes[i - 1] != 0x00) {
                    len = i;
                    break;
                }
            }
            return new String(Arrays.copyOf(bytes, len), charset);
        } else {
            return byteBuf.readBytes(length).toString(charset);
        }
    }
 
    /**
     * 解析GBK字符串
     *
     * @param complement 是否考虑右边补零的情况
     */
    public static String readGBKString(ByteBuf byteBuf, int length, boolean complement) {
        return readString(byteBuf, length, Charset.forName("GBK"), complement);
    }
 
    /**
     * 解析GBK字符串
     */
    public static String readGBKString(ByteBuf byteBuf, int length) {
        return readGBKString(byteBuf, length, true);
    }
 
}