联动控制箱解析

master
小鱼干 2 months ago
parent c696dc477d
commit febc6291b8

@ -2,9 +2,10 @@ package cc.iotkit.plugins.emqx.conf;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class EventTypeMapper { public class EventTypeMapper {
private static final Map<Integer, String> EVENT_TYPE_MAP = new HashMap<>(); private static final Map<Integer, String> EVENT_TYPE_MAP = new ConcurrentHashMap<>();
static { static {
// 节点相关事件 // 节点相关事件
@ -23,7 +24,11 @@ public class EventTypeMapper {
EVENT_TYPE_MAP.put(13, "模块联动"); EVENT_TYPE_MAP.put(13, "模块联动");
EVENT_TYPE_MAP.put(14, "阀门动作"); EVENT_TYPE_MAP.put(14, "阀门动作");
EVENT_TYPE_MAP.put(15, "浓度变化上报"); EVENT_TYPE_MAP.put(15, "浓度变化上报");
EVENT_TYPE_MAP.put(16, "预热");
EVENT_TYPE_MAP.put(17, "预热完成上报");
EVENT_TYPE_MAP.put(18, "寿命到期上报");
EVENT_TYPE_MAP.put(19, "新节点连接");
EVENT_TYPE_MAP.put(20, "节点联动恢复");
// 控制器相关事件 // 控制器相关事件
EVENT_TYPE_MAP.put(30, "自检"); EVENT_TYPE_MAP.put(30, "自检");
EVENT_TYPE_MAP.put(31, "备电故障"); EVENT_TYPE_MAP.put(31, "备电故障");
@ -47,6 +52,8 @@ public class EventTypeMapper {
// 正常上报事件 // 正常上报事件
EVENT_TYPE_MAP.put(128, "燃气报警器正常数据上报"); EVENT_TYPE_MAP.put(128, "燃气报警器正常数据上报");
EVENT_TYPE_MAP.put(129, "动火离人正常数据上报"); EVENT_TYPE_MAP.put(129, "动火离人正常数据上报");
EVENT_TYPE_MAP.put(130, "联动控制箱正常数据上报");
EVENT_TYPE_MAP.put(151, "上报输出反馈状态变化");
} }
public static String getEventTypeName(int eventType) { public static String getEventTypeName(int eventType) {

@ -1,5 +1,7 @@
package cc.iotkit.plugins.emqx.conf; package cc.iotkit.plugins.emqx.conf;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@ -121,8 +123,9 @@ public class GasAlarmDataParser {
Map<String, Object> eventMap = new LinkedHashMap<>(); Map<String, Object> eventMap = new LinkedHashMap<>();
eventMap.put("dataType", "CONTROLLER_EVENT"); eventMap.put("dataType", "CONTROLLER_EVENT");
eventMap.put("eventType", buffer.getShort() & 0xFFFF); int eventType = buffer.getShort() & 0xFFFF;
eventMap.put("eventTypeValue", EventTypeMapper.getEventTypeName(Integer.parseInt(eventMap.get("eventType").toString()))); eventMap.put("eventType", eventType);
eventMap.put("eventTypeValue", EventTypeMapper.getEventTypeName(eventType));
eventMap.put("timestamp", parseBcdTime(buffer)); eventMap.put("timestamp", parseBcdTime(buffer));
// eventList.add(eventMap); // eventList.add(eventMap);
@ -135,19 +138,30 @@ public class GasAlarmDataParser {
Map<String, Object> eventMap = new LinkedHashMap<>(); Map<String, Object> eventMap = new LinkedHashMap<>();
eventMap.put("dataType", "NODE_EVENT"); eventMap.put("dataType", "NODE_EVENT");
eventMap.put("eventType", buffer.getShort() & 0xFFFF); int eventType = buffer.getShort() & 0xFFFF;
eventMap.put("eventType", eventType);
if (!Objects.equals(eventMap.get("eventType"), 15)) { if (!Objects.equals(eventMap.get("eventType"), 15)) {
eventMap.put("eventTypeValue", EventTypeMapper.getEventTypeName(Integer.parseInt(eventMap.get("eventType").toString()))); eventMap.put("eventTypeValue", EventTypeMapper.getEventTypeName(eventType));
eventMap.put("timestamp", parseBcdTime(buffer)); eventMap.put("timestamp", parseBcdTime(buffer));
eventMap.put("nodeId", buffer.getShort() & 0xFFFF); eventMap.put("nodeId", buffer.getShort() & 0xFFFF);
eventMap.put("dataValue", 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 { } else {
eventMap.put("eventTypeValue", EventTypeMapper.getEventTypeName(Integer.parseInt(eventMap.get("eventType").toString()))); eventMap.put("eventTypeValue", EventTypeMapper.getEventTypeName(eventType));
eventMap.put("timestamp", parseBcdTime(buffer)); eventMap.put("timestamp", parseBcdTime(buffer));
eventMap.put("totalNodes", buffer.getShort() & 0xFF); eventMap.put("totalNodes", buffer.get() & 0xFF);
eventMap.put("nodeId", buffer.getShort() & 0xFFFF); eventMap.put("nodeId", buffer.getShort() & 0xFFFF);
System.out.println("浓度变化的剩余长度"+buffer.remaining());
// int nodeCounter = 0;
while (buffer.remaining() >= 2) { while (buffer.remaining() >= 2) {
eventMap.put("dataValue", buffer.getShort() & 0xFFFF); // 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"));
} }
} }
@ -164,8 +178,9 @@ public class GasAlarmDataParser {
// 基础信息 // 基础信息
Map<String, Object> baseInfo = new LinkedHashMap<>(); Map<String, Object> baseInfo = new LinkedHashMap<>();
baseInfo.put("dataType", "NORMAL_DATA"); baseInfo.put("dataType", "NORMAL_DATA");
baseInfo.put("eventType", buffer.getShort() & 0xFFFF); int eventType = buffer.getShort() & 0xFFFF;
baseInfo.put("eventTypeValue", EventTypeMapper.getEventTypeName(Integer.parseInt(baseInfo.get("eventType").toString()))); baseInfo.put("eventType", eventType);
baseInfo.put("eventTypeValue", EventTypeMapper.getEventTypeName(eventType));
baseInfo.put("timestamp", parseBcdTime(buffer)); baseInfo.put("timestamp", parseBcdTime(buffer));
baseInfo.put("totalNodes", buffer.getShort() & 0xFFFF); baseInfo.put("totalNodes", buffer.getShort() & 0xFFFF);
baseInfo.put("reportedNodes", buffer.get() & 0xFF); baseInfo.put("reportedNodes", buffer.get() & 0xFF);
@ -182,13 +197,18 @@ public class GasAlarmDataParser {
// nodeMap.put("unit", buffer.get() & 0xFF); // 节点节点参数 // nodeMap.put("unit", buffer.get() & 0xFF); // 节点节点参数
// nodeMap.put("precision", buffer.get() & 0xFF); // nodeMap.put("precision", buffer.get() & 0xFF);
baseInfo.put("gasType" + suffix, GasDetectorParser.parse(buffer.getShort() & 0xFFFF)); baseInfo.put("gasType" + suffix, GasDetectorParser.parse(buffer.getShort() & 0xFFFF));
baseInfo.put("dataValue" + suffix, buffer.getShort() & 0xFFFF); Integer dataValue = buffer.getShort() & 0xFFFF;
if (Objects.equals(baseInfo.get("nodeType" + suffix), 0)) { 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节点为探测器 // 0节点为探测器
baseInfo.put("dataTypeValue" + suffix, baseInfo.get("dataValue" + suffix)); baseInfo.put("dataDetectorValue" + suffix, baseInfo.get("dataValues" + suffix));
} else if (Objects.equals(baseInfo.get("nodeType" + suffix), 1)) { } else if (Objects.equals(baseInfo.get("nodeType" + suffix), 1)) {
baseInfo.put("dataValues" + suffix, dataValue);
//1节点为输出模块 //1节点为输出模块
baseInfo.put("dataTypeValue" + suffix, baseInfo.get("dataValue" + suffix).equals("0") ? "未动作" : "已动作"); baseInfo.put("dataSinksValue" + suffix, baseInfo.get("dataValues" + suffix).equals("0") ? "未动作" : "已动作");
} }
// dataList.add(nodeMap); // dataList.add(nodeMap);
} }

@ -25,6 +25,7 @@ public class IoTConfigProtocol {
public static final int SIGNAL = 0x0024; public static final int SIGNAL = 0x0024;
public static final int TIME_SYNC = 0x0025; public static final int TIME_SYNC = 0x0025;
public static final int VERSION = 0x0026; public static final int VERSION = 0x0026;
public static final int REPORT_RATE_LinkConstraint = 0x0100;
// 生成读取指令 // 生成读取指令
// 反向映射Map // 反向映射Map
private static final Map<Integer, String> CONFIG_ID_TO_KEY = new HashMap<>(); private static final Map<Integer, String> CONFIG_ID_TO_KEY = new HashMap<>();
@ -47,6 +48,8 @@ public class IoTConfigProtocol {
CONFIG_ID_TO_KEY.put(SIGNAL, "signal"); CONFIG_ID_TO_KEY.put(SIGNAL, "signal");
CONFIG_ID_TO_KEY.put(TIME_SYNC, "timeSyncInternal"); CONFIG_ID_TO_KEY.put(TIME_SYNC, "timeSyncInternal");
CONFIG_ID_TO_KEY.put(VERSION, "version"); CONFIG_ID_TO_KEY.put(VERSION, "version");
CONFIG_ID_TO_KEY.put(REPORT_RATE_LinkConstraint, "controlOutput");
} }
public static String getKeyByConfigId(int configId) { public static String getKeyByConfigId(int configId) {

@ -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;
}
}

@ -3,13 +3,16 @@ package cc.iotkit.plugins.emqx.conf;
import io.vertx.core.buffer.Buffer; import io.vertx.core.buffer.Buffer;
import io.vertx.core.json.JsonObject; import io.vertx.core.json.JsonObject;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.*;
import java.util.HashMap; import java.util.regex.Matcher;
import java.util.Map; import java.util.regex.Pattern;
import static cc.iotkit.plugins.emqx.conf.CRC16ModbusUtil.buildFrame; import static cc.iotkit.plugins.emqx.conf.CRC16ModbusUtil.buildFrame;
import static cc.iotkit.plugins.emqx.conf.IoTConfigProtocol.*; import static cc.iotkit.plugins.emqx.conf.IoTConfigProtocol.*;
@ -70,9 +73,75 @@ public class ProtocolTest {
return ByteBuffer.wrap(bytes); return ByteBuffer.wrap(bytes);
} }
public static String formatHexByte(String input) {
// 移除0x前缀并保留纯十六进制字符
String hex = input.replaceAll("(?i)^0x", "").replaceAll("[^0-9a-fA-F]", "");
// 标准化为2位十六进制不足补零超长截断
return hex.isEmpty() ? "00"
: hex.length() == 1 ? "0" + hex
: hex.substring(hex.length() - 2);
}
public static void extractDetectorData(Map<String, Object> baseInfo) {
for (Map.Entry<String, Object> entry : baseInfo.entrySet()) {
if (entry.getKey().startsWith("dataDetectorValue")) {
String suffix = entry.getKey().substring(17); // 去掉前缀"dataDetectorValue"
Integer value = (Integer) entry.getValue();
// 获取对应节点信息
String nodeIdKey = "nodeId" + suffix;
String gasTypeKey = "gasType" + suffix;
System.out.println("NodeID: " + baseInfo.get(nodeIdKey) +
", GasType: " + baseInfo.get(gasTypeKey) +
", DetectorValue: " + value);
}
}
}
public static String generateWriteCommand(int configId, byte[] data) {
ByteBuffer buf = ByteBuffer.allocate(3 + data.length);
//buf.putShort((short) (5 + data.length)); // 数据长度
// buf.putShort((short) terminalType);
buf.putShort((short) configId);
buf.put((byte) data.length); // 数据长度字节
buf.put(data); // 实际数据
return bytesToHex(buf.array());
}
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02X", b));
}
return sb.toString();
}
public static void main(String[] args) { public static void main(String[] args) {
String dsada=null;
System.out.println(dsada.startsWith("https"));
System.out.println(generateWriteCommand(0x0100,ByteBuffer.allocate(4)
.order(ByteOrder.BIG_ENDIAN)
.putInt(Integer.parseUnsignedInt("00010001", 16)).array()));
System.out.println(ByteBuffer.allocate(2).putShort(Short.parseShort("1")).array());
System.out.println(EventTypeMapper.getEventTypeName(Integer.parseInt("20")));
BigDecimal decimalValue = new BigDecimal("1123.391111111111111")
.divide(new BigDecimal(1), 4, RoundingMode.HALF_UP).stripTrailingZeros();
System.out.println(decimalValue);
Map<String, Object> baseInfo = new HashMap<>();
baseInfo.put("nodeId", 12345);
baseInfo.put("nodeType", 0); // 探测器
baseInfo.put("dataDetectorValue", 0);
baseInfo.put("gasType", "ddddddddddddddddd");
baseInfo.put("dataValue", "ddddddddddaaaa"); // 探测器值
baseInfo.put("nodeId0111", 67890);
baseInfo.put("nodeType0111", 1); // 输出模块
baseInfo.put("dataDetectorValue0111", 0);
baseInfo.put("gasType0111", "dasa12321");
baseInfo.put("dataValue0111", "Ddsa");
extractDetectorData(baseInfo);
System.out.println(formatHexByte("0x014"));
// GasAlarmDataParser.parseBcdTime(createBcdTimeBuffer("250707131758")); // GasAlarmDataParser.parseBcdTime(createBcdTimeBuffer("250707131758"));
System.out.println(GasAlarmDataParser.parseBcdTime(createBcdTimeBuffer("250703103146"))); System.out.println(GasAlarmDataParser.parseBcdTime(createBcdTimeBuffer("250703103146")));
//String url = "https://minio.dddd.com/feijialuo/20250702/lQLPKHYULtpjo8HM_Mz8sCPMoZZYPmEbCD1keBQpVgA_252_2521751416904105.png"; //String url = "https://minio.dddd.com/feijialuo/20250702/lQLPKHYULtpjo8HM_Mz8sCPMoZZYPmEbCD1keBQpVgA_252_2521751416904105.png";

@ -99,8 +99,8 @@ public class EmqxPlugin implements PluginCloseListener, IPlugin, Runnable {
String serverPassword = IdUtil.fastSimpleUUID(); String serverPassword = IdUtil.fastSimpleUUID();
MqttClientOptions options = new MqttClientOptions() MqttClientOptions options = new MqttClientOptions()
.setClientId("server11223") .setClientId("server112233")
.setUsername("server11223") .setUsername("server112233")
.setPassword(serverPassword) .setPassword(serverPassword)
.setCleanSession(true) .setCleanSession(true)
.setMaxInflightQueue(100) .setMaxInflightQueue(100)
@ -244,19 +244,23 @@ public class EmqxPlugin implements PluginCloseListener, IPlugin, Runnable {
switch(result.get("deviceType").toString()) { switch(result.get("deviceType").toString()) {
case "0": case "0":
device.setProductKey("CEMpmANABN7Tt6Jh"); device.setProductKey("CEMpmANABN7Tt6Jh");
//家用报警器
break; break;
case "1": case "1":
device.setProductKey("XmXYxjzihseT76As"); device.setProductKey("XmXYxjzihseT76As");
//独立式报警器
break; break;
case "2": case "2":
device.setProductKey("bAASX8tBjYQjBGFP"); device.setProductKey("bAASX8tBjYQjBGFP");
//工商业控制器
break; break;
case "3": case "3":
//动火离人设备
device.setProductKey("WfpZZFkMxxbGfRca"); device.setProductKey("WfpZZFkMxxbGfRca");
case "4":
//联动控制箱设备
System.out.println("联动控制箱设备注册++++++++++++++++++++++++++++++++++++++++++");
device.setProductKey("MQFejp7cyDMH3enG");
break; break;
} }
//注册 //注册
@ -282,6 +286,11 @@ public class EmqxPlugin implements PluginCloseListener, IPlugin, Runnable {
FireSafetyDataReceiver.handleHexData(data).forEach( FireSafetyDataReceiver.handleHexData(data).forEach(
(key, value) -> result.merge(key, value, (v1, v2) -> v2)); (key, value) -> result.merge(key, value, (v1, v2) -> v2));
payload.put("params",result); payload.put("params",result);
}else if(cmd.equals("0x15")){
//联动控制箱设备状态及参数数据上报
LinkageControlDataParser.parseHexDataToList(data).forEach(
(key, value) -> result.merge(key, value, (v1, v2) -> v2));
payload.put("params",result);
} }
else if(cmd.equals("0x23")){ else if(cmd.equals("0x23")){
flag=false; flag=false;
@ -460,8 +469,8 @@ public class EmqxPlugin implements PluginCloseListener, IPlugin, Runnable {
private String replyToInstructions(JsonObject payload) { private String replyToInstructions(JsonObject payload) {
String mid = payload.getString("messageId"); String mid = payload.getString("messageId");
String cmd = payload.getString("cmd"); String cmd = payload.getString("cmd");
payload.getString("cmd"); //payload.getString("cmd");
System.out.println("mid1" + mid); /* System.out.println("mid1" + mid);
System.out.println("cmd1" + cmd); System.out.println("cmd1" + cmd);
if (mid.toLowerCase().startsWith("0x")) { if (mid.toLowerCase().startsWith("0x")) {
mid = mid.substring(2); mid = mid.substring(2);
@ -471,12 +480,22 @@ public class EmqxPlugin implements PluginCloseListener, IPlugin, Runnable {
} }
cmd = cmd.replaceAll("\\D", ""); cmd = cmd.replaceAll("\\D", "");
mid = mid.replaceAll("\\D", ""); mid = mid.replaceAll("\\D", "");
if (cmd.length() == 0) {
cmd = "00"; // 空值默认补零
} else if (cmd.length() == 1) {
cmd = "0" + cmd; // 单字符左侧补零
} else if (cmd.length() > 2) {
cmd = cmd.slice(-2); // 超长取最后两位
}
if (mid.length() % 2 != 0) { if (mid.length() % 2 != 0) {
mid = "0" + mid; // 左侧补零 mid = "0" + mid; // 左侧补零
} }
if (cmd.length() % 2 != 0) { if (cmd.length() % 2 != 0) {
cmd = "0" + cmd; // 左侧补零 cmd = "0" + cmd; // 左侧补零
} }*/
cmd = formatHexByte(cmd);
mid = formatHexByte(mid);
System.out.println("mid" + mid); System.out.println("mid" + mid);
System.out.println("cmd" + cmd); System.out.println("cmd" + cmd);
// System.out.println(mid + "re++++++++++++++++++++++++++++++++++++++++++++++++++" + cmd); // System.out.println(mid + "re++++++++++++++++++++++++++++++++++++++++++++++++++" + cmd);
@ -485,7 +504,17 @@ public class EmqxPlugin implements PluginCloseListener, IPlugin, Runnable {
mid, cmd, "00" + formatBCDToHex(generateBCDTime())); mid, cmd, "00" + formatBCDToHex(generateBCDTime()));
return replyMessage; return replyMessage;
} }
/** public static String formatHexByte(String input) {
// 移除0x前缀并保留纯十六进制字符
String hex = input.replaceAll("(?i)^0x", "").replaceAll("[^0-9a-fA-F]", "");
// 标准化为2位十六进制不足补零超长截断
return hex.isEmpty() ? "00"
: hex.length() == 1 ? "0" + hex
: hex.substring(hex.length() - 2);
}
/**
* *
*/ */
private void reply1(String replyMessage,String deviceName, JsonObject payload) { private void reply1(String replyMessage,String deviceName, JsonObject payload) {

@ -19,6 +19,7 @@ import lombok.Setter;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -94,6 +95,14 @@ public class MqttDevice implements IDevice {
configId = REPORT_RATE_LOWER; configId = REPORT_RATE_LOWER;
tlvData = ByteBuffer.allocate(2).putShort(Short.parseShort(value)).array(); tlvData = ByteBuffer.allocate(2).putShort(Short.parseShort(value)).array();
break; break;
case "controlOutput":
configId = REPORT_RATE_LinkConstraint;
tlvData = ByteBuffer.allocate(4)
.order(ByteOrder.BIG_ENDIAN)
.putInt(Integer.parseUnsignedInt(value, 16)).array();
break;
case "card": case "card":
case "signal": case "signal":
case "version": case "version":
@ -180,6 +189,9 @@ public class MqttDevice implements IDevice {
case "version": case "version":
configId = VERSION; configId = VERSION;
break; break;
case "controlOutput":
configId = REPORT_RATE_LinkConstraint;
break;
default: default:
System.out.println("Unsupported config: " + key); System.out.println("Unsupported config: " + key);
continue; continue;
@ -228,10 +240,10 @@ public class MqttDevice implements IDevice {
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
String replyMessage = buildFrame("01","01", String replyMessage = buildFrame("01","01",
"00", "24", list.get(i).get("data").toString()); "00", "24", list.get(i).get("data").toString());
//循环发送配置指令 //循环发送配置指令
/* String replyMessage = buildFrame("01", "01", /* String replyMessage = buildFrame("01", "01",
"01", "24", "01" + list.get(i).get("data"));*/ "01", "24", "01" + list.get(i).get("data"));*/
System.out.println("配置指令" + replyMessage);
send( send(
topic,replyMessage topic,replyMessage
); );

@ -1,9 +1,9 @@
plugin: plugin:
runMode: dev runMode: prod
mainPackage: cc.iotkit.plugin mainPackage: cc.iotkit.plugin
emqx: emqx:
host: 127.0.0.1 host: 123.57.78.108
port: 1883 port: 1883
topics: /sys/# topics: FIGARO/#
authPort: 8104 authPort: 8104

Loading…
Cancel
Save