基于DL/T645-07协议的电表数据采集终端

本文介绍了一种针对智能电表的非环保行业数据采集系统设计,详细阐述了数据采集流程、DL/T645-07协议解析、数据采集模块设计、数据统计模块设计等关键环节,以及系统的稳定性和可靠性保障措施。

本文总结自两年前我负责的一个小项目,完全自主架构,同时也是所开发的唯一一个非环保行业数据采集软件,我觉得很有必要记录下。

一、前言

工作中经手的数采系统也不算少了,之前接触到的都是环境监测行业的数据采集,直到两年前接收了一个远程采集智能电表电能数据的项目。

由于行业不同,外加采集方式有所区别,此前数采系统的架构均不适合,需要重新设计一个结构。

当时我开发的这套电表数采,在这个项目中充当数据源的角色,仅需要实现智能电表的数据采集、统计和保存,展示和应用分析不在要求之内。也就是说,我只需要保证数据正常入库即可。

二、数据采集流程

之前说过,智能电表的数据采集方式跟我之前接触过的环保行业有所区别。

2.1 环保行业数据采集流程

环保行业(环境空气地表水)现场都具备工控机,由工控机跟分析仪通过串口或网口直接通讯,采集完数据后,按照HJ212-2017协议组包上传给中心服务器,大致的流程如下图:
在这里插入图片描述

2.2 电表数据采集流程

对于智能电表而言,现场不配备工控机,直接通过DTU实现透传。每个电表有一个唯一地址,即中心服务器可直接通过DTU与其下挂载的电表直接通讯,大致如下图所示。
在这里插入图片描述
由于DTU数量是不确定的,后期可能会加装,联网状态也是不确定的,程序启动时无法预知有效客户端的数量。因此,设计时需要考虑动态挂载。

首先,DTU需要配置服务器的IP和端口号,并在上线后向服务器发送一个注册包,约定好注册包的内容为此DTU的ID。这个ID是人为定义的,且必须唯一,其作用是在服务器上能识别出是哪个DTU上线。

此外,单个DTU下可挂载多个电表,DTU和电表对的对应关系需要提前在数据库中配置好,一旦DTU上线后成功识别出注册包,根据配置创建出此DTU下所有挂载的电表,由服务器根据电表地址,主动轮询取数。

解析出数据后,每隔5分钟或者10分钟保存一组瞬时数据,直接入库。

三、DL/T645-07协议解析

DL/T645协议是针对电表通信而制定的通信协议,主要有两个版本,分别是DL/T645-97和DL/T645-07,目前最新版本是2007版,而项目中电表虽然有多个幸好,但采用的都是07版本。因此,仅需要兼容这一个版本的协议即可。

有点类似ModBus协议,格式如下:
在这里插入图片描述
据此设计如下的出解析算法。

public bool TryParse(byte[] data)
{
   
   
    // 校验包头和包尾
    if (data[0] != 0x68 && data[data.Length - 1] != 0x16)
    {
   
   
        return false;
    }

    // 校验和
    byte[] dest = new byte[data.Length - 2];
    Buffer.BlockCopy(data, 0, dest, 0, data.Length - 2);
    if (CheckSum(dest) != data[data.Length - 2])
    {
   
   
        return false;
    }

    // 校验地址
    bool isSameAddress = true;
    for (int i = 0; i < m_Address.Length; i++)
    {
   
   
        if (m_Address[i] != dest[i + 1])
        {
   
   
            isSameAddress = false;
            break;
        }
    }
    if (!isSameAddress)
    {
   
   
        return false;
    }

    // 校验数据长度
    int dataLen = dest[9];
    int realLen = dest.Length - 10;
    if (dataLen != realLen)
    {
   
   
        return false;
    }

    // 截取数据段
    byte[] realData = new byte[dataLen];
    Buffer.BlockCopy(dest, 10, realData, 0, dataLen);
    // 数据包-0x33
    List<byte> dataFlagMinus33 = new List<byte>();
    for (int i = 0; i < realData.Length; i++)
    {
   
   
        realData[i] -= 0x33;
        if (i < 4)
        {
   
   
            dataFlagMinus33.Add(realData[i]);
        }
    }

    // DataFlag倒置回来
    dataFlagMinus33.Reverse();
    for (int i = 0; i < 4; i++)
    {
   
   
        realData[i] = dataFlagMinus33[i];
    }

    return Parse(realData);
}

/// <summary>
/// 和校验
/// </summary>
protected static short CheckSum(IEnumerable<byte> data)
{
   
   
    int result = 0;
    foreach (byte b in data)
    {
   
   
        result += b;
    }
    return (byte)(result % 256);
}

四、数据采集模块设计

按照之前的开发习惯,将电表抽象为仪器Device,需要采集的数据抽象为因子Factor,DTU抽象为总线Bus。

4.1 因子类定义

public class Factor
{
   
   
    /// <summary>
    /// 电表地址
    /// </summary>
    public string TerminalID {
   
    get; private set; }

    /// <summary>
    /// 电表内挂载因子的索引
    /// </summary>
    public int IndexInDevice {
   
    get; private set; }

    /// <summary>
    /// 名称
    /// </summary>
    public string Name {
   
    get; private set; }

    /// <summary>
    /// 单位
    /// </summary>
    public string Unit {
   
    get; private set; }

    /// <summary>
    /// 统计系数,
    /// </summary>
    private float RealValuePara {
   
   
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值