我正在尝试创建一个小型家庭监控系统。我有一系列将测量数据传输到基站的无线发射器。我可以使用 Modbus RTU 查询该基站,以找出每个发射器的最新测量值。
为了存储测量结果和可视化,我使用了 InfluxDB 和 Grafana。我的一切都在 Raspberry Pi Model 3B+ 上运行,包括与基站的 RS-485 通信。
我选择使用 Python 从 Modbus RTU 读取数据,然后将其转发到 InfluxDB 进行存储,因为 Python 已经为两者提供了现成的库。但是,我正在努力使 Python 脚本稳定。不可避免地,我时不时地在 Modbus 传输中遇到 CRC 错误,并且当 minimummodbus 库引发这些异常之一时,脚本似乎卡住了。
我不确定我应该如何解决这个问题。
目前我正在使用 try-except-else 结构,但是因为我是 Python 的新手,所以我无法让它按照我想要的方式工作。如果我失去一个测量点也没关系。这意味着如果我得到一个 CRC 错误,我可以忘记那个测量并像什么都没发生过一样继续进行。
我目前使用的代码(最小化)如下所示:
#!/user/bin/env python
import minimalmodbus
import time
from influxdb import InfluxDBClient
# influxdb stuff
influx = InfluxDBClient(host='localhost', port=8086)
influx.switch_database('dbname')
# minimalmodbus stuff
minimalmodbus.BAUDRATE = 9600
instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 1)
errorcounter = 0
cyclecounter = 0
while True:
try:
sid1te = instrument.read_register(247, 1, 4)
print "SID 1 TE:", sid1te
influxquery = [
{"measurement": "sid1", "fields": { "te": sid1te}},
{"measurement": "system", "fields": { "errorcounter": errorcounter}},
{"measurement": "system", "fields": { "cyclecounter": cyclecounter}}
]
print "InfluxDB query result:", influx.write_points(influxquery)
except Exception as error:
print "[!] Exception occurred: ", error
errorcounter = errorcounter + 1
else:
print "[i] One cycle completed."
cyclecounter = cyclecounter + 1
time.sleep(30)
最终发生的是脚本可以像梦一样运行几个小时,然后,当传输中发生单个 CRC 错误时,它会进入一个永无止境的异常循环,如下所示:
[!] Exception occurred: Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
[!] Exception occurred: Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
[!] Exception occurred: Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
[!] Exception occurred: Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
[!] Exception occurred: Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
[!] Exception occurred: Checksum error in rtu mode: '\xeb\xf9' instead of 'p\x97' . The response is: '\x7f\x01\x04\x02\x00\xeb\xf9' (plain response: '\x7f\x01\x04\x02\x00\xeb\xf9')
当我使用 CTRL-C 退出时,脚本实际上看起来在 sleep 命令中:
^CTraceback (most recent call last):
File "temp.py", line 92, in <module>
time.sleep(30)
KeyboardInterrupt
所以我很困惑,如果它实际上在程序循环中,为什么它不向控制台输出正常的打印命令。
在实际脚本中,我有三打 instrument.read_register 调用,所以我不确定是否应该创建一个不同的函数来处理 per-read_register 调用的异常或什么?在过去的一周里,我尝试了六种代码的变体,但由于脚本陷入异常循环,我在 Grafana 中获得的数据非常糟糕。
有什么建议么?