Search for examples for serial request node usage (/dev/ttyUSB0)

Hello everyone,

I hope you all had a wonderful Christmas!

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?

Many thanks in advance!!!

Best regards,
Thomas

Yes.

A couple of initial things.

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. :smiley:

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?

1 Like

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...

Screenshot 2025-12-27 at 22.12.19

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.

Good Morning!

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 changing position. 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.

Understood, thank you!
:grinning_face:

@Colin
I'm afraid I didn't quite understand.

My device shows:

pi@rpi4B:~ $ ls -l /dev/serial/by-id
insgesamt 0
lrwxrwxrwx 1 root root 13 27. Dez 19:03 usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 -> ../../ttyUSB0

But how can I use (select) this in the serial request node?
Only /dev/ttyUSB0 is shown there…

Thx!

/dev/serial/by-id/usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0

You use that instead of what you have.

Can't you just paste it in?

One other thing you could do is use mqtt to publish the data and have NR subscribe to it.
If you want an example, you could take a look at this:

I’ve been using it since 2023.

@TotallyInformation

of course I can paste it in, but it does not work.
I get the following error messages:

[serialconfig:09614f9a6fbf61f0] Serieller Port Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001 FEHLER: Error: Error: No such file or directory, cannot open Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001
[serialconfig:09614f9a6fbf61f0] Serieller Port usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 FEHLER: Error: Error: No such file or directory, cannot open usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0

So I have to live with heartache :wink:

Did you include the /dev... On the front? It should be exactly the same as you get on your system from the ls /dev/serial/by-id command

I don't use the generic serial node but I do use the RFX nodes:

Which work perfectly.

I believe Max borrowed from the original core serial node when he created the RFX ones.

@TotallyInformation
Thanks a lot and sorry!
When using the the “correct string” it works also on my side!

But it was not clear to me (linux laymen) that
“It should be exactly the same as you get on your system from the ls /dev/serial/by-id command”
means that I should use what got (usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0)
and also what I entered (/dev/serial/by-id).

But the headache still present and I need help using the serial Node(s).
Post coming soon…

To everyone!

Which serial nodes (serial in, serial out, serial request or serial control) do I need to use to replicate the following communication with Node-Red:


15:18:59.118 Read 05
15:18:59.246 Write 01 C7 F8 04 04
15:18:59.381 Read 20 53 01 1E
15:18:59.500 Write 04

Explanation:
0x05 is sent from a heating device approximately every second and shall be received by /dev/ttyUSB0.

As can be seen, approximately 100ms after receiving 05, 5 bytes (01 C7 F8 04 04) shall be sent and 4 bytes (20 53 01 1E) shall be received (by /dev/ttyUSB0).

As can be seen, approximately 100ms later, 04 shall be sent.

I hope somebody can help me with an example.
I probably won't be able to do it on my own so quickly :downcast_face_with_sweat:

Thank you!

Understandable. One of the first things to learn about UNIX-like operating systems though is that they tend to treat everything as a file. Also, on all OS's it is best to use absolute rather than relative filing system paths to save heartache later on. :smiley:

@dceejay

Thank you!
And yes, communication probably works just as you described it…

In the meantime, I have figured out the following:
You wrote send a buffer with ["0x01, 0xc7, 0xf8, 0x04"]
I think it should be ["0x01","0xc7","0xf8","0x04","0x04"]or [1, 199, 248, 4, 4]

because ["0x01, 0xc7, 0xf8, 0x04, 0x04"] “creates” a totally different buffer:

Further questions will probably follow...

Thank you very much!

1 Like

@dceejay & and to everyone else who is bored :sweat_smile:

Now I am ready for the next question:

As you can see in the screenshot at the bottom, I am able to receive the cyclic “value” 5 sent from my Viessmann heating device as expected using the serial in node configured as shown below.

For testing purposes, I wanted to deactivate and activate the serial interface /dev/ttyUSB0 using the serial control node, but this did not work as expected. Only deactivation works (marked with red arrows), activation (marked with green arrows) does not work.

Only after redeploying will the cyclical messages be received again.

What could be the reason for this?

Thanks and best regards
Thomas

Do you get the same symptom if you use /dev/serial/by-id/... as discussed earlier?