电表数据采集

技术背景

在能源管理、建筑分项计量等工程应用场景中,对于电表数据的采集是经常使用的技术之一。电表数据采集的实现方法有很多,如利用组态软件采集、利用采集器硬件终端采集等,本文将利用开源框架编写电表数据采集程序,该程序可以运行在任何智能硬件上,更加符合软件定义硬件的理念。

技术基础

  • 基础框架:springboot 2.4.2
  • modbus模块
<dependency>
	<groupId>com.ghgande</groupId>
	<artifactId>j2mod</artifactId>
	<version>LATEST</version>
</dependency>
  • 数据库:mongodb 4.4.4
    采用docker部署,简单快捷。

技术原理

电表采集的常用通讯方式是modbus-rtu协议,需要敷设RS485通讯线,但是工程现场往往不具备线缆敷设条件,因此需要外加一个透传网关,利用以太网下发modbus-tcp协议指令,再转换成modbus-rtu协议,而以太网则可以通过现场安装无线路由器将4G信号转换成wifi信号,实现远程电表采集应用。

主要代码

采集总线-电表关系模型

  1. Meter.java
    电表类模型,描述电表的相关属性。
public class Meter {
    private int meterAddr;//表地址
    private String meterAsset;//表编号
    private Map<MetricName,PointSamplingMethod> metric;//电气量的采集方法
    //方法略
}
  1. PoingSamplingMethod.java
    采集方法模型,描述电表的电气量所采用的采集方法,电气量包括功率、电能等。
public class PointSamplingMethod {    
    private int addr;//电表地址
    private int registerAddr;//寄存器地址
    private int registerCount;//寄存器长度
    private float ratio;//变比
    private Integer point;//测点序号
    //方法略
}
  1. ModbusConfig.java
    modbus协议的基本配置,描述总线与电表之间的逻辑关系。
public class ModbusConfig {
    private String dnID;//采集设备编号
    private String busAddr;//总线地址
    private List<Meter> meters;//该总线上的电表列表       
    //方法略
}

modbus协议实现类

  1. ModbusController.java
    实现类代码如下。
public class ModbusController {
    private ModbusTCPMaster master;
    private boolean isConnect;
    private Integer delay;

    private ModbusConfig config;

    public ModbusController(ModbusConfig config) {
        this.config = config;
        this.master = new ModbusTCPMaster(config.getBusIp(),config.getBusPort(),false);
        this.master.setRetries(2);
        this.isConnect = false;
    }

    public void connect() throws Exception {
        this.master.connect();
         this.isConnect = true;        
    }

    public void disconnect() {
        this.master.disconnect();
        this.isConnect = false;
    }

    public List<DnPointData> read(MetricName metric, String period) throws Exception{
        List<DnPointData> data = new ArrayList<>();
        List<Meter> meters = config.getMeters();
        if (meters==null || meters.isEmpty()) {
            return data;
        }
        for (Meter meter:meters) {
            PointSamplingMethod method = meter.getMethod(metric);
            data.add(readValue(config.getDnID(),method.getAddr(),method.getRegisterAddr(),method.getRegisterCount(),method.getRatio(),method.getPoint(), Duration.parse(period)));
        }  
        return data;      
    }

    private DnPointData readValue(String dnID, int addr, int ref, int count, float ratio, Integer point, Duration period) {
        DnPointData pointData = new DnPointData();
        pointData.setDnID(dnID);
        pointData.setPoint(point);
        pointData.setPeriod(period);
        
        LocalDateTime timestamp = LocalDateTime.now();
        pointData.setTimestamp(timestamp);
        try {                
            if (!isConnect) {
                connect();
            }
            InputRegister[] registers = this.master.readMultipleRegisters(addr,ref,count);                
            if (registers.length==0 || registers.length>2) {          
                pointData.setValue((float) 0);          
                pointData.setQuality(DataQuality.failure);
                return pointData;
            }               

            int value = registers[0].getValue();
            if (count==2) {
                value = value<<16 | registers[1].getValue();
            }
                
            pointData.setValue(value*ratio);
            pointData.setQuality(DataQuality.good);
        }catch (Exception e) {
            pointData.setValue((float) 0);          
            pointData.setQuality(DataQuality.failure);
        }
        return pointData;
    }

    public Integer getDelay() {
        return delay;
    }

    public void setDelay(Integer delay) {
        this.delay = delay;
    }
}
  1. 代码说明
  • 首先,modbus-tcp协议需要建立tcp连接,因此可以通过构造方法导入总线-电表的关联关系,再使用connect()方法开启连接。
  • 其次,如果成功建立连接后,即可利用read()方法读取电表中寄存器的值。该方法有两个形参,第一个是描述所采集的电气量,第二个是描述采集的频率,该频率的描述需要符合ISO 8601。
  • 其中,read()方法调用了该类的私有方法readValue(),其核心的采集寄存器数据使用的是readMultipleRegisters(),并对读取出来的值进行处理,如果寄存器长度是2,则需要拼接,还要乘上变比,而对于读取失败的数据,还要置0并标记失败(failure)。
  • 最后,将采集结果存入数据库。

采集数据类

DnPointData.java
采集数据类,描述电表数据。

public class DnPointData {
    private String dnID;//采集设备编号
    private Integer point;//测点编号
    private Duration period;//采集频率
    private Float value;//采集的数据值
    private LocalDateTime timestamp;//采集的时间戳
    private DataQuality quality;//采集的数据质量
    //方法略
}

结语

本文简要描述了如何利用开源框架实现利用modbus协议的电表数据采集技术,在实际的远程抄表工程应用中,往往需要同时对现场多条总线的多块电表进行采集,在下一篇文章中,我将继续讲述如何利用xxl-job开源框架实现远程电表并发采集,敬请期待。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值