最近在做一个抄表系统,其协议是基于DL645-2007的,内容如下
根据以上规则可以尝试解析 68 78 56 34 12 00 00 68 91 08 33 33 34 33 A4 56 79 38 F5 16
传输次序-低在前,高在后,然后再加0x33,就是33 33 34 33了
返回数据:68 78 56 34 12 00 00 68 91 08 33 33 34 33 A4 56 79 38 F5 16
注意,这里面没有前导字节FE,并不代表所有的电表厂家都没有,而且还是不固定的,所以一定小心写程序,因为不同厂家电表回的前导字节个数不一样。
其中:78 56 34 12 00 00 是表地址,传输次序是低在前,高在后,而且是十六进制。
91-为从返回命令
08-共8个字节
33 33 34 33-数据块,可以理解成寄存器地址。
A4 56 79 38-具体数据,分析时,应减33,所以为:
A4-33=71
56-33=23
79-33=46
38-33=5
实际的电表数为:54623.71度
看下效果 数据是base64加密的
代码解析效果
主要解析代码
public void analysis(String command) {
JSONObject m_data = new JSONObject();
//解析报文格式
String[] newCommands = command.trim().split(" ");
if (newCommands.length < 16 || newCommands.length > 26 || Integer.parseInt(newCommands[0]) != 68 || Integer.parseInt(newCommands[newCommands.length - 1]) != 16) {
log.error("非法帧,无法解析!");
} else {
log.debug("报文源码:" + command);
log.debug("帧起始符:" + newCommands[0]);
String meter_serial = newCommands[6].concat(newCommands[5]).concat(newCommands[4]).concat(newCommands[3]).concat(newCommands[2]).concat(newCommands[1]);
log.debug("电表地址:" + meter_serial);
log.debug("控制域:" + newCommands[8]);
log.debug("数据域长度:" + newCommands[9]);
log.debug("校验码:" + newCommands[newCommands.length - 2]);
log.debug("停止位:" + newCommands[newCommands.length - 1]);
//取单个电表地址,组成单个对象
String a1 = Integer.toHexString(Integer.parseInt(newCommands[13], 16) - 51);
String a2 = Integer.toHexString(Integer.parseInt(newCommands[12], 16) - 51);
String a3 = Integer.toHexString(Integer.parseInt(newCommands[11], 16) - 51);
String a4 = Integer.toHexString(Integer.parseInt(newCommands[10], 16) - 51);
String DTID0 = newCommands[13].equals("32") ? newCommands[13] = "FF" : (a1.length() > 1 ? a1 : "0".concat(a1));
String DTID1 = newCommands[12].equals("32") ? newCommands[12] = "FF" : (a2.length() > 1 ? a2 : "0".concat(a2));
String DTID2 = newCommands[11].equals("32") ? newCommands[11] = "FF" : (a3.length() > 1 ? a3 : "0".concat(a3));
String DTID3 = newCommands[10].equals("32") ? newCommands[10] = "FF" : (a4.length() > 1 ? a4 : "0".concat(a4));
String sbr = DTID0.concat(DTID1).concat(DTID2).concat(DTID3);
Map map = CommandEnum.getMap();
String obj = map.get(sbr);
if (obj != null) {
log.debug("标识符 {}, 数据标识{} ", sbr, obj);
} else {
log.debug("未知数据标识 {} ", sbr);
return;
}
//解析返回数据
if (newCommands.length > 16) {
List list3 = new ArrayList();
for (int i = 0; i < Integer.parseInt(newCommands[9], 16) - 4; i++) {
list3.add(newCommands[newCommands.length - 3 - i]);
}
String[] data = list3.toArray(new String[list3.size()]);
String num = (Tools.dataFormat(data)).toString();
BigDecimal bigDecimal = new BigDecimal(num);
if (DTID0.equals("00") && DTID1.equals("00") && DTID2.equals("00") && DTID3.equals("00")) {
BigDecimal totalPower = bigDecimal.multiply(new BigDecimal("0.01"));
log.debug("当前组合有功总电能: {} k·Wh", totalPower);
m_data.put("totalPower", totalPower);
} else if (DTID0.equals("02") && DTID1.equals("01") && !DTID2.equals("FF")) { //电压0.1v
BigDecimal UA = bigDecimal.multiply(new BigDecimal("0.1"));
m_data.put("UA", UA.doubleValue());
} else if (DTID0.equals("02") && DTID1.equals("02") && !DTID2.equals("FF")) { //电流0.001A
String isNegative = bigDecimal.toString().substring(0, 1).equals("8") ? "0".concat(bigDecimal.toString().substring(1)) : bigDecimal.toString();
BigDecimal IA = new BigDecimal(isNegative).multiply(new BigDecimal("0.001"));
m_data.put("IA", IA.doubleValue());
} else if ((DTID0.equals("02") && DTID1.equals("03")) || (DTID0.equals("02") && DTID1.equals("04")) || (DTID0.equals("02") && DTID1.equals("05"))) { //有无功功率0.0001kW
String isNegative = bigDecimal.toString().substring(0, 1).equals("8") ? "0".concat(bigDecimal.toString().substring(1)) : bigDecimal.toString();
BigDecimal POWER_TOTAL = new BigDecimal(isNegative).multiply(new BigDecimal("0.0001"));
m_data.put("POWER", POWER_TOTAL.doubleValue());
} else if (DTID0.equals("02") && DTID1.equals("06")) { //功率因数0.001
String isNegative = bigDecimal.toString().substring(0, 1).equals("8") ? "0".concat(bigDecimal.toString().substring(1)) : bigDecimal.toString();
String pf = Integer.parseInt(isNegative) > 1000 ? "1000" : isNegative;
BigDecimal POWER_FACTOR = new BigDecimal(pf).multiply(new BigDecimal("0.001"));
m_data.put("POWER_FACTOR", POWER_FACTOR.doubleValue());
} else if (DTID0.equals("00") && DTID1.equals("01")) { //正向有功总电能0.01
BigDecimal USE_TOTAL = bigDecimal.multiply(new BigDecimal("0.01"));
m_data.put("POSITIVE_TOTAL", USE_TOTAL.doubleValue());
} else if (DTID0.equals("00") && DTID1.equals("02")) { //反向有功总电能0.01
BigDecimal USE_TOTAL = bigDecimal.multiply(new BigDecimal("0.01"));
m_data.put("REVERSE_TOTAL", USE_TOTAL.doubleValue());
} else if (DTID0.equals("02") && DTID3.equals("02")) { //电网频率0.01
BigDecimal GRID_FREQUENCY = bigDecimal.multiply(new BigDecimal("0.01"));
m_data.put("GRID_FREQUENCY", GRID_FREQUENCY.doubleValue());
} else if (DTID0.equals("02") && DTID1.equals("01") && DTID2.equals("FF")) { //电压数据块
BigDecimal UC = new BigDecimal(String.valueOf(num).substring(0, 4)).multiply(new BigDecimal("0.1"));
log.debug("C相电压" + UC);
BigDecimal UB = new BigDecimal(String.valueOf(num).substring(4, 8)).multiply(new BigDecimal("0.1"));
log.debug("B相电压" + UB);
BigDecimal UA = new BigDecimal(String.valueOf(num).substring(8)).multiply(new BigDecimal("0.1"));
log.debug("A相电压" + UA);
m_data.put("UA", UA.doubleValue());
m_data.put("UB", UB.doubleValue());
m_data.put("UC", UC.doubleValue());
} else if (DTID0.equals("02") && DTID1.equals("02") && DTID2.equals("FF")) { //电流数据块
String icString = String.valueOf(num).substring(0, 6);
String icisNegative = icString.substring(0, 1).equals("8") ? "0".concat(icString.substring(1)) : icString;
BigDecimal IC = new BigDecimal(icisNegative).multiply(new BigDecimal("0.001"));
log.debug("C相电流" + IC);
String ibString = String.valueOf(num).substring(6, 12);
String ibisNegative = ibString.substring(0, 1).equals("8") ? "0".concat(ibString.substring(1)) : ibString;
BigDecimal IB = new BigDecimal(ibisNegative).multiply(new BigDecimal("0.001"));
log.debug("B相电流" + IB);
String iaString = String.valueOf(num).substring(12);
String iaisNegative = iaString.substring(0, 1).equals("8") ? "0".concat(iaString.substring(1)) : iaString;
BigDecimal IA = new BigDecimal(iaisNegative).multiply(new BigDecimal("0.001"));
log.debug("A相电流" + IA);
m_data.put("IA", IA.doubleValue());
m_data.put("IB", IB.doubleValue());
m_data.put("IC", IC.doubleValue());
} else {
System.out.println("未知数据标识!");
}
System.out.println("m_data = " + m_data);
}
}
}