Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node-Red Serial port? #80

Closed
crossband opened this issue Nov 18, 2019 · 10 comments
Closed

Node-Red Serial port? #80

crossband opened this issue Nov 18, 2019 · 10 comments

Comments

@crossband
Copy link

Dear All,

I have grafana, influxdb, mosquitto, nodered and portainer installed on Raspberry Pi 4, everything seems to be running. Node-Red GUI is also accessible on port 1880.

But I can not get the local serial port to work. Serial device is definitely working, I have checked it using screen /dev/ttyUSB0 115200 command. But it shows "not connected" in GUI.

Node-Red commands like node-red-stop are also do not work.

Did I perhaps something wrong? I have installed it following the IOTstack instructions, using ./menu.sh.

image

@gcgarner
Copy link
Owner

@crossband docker containers are placed in a sandbox and cannot access system hardware unless explicitly told to do so. I haven't 'enabled' the serial device by default, because I haven't had the opportunity to test it yet.

I've got a usb serial device lying around in a drawer somewhere, I'll try to get it working by Friday. There are some hoops with rights and the dialout group. That functionally I would need to build into the stack script

node-red-stop will not work when executing from the Pi's terminal. The sandbox concept means for all intents and purposed the nodered container is separate machine. Therefore you would need to access its terminal (like using ssh) to run commands against that container.

The preferred way of stopping and starting containers is via the docker command. You can type docker stop nodered and docker start nodered to stop and start them

@gcgarner
Copy link
Owner

I did a quick test and i was able to connect to the serial port, would you mind testing the following for me? edit you docker-compose.yml file and under nodered insert the privileged key

  nodered:
    container_name: nodered
    build: ./services/nodered/.
    restart: unless-stopped
    user: "0"
    privileged: true
    ports:
      - 1880:1880
    volumes:
      - ./volumes/nodered/data:/data

i can connect to my serial port but i've got nothing to talk to at the moment. I'd appreciate if you could test and let me know then i can update the project to reflect the changes

image

@gcgarner
Copy link
Owner

I forgot to add you will need to run docker-compose up -d from the IOTstack folder to restart nodered with the changes

@crossband
Copy link
Author

Thanks Graham for your prompt reply. It worked!
Now docker-compose.yml file looks like this:

version: '2'
services:
  nodered:
    container_name: nodered
    build: ./services/nodered/.
    restart: unless-stopped
    user: "0"
    privileged: true
    ports:
      - 1880:1880
    volumes:
      - ./volumes/nodered/data:/data

@gcgarner gcgarner changed the title Node-Red does not work properly on Raspbian 10? Node-Red Serial port? Nov 18, 2019
@gcgarner
Copy link
Owner

gcgarner commented Nov 18, 2019

I'll push an update later to make it available to everyone. For now to 'protect' your version from being overwritten the next time when you build the stack edit the file called services/nodered/service.yml (that file is used to build the docker-compose.yml file). add the privileged key there as well and if you build the stack select "dont overwrite" for node red

@gcgarner
Copy link
Owner

added to project on latest push

wemakerspace pushed a commit to wemakerspace/IOTstack that referenced this issue Sep 15, 2020
…rt9001

Mosquitto - remove port 9001 from template
@fewrainbows
Copy link

Hello Graham,

thank you in advance for you wordeful effort.

I'm getting an issue similar to Crossband.

A device (USB 2 RS485 dongle) connected to my RPi4 is giving me problems in nodered.

It has worked almost 12 hours (polling time 1 sec)...

and then I get Error: {"name":"TransactionTimedOutError","message":"Timed out","errno":"ETIMEDOUT"}

immagine

I tried to add privileged: YES in docker-compose.yml
And yesterday it worked.

Today no way.

Added /dev/ttyUSB0 (needed!!) and /dev/ttyUSB1 (not needed)....but no luck

immagine

Can you help me with this?

Thank you for your effort!

Regards

Paolo

@fewrainbows
Copy link

After seferal docker-compose up -d seems to work in a scattered way.

I get timeout from time to time
My polltime is 1 sec

Your feedback would be highly appreciated!!

Thank you again

@Paraphraser
Copy link
Contributor

First, please see this project is dormant. If you really are still on this repo (gcgarner/IOTstack) you might want to migrate to sensorsIot/IOTstack because it's getting a bit more maintenance.


My guess is that the USB device is disconnecting periodically and that's what is causing it to change its name.

One of my own projects is an ESP8266 with a serial-to-RS485 adapter talking to an electricity meter. I built it April 2018 and it has always been pretty flaky in the sense that the ESP8266 will stop getting responses from the adapter, which it cures by restarting. Happens several times a day. It was one of my first IoT projects and I've learned a fair bit since then, plus I've got a lot more test tools than I had back then. I've since realised that the most likely reason for the flakiness is a combination of the RS485 adapter board not being all that good plus me misunderstanding who had responsibility for the RS485 timing (I thought it was my sketch but my sketch might be fighting with the adapter). I'm in the process of rebuilding the project with an ESP32 and a much better RS485 adapter. I'm only telling you all this because the idea of "RS485" being mentioned in the same sentence as "timeouts" and other misbehaviour comes as no surprise to me. You're not alone!

I have two "solutions" to offer you but I'd like you to carefully consider whether doing the work of reading the RS485 adapter from Node-RED is the most appropriate way of going about it?

My personal view is that, if Node-RED is running in a container, it shouldn't be concerning itself with hardware outside the container; the corollary being that if Node-RED needs to concern itself with hardware then it should probably be installed natively rather than under IOTstack. I see all the scaffolding needed to help containerized Node-RED get to hardware as fighting against the system rather than working with the system. There are usually better ways.

Possible solution 1 - Node-RED talks to the hardware

See this gist for background info. Just ignore the fact that it's discussing 3D printers and a totally different container (OctoPrint).

It boils down to the steps at device discovery:

  1. Disconnect the USB device.

  2. Run the command:

    $ tail -f /var/log/messages
    
  3. Connect the USB device.

  4. Terminate the tail with a control+c and then capture whatever appeared in the messages file as a result of connecting the USB device.

  5. Disconnect the USB device again.

  6. Using this as a template:

    SUBSYSTEM=="tty", ATTRS{idVendor}=="«vendor»", ATTRS{idProduct}=="«product»", ATTRS{serial}=="«serial»", SYMLINK+="rs485adapter"
    

    replace «vendor», «product» and «serial» with the values captured during step 4. See device discovery for an example where to find the values.

  7. Turn the completed template into a one-line file at the path:

    /etc/udev/rules.d/99-rs485adapter.rules
    

    You will need sudo. The file should have mode 644 and be owned root:root.

Once that is in place then, when you connect the USB device, it should show up as /dev/rs485adapter.

It will still show up as /dev/ttyUSBn but that doesn't matter.

If /dev/rs485adapter doesn't turn up then maybe edit the rules file (step 7) and change the SUBSYSTEM from "tty" to "usb" and try again.

When disconnecting/reconnecting reliably shows up as /dev/rs485adapter then change the Node-RED service definition to use ONE of the following device mappings:

- "/dev/rs485adapter:/dev/ttyUSB0"
- "/dev/rs485adapter:/dev/rs485adapter"

If it were me, I'd probably go for the second line so what I was seeing inside containerspace was the same as I saw outside. However, if the Node-RED mechanism for getting to external devices only likes standard-form names, you might have to make do with the first line.

I've never tried anything like this with Node-RED but my experience with OctoPrint tells me that an external device going away can be expected to cause the container to crash.

Node-RED might be smart enough to only crash the flow, and it may even recover gracefully, but I kinda doubt it because device-mapping is a Docker thing, not a Node-RED thing.

If the device going away crashes the container, docker will auto-restart the container. If the device still isn't there (eg you unplugged it), the container will go into a restart loop. If you're running other flows besides this one, you'll lose those too.

It's these kinds of issues that lead to the question I posed at the beginning, and the idea of "a better way"…

Possible solution 2 - work with the system

See this gist.

It talks about logging CPU temperatures but it's no great stretch to use this basic approach to run an external process (possibly in conjunction with the udev rule set as earlier) to probe the RS485 adapter, format the data into an MQTT message, and send it on its way.


Hope something in this helps you solve your problem.

@fewrainbows
Copy link

Hello Paraphraser!!

First, please see this project is dormant. If you really are still on this repo (gcgarner/IOTstack) you might want to migrate to sensorsIot/IOTstack because it's getting a bit more maintenance.

I understood it now!

My guess is that the USB device is disconnecting periodically and that's what is causing it to change its name.

I'm only telling you all this because the idea of "RS485" being mentioned in the same sentence as "timeouts" and other misbehaviour comes as no surprise to me. You're not alone!

THIS IS VERY HANDSOME. Mention for good coaching.

Sounds like u're a Morpheus..

I have two "solutions" to offer you but I'd like you to carefully consider whether doing the work of reading the RS485 adapter from Node-RED is the most appropriate way of going about it?

In the project i will need 2 further simple "dry contacts" collected on Rpi GPIO.
The question on solution 1/2 is still open.

Possible solution 1 - Node-RED talks to the hardware

mmm. gonna study this more to understand 100%.
By the way...in this project I dont foresee more USB stuff...

But I'm thinking what I've done: just before the start of the above mentioned misreadings I connected the arduino (just to have power supply) to a RPi usb port.

Possible solution 2 - work with the system

Not confident with MQTT yet.
Gonna study more...
In this case#2 I might go with a simple python code polling data from RS485 and GPIOs?

Hope something in this helps you solve your problem.
This is a great help, u did it!

Many many "Thank you" for your brilliant advice!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants