0

小さな家庭用監視システムを作成しようとしています。測定データを基地局に送信する一連のワイヤレス送信機があります。Modbus RTU を使用してその基地局にクエリを実行し、各送信機からの最新の測定値を見つけることができます。

測定値を保存して視覚化するために、InfluxDB と Grafana を使用しています。基地局への RS-485 通信を含め、Raspberry Pi Model 3B+ ですべてを実行しています。

Python を使用して Modbus RTU からデータを読み取り、それをストレージ用に InfluxDB に転送することにしました。これは、Python には両方の既製のライブラリがあるためです。ただし、Python スクリプトを安定させるのに苦労しています。必然的に、Modbus 送信で時々 CRC エラーが発生し、minimalmodbus ライブラリがこれらの例外の 1 つを発生させると、スクリプトが動かなくなるようです。

この問題にどのように取り組むべきかわかりません。

現時点では、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)

最終的に何が起こるかというと、スクリプトは夢のように何時間も実行できるということです。その後、送信で 1 つの 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

したがって、実際にプログラムループにある場合、通常の印刷コマンドをコンソールに出力しない理由について困惑しています。

実際のスクリプトでは、3 ダースの instrument.read_register 呼び出しがあるため、read_register 呼び出しごとに例外を処理する別の関数を作成する必要があるかどうかわかりません。この 1 週間で、このコードの 6 つのバリエーションを試しましたが、Grafana で取得したデータは、スクリプトが例外ループでスタックしているため、ひどいものです。

助言がありますか?

4

2 に答える 2