
对电表的读数进行远程收集并不是一项艰巨的任务,电表每年都越来越智能,必须自行发送所有信息,但是当然没有信息,但是信息分散了。 设备制造商显然也想通过销售他们的软件来赚钱。 我写这篇文章是为了节省所有执行类似任务的时间。
开始
该公司需要从电表中自动收集大约二十个读数。 为此,需要尽快且尽可能便宜。 因此,他们决定使用已经部署的Zabbix收集数据,但是要连接到计数器,有必要编写一个小的脚本,更多内容请参见下文。 事实证明,读数的收集只是需要收集的参数之一,板上有Debian的PC负责其余的工作,因此通过COM端口连接到计数器并不困难。 当然,对于大多数人来说,使用本地网络并从工业交换机或接口转换器获取信息将更加方便。
在连接选项中,您也可以考虑使用光学端口,尽管您将需要购买其他设备,但另一方面,您无需卸下密封圈。

用于连接仪表的端子位于密封盖下方。
因此,我们必须在一家网络公司上达成一致,我们需要拆除封条,执行工作,重新密封仪表。 但是最后达成了协议,有可能从容应对主要问题的解决。

解决问题
如下来自
官方文档。计数器采用ADDR-CMD-CRC格式的字节输入字符串,并给出ADDR-CMD-DATA-CRC,其中:
- ADDR-计数器名称(对于Mercury 203.2T-与序列号相同)
- CMD-代码命令
- 数据-数据取决于请求
- CRC-在此数据包的所有先前字节上计算出的2字节循环冗余码。 根据这种解释,不清楚在校验和字段中写什么。
不使用序列中的连字符;此处用于分隔逻辑块。
首先,使用标准的
konfigurator程序连接到计数器,然后使用嗅探器查看传输的数据包,找出应该添加到末尾的校验和。 下面是从柜台收到的那一行。

使用
CRC在线计算器 ,我们找到了需要用多项式0xA001计算CRC-16(Modbus)的条件。
一点Python
有足够的链接可以计算算法,因此我不再赘述。 为了进行开发,我使用了Python 3
def crc16(data): crc = 0xFFFF l = len(data) i = 0 while i < l: j = 0 crc = crc ^ data[i] while j < 8: if (crc & 0x1): mask = 0xA001 else: mask = 0x00 crc = ((crc >> 1) & 0x7FFF) ^ mask j += 1 i += 1 if crc < 0: crc -= 256 result = data + chr(crc % 256).encode() + chr(crc // 256).encode('latin-1') return result
现在,让我们尝试从计数器中获取其序列号并检查CRC。 您将
需要安装
pyserial模块
import serial import struct import time sn = 26222790
太好了! 现在,我们获得了第一费率和第二费率的能耗值,实际上,我们只需要更改团队字段并解析结果即可。
chunk += b'\x27' t1 = ''.join('{:02x}'.format(c) for c in out[5:9]) t2 = ''.join('{:02x}'.format(c) for c in out[9:13]) print ('T1 =', float(t1)*0.01, '(*)', 'T2 =', float(t2)*0.01, '(*)')
一切正常。 脚本的最终版本发布在
git上 。 将来,我计划增加对在本地网络上工作的支持。
为了进行开发,使用了Mercury-221 USB-> COM适配器,但是您可以将计数器直接连接到COM端口。
参考文献:
有关连接仪表的有用信息,请
点击此处。官方网站上的文件技术支持网站关于
Wikipedia上的 CRC