Closed glsf91 closed 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?
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?
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
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
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
.
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.
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.
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?
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.
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 :-)
Top, jij ook bedankt voor het proberen. Ik zal het later toevoegen aan de documentatie, lijkt me inderdaad een nuttige toevoeging.
Toegevoegd voor de volgende release.
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?
Misschien de rechten op /dev/ttyVUSB0 aangezien deze onder root wordt gestart?
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.
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?
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.
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 :)
Dat kan wel. Doe ik ook. Maar dan wel op Linux zonder docker
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/
@zuidwijk , thanks, precies de configuratie die ik ook nodig had 👍 Vreemd dat de devices niet werkt maar dit is ook prima zo.
@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 :)
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.
@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:
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.