I am looking for help with the following ‘problem’:
My gas heating is connected to my Rpi4B (USB Interface) and I can read data using the following Python script:
import serial
import time
SERIAL_PORT = '/dev/ttyUSB0'
def main():
ser = None
try:
ser = serial.Serial(SERIAL_PORT,
baudrate=4800,
parity=serial.PARITY_EVEN,
stopbits=serial.STOPBITS_TWO,
bytesize=serial.EIGHTBITS,
exclusive=True,
timeout=0)
# send reset
ser.write(bytes([0x04]))
print("tx 0x04")
if(wait_for_05(ser)):
# now read F8 4 bytes
#outbuff = bytes([0xC7,0xF8,0x04])
outbuff = bytes([0x01,0xC7,0xF8,0x04])
ser.reset_input_buffer()
ser.write(outbuff)
print("tx", bbbstr(outbuff))
receive_resp_telegr(4,0xF8,ser)
except Exception as e:
print(e)
finally:
if ser:
ser.close()
print("done. bye!")
def wait_for_05(ser:serial.Serial) -> bool:
# and for 30x100ms waited for an ENQ (0x05) - we do 50x100ms (1 byte @4800 ca. 0.002s)
for _ in range(50):
time.sleep(0.1)
try:
buff = ser.read(1)
print(buff)
except Exception as e:
print(e)
return False
#print(buff)
if(len(buff) > 0) and (int(buff[0]) == 0x05):
return True
print("Timeout waiting for 0x05")
return False
def receive_resp_telegr(rlen:int, addr:int, ser:serial.Serial):
inbuff = bytearray()
# for up 20x50ms serial data is read. (we do 20x100ms)
for _ in range(20):
time.sleep(0.1)
try:
inbytes = ser.read_all()
if(inbytes):
inbuff += inbytes
print("rx", bbbstr(inbuff))
except Exception as e:
print(e)
# 'evaluate'
if(len(inbuff) >= rlen):
print("f8 received", bbbstr(inbuff))
return
# timout
print("rx telegr timeout")
def bbbstr(data):
try:
return ' '.join([format(byte, '02x') for byte in data])
except:
return data
if __name__ == "__main__":
main()
The heating system then provides the following data, for example:
(myvenv) pi@rpi4B:~/optolink-splitter $ python3 readf8gwg_outbuff_0x01_0xC7_0xF8_0x04.py
tx 0x04
b'\x05'
tx 01 c7 f8 04
rx 20 53 01 1e
f8 received 20 53 01 1e
I assume that what works with the Python script can also be implemented directly in Node-RED with the serial request node.
Could someone assist me with this and tell me which values need to be entered in the yellow marked areas and show me how the Inject??? node needs to be structured so that exactly the same data can be sent and received as shown above?
Firstly, Serial ports are often exclusive. So if you have something already opening the port, you generally won't be able to have another process also opening it. There are ways around that but that is more complex and best avoided if possible.
The second point of note is that USB serial ports have a nasty habit of occasionally changing position. So on Linux, it is often best to use one of the more explicit dev locations that the udev service provides:
Using these will save you heartache in the future.
So noting those things, make sure your Python code isn't running before trying to connect Node-RED to the port.
As for the rest, I generally don't directly use a serial port and don't have the node installed. However, I would have thought that simply leaving those fields blank and dumping the output to debug would give you the clues you need?
If you leave those blank then it will use the timeout, so as you show it, it will give you the data after 10 seconds, so you might want to reduce that a bit. Once you see what comes back you will be better able to work out the best strategy.
Looking at the python code it looks like you may need to do two inject nodes...
one with a buffer of ["0x04"] then it should reply with "0x05" - then send a buffer with ["0x01, 0xc7, 0xf8, 0x04"] and you should get 4 bytes back...
To start with I would leave the wait for start char blank (IE don't wait for anything special - just dump anything - also set the split to be a timeout of say 20mS - (do experiment) - and deliver a binary buffer.
Then try each inject in turn - the first seems to say it is a reset - so maybe you only need to do that one - so that could be set to fire on deploy then the other any time you want to read.
Firstly, Serial ports are often exclusive. So if you have something already opening the port, you generally won't be able to have another process also opening it. There are ways around that but that is more complex and best avoided if possible.
Thank you very much for this hint!
The second point of note is that USB serial ports have a nasty habit of occasionally changingposition. So on Linux, it is often best to use one of the more explicit dev locations that the udev service provides:
I have read this somewhere before and have taken it into account by ensuring that only one USB port on my Rpi4B was in use during the “tests” listed above.
Thank you very much for that as well!
So noting those things, make sure your Python code isn't running before trying to connect Node-RED to the port.
Same!
And now I will try to understand and work on the other useful answers below.
That is not sufficient. If, during use, the USB port (not the serial connection but the USB itself) disconnects and then reconnects (which is not unusual) then it may well reconnect as a different port number. As suggested it is better to use /dev/serial/by-id/xxx as that will not change. Unless you change the serial/usb interface at least.