wjc
2025-01-07 90d5f028ccdaaaf64286f9d632cb335a4d0544b9
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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
package com.hdl.sdk.link.core.utils;
 
import com.hdl.sdk.link.common.utils.LogUtils;
import com.hdl.sdk.link.core.bean.BusProRequest;
 
import java.util.HashMap;
import java.util.Map;
 
/**
 * buspro协议工具类
 * Created by hxb on 2024/3/25.
 */
public class BusProUtils {
 
    //HDLMIRACLE的值
    static final byte[] matchHdlBytes = new byte[]{'H','D','L','M','I','R','A','C','L','E'};
 
    /**
     * 操作码对应匹配回复数据的索引,主要为了实现数据发送后能正常回调,Byte[]是附加数据的偏移量
     */
    private static final HashMap<String, Byte[]> matchIndex = new HashMap();
 
    static final String TAG = "BusProUtils";
 
    /**
     * 本设备子网号,默认值99
     */
    private static byte sourceSubnetId = 99;
    /**
     * 本设备设备号,默认值99
     */
    private static byte sourceDeviceId = 99;
    /**
     * 本设备设备类型,默认0xFEFE
     */
    private static byte[] deviceType = new byte[]{(byte) 0xFE, (byte) 0xFE};
 
    /**
     * 获取本地设备Id
     *
     * @return
     */
    public static byte getSourceSubnetId() {
        return sourceSubnetId;
    }
 
    /**
     * 设置本地设备Id
     */
    public static void setSourceSubnetId(byte sourceSubnetId) {
        BusProUtils.sourceSubnetId = sourceSubnetId;
    }
 
    /**
     * 获取本地设备Id
     */
    public static byte getSourceDeviceId() {
        return sourceDeviceId;
    }
 
    /**
     * 设置本地设备Id
     */
    public static void setSourceDeviceId(byte sourceDeviceId) {
        BusProUtils.sourceDeviceId = sourceDeviceId;
    }
 
    /**
     * 获取设备类型
     */
    public static byte[] getDeviceType() {
        return deviceType;
    }
 
    /**
     * 设置设备类型
     *
     * @param deviceType
     */
    public static void setDeviceType(byte[] deviceType) {
        BusProUtils.deviceType = deviceType;
    }
 
    /**
     * 是否buspro数据格式
     *
     * @param bytes bus协议每条数据
     * @return true表示是bus协议数据,false表示不是
     */
    public static boolean isBusProBytes(byte[] bytes) {
        //类似接收到以下数据 C0 A8 01 66 48 44 4C 4D 49 52 41 43 4C 45 AA AA 0B FD FE FF FE 00 0E FF FF A0 0D
        if (bytes == null || bytes.length < 27) {//最小的buspro数据包大小为27个byte
            return false;
        }
 
        for (int i = 0; i < matchHdlBytes.length; i++) {
            //HDLMIRACLE是从接收数据的索引4开始,前面4位是IP地址
            if (matchHdlBytes[i] != bytes[4 + i]) {
                return false;
            }
        }
        return true;
    }
 
    /**
     * 通过请求对象获取发送数据
     *
     * @param busProRequest bus协议的封装数据
     * @return 最终发出去的bus数据
     */
    public static byte[] getBusBytes(BusProRequest busProRequest) {
        if (busProRequest == null) {
            return null;
        }
        byte[] extraBytes = busProRequest.getExtraBytes();
        if (extraBytes == null) {
            LogUtils.i(TAG, "附加数据为null");
        }
        // 要计算CRC的数据和CRC两个字节
        byte[] crcBytes = new byte[9 + extraBytes.length + 2];
 
        // 发送出去的数据
        byte[] sendBytes = new byte[16 + crcBytes.length];
 
//        String[] ip = Net.CurrentNet.getPsdnIp().split("\\.");
//        // IP地址
//        sendBytes[0] = (byte) Global.GetStringToInteger(ip[0]);
//        sendBytes[1] = (byte) Global.GetStringToInteger(ip[1]);
//        sendBytes[2] = (byte) Global.GetStringToInteger(ip[2]);
//        sendBytes[3] = (byte) Global.GetStringToInteger(ip[3]);
 
        // HDLMIRACLE
        sendBytes[4] = (byte) 'H';
        sendBytes[5] = (byte) 'D';
        sendBytes[6] = (byte) 'L';
        sendBytes[7] = (byte) 'M';
        sendBytes[8] = (byte) 'I';
        sendBytes[9] = (byte) 'R';
        sendBytes[10] = (byte) 'A';
        sendBytes[11] = (byte) 'C';
        sendBytes[12] = (byte) 'L';
        sendBytes[13] = (byte) 'E';
        // 引导码
        sendBytes[14] = (byte) 0xAA;
        sendBytes[15] = (byte) 0xAA;
 
        // 16 数据包长度 11-78
        crcBytes[0] = (byte) crcBytes.length;
        // 17 源子网地址 0-254
        crcBytes[1] = sourceSubnetId;
        // 18 源设备地址 0-254
        crcBytes[2] = sourceDeviceId;
        byte[] deviceType = getDeviceType();
        if (deviceType == null || deviceType.length < 2) {
            LogUtils.i(TAG, "设备类型为null或者长度小于2");
        }
        // 19 源设备类型高位
        crcBytes[3] = deviceType[0];
        // 20 源设备类型低位
        crcBytes[4] = deviceType[1];
 
        byte[] command = busProRequest.getCommand();
        if (command == null || command.length < 2) {
            LogUtils.i(TAG, "操作码为null或者长度小于2");
        }
        // 21 操作码高位
        crcBytes[5] = busProRequest.getCommand()[0];
        // 22 操作码低位
        crcBytes[6] = busProRequest.getCommand()[1];
        // 23 目标子网地址 0-254
        crcBytes[7] = busProRequest.getDesSubnetId();
        // 24 目标设备地址 0-254
        crcBytes[8] = busProRequest.getDesDeviceId();
        // 25~n附加数据
        System.arraycopy(extraBytes, 0, crcBytes, 9, extraBytes.length);
        // CRC校验
        CRCUtil.ConCRC(crcBytes, crcBytes.length - 2);
 
        // 复制CRC数据到发送数据里面
        System.arraycopy(crcBytes, 0, sendBytes, 16, crcBytes.length);
 
        return sendBytes;
    }
 
    /**
     * 根据操作码动态获取匹配数据
     * @param subnetId 子网号
     * @param deviceId 设备号
     * @param command  操作码
     * @param extraBytes 发送或者接收到的附加数据
     * @return
     */
    public static String getMatchString(byte subnetId, byte deviceId, byte[] command, byte[] extraBytes) {
        String commandString=ByteUtils.encodeHexString(command);
        String result = String.format("BusPro_%s%s%s", ByteUtils.encodeHexString(subnetId), ByteUtils.encodeHexString(deviceId), commandString);
        Byte[] value = matchIndex.get(commandString);
        if (value != null) {
            //value[i]是附加数据偏移量,从0开始
            for (int i = 0; i < value.length; i++) {
                result += String.format("%s", ByteUtils.encodeHexString(extraBytes[value[i]]));
            }
        }
        return result;
    }
 
    public static void setMatchIndex(String key,Byte []value)
    {
        matchIndex.put(key,value);
    }
 
}