commit 9dd75085ad8b1a0f69aa2a58ac8ed1bcd246aef7 Author: Franziska Kunsmann Date: Sat Jul 27 15:42:50 2024 +0200 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f7275bb --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +venv/ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7544f5b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +paho-mqtt==1.6.1 +pyModbusTCP==0.2.1 diff --git a/sdm630_mqtt.py b/sdm630_mqtt.py new file mode 100644 index 0000000..9e2aaa5 --- /dev/null +++ b/sdm630_mqtt.py @@ -0,0 +1,121 @@ +import logging +from sys import argv +from time import sleep + +import paho.mqtt.client as mqtt +from pyModbusTCP.client import ModbusClient +from pyModbusTCP.utils import decode_ieee, word_list_to_long + +logging.basicConfig(level=logging.DEBUG) +LOG = logging.getLogger(__name__) + + +class SDM630_MQTT: + def __init__( + self, + modbus_host, + mqtt_host="localhost", + modbus_port=4196, + mqtt_port=1883, + modbus_unit=1, + mqtt_prefix="sdm630", + ): + self.modbus = ModbusClient( + host=modbus_host, + port=modbus_port, + unit_id=modbus_unit, + ) + self.modbus.timeout = 10 + + self.mqtt = mqtt.Client() + self.mqtt_host = mqtt_host + self.mqtt_port = mqtt_port + self.mqtt_prefix = mqtt_prefix + + self.mqtt.on_connect = self._on_mqtt_connect + self.mqtt.on_disconnect = self._on_mqtt_disconnect + + def _publish(self, topic, msg): + LOG.debug(f"_publish({topic!r}, {msg!r})") + self.mqtt.publish(f"{self.mqtt_prefix.rstrip('/')}/{topic}", msg) + + def _on_mqtt_connect(self, client, userdata, flags, rc): + LOG.info(f"Connected to mqtt server {self.mqtt_host}:{self.mqtt_port}") + + def _on_mqtt_disconnect(self, client, userdata, rc): + LOG.info(f"Disconnected from mqtt server {self.mqtt_host}:{self.mqtt_port}") + + def start(self): + LOG.debug("_start()") + self.mqtt.connect(self.mqtt_host, self.mqtt_port, 10) + self.mqtt.loop_start() + + def stop(self): + self.mqtt.loop_stop() + self.mqtt.disconnect() + + def request_and_publish(self): + self.modbus.open() + for idx, (readable, address) in enumerate( + { + "apparent-power/L1": 0x000C, + "apparent-power/L2": 0x000E, + "apparent-power/L3": 0x0010, + "apparent-power/total": 0x0034, + "current/L1": 0x0006, + "current/L2": 0x0008, + "current/L3": 0x000A, + "current/average": 0x002E, + "current/neutral": 0x00E0, + "current/total": 0x0030, + "export_kVArh": 0x004C, + "export_kWh": 0x004A, + "frequency": 0x0046, + "import_kVArh": 0x004E, + "import_kWh": 0x0048, + "phase-angle/L1": 0x0024, + "phase-angle/L2": 0x0026, + "phase-angle/L3": 0x0028, + "phase-angle/total": 0x003E, + "power-factor/L1": 0x001E, + "power-factor/L2": 0x0020, + "power-factor/L3": 0x0022, + "power-factor/total": 0x003E, + "reactive-power/L1": 0x0018, + "reactive-power/L2": 0x001A, + "reactive-power/L3": 0x001E, + "reactive-power/total": 0x003C, + "voltage/L1_L2": 0x00C8, + "voltage/L1_N": 0x0000, + "voltage/L2_L3": 0x00CA, + "voltage/L2_N": 0x0002, + "voltage/L3_L1": 0x00CC, + "voltage/L3_N": 0x0004, + "voltage/average": 0x002A, + }.items() + ): + read = self.modbus.read_input_registers(address, 2) + longs = word_list_to_long(read) + if len(longs) == 1: + self._publish(readable, decode_ieee(longs[0])) + else: + self._publish(readable, sum([decode_ieee(x) for x in longs])) + if idx % 20: + self.modbus.close() + self.modbus.open() + self.modbus.close() + + +if __name__ == "__main__": + client = SDM630_MQTT( + "192.168.1.254", + "nas.home.kunbox.net", + ) + client.start() + try: + while True: + client.request_and_publish() + sleep(2) + except Exception as e: + LOG.exception('oops') + client.stop()