|
|
|
@ -0,0 +1,248 @@
|
|
|
|
|
package cc.iotkit.plugins.emqx.conf;
|
|
|
|
|
|
|
|
|
|
import java.nio.ByteBuffer;
|
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
|
|
|
|
|
public class LinkageControlDataParser {
|
|
|
|
|
|
|
|
|
|
private static void testEventGroup(String groupName, String[] testCases) {
|
|
|
|
|
System.out.println("\n=== " + groupName + "测试 ===");
|
|
|
|
|
for (String hexData : testCases) {
|
|
|
|
|
try {
|
|
|
|
|
Map<String, Object> result = LinkageControlDataParser.parseHexDataToList(hexData);
|
|
|
|
|
System.out.println("原始数据: " + hexData);
|
|
|
|
|
System.out.println("解析结果: " + result.get("eventType")
|
|
|
|
|
+ " - " + result.get("dataType"));
|
|
|
|
|
System.out.println("rrr解析结果: " + result.get(0));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.out.println("解析异常: " + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Map<String, Object> parseHexDataToList(String hexData) {
|
|
|
|
|
System.out.println("parseHexDataToList: " + hexData);
|
|
|
|
|
byte[] data = hexStringToByteArray(hexData);
|
|
|
|
|
return parseDataToList(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Map<String, Object> parseDataToList(byte[] data) {
|
|
|
|
|
Map<String, Object> resultList = new HashMap<>();
|
|
|
|
|
if (data == null || data.length < 1) {
|
|
|
|
|
return resultList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int eventType = Byte.toUnsignedInt(data[0]) + Byte.toUnsignedInt(data[1]);
|
|
|
|
|
System.out.println("eventType: " + eventType);
|
|
|
|
|
if (eventType == 130) {
|
|
|
|
|
// // 正常数据上报 (NORMAL_DATA)
|
|
|
|
|
return parseNormalDataToList(data);
|
|
|
|
|
} /*else if (isControllerEvent(eventType)) {
|
|
|
|
|
|
|
|
|
|
// 控制器事件 (CONTROLLER_EVENT)
|
|
|
|
|
return parseControllerEventToList(data);
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
// 节点事件 (NODE_EVENT)
|
|
|
|
|
return LinkageControlEventToList(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Map<String, Object> LinkageControlEventToList(byte[] data) {
|
|
|
|
|
// List<Map<String, Object>> eventList = new ArrayList<>();
|
|
|
|
|
ByteBuffer buffer = ByteBuffer.wrap(data);
|
|
|
|
|
Map<String, Object> eventMap = new LinkedHashMap<>();
|
|
|
|
|
|
|
|
|
|
eventMap.put("dataType", "LINKAGE_CONTROL_EVENT");
|
|
|
|
|
int eventType = buffer.getShort() & 0xFFFF;
|
|
|
|
|
eventMap.put("eventType", eventType);
|
|
|
|
|
eventMap.put("eventTypeValue", EventTypeMapper.getEventTypeName(eventType));
|
|
|
|
|
eventMap.put("timestamp", parseBcdTime(buffer));
|
|
|
|
|
eventMap.put("nodeId", buffer.getShort() & 0xFFFF);
|
|
|
|
|
Integer dataValue = buffer.getShort() & 0xFFFF;
|
|
|
|
|
eventMap.put("dataValues", dataValue);
|
|
|
|
|
String status = (dataValue == 0) ? "不支持反馈" :
|
|
|
|
|
(dataValue == 1) ? "反馈未动作" :
|
|
|
|
|
(dataValue == 2) ? "反馈动作" : "未知状态";
|
|
|
|
|
eventMap.put("dataDetectorValue" , status);
|
|
|
|
|
return eventMap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Map<String, Object> parseNodeEventToList(byte[] data) {
|
|
|
|
|
// Map<String, Object> eventList = new HashMap<>();
|
|
|
|
|
ByteBuffer buffer = ByteBuffer.wrap(data);
|
|
|
|
|
Map<String, Object> eventMap = new LinkedHashMap<>();
|
|
|
|
|
|
|
|
|
|
eventMap.put("dataType", "NODE_EVENT");
|
|
|
|
|
int eventType = buffer.getShort() & 0xFFFF;
|
|
|
|
|
eventMap.put("eventType", eventType);
|
|
|
|
|
if (!Objects.equals(eventMap.get("eventType"), 15)) {
|
|
|
|
|
eventMap.put("eventTypeValue", EventTypeMapper.getEventTypeName(eventType));
|
|
|
|
|
eventMap.put("timestamp", parseBcdTime(buffer));
|
|
|
|
|
eventMap.put("nodeId", buffer.getShort() & 0xFFFF);
|
|
|
|
|
// BigDecimal decimalValue = new BigDecimal(buffer.getShort() & 0xFFFF)
|
|
|
|
|
// .divide(new BigDecimal(1), 4, RoundingMode.HALF_UP).stripTrailingZeros();
|
|
|
|
|
eventMap.put("dataValues", buffer.getShort() & 0xFFFF);
|
|
|
|
|
// eventMap.put("dataDetectorValue" , eventMap.get("dataValues"));
|
|
|
|
|
} else {
|
|
|
|
|
eventMap.put("eventTypeValue", EventTypeMapper.getEventTypeName(eventType));
|
|
|
|
|
eventMap.put("timestamp", parseBcdTime(buffer));
|
|
|
|
|
eventMap.put("totalNodes", buffer.get() & 0xFF);
|
|
|
|
|
eventMap.put("nodeId", buffer.getShort() & 0xFFFF);
|
|
|
|
|
System.out.println("浓度变化的剩余长度"+buffer.remaining());
|
|
|
|
|
// int nodeCounter = 0;
|
|
|
|
|
while (buffer.remaining() >= 2) {
|
|
|
|
|
// String suffix = String.valueOf(nodeCounter++);
|
|
|
|
|
// BigDecimal decimalValue = new BigDecimal(buffer.getShort() & 0xFFFF)
|
|
|
|
|
// .divide(new BigDecimal(1), 4, RoundingMode.HALF_UP).stripTrailingZeros();
|
|
|
|
|
eventMap.put("dataValues", buffer.getShort() & 0xFFFF);
|
|
|
|
|
// 0:节点为探测器
|
|
|
|
|
eventMap.put("dataDetectorValue" , eventMap.get("dataValues"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
System.out.println("eventMap+++++++++++: " + eventMap);
|
|
|
|
|
//eventList.add(eventMap);
|
|
|
|
|
|
|
|
|
|
return eventMap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Map<String, Object> parseNormalDataToList(byte[] data) {
|
|
|
|
|
// List<Map<String, Object>> dataList = new ArrayList<>();
|
|
|
|
|
ByteBuffer buffer = ByteBuffer.wrap(data);
|
|
|
|
|
|
|
|
|
|
// 基础信息
|
|
|
|
|
Map<String, Object> baseInfo = new LinkedHashMap<>();
|
|
|
|
|
baseInfo.put("dataType", "Linkage_DATA");
|
|
|
|
|
int eventType = buffer.getShort() & 0xFFFF;
|
|
|
|
|
baseInfo.put("eventType", eventType);
|
|
|
|
|
baseInfo.put("eventTypeValue", EventTypeMapper.getEventTypeName(eventType));
|
|
|
|
|
baseInfo.put("timestamp", parseBcdTime(buffer));
|
|
|
|
|
// baseInfo.put("totalNodes", buffer.getShort() & 0xFFFF);
|
|
|
|
|
baseInfo.put("reportedNodes", buffer.get() & 0xFF);
|
|
|
|
|
// dataList.add(baseInfo);
|
|
|
|
|
System.out.println(buffer.remaining());
|
|
|
|
|
// 节点数据
|
|
|
|
|
// 节点数据(动态添加数字后缀)
|
|
|
|
|
int nodeCounter = 0;
|
|
|
|
|
while (buffer.remaining() >= 7) {
|
|
|
|
|
String suffix = String.valueOf(nodeCounter++);
|
|
|
|
|
// Map<String, Object> nodeMap = new LinkedHashMap<>();
|
|
|
|
|
baseInfo.put("nodeId" + suffix, buffer.getShort() & 0xFFFF);
|
|
|
|
|
// baseInfo.put("nodeType" + suffix, buffer.get() & 0xFF);
|
|
|
|
|
// nodeMap.put("unit", buffer.get() & 0xFF); // 节点节点参数
|
|
|
|
|
// nodeMap.put("precision", buffer.get() & 0xFF);
|
|
|
|
|
// baseInfo.put("gasType" + suffix, GasDetectorParser.parse(buffer.getShort() & 0xFFFF));
|
|
|
|
|
Integer dataValue = buffer.getShort() & 0xFFFF;
|
|
|
|
|
// if (Objects.equals(baseInfo.get("nodeType" + suffix), 0)) {
|
|
|
|
|
// BigDecimal decimalValue = new BigDecimal(dataValue)
|
|
|
|
|
// .divide(new BigDecimal(1), 4, RoundingMode.HALF_UP).stripTrailingZeros();
|
|
|
|
|
baseInfo.put("dataValues" + suffix, dataValue);
|
|
|
|
|
// 0:节点为探测器
|
|
|
|
|
// if (Objects.equals(baseInfo.get("nodeType" + suffix), 0)) {
|
|
|
|
|
String status = (dataValue == 0) ? "不支持反馈" :
|
|
|
|
|
(dataValue == 1) ? "反馈未动作" :
|
|
|
|
|
(dataValue == 2) ? "反馈动作" : "未知状态";
|
|
|
|
|
baseInfo.put("dataDetectorValue" + suffix, status);
|
|
|
|
|
// } else if (Objects.equals(baseInfo.get("nodeType" + suffix), 1)) {
|
|
|
|
|
|
|
|
|
|
// baseInfo.put("dataValues" + suffix, dataValue);
|
|
|
|
|
//1:节点为输出模块
|
|
|
|
|
// baseInfo.put("dataSinksValue" + suffix, baseInfo.get("dataValues" + suffix).equals("0") ? "未动作" : "已动作");
|
|
|
|
|
// }
|
|
|
|
|
// dataList.add(nodeMap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return baseInfo;
|
|
|
|
|
}
|
|
|
|
|
// 辅助方法:字节数组转十六进制字符串
|
|
|
|
|
|
|
|
|
|
private static String bytesToHex(byte[] bytes) {
|
|
|
|
|
|
|
|
|
|
StringBuilder hexSb = new StringBuilder();
|
|
|
|
|
for (byte b : bytes) {
|
|
|
|
|
hexSb.append(String.format("%02X", b));
|
|
|
|
|
}
|
|
|
|
|
return hexSb.toString();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
// 保留原有辅助方法
|
|
|
|
|
/*public static String parseBcdTime(ByteBuffer buffer) {
|
|
|
|
|
// 打印ByteBuffer的十六进制表示
|
|
|
|
|
System.out.println("ByteBuffer内容(十六进制): " + bytesToHex(buffer.array()));
|
|
|
|
|
|
|
|
|
|
byte[] bcdTime = new byte[6];
|
|
|
|
|
|
|
|
|
|
buffer.get(bcdTime);
|
|
|
|
|
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
for (byte b : bcdTime) {
|
|
|
|
|
|
|
|
|
|
// 提取高四位和低四位,并转换为十进制数字
|
|
|
|
|
|
|
|
|
|
int high = (b >> 4) & 0x0F;
|
|
|
|
|
|
|
|
|
|
int low = b & 0x0F;
|
|
|
|
|
|
|
|
|
|
// 组合成两位十进制字符串
|
|
|
|
|
|
|
|
|
|
sb.append(String.format("%1d%1d", high, low));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String bcdStr = sb.toString();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");
|
|
|
|
|
|
|
|
|
|
sdf.set2DigitYearStart(new Date(946684800000L)); // 2000-01-01
|
|
|
|
|
|
|
|
|
|
Date date = sdf.parse(bcdStr);
|
|
|
|
|
|
|
|
|
|
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
|
|
|
|
return bcdStr; // 返回原始BCD字符串(可能包含越界值)
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
public static String parseBcdTime(ByteBuffer buffer) {
|
|
|
|
|
// 打印ByteBuffer的十六进制表示
|
|
|
|
|
System.out.println("ByteBuffer内容(十六进制): " + bytesToHex(buffer.array()));
|
|
|
|
|
|
|
|
|
|
byte[] bcdTime = new byte[6];
|
|
|
|
|
buffer.get(bcdTime);
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
for (byte b : bcdTime) {
|
|
|
|
|
sb.append(String.format("%02X", b));
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");
|
|
|
|
|
sdf.set2DigitYearStart(new SimpleDateFormat("yyyy").parse("2000")); // 设置世纪转折点
|
|
|
|
|
Date date = sdf.parse(sb.toString());
|
|
|
|
|
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
return sb.toString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static byte[] hexStringToByteArray(String s) {
|
|
|
|
|
int len = s.length();
|
|
|
|
|
byte[] data = new byte[len / 2];
|
|
|
|
|
for (int i = 0; i < len; i += 2) {
|
|
|
|
|
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
|
|
|
|
|
+ Character.digit(s.charAt(i + 1), 16));
|
|
|
|
|
}
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static boolean isControllerEvent(int eventType) {
|
|
|
|
|
return eventType >= 30 && eventType <= 38;
|
|
|
|
|
}
|
|
|
|
|
}
|