严智鑫
2025-11-13 945bc394f40d8af1072a53da9a94f24207124e6d
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
package com.northglass.service.common;
 
import java.util.Date;
 
import org.slf4j.Logger;
 
import com.northglass.constants.ConnectState;
import com.northglass.constants.FunctionNumber;
import com.northglass.entity.AbstractMachine;
import com.northglass.log.GLoggerFactory;
import com.northglass.util.HexUtil;
 
public abstract class AbstractMessageProcessor {
 
    private static final Logger LOGGER = GLoggerFactory.getLogger(AbstractMessageProcessor.class);
    
    /**
     * 信息头,字符串“<STA>”的16进制表示
     */
    protected static final String HEAD = "3c5354413e";
    
    /**
     * 信息尾,字符串“<EOF>”的16进制表示
     */
    protected static final String END = "3c454f463e";
    
    /**
     * 备用,共8个字节
     */
    protected static final String BACKUP = "0000000000000000";
    
    /**
     * 加密方式00,表示不加密
     */
    protected static final String NO_ENCRYPT = "00";
    
    /**
     * 数据区内容分隔符
     */
    protected static final String SEPARATOR_HEX = "7c";
    
    protected static final int START_SIGN_START = 0;
    protected static final int START_SIGN_END = 9;
    
    protected static final int MESSAGE_LENGTH_START = 10;
    protected static final int MESSAGE_LENGTH_END = 13;
    
    protected static final int ORDER_NUMBER_START = 14;
    protected static final int ORDER_NUMBER_END = 37;
    
    protected static final int FUNCTION_NUMBER_START = 38;
    protected static final int FUNCTION_NUMBER_END = 41;
    
    protected static final int ENCRYPT_START = 42;
    protected static final int ENCRYPT_END = 43;
    
    protected static final int SEND_TIME_START = 44;
    protected static final int SEND_TIME_END = 57;
    
    protected static final int DATA_START = 74;
    
    protected static final String SEPARATOR = "|";
    
    protected String parseString(String messageHex, int start, int end, String attributeName) {
        String message = messageHex.substring(start, end + 1);
        return attributeName + "=" + message + SEPARATOR;
    }
    
    protected String parseInt(String messageHex, int start, int end, String attributeName) {
        String hex = messageHex.substring(start, end + 1);
        return attributeName + "=" + HexUtil.hexToInt(hex) + SEPARATOR;
    }
    
    protected String parseTime(String messageHex, int start, int end, String attributeName) {
        String hexTime = messageHex.substring(start, end + 1);
        return attributeName + "=" + HexUtil.hexToTime(hexTime) + SEPARATOR;
    }
    
    /**
     * 构造消息头部
     * 
     * 通信头部 = 开始标志 + 信息长度 + 订单编号 + 功能号 + 加密方式 + 发送时刻 + 备用
     * 
     * @param data
     * @param functionNumber
     * @return
     */
    protected String generateHead(String data, String functionNumber) {
        // 信息长度
        int length = (data + END).length() / 2;
        
        // TODO 订单编号待定
        String orderNumber = "000000000000000000000000";
        
        String head = HEAD 
                + HexUtil.intTo2ByteHex(length) 
                + orderNumber 
                + functionNumber 
                + NO_ENCRYPT
                + HexUtil.timeToHex(new Date())
                + BACKUP;
        
        return head;
    }
    
    public String getHeartBeatMessage() {
        String data = "";
        String head = generateHead(data, FunctionNumber.HEART_BEAT);
        return head + data + END;
    }
    
    public String getUpdateRTCMessage() {
        String data = "";
        String head = generateHead(data, FunctionNumber.UPDATE_RTC);
        return head + data + END;
    }
    
    public String getResetMessage() {
        String data = "";
        String head = generateHead(data, FunctionNumber.RESET);
        return head + data + END;
    }
    
    protected String parseHead(String messageHex) {
        if (messageHex.length() < 84) {
            LOGGER.error("消息无效:消息长度为至少42个字节!");
            LOGGER.error("无效消息:" + messageHex);
            return "无效消息:" + messageHex;
        }
        
        String startSign = messageHex.substring(START_SIGN_START, START_SIGN_END + 1);
        if (!startSign.equalsIgnoreCase("3c5354413e")) {
            LOGGER.error("消息无效:消息没有以<STA>开头!");
            LOGGER.error("无效消息:" + messageHex);
            return "无效消息:" + messageHex;
        }
        
        StringBuffer messageDescription = new StringBuffer();
        
        // 消息长度
        messageDescription.append(parseInt(messageHex, MESSAGE_LENGTH_START, MESSAGE_LENGTH_END, "消息长度"));
        
        // 订单编号
        messageDescription.append(parseString(messageHex, ORDER_NUMBER_START, ORDER_NUMBER_END, "订单编号"));
        
        // 功能号
        messageDescription.append(parseString(messageHex, FUNCTION_NUMBER_START, FUNCTION_NUMBER_END, "功能号"));
        
        // 加密方式
        messageDescription.append(parseString(messageHex, ENCRYPT_START, ENCRYPT_END, "加密方式"));
        
        // 发送时刻
        messageDescription.append(parseTime(messageHex, SEND_TIME_START, SEND_TIME_END, "发送时刻"));
        
        return messageDescription.toString();
    }
    
    protected String parseData(String messageHex) {
        String functionNumber = messageHex.substring(FUNCTION_NUMBER_START, FUNCTION_NUMBER_END + 1);
        
        if (functionNumber.equals(FunctionNumber.HEART_BEAT)) {
            return "心跳包";
        }
        else if (functionNumber.equals(FunctionNumber.UPDATE_RTC)) {
            return "更新RTC";
        }
        else if (functionNumber.equals(FunctionNumber.RESET)) {
            return "重置连接";
        }
        
        return "";
    }
    
    /**
     * 判断客户端发送的消息是否为常用处理信息,具体描述如下:
     * - 消息为null或空字符串;
     * - 消息为心跳包;
     * - 消息为更新RTC信息;
     * - 消息为重置信息;
     * 
     * @param sendMessageHex
     * @return true - 当消息满足以上条件;false - 当消息不满足以上条件。
     * @retur
     */
    public boolean isGeneralMessage(String sendMessageHex) {
        if (sendMessageHex == null || sendMessageHex.equals("")) {
            return true;
        }
        
        String functionNumber = sendMessageHex.substring(FUNCTION_NUMBER_START, FUNCTION_NUMBER_END + 1);
        LOGGER.debug("functionNumber: " + functionNumber);
        
        if (functionNumber.equals(FunctionNumber.HEART_BEAT) 
                || functionNumber.equals(FunctionNumber.UPDATE_RTC) 
                || functionNumber.equals(FunctionNumber.RESET)) {
            return true;
        }
        
        return false;
    }
    
    public String processGeneralMessage(String sendMessageHex, AbstractMachine machine, AbstractMachineService machineService) {
        if (sendMessageHex == null || sendMessageHex.equals("")) {
            LOGGER.error("接收到的消息为空!向【" + machine.getNumber() + "】发送重启信息!");
            return getResetMessage();
        }
        
        String functionNumber = sendMessageHex.substring(FUNCTION_NUMBER_START, FUNCTION_NUMBER_END + 1);
        LOGGER.trace("functionNumber: " + functionNumber);
        
        if (functionNumber.equals(FunctionNumber.HEART_BEAT)) {
            LOGGER.trace("从【" + machine.getNumber() + "】接收心跳包:" + parseMessage(sendMessageHex));
            String heartBeatMessage = getHeartBeatMessage();
            machineService.setConnectState(machine, ConnectState.CONNECTED);
            LOGGER.trace("向【" + machine.getNumber() + "】发送心跳包:" + heartBeatMessage);
            return heartBeatMessage;
        }
        else if (functionNumber.equals(FunctionNumber.UPDATE_RTC)) {
            LOGGER.debug("从【" + machine.getNumber() + "】收到更新RTC:" + parseMessage(sendMessageHex));
            String updateRTCMessage = getUpdateRTCMessage();
            LOGGER.debug("向【" + machine.getNumber() + "】发送更新RTC:" + updateRTCMessage);
            return updateRTCMessage;
        }
        else if (functionNumber.equals(FunctionNumber.RESET)) {
            LOGGER.debug("从【" + machine.getNumber() + "】收到重置反馈:" + parseMessage(sendMessageHex));
            return "";
        }
        
        return "";
    }
    
    public abstract String processMessage(String sendMessageHex, AbstractMachine machine);
    
    public String parseMessage(String sendMessageHex) {
        // 解析头部
        String messageDescriptionHead = parseHead(sendMessageHex);
        
        // 解析数据区
        String messageDescriptionData = parseData(sendMessageHex);
        
        return messageDescriptionHead + messageDescriptionData;
    }
}