dsmrreader / dsmr-reader

DSMR-telegram reader & data visualizer for hobbyists. Free for non-commercial use.
https://dsmr-reader.readthedocs.io
Other
460 stars 95 forks source link

Plugin/hook voor doorsturen telegrammen #557

Closed glsf91 closed 5 years ago

glsf91 commented 5 years ago

In de documentatie zie ik iets over hooks. Naar mijn idee zou je dan (denk ik) eenvoudig met dsmr_datalogger.signals.raw_telegram een stukje software moeten kunnen maken om het telegram naar een andere (virtuele) seriele poort weer uit te sturen. Dan kan dat bijv door Domoticz worden opgepakt. Maar het is me onduidelijk hoe je dat zou moeten doen. Daar is helaas geen voorbeeld van.

dennissiemensma commented 5 years ago

Bedankt voor je vraag. De reden dat er geen andere voorbeelden zijn, is dat er tot nu toe ook geen vraag naar is geweest (en het vaak redelijk geavanceerd is). Ik ondersteun je graag om te kijken of je wens via een plugin te realiseren is.

Heb je concreet wat meer informatie naar welke poort je het wil forwarden? Wellicht zelfs hoe dit makkelijk te testen is?

glsf91 commented 5 years ago

Ik wil met socat een virtuele poort A maken die doorlinkt naar een virtuele poort B. Het telegram wil ik dan doorsturen naar poort A. Socat stuurt dit weer door naar poort B. Deze poort B wil ik dan weer uitlezen met een ander programma (Domoticz). Zo dus 2 programma's voorzien van het P1 telegram. Ik zou verwachten dat dit relatief eenvoudig zou moeten zijn.

Wat nog wel relevant is of het telegram dan direct wordt doorgezet als het binnenkomt op DMSR-reader en niet pas als het verwerkt is?

dennissiemensma commented 5 years ago

Aah oke, dan denk ik dat ik even moet uitzoeken hoe ik met pySerial het dan kan doorsturen. Weet jij of daarvoor dezelfde regels gelden op die virtuele poort A? Baud rate, etc. Ik ben namelijk alleen bekend met het uitlezen ervan.

Wat betreft je vraag of het direct doorgezet wordt. Het gebeurt vrij vlot, direct nadat de meting (onverwerkt) wordt opgeslagen in de database: https://github.com/dennissiemensma/dsmr-reader/blob/v1.26.1/dsmr_datalogger/services.py#L278

glsf91 commented 5 years ago

Ja baudrate e.d. moet gelijk zijn. Volgens mij ziet de software geen verschil tussen een "echte" poort en een virtuele poort. Met socat kun je eventueel ook de baudrate zetten. Zo maak je de poort: sudo socat -u pty,link=/dev/ttyUSBvA,raw,echo=0,group=dialout,mode=0660 pty,link=/dev/ttyUSBvB,raw,echo=0,group=dialout,mode=0660 &

Je kan dan testen met: cat /dev/ttyUSBvB Alles wat je naar /dev/ttyUSBvA stuurt zie je op je scherm van de cat. Als je de socat wil testen doe je bijv: ls > /dev/ttyUSBvA. Dan moet het ook zichtbaar worden op de cat.

edit: socat unidirectioneel gemaakt

dennissiemensma commented 5 years ago

Ik heb in ieder geval iets werkend gekregen, wil je het eens proberen?

dsmrreader/settings.py (vermoedelijk toevoegen op nieuwe regel):

DSMRREADER_PLUGINS = [
    'dsmr_plugins.modules.forward_raw_telegram',
]

dsmr_plugins/modules/forward_raw_telegram.py (nieuw bestand):

import serial

from dsmr_datalogger.signals import raw_telegram
import dsmr_datalogger.services

def handle_raw_telegram(sender, **kwargs):
    DEST_PORT = '/dev/ttyUSBvA'
    connection_parameters = dsmr_datalogger.services.get_dsmr_connection_parameters()

    serial_handle = serial.Serial()
    serial_handle.port = DEST_PORT
    serial_handle.baudrate = connection_parameters['baudrate']
    serial_handle.bytesize = connection_parameters['bytesize']
    serial_handle.parity = connection_parameters['parity']
    serial_handle.stopbits = serial.STOPBITS_ONE
    serial_handle.xonxoff = 1
    serial_handle.rtscts = 0
    serial_handle.timeout = 1
    serial_handle.write_timeout = 0.2

    try:
        serial_handle.open()
        bytes_sent = serial_handle.write(bytes(kwargs['data'], 'utf-8'))
    except Exception as error:
        print(error)
    else:
        print(' >>> Sent {} bytes to {}'.format(bytes_sent, DEST_PORT))

    serial_handle.close()

raw_telegram.connect(receiver=handle_raw_telegram)

Vergeet niet om de app te herladen, het makkelijkste is dat met ./post-deploy.sh.

glsf91 commented 5 years ago

Dat werkt prima zo te zien. Er is alleen 1 probleem. Als er niets luistert op poort B dan wordt de verwerking P1 DSMR TELEGRAMS in DSMR-reader geblokkeerd na een tijdje. Waarschijnlijk omdat de buffer volloopt. Ben even aan het zoeken of dat in socat is op te lossen. Het is niet erg dat er pakketten verloren gaan als de buffer volloopt. Alleen blokkeren is niet de bedoeling.

dennissiemensma commented 5 years ago

Je zou nog kunnen kijken of het instellen van een timeout helpt: https://pyserial.readthedocs.io/en/latest/pyserial_api.html

write() is blocking by default, unless write_timeout is set. For possible values refer to the list for timeout above.
Possible values for the parameter timeout which controls the behavior of read():

timeout = None: wait forever / until requested number of bytes are received
timeout = 0: non-blocking mode, return immediately in any case, returning zero or more, up to the requested number of bytes
timeout = x: set timeout to x seconds (float allowed) returns immediately when the requested number of bytes are available, otherwise wait until the timeout expires and return all bytes that were received until then.

Ik zie in mijn code dat de timeout nog op 20 seconden staat:

 serial_handle.timeout = 20

Kun je daar mee spelen om te kijken of dat het oplost? Vergeet niet de applicatie te herladen na wijzigingen.

glsf91 commented 5 years ago

Deze is voor read. Voor write moet serial_handle.write_timeout = 0.2 worden gebruikt. Ik krijg elke 1 sec een telegram vandaar nu op 0.2 gezet. Dit gaat zo te zien goed: Most recent reading: a second ago. Soms 2 seconden.

Waar komt overigens de logging (bijv print(' >>> Sent {} bytes to {}'.format(bytes_sent, DEST_PORT))) te staan? Of moet je die eerst nog aanzetten?

dennissiemensma commented 5 years ago

Die komt terug in de log van het proces dat de datalogging verzorgt. Meestal is dat dsmr_datalogger, maar het kan ook de API zijn. In jouw geval is het de eerste denk ik en die staat in /var/log/supervisor/dsmr_datalogger.log.

Je kunt hem ook uitzetten door de hele print-regel te vervangen met pass. Edit: Nog beter, je kunt gewoon de regel plus de else weghalen.

glsf91 commented 5 years ago

Zie het:

Write timeout Write timeout Write timeout

Sent 884 bytes to /dev/ttyUSBvA Sent 884 bytes to /dev/ttyUSBvA Sent 884 bytes to /dev/ttyUSBvA Sent 884 bytes to /dev/ttyUSBvA

Werkt dus goed zo te zien. Bedankt. Heb je gelijk weer een voorbeeld voor in de documentatie :-)

dennissiemensma commented 5 years ago

Top, jij ook bedankt voor het proberen. Ik zal het later toevoegen aan de documentatie, lijkt me inderdaad een nuttige toevoeging.

dennissiemensma commented 5 years ago

Toegevoegd voor de volgende release.

zuidwijk commented 4 years ago

Ik heb een vraagje over bovenstaand. Ik ben namelijk met het omgekeerde bezig. In de meterkast hangt een RPi met p1 monitor erop. Deze heeft ook fysiek de usb-device gekoppeld zitten. Nu wil ik dsmr-reader parallel gaan draaien. Deze draait in een docker op een andere device.

Op de RPi stuur ik alles van /dev/ttyUSB0 door via socat op een specifieke poort: socat /dev/ttyUSB0,raw,echo=0,ospeed=115200 tcp-listen:8888,reuseaddr Op de andere device maak ik een virtuele poortmapping met: sudo socat PTY,raw,echo=0,ispeed=115200,link=/dev/ttyVUSB0 tcp:<ip-van-rpi>:8888 Als ik vervolgens op de andere device daar deze poort kijkt, zie ik alle pakketten binnen komen: sudo screen /dev/ttyVUSB0 115200

1-3:0.2.8(50) 0-0:1.0.0(200111155231W) 0-0:96.1.1(4530303433303036393832323537393137) 1-0:1.8.1(003544.314kWh) 1-0:1.8.2(003220.083kWh) 1-0:2.8.1(000001.545kWh) 1-0:2.8.2(000000.000kWh) 0-0:96.14.0(0001) 1-0:1.7.0(00.290kW) 1-0:2.7.0(00.000kW) 0-0:96.7.21(00011) 0-0:96.7.9(00003) 1-0:99.97.0(1)(0-0:96.7.19)(171027165014S)(0000070436s) 1-0:32.32.0(00004) 1-0:32.36.0(00001) 0-0:96.13.0() 1-0:32.7.0(228.2V) 1-0:31.7.0(001A) 1-0:21.7.0(00.289kW) 1-0:22.7.0(00.000kW) 0-1:24.1.0(003) 0-1:96.1.0(4730303332353635353431303434313137) 0-1:24.2.1(200111155004W)(01340.039m3) !F61E

Als ik daarna dsmr-reader via een docker start met de mapping /dev/ttyVUSB0:/dev/ttyUSB0 komt er niks binnen.

Als ik de USB direct koppel (en dus /dev/ttyUSB0:/dev/ttyUSB0 als mapping gebruik) werkt het wel.

Zie ik iets over het hoofd?

glsf91 commented 4 years ago

Misschien de rechten op /dev/ttyVUSB0 aangezien deze onder root wordt gestart?

zuidwijk commented 4 years ago

Misschien de rechten op /dev/ttyVUSB0 aangezien deze onder root wordt gestart?

Da's inderdaad een goeie. /dev/ttyVUSB0 is een link naar /dev/pts/1 met 660 als rechten en root.tty als groep. Zelfs als ik er 777 van maak en dialout als groep, werkt het nog niet... ff verder puzzelen maar, berichten komen iig binnen, nu nog lezen.

zuidwijk commented 4 years ago

Misschien de rechten op /dev/ttyVUSB0 aangezien deze onder root wordt gestart?

Heb wat extra parameters meegegeven group-late=dialout,mode=666 zodat het er nu zo uitziet: sudo socat PTY,raw,echo=0,ispeed=115200,link=/dev/ttyVUSB0,group-late=dialout,mode=666 tcp:<ip-adres>:8888

pi@pi:\~/docker/dsmr $ ls -lah /dev/ttyVUSB0 lrwxrwxrwx 1 root root 10 Jan 11 16:02 /dev/ttyVUSB0 -> /dev/pts/1 pi@pi:\~/docker/dsmr $ ls -lah /dev/pts/ total 0 drwxr-xr-x 2 root root 0 Feb 14 2019 . drwxr-xr-x 16 root root 3.7K Jan 11 16:02 .. crw--w---- 1 pi tty 136, 0 Jan 11 16:02 0 crw-rw-rw- 1 root dialout 136, 1 Jan 11 16:02 1 crw--w---- 1 pi tty 136, 2 Jan 11 16:03 2 c--------- 1 root root 5, 2 Feb 14 2019 ptmx pi@pi:~/docker/dsmr $

Ik kan als gewone user nu de screen uitvoeren, dus de rechten zijn aangepast (voorheen moest ik sudo screen doen). Maar er komen helaas nog geen berichten binnen dsmr-reader.

Heb je nog een paar tips voor me?

glsf91 commented 4 years ago

Ik zou het niet weten. Je moet niet met 2 progs tegelijk een port openen. Mijn ervaring is dat het naar 1 vd gaat. Je ziet dus niet alles dubbel. Mogelijk een docker dingetje. Daar heb ik geen ervaring mee.

Je kan ook nog even hier kijken: https://dsmr-reader.readthedocs.io/en/v2/troubleshooting.html maar ik weet niet of je de logging in docker kan aanzetten en bekijken. Je zou een foutmelding verwachten.

zuidwijk commented 4 years ago

Ik zou het niet weten. Je moet niet met 2 progs tegelijk een port openen. Mijn ervaring is dat het naar 1 vd gaat. Je ziet dus niet alles dubbel. Mogelijk een docker dingetje. Daar heb ik geen ervaring mee.

Je kan ook nog even hier kijken: https://dsmr-reader.readthedocs.io/en/v2/troubleshooting.html maar ik weet niet of je de logging in docker kan aanzetten en bekijken. Je zou een foutmelding verwachten.

Wat er nu gebeurd is dat dsmr-reader een virtuele poort gaat uitlezen, misschien kan dat niet? Zal de tshoot ff doornemen :)

glsf91 commented 4 years ago

Dat kan wel. Doe ik ook. Maar dan wel op Linux zonder docker

zuidwijk commented 4 years ago

Het is gelukt! In plaats van als device doorgeven aan docker, geef ik het als volume door aan docker.

Dus niet:

    devices:
      - /dev/ttyUSB0:/dev/ttyUSB0

Maar wel:

    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./dsmr_backups:/dsmr/backups
      - /dev/:/dev/
PhyxionNL commented 4 years ago

@zuidwijk , thanks, precies de configuratie die ik ook nodig had 👍 Vreemd dat de devices niet werkt maar dit is ook prima zo.

zuidwijk commented 4 years ago

@zuidwijk , thanks, precies de configuratie die ik ook nodig had 👍 Vreemd dat de devices niet werkt maar dit is ook prima zo.

Heeft denk met de rechten te maken van tty, daarom kan je het niet als device doorgeven, maar vreemd genoeg wel als een map/folder ;) Maar hey, het werkt of het werkt niet :)

bennybubble commented 6 months ago

Om de P1 data ook in een andere applicatie te kunnen gebruiken, wil ik bovenstaande ook proberen. Voordat ik dit ga testen heb ik maar 1 vraag, hoe vaak wordt de data verstuurd naar de tweede seriele poort? Maw wanneer wordt de 'hook' aangeroepen? Is dit maar 1 keer per minuut of elke keer als er P1 data binnenkomt? Dit laatste zou mijn voorkeur hebben omdat ik 'near realtime' mijn teruggeleverde vermogen kWh wil monitoren.

dennissiemensma commented 6 months ago

@bennybubble bij elk telegram, dus daar heb je zelf invloed op met de sleep.

Het is wellicht makkelijker om ser2net te gebruiken en zowel DSMR-reader als je tweede applicatie het te laten uitlezen. Dat is ook wat robuuster en minder gehack, mits in hetzelfde netwerk.

Zoals bijv: