基于DL645-2007多功能电能表通信协议报文解析

最近在做一个抄表系统,其协议是基于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加密的

 经过解密,转为16进制的

 代码解析效果

主要解析代码

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<String, String> 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<String> list3 = new ArrayList<String>();
                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);

            }

        }
    }

  • 6
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值