diff --git a/README.md b/README.md index a0ac6c5..4a9f949 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ This bridigng component reads Dutch Smart Meter Requirements (DSMR) telegrams an * [DSMR Parser](https://github.com/ndokter/dsmr_parser) * [Homie4](https://github.com/mjcumming/homie4) -## Configuration +## Configuring the bridge Create some environment variables (e.g. with a .env file) to specify the required settings: @@ -18,10 +18,10 @@ DSMR_PORT=/dev/ttyUSB0 DSMR_PROTOCOL=V5 ``` -If you have forwared the raw serial signal through ser2net, you should use `DSMR_PORT=remote://:`, e.g.: +If you have forwared the raw serial signal through ser2net, you should use `DSMR_PORT=tcp://:`, e.g.: ```bash -DSMR_PORT=remote://forwarding-pi.local:3333 +DSMR_PORT=tcp://forwarding-pi.local:3334 ``` If you use credentials to access the MQTT broker, then alsp specify: @@ -33,4 +33,22 @@ MQTT_PASSWORD= Inspect the source [`app_settings.py`](app_settings.py) to find out about the other less frequently used settings. +## Configuring ser2net + +On the forwarding computer (e.g a Raspberry Pi) you need to install ser2net: + +```bash +sudo apt upgrade && sudo apt install ser2net +``` + +Then edit the configurion file `/etc/ser2net.yaml` and add + +```yaml +connection: &Dsmr + accepter: tcp,3334 + connector: serialdev, + /dev/ttyUSB0, + 115200n81, local +``` + ![Works with Homie](https://homieiot.github.io/img/works-with-homie.png) diff --git a/app.py b/app.py index c1e6e96..501dc51 100644 --- a/app.py +++ b/app.py @@ -9,24 +9,24 @@ from dsmr_parser.clients import SerialReader, SocketReader, SERIAL_SETTINGS_V2_2 from app_settings import Settings from device_dsmr import Device_DSMR -from serial import SerialException import logging logger = logging.getLogger(__name__) def main(): + cfg = Settings() + logfmt = "%(asctime)s [%(levelname)-5.5s] [%(name)s] %(message)s" - logging.basicConfig(level=logging.INFO, format=logfmt, filename="dsmr2mqtt.log") + logging.basicConfig(level=cfg.loglevel, format=logfmt, filename="dsmr2mqtt.log") # set up logging to console consolelog = logging.StreamHandler(sys.stdout) - consolelog.setLevel(logging.INFO) + consolelog.setLevel(cfg.loglevel) # set a format which is simpler for console use formatter = logging.Formatter(logfmt) consolelog.setFormatter(formatter) logging.getLogger("").addHandler(consolelog) - cfg = Settings() protocol_version: str = str(cfg.dsmr_protocol) if 'V2' in protocol_version: serial_setup = SERIAL_SETTINGS_V2_2 @@ -42,34 +42,35 @@ def main(): spec = telegram_specifications.V5 device = Device_DSMR("dsmr", name="Digitale Slimme Meter") - if "remote:" not in cfg.dsmr_port: - logger.info(f"using serial port {cfg.dsmr_port}") - reader = SerialReader(cfg.dsmr_port, serial_setup, spec) - else: - result = re.search(r"remote://([^:]+):(.+)", cfg.dsmr_port) + if "tcp:" in cfg.dsmr_port: + result = re.search(r"tcp://([^:]+):(.+)", cfg.dsmr_port) host = result.group(1) port = int(result.group(2)) logger.info(f"reading from remote host {host} on port {port}") reader = SocketReader(host, port, spec) + else: + logger.info(f"using serial port {cfg.dsmr_port}") + reader = SerialReader(cfg.dsmr_port, serial_setup, spec) def handle_next_telegram(): telegram = next(reader.read_as_object()) device.update(telegram) logger.info(f"New telegram at {telegram.P1_MESSAGE_TIMESTAMP.value}") - def startTimer(): - threading.Timer(cfg.dsmr_update_interval, startTimer).start() + def start_timer(): + threading.Timer(cfg.dsmr_update_interval, start_timer).start() try: handle_next_telegram() - except: + except UnicodeDecodeError: + logger.warning("Cannot decode telegram") + except Exception as ex: _thread.interrupt_main() + start_timer.has_decode_error = False - startTimer() + start_timer() # for telegram in serial_reader.read_as_object(): # device.update(telegram) - - if __name__ == "__main__": main() diff --git a/device_dsmr.py b/device_dsmr.py index a849143..a1a67d5 100644 --- a/device_dsmr.py +++ b/device_dsmr.py @@ -1,5 +1,4 @@ import logging -import datetime from homie.device_base import Device_Base from homie.node.node_base import Node_Base