|
|
@@ -1,8 +1,8 @@
|
|
|
package com.zksy.gas.utils;
|
|
|
|
|
|
import com.zksy.gas.domain.GasMonitorData;
|
|
|
-
|
|
|
import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
import java.time.LocalDateTime;
|
|
|
|
|
|
public class DataParser {
|
|
|
@@ -10,72 +10,106 @@ public class DataParser {
|
|
|
public static GasMonitorData parseMessage(byte[] frame) {
|
|
|
GasMonitorData data = new GasMonitorData();
|
|
|
|
|
|
- // 帧类型
|
|
|
- data.setFrameType(frame[2] & 0xFF);
|
|
|
+ // 帧类型(直接输出)
|
|
|
+ data.setFrameType(Integer.valueOf(String.format("%02X", frame[3])));
|
|
|
|
|
|
- // MAC 地址
|
|
|
+ // MAC 地址 (4~11)
|
|
|
byte[] macBytes = new byte[8];
|
|
|
- System.arraycopy(frame, 3, macBytes, 0, 8);
|
|
|
+ System.arraycopy(frame, 4, macBytes, 0, 8);
|
|
|
data.setMacAddress(ProtocolUtils.bytesToHex(macBytes));
|
|
|
|
|
|
- // 短地址
|
|
|
- data.setShortAddress(String.format("%02X%02X", frame[11], frame[12]));
|
|
|
+ // 短地址 (12~13)
|
|
|
+ data.setShortAddress(String.format("%02X%02X", frame[12], frame[13]));
|
|
|
+
|
|
|
+ // 自动应答 (14)
|
|
|
+ data.setAutoReplyOption(Integer.valueOf(String.format("%02X", frame[14])));
|
|
|
|
|
|
- // 自动应答
|
|
|
- data.setAutoReplyOption(frame[13] & 0xFF);
|
|
|
+ // 跳过 AA 帧头(15) 和数据长度(16)
|
|
|
+ int offset = 17;
|
|
|
|
|
|
- // 序号
|
|
|
- data.setSequenceNo(frame[15] & 0xFF);
|
|
|
+ // 序号 (17)
|
|
|
+ data.setSequenceNo(frame[offset] & 0xFF);
|
|
|
+ offset++;
|
|
|
|
|
|
- // 命令
|
|
|
- data.setCommand(frame[16] & 0xFF);
|
|
|
+ // 命令 (18)
|
|
|
+ data.setCommand(frame[offset] & 0xFF);
|
|
|
+ offset++;
|
|
|
|
|
|
- // 设备属性
|
|
|
- data.setDeviceAttr(frame[17] & 0xFF);
|
|
|
+ // 设备属性 (19)
|
|
|
+ data.setDeviceAttr(frame[offset] & 0xFF);
|
|
|
+ offset++;
|
|
|
|
|
|
- // 协议版本
|
|
|
- data.setProtocolVersion(String.format("%02X", frame[18]));
|
|
|
+ // 协议版本 (20)
|
|
|
+ data.setProtocolVersion(String.format("%02X", frame[offset]));
|
|
|
+ offset++;
|
|
|
|
|
|
- // 报警信息(小端序 00 04 -> 0x0400)
|
|
|
- int alarmInfo = ((frame[20] & 0xFF) << 8) | (frame[19] & 0xFF);
|
|
|
+ // 报警信息 (21~22)
|
|
|
+ int alarmInfo = ((frame[offset + 1] & 0xFF) << 8) | (frame[offset] & 0xFF);
|
|
|
data.setAlarmInfo(alarmInfo);
|
|
|
+ offset += 2;
|
|
|
|
|
|
- // 时间戳(BCD)
|
|
|
- LocalDateTime reportTime = ProtocolUtils.parseTimestamp(frame, 21);
|
|
|
+ // 时间戳 (23~28)
|
|
|
+ LocalDateTime reportTime = ProtocolUtils.parseTimestamp(frame, offset);
|
|
|
data.setReportTime(reportTime);
|
|
|
+ offset += 6;
|
|
|
|
|
|
- // 数据个数
|
|
|
- int dataCount = frame[27] & 0xFF;
|
|
|
+ // 数据个数 (29)
|
|
|
+ int dataCount = frame[offset] & 0xFF;
|
|
|
+ offset++;
|
|
|
|
|
|
- // ------- 数据段开始(例子里有 5 个数据) -------
|
|
|
- int offset = 28;
|
|
|
+ // ------------------- 数据段 -------------------
|
|
|
|
|
|
- // 1. 气体浓度 + 气体类型
|
|
|
- // 格式:04 10 00 00 00 00 -> 1004 (浓度=100, 类型=CH4)
|
|
|
- int gasValue = ((frame[offset + 1] & 0xFF) << 8) | (frame[offset] & 0xFF);
|
|
|
- int gasTypeCode = ((frame[offset + 3] & 0xFF) << 8) | (frame[offset + 2] & 0xFF);
|
|
|
- data.setGasConcentration(BigDecimal.valueOf(gasValue));
|
|
|
- data.setGasType(gasTypeCode == 0x0004 ? "CH4" : "未知");
|
|
|
+ // 1. 气体浓度 + 类型 (6 字节)
|
|
|
+ int gasTypeCode = frame[offset] & 0xFF; // 第1字节:气体类型
|
|
|
+ int unitCode = frame[offset + 1] & 0xFF; // 第2字节:单位
|
|
|
+ offset += 2;
|
|
|
|
|
|
- offset += 6;
|
|
|
+ long gasValueRaw = ((long)(frame[offset + 3] & 0xFF) << 24)
|
|
|
+ | ((long)(frame[offset + 2] & 0xFF) << 16)
|
|
|
+ | ((long)(frame[offset + 1] & 0xFF) << 8)
|
|
|
+ | ((long)(frame[offset] & 0xFF));
|
|
|
+ offset += 4;
|
|
|
+
|
|
|
+ String gasType;
|
|
|
+ switch (gasTypeCode) {
|
|
|
+ case 0x04: gasType = "CH4"; break;
|
|
|
+ case 0x05: gasType = "CO"; break;
|
|
|
+ case 0x06: gasType = "O2"; break;
|
|
|
+ default: gasType = "未知";
|
|
|
+ }
|
|
|
+
|
|
|
+ BigDecimal gasConcentration = BigDecimal.valueOf(gasValueRaw / 10.0);
|
|
|
+ data.setGasType(gasType);
|
|
|
+ data.setGasConcentration(gasConcentration);
|
|
|
+ data.setGasUnit(unitCode == 0x10 ? "%LEL" : "未知单位");
|
|
|
|
|
|
// 2. 电池电量
|
|
|
- float battery = ProtocolUtils.bytesToFloatLE(frame, offset + 2);
|
|
|
+ float battery = ProtocolUtils.readFloat6(frame, offset);
|
|
|
data.setBattery(BigDecimal.valueOf(battery));
|
|
|
offset += 6;
|
|
|
|
|
|
// 3. 信号强度
|
|
|
- float signal = ProtocolUtils.bytesToFloatLE(frame, offset + 2);
|
|
|
+ float signal = ProtocolUtils.readFloat6(frame, offset);
|
|
|
data.setSignalStrength(signal);
|
|
|
offset += 6;
|
|
|
|
|
|
- // 4. 经度
|
|
|
- float lon = ProtocolUtils.bytesToFloatLE(frame, offset + 2);
|
|
|
+ // 4. 温度(保留两位小数)
|
|
|
+ float temperature = ProtocolUtils.readFloat6(frame, offset);
|
|
|
+ data.setTemperature(new BigDecimal(temperature).setScale(2, RoundingMode.HALF_UP).floatValue());
|
|
|
+ offset += 6;
|
|
|
+
|
|
|
+ // 5. 湿度(保留两位小数)
|
|
|
+ float humidity = ProtocolUtils.readFloat6(frame, offset);
|
|
|
+ data.setHumidity(new BigDecimal(humidity).setScale(2, RoundingMode.HALF_UP).floatValue());
|
|
|
+ offset += 6;
|
|
|
+
|
|
|
+ // 6. 经度
|
|
|
+ float lon = ProtocolUtils.readFloat6(frame, offset);
|
|
|
data.setLongitude(BigDecimal.valueOf(lon));
|
|
|
offset += 6;
|
|
|
|
|
|
- // 5. 纬度
|
|
|
- float lat = ProtocolUtils.bytesToFloatLE(frame, offset + 2);
|
|
|
+ // 7. 纬度
|
|
|
+ float lat = ProtocolUtils.readFloat6(frame, offset);
|
|
|
data.setLatitude(BigDecimal.valueOf(lat));
|
|
|
offset += 6;
|
|
|
|
|
|
@@ -86,12 +120,8 @@ public class DataParser {
|
|
|
}
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
- // 示例报文
|
|
|
- String hex = "7E003A902509040070010000FFFE01AA2B00010813000425091908473305"
|
|
|
- + "041000000000F96F00000000F76F0000F841FA6F00000000FB6F0000000007";
|
|
|
-
|
|
|
+ String hex = "7E0046902509250560010000FFFE01AA37FA350813180025101614432007041000000000F96F00004442F76F00000000FF6F102CE841FE6F96646642FA6FEEB3E142FB6FF368E141C08E";
|
|
|
byte[] frame = ProtocolUtils.hexStringToBytes(hex);
|
|
|
-
|
|
|
GasMonitorData parsed = parseMessage(frame);
|
|
|
|
|
|
System.out.println("========== 解析结果 ==========");
|
|
|
@@ -105,12 +135,14 @@ public class DataParser {
|
|
|
System.out.println("协议版本: " + parsed.getProtocolVersion());
|
|
|
System.out.println("报警信息: " + parsed.getAlarmInfo());
|
|
|
System.out.println("时间戳: " + parsed.getReportTime());
|
|
|
- System.out.println("气体浓度: " + parsed.getGasConcentration() + " %LEL");
|
|
|
+ System.out.println("气体浓度: " + parsed.getGasConcentration() + " " + parsed.getGasUnit());
|
|
|
System.out.println("气体类型: " + parsed.getGasType());
|
|
|
System.out.println("电池电量: " + parsed.getBattery());
|
|
|
System.out.println("信号强度: " + parsed.getSignalStrength());
|
|
|
+ System.out.println("温度: " + parsed.getTemperature() + " °C");
|
|
|
+ System.out.println("湿度: " + parsed.getHumidity() + " %");
|
|
|
System.out.println("经度: " + parsed.getLongitude());
|
|
|
System.out.println("纬度: " + parsed.getLatitude());
|
|
|
System.out.println("入库时间: " + parsed.getCreateTime());
|
|
|
}
|
|
|
-}
|
|
|
+}
|