Koenkk / zigbee2mqtt

Zigbee 🐝 to MQTT bridge 🌉, get rid of your proprietary Zigbee bridges 🔨
https://www.zigbee2mqtt.io
GNU General Public License v3.0
12.03k stars 1.67k forks source link

Adapter cannot be reached via /dev/serial/by-id on Docker #16072

Closed nielsfaber closed 1 year ago

nielsfaber commented 1 year ago

What happened?

On my system, my zigbee USB dongle and another USB device are not consistently assigned with a tty port, they are alternately named ttyUSB0 and ttyUSB1 between reboots.

The following recommendation is given on the adapter settings page:

Where possible you should use the /dev/serial/by-id/ path of the stick, instead of /dev/tty*. This is because the /dev/tty* path can change - for example /dev/ttyACM0 may become /dev/ttyACM1 and then later back to /dev/ttyACM0. The /dev/serial/by-id/ path won't change.

I identified my zigbee dongle as: /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_[REDACTED]-if00-port0.

So I modified my configuration.yaml as follows:

serial:
  port: /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_[REDACTED]-if00-port0

However, when restarting zigbee2mqtt, I get:

Error: Error while opening serialport 'Error: Error: No such file or directory, cannot open /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_DonglePlus[REDACTED]-if00-port0',

I'm running zigbee2mqtt via Docker.

I tried different settings for the device mapping (such as mapping to ttyACM0 and using that configuration.yaml instead), but without any success. I also tried making a symlink in the /etc/udev/rules.d/99-usb-serial.rules to /dev/tty-zigbee, but also this port is not reachable from within the Docker container. Debugging inside the container seems difficult since the container is continuously restarting itself. So at this point I am not sure whether the problem is in Docker or in Zigbee2mqtt.

It would be very helpful if some 'known good' example was provided in the documentation.

What did you expect to happen?

I would expect any tty port to be accessible from within the docker container, especially if the device mapping is provided in the container settings.

How to reproduce it (minimal and precise)

My docker-compose configuration:

  zigbee2mqtt:
    container_name: zigbee2mqtt
    image: koenkk/zigbee2mqtt:latest
    volumes:
      - /mnt/data/zigbee2mqtt/data:/app/data
      - /run/udev:/run/udev:ro 
    devices:
      - /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_[REDACTED]-if00-port0:/dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_[REDACTED]-if00-port0
    ports:
      - 8080:8080
    restart: unless-stopped
    network_mode: host
    privileged: true
    environment:
      - TZ=Europe/Amsterdam

Zigbee2MQTT version

1.25.1

Adapter firmware version

unknown

Adapter

ITead Sonoff Zigbee 3.0

Debug log

No response

ikarisan commented 1 year ago

Should't it be something like this?

devices:
      - /dev/serial/by-id/usb-ITead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_[REDACTED]-if00-port0:/dev/ttyACM0

See: https://www.zigbee2mqtt.io/guide/installation/02_docker.html

Then use

serial:
  port: /dev/ttyACM0

in your configuration.yaml file.

nielsfaber commented 1 year ago

@ikarisan I tried that as well. The output becomes:

Error: Error while opening serialport 'Error: Error: No such file or directory, cannot open /dev/ttyACM0'

I don't think it actually matters. (or should matter) to which port you map, as long as you keep the configuration.yaml in sync. I also tried port: null, but the result was that the auto detection fails.

jeroen85 commented 1 year ago

Are you sure that your system supports the /dev/serial/by-id/? For example my Synology NAS does not support this, unfortunatelly :-(

nielsfaber commented 1 year ago

@jjansen85 I'm running Raspbian on the Raspberry Pi and yes, it is supported:

pi@raspberrypi:~$ ls -l /dev/serial/by-id total 0 lrwxrwxrwx 1 root root 13 Jan 9 14:17 usb-ITead_Sonoff_Zigbee_3.0_USB_DonglePlus[redacted]-port0 -> ../../ttyUSB1 lrwxrwxrwx 1 root root 13 Jan 10 06:50 usb-RFXCOMRFXtrx433[redacted]-if00-port0 -> ../../ttyUSB0

ikarisan commented 1 year ago

I'm guessing you entered the [redacted] for github, right? I don't know how you run your container. I am using portainer for everything. Maybe you have to start your container with "--privileged". That's because only root can access serial devices by default. Or generate a '/etc/udev/rules.d/99-my_serial.rules' file with

KERNEL=="ttyUSB[0-9]*",MODE="0666"
KERNEL=="ttyACM[0-9]*",MODE="0666"

in it. Since I never unplug the ZigBee stick on my Pi4, this has been working fine for about 2 years:

devices:
    - '/dev/ttyACM0:/dev/ttyACM0'

Unfortunately, I do not have more ideas.

danieledwardgeorgehitchcock commented 1 year ago

Have you tried completely removing and rebuilding the Z2M container after changing your compose file?

nielsfaber commented 1 year ago

@ikarisan

I'm guessing you entered the [redacted] for github, right?

Yes, I didn't want to share its mac address (no idea if this is sensitive information).

I don't know how you run your container. I am using portainer for everything.

I'm also using portainer.

Maybe you have to start your container with "--privileged". That's because only root can access serial devices by default. Or generate a '/etc/udev/rules.d/99-my_serial.rules' file with

My docker-compose rule has privileged: true, so I'd say this is covered. I don't think the udev rule would help, since I want to approach the device via its unique id rather than the tty port. Via ttyUSB0 it works fine permission-wise, but after rebooting occasionally the device moves to ttyUSB1.

@danieledwardgeorgehitchcock

Have you tried completely removing and rebuilding the Z2M container after changing your compose file?

I tried it just now, the result is the same Error: Error: No such file or directory, cannot open ....

It would be helpful to know how to stop the container from auto rebooting every 6 seconds, to start a command line session from within the container and check whether the tty mapping works OK there. But I didn't succeed with this yet.

raoulx24 commented 1 year ago

It would be helpful to know how to stop the container from auto rebooting every 6 seconds, to start a command line session from within the container and check whether the tty mapping works OK there. But I didn't succeed with this yet.

I took a look inside the image and it should be enough to add command override

    container_name: zigbee2mqtt
    command: tail -f /dev/null
    image: koenkk/zigbee2mqtt:latest

Then you will be able to

docker exec -it zigbee2mqtt /bin/sh

and do your debugging.

Further info: why docker run -d centos tail -f /dev/null command can keep the docker container running in the background? and Demystifying ENTRYPOINT and CMD in Docker and Compose specification | Docker Documentation

Hope it helps...

IncalSchorsch commented 1 year ago

Hello everybody

I ran into the same problem: I could not reach the Zigbee Dongle and I tried the same different settings as @nielsfaber but also without success.

My problem was, that another software (FHEM) did access another USB device (Enocean Dongle) directly via path /dev/ttyUSB1. I changed the FHEM configuration to access the USB device by its id.

After this change, zigbee2mqtt worked like a charm with following setup:

Docker: docker-compose.yml (The only change was the by-id path)

devices:
  - /dev/serial/by-id/usb-Silicon_Labs_Sonoff_Zigbee_3.0_USB_Dongle_Plus_0001-if00-port0:/dev/ttyUSB0 
group_add:
  - dialout
user: 1000:1000

Zigbee2Mqqt: configuration.yaml (unchanged)

serial:
  port: /dev/ttyUSB0

Hope this might help people with the same problem.

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days