diff --git a/sdm630_mqtt.py b/sdm630_mqtt.py index 0bd413c..244f39c 100644 --- a/sdm630_mqtt.py +++ b/sdm630_mqtt.py @@ -31,6 +31,8 @@ class SDM630_MQTT: self.mqtt.on_connect = self._on_mqtt_connect self.mqtt.on_disconnect = self._on_mqtt_disconnect + self.idx = 0 + def _publish(self, topic, msg): LOG.debug(f"_publish({topic!r}, {msg!r})") self.mqtt.publish(f"{self.mqtt_prefix.rstrip('/')}/{topic}", msg) @@ -45,67 +47,71 @@ class SDM630_MQTT: LOG.debug("_start()") self.mqtt.connect(self.mqtt_host, self.mqtt_port, 10) self.mqtt.loop_start() + self.modbus.open() def stop(self): + LOG.debug("_stop()") + self.modbus.close() self.mqtt.loop_stop() self.mqtt.disconnect() def request_and_publish(self): - self.modbus.open() - for idx, (readable, address) in enumerate( - { - "active-power/L1": 0x000C, - "active-power/L2": 0x000E, - "active-power/L3": 0x0010, - "active-power/total": 0x0034, - "apparent-power/L1": 0x0012, - "apparent-power/L2": 0x0014, - "apparent-power/L3": 0x0016, - "apparent-power/total": 0x0038, - "current-demand/L1": 0x0102, - "current-demand/L2": 0x0104, - "current-demand/L3": 0x0106, - "current-demand/N": 0x0068, - "current-demand/max_L1": 0x0108, - "current-demand/max_L2": 0x010A, - "current-demand/max_L3": 0x010C, - "current-demand/max_N": 0x006A, - "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-demand/max": 0x0056, - "power-demand/total": 0x0054, - "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() - ): + for readable, address in { + "active-power/L1": 0x000C, + "active-power/L2": 0x000E, + "active-power/L3": 0x0010, + "active-power/total": 0x0034, + "apparent-power/L1": 0x0012, + "apparent-power/L2": 0x0014, + "apparent-power/L3": 0x0016, + "apparent-power/total": 0x0038, + "current-demand/L1": 0x0102, + "current-demand/L2": 0x0104, + "current-demand/L3": 0x0106, + "current-demand/N": 0x0068, + "current-demand/max_L1": 0x0108, + "current-demand/max_L2": 0x010A, + "current-demand/max_L3": 0x010C, + "current-demand/max_N": 0x006A, + "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-demand/max": 0x0056, + "power-demand/total": 0x0054, + "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(): try: read = self.modbus.read_input_registers(address, 2) + self.idx += 1 + if read is None: + LOG.error(f'reading {readable} was None: {self.modbus.last_error_as_txt}') + continue longs = word_list_to_long(read) if len(longs) == 1: self._publish(readable, decode_ieee(longs[0])) @@ -113,10 +119,10 @@ class SDM630_MQTT: self._publish(readable, sum([decode_ieee(x) for x in longs])) except Exception: LOG.exception(f'error while reading {readable} from meter') - if idx % 20: + if self.idx >= 20: self.modbus.close() self.modbus.open() - self.modbus.close() + self.idx = 0 if __name__ == "__main__": @@ -127,11 +133,12 @@ if __name__ == "__main__": except Exception as e: print(f"Usage: {argv[0]} config.toml") exit(1) - client = SDM630_MQTT(config) - client.start() try: + client = SDM630_MQTT(config) + client.start() while True: client.request_and_publish() except Exception as e: LOG.exception("oops") + finally: client.stop()