Using remote via tcp

This commit is contained in:
Ard Kuijpers
2023-02-12 16:10:03 +01:00
parent 5a9d08a611
commit 53022aebb8
3 changed files with 37 additions and 19 deletions

View File

@@ -7,7 +7,7 @@ This bridigng component reads Dutch Smart Meter Requirements (DSMR) telegrams an
* [DSMR Parser](https://github.com/ndokter/dsmr_parser) * [DSMR Parser](https://github.com/ndokter/dsmr_parser)
* [Homie4](https://github.com/mjcumming/homie4) * [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: 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 DSMR_PROTOCOL=V5
``` ```
If you have forwared the raw serial signal through ser2net, you should use `DSMR_PORT=remote://<hostname>:<port>`, e.g.: If you have forwared the raw serial signal through ser2net, you should use `DSMR_PORT=tcp://<hostname>:<port>`, e.g.:
```bash ```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: If you use credentials to access the MQTT broker, then alsp specify:
@@ -33,4 +33,22 @@ MQTT_PASSWORD=<mqtt-password>
Inspect the source [`app_settings.py`](app_settings.py) to find out about the other less frequently used settings. 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) ![Works with Homie](https://homieiot.github.io/img/works-with-homie.png)

31
app.py
View File

@@ -9,24 +9,24 @@ from dsmr_parser.clients import SerialReader, SocketReader, SERIAL_SETTINGS_V2_2
from app_settings import Settings from app_settings import Settings
from device_dsmr import Device_DSMR from device_dsmr import Device_DSMR
from serial import SerialException
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def main(): def main():
cfg = Settings()
logfmt = "%(asctime)s [%(levelname)-5.5s] [%(name)s] %(message)s" 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 # set up logging to console
consolelog = logging.StreamHandler(sys.stdout) consolelog = logging.StreamHandler(sys.stdout)
consolelog.setLevel(logging.INFO) consolelog.setLevel(cfg.loglevel)
# set a format which is simpler for console use # set a format which is simpler for console use
formatter = logging.Formatter(logfmt) formatter = logging.Formatter(logfmt)
consolelog.setFormatter(formatter) consolelog.setFormatter(formatter)
logging.getLogger("").addHandler(consolelog) logging.getLogger("").addHandler(consolelog)
cfg = Settings()
protocol_version: str = str(cfg.dsmr_protocol) protocol_version: str = str(cfg.dsmr_protocol)
if 'V2' in protocol_version: if 'V2' in protocol_version:
serial_setup = SERIAL_SETTINGS_V2_2 serial_setup = SERIAL_SETTINGS_V2_2
@@ -42,34 +42,35 @@ def main():
spec = telegram_specifications.V5 spec = telegram_specifications.V5
device = Device_DSMR("dsmr", name="Digitale Slimme Meter") device = Device_DSMR("dsmr", name="Digitale Slimme Meter")
if "remote:" not in cfg.dsmr_port: if "tcp:" in cfg.dsmr_port:
logger.info(f"using serial port {cfg.dsmr_port}") result = re.search(r"tcp://([^:]+):(.+)", cfg.dsmr_port)
reader = SerialReader(cfg.dsmr_port, serial_setup, spec)
else:
result = re.search(r"remote://([^:]+):(.+)", cfg.dsmr_port)
host = result.group(1) host = result.group(1)
port = int(result.group(2)) port = int(result.group(2))
logger.info(f"reading from remote host {host} on port {port}") logger.info(f"reading from remote host {host} on port {port}")
reader = SocketReader(host, port, spec) 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(): def handle_next_telegram():
telegram = next(reader.read_as_object()) telegram = next(reader.read_as_object())
device.update(telegram) device.update(telegram)
logger.info(f"New telegram at {telegram.P1_MESSAGE_TIMESTAMP.value}") logger.info(f"New telegram at {telegram.P1_MESSAGE_TIMESTAMP.value}")
def startTimer(): def start_timer():
threading.Timer(cfg.dsmr_update_interval, startTimer).start() threading.Timer(cfg.dsmr_update_interval, start_timer).start()
try: try:
handle_next_telegram() handle_next_telegram()
except: except UnicodeDecodeError:
logger.warning("Cannot decode telegram")
except Exception as ex:
_thread.interrupt_main() _thread.interrupt_main()
start_timer.has_decode_error = False
startTimer() start_timer()
# for telegram in serial_reader.read_as_object(): # for telegram in serial_reader.read_as_object():
# device.update(telegram) # device.update(telegram)
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@@ -1,5 +1,4 @@
import logging import logging
import datetime
from homie.device_base import Device_Base from homie.device_base import Device_Base
from homie.node.node_base import Node_Base from homie.node.node_base import Node_Base