HA on Synology using Docker with ZHA integration and Conbee2 USB stick

Hi,

I am running HomeAssistant in a Docker session on my Synology NAS.

I bought a Conbee2 stick and plugged that in, it got USB address /dev/ttyACM0 and ZHA integration found it on restart and everything works fine.
Now I also got a Z-Wave stick and when I plug that in the Conbee2 stick cannot be found by HA/ZHA anymore (it probably got another USB address, because I know the USB order is critical).
I know there should be a way to map against device instead of USB port, but not good enough on Linux to understand how I should do and could not find a beginners guide to this.

If the unit gets a new address, can I change it in some way from the GUI or can ZHA integration be triggered to find the stick again with all its devices?
How to map against device instead of port?

Anyone that can help me forward with this?

Thanks,
AseKarlsson

The problem with using /dev/ttyACM0 from the host is that it is a symlink that can change around on you. One startup it points to the Conbee, next time it goes to the Zstick, randomly depending on whichever one loads first.

To avoid this, you can create a UDEV rule to create a symlink to another name that will “stick”. I did that and created a /dev/ttyusb.zigbee that I can map into my zigbee2mqtt container.

Probably the easier option though instead of a UDEV rule is to use /dev/serial/by-id to identify your device. Navigate to the /dev/serial/by-id folder on the host (terminal or file explorer) with both zigbee and zwave sticks plugged into the machine. Both should be listed by some code. Then, unplug one. The unplugged one will “disappear” from the list and then you will know which is which.

My zigbee stick is /dev/serial/by-id/usb-0658_0200-if00 . If I want to map that to a docker container I can use the --device option and specify the mapping. So for a Home Assistant docker container mapping, it would look like this:

--device /dev/serial/by-id/usb-0658_0200-if00:/dev/ttyACM0

It would then map to the container’s ttyACM0 port so on the Home Assistant side in ZHA if I specify ttyACM0 it would go to the zigbee stick. The mapping would stay the same no matter which stick is connected and which order they are put in because your are using the by-id.

Also here’s a post I wrote on another thread about doing the udev rule if the by-id doesn’t work for some reason

1 Like

Hi Tim,

Thanks for your guidance, your suggestion for me sounds the easiest.
Where should put the --device… line as an Environment variable in the GUI when creating the container or can it be placed in a configuration file and dont need to entered again everytime I build a new container?

I can find the /dev folder but there is no /serial folder under that.
I tried to use lsusb -e command and the result is this:

|__2-1 1cf1:0030:0100 02 2.01 12MBit/s 100mA 2IFs (dresden elektronik ingenieurtechnik GmbH ConBee II DE2405716)

Is the “1cf1:0030:0100” part the ID?

Thanks,
AseKarlsson

Synology does not do the device by serial ID. Your only option with a USB device on a Synology is using the /dev/tty path.

EDIT: keep reading this thread, an alternative has been found to the serial by-id udev rules by creating our own virtual com port using the rules.d folder.

1 Like

The device option needs to be specified in the docker run command or compose file each time the container is built. It’s not under environment variables and will have its own flag in the run command with --device or be specified under devices in a docker compose yaml (see example below )

So you’re not having to type it out all the time, you might want to look into creating a docker-compose. Once you create the container by compose, updating is as simple as going to the folder the compose is in and running docker-compose up -d --force-recreate to upgrade to the latest docker image.

This is my compose for zwavejs2mqtt which defines the path to my zstick created by the udev rule

version: '3.3'
services:
    zwavejs2mqtt:
        restart: always
        ports:
            - '8091:8091'
            - '3000:3000'
        devices:
            - '/dev/ttyusb.zstick:/dev/ttyACM0'
        volumes:
            - '/home/$user/docker/zwave/store:/usr/src/app/store'
        environment:
            - TZ=America/New_York
            - SESSION_SECRET=$mysecretkey
            - PGID=1000
            - PUID=1000
        image: 'zwavejs/zwavejs2mqtt:latest'

Another option to easily upgrade and pull a new image is to use Portainer, click your container, click “recreate” and toggle “pull latest image”. This will then recreate the container as initially setup from your run command/compose, preserving the device option, with the latest image.

Sorry for the wild goose chase on this, I see from the post above synology doesn’t do device by serial ID. I’m using Ubuntu which has it.

Looks like you’d have to do the udev rule then. @squirtbrnr do you know if /dev/serial/by-path is an option in synology that might work?

Update- I don’t think it will since it seems there isn’t even a serial folder present.

correct, the serial folder doesn’t even exist. so the dev rule will not work on Synology.

Hi,

Thanks for your feedback. You obviously worked with Synology Docker.
How did you solve this so both the USB sticks get the same address every time?

Thanks,
AseKarlsson

I only have one USB device, a Zwave stick. The USB devices are assigned ttyACM* when plugged into the system. However, on a restart of the host machine, it all depends on which device is polled/responds first or faster. That’s why sometimes a device will be at ttyACM0 and other times at ttyACM1. It has even happened to me where if I unplug my Zwave stick and plug it back in, it’s now at 1, but if I unplug and plug it back in, it’s back to 0. My only suggestion or recommendation is if you have to reboot the host, unplug the devices and plug them in one at a time after it starts to ensure they are at the correct mapping you set up. They will stay at that port until you either unplug them or reboot the host.

1 Like

Hi,
Thanks both for taking your time to help me.
So no idea to continue searching for a solution.
If anyone that sees this thread know a solution, please reply!

Thanks,
AseKarsson

Somone on OpenHab was able to write a udev rule on Synology to set a static usb address so it must be possible.

It appears they just specified the devices as higher number tty ports (ie ttyACM4) to define the ports statically.

2 Likes

Interesting. They did the mapping purely at the host level. Then just mapped this new virtual ttyACM# port which will not change to the OH controller. In theory this should work for HA Container as well. Just map whatever virtual port is created to the container and setup the integration in HA to look for it. I’m not able to try this on mine at this time, but next time I need to restart my HA container I will give it a shot.

2 Likes

Hi,

Great!

Did run “udevadm info -a /dev/ttyACM0” and the result was:

looking at device ‘/devices/pci0000:00/0000:00:04.0/0000:04:00.0/usb2/2-1/2-1:1.0/tty/ttyACM0’:
KERNEL==“ttyACM0”
SUBSYSTEM==“tty”
DRIVER==""

looking at parent device ‘/devices/pci0000:00/0000:00:04.0/0000:04:00.0/usb2/2-1/2-1:1.0’:
KERNELS==“2-1:1.0”
SUBSYSTEMS==“usb”
DRIVERS==“cdc_acm”
ATTRS{bInterfaceClass}==“02”
ATTRS{bmCapabilities}==“2”
ATTRS{bInterfaceSubClass}==“02”
ATTRS{bInterfaceProtocol}==“01”
ATTRS{bNumEndpoints}==“01”
ATTRS{supports_autosuspend}==“1”
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceNumber}==“00”

and after that a a full list of more parental devices.

Then i did run “udevadm info -a /dev/ttyACM1” and the result was:

looking at device ‘/devices/pci0000:00/0000:00:04.0/0000:04:00.0/usb2/2-2/2-2:1.0/tty/ttyACM1’:
KERNEL==“ttyACM1”
SUBSYSTEM==“tty”
DRIVER==""

looking at parent device ‘/devices/pci0000:00/0000:00:04.0/0000:04:00.0/usb2/2-2/2-2:1.0’:
KERNELS==“2-2:1.0”
SUBSYSTEMS==“usb”
DRIVERS==“cdc_acm”
ATTRS{bInterfaceClass}==“02”
ATTRS{bmCapabilities}==“0”
ATTRS{bInterfaceSubClass}==“02”
ATTRS{bInterfaceProtocol}==“01”
ATTRS{bNumEndpoints}==“01”
ATTRS{supports_autosuspend}==“1”
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceNumber}==“00”

Now both sticks connected.
With this information how should I format the .rules file, i feel there is info missing?

ttyACM0 = ConBee II
ttyACM1 = Aeotec Z-stick Gen5

Thanks,
AseKarlsson

Try following this guide

You need to list the full attributes to ideally find a value that uniquely identifies the two different sticks, like a vendor ID or something.

udevadm info --name=/dev/ttyACMx --attribute-walk

To list the all the attributes

Then go to /lib/udev/rules.d

Use vi to create a .rules file. Try this:

sudo vi 99-hass.rules

Try these udev rules. You will have to replace what is between the {} with the attributes you found from the udevadm info command. Then after the == in quotes will be the attributes value from the corresponding attribute you found.

Here’s the .rules file contents (assuming zwave first then zigbee second)- one I specified vendor and product, yours could vary.

KERNEL==“ttyACM*”, ATTRS{serial}==“0000:00:1d.7”, SYMLINK+=“ttyACM4”
KERNEL==“ttyACM*”, ATTRS{idVendor}==“1a86”, ATTRS{idProduct}==“7523”, SYMLINK+=“ttyACM5”

This should hopefully statically set the zstick to ttyACM4 and the zigbee stick to ttyACM5 (even if they are swapped around)

Hopefully that works but if not you might have to modify the .rules file to be more like the one from the Openhab forum linked above.

Thanks Tim,

I found both ATTRS{serial} and ATTRS{idVendor} for both devices, idVendor i think is the way to go for me.
Can i make SYMLINK+=“ttyACM10” and “ttyACM11” of these or is there an upper limit in numbers?
Must the .rules file start with 99-?
If this works and I have to delete my Conbee2 Integration and add it again as “ttyACM10” will my devices and entities still be intact in HA?

This would be my file content:
KERNEL==“ttyACM*”, ATTRS{idVendor}==“1cf1”, SYMLINK+=“ttyACM10”
KERNEL==“ttyACM*”, ATTRS{idVendor}==“0658”, SYMLINK+=“ttyACM11”

Thanks,
AseKarlsson

That should be fine. I saw older kernels the limit is 32, newer is 256, so 10 and 11 should be no problem, unless I’m missing some unique synology thing.

Mine does and the example one in the openhab forum does. I dont know if it has to, but I would start it with 99.

You can keep the mapping into the docker container whatever it was before. This should prevent the need from reinstalling the integration. You map the device from host to container.

So just do

--device /dev/ttyACM10:/dev/ttyACM0

This will map the ttyACM10 on the host to ttyACM0 in the Home Assistant docker container, which should be what it was before and keep everything in tact.

Looks good to me. Give it a try, you can always change it or delete it if there is an issue.

1 Like

Hi Tim,
If this works I gladly delete my old ttyACM0 Integration and start over and map to the new ttyACM10, its only 38 entities at the moment.
This would be so much easier in the future to not have to add the --device option every time i update my docker container…
squirtbrnr, Do you know what happens when there is a new version of DSM och Docker?

Thanks,
AseKarlsson

last thing I think you have to do is reboot the Synology host for the rules to apply, or try running udevadm control --reload-rules. Make sure permissions on the rules file are correct too. EDIT: the reload rules did not produce the virtual port, but it’s possibly because I did not shutdown my HA container which currently has a lock on the port/device. Just a guess as to why it didn’t work.

according to linuxconfig.org:

The files in which the rules are defined are conventionally named with a number as prefix (e.g 50-udev-default.rules ) and are processed in lexical order independently of the directory they are in. Files installed in /etc/udev/rules.d , however, override those with the same name installed in the system default path.

new version of DSM will potentially wipe out your udev rule in the rules.d folder as noted in the OH forum post.

Every Synology update you need to recreate the 99-openhab.rules file, so keep a copy somewhere!

an update to the Docker package or the HA container image will not affect your udev rules and should not affect any mapping with the --device flag

1 Like

Even without the symlink you have to get the device mapped to the container somehow. What were you doing before? The only other way I can think of is priviledged mode. I don’t like priviledged mode for docker containers but basically it takes whatever was on the host USB wise and puts it in the docker container as is. If you are using priviledged mode you would have to specify ttyACM10 on the Home Assistant side in the ZHA integration as well.

We had a discussion recently about priviledged mode here

You may want to post your entire docker run command to double check its setting up the container properly.

I recall having to reboot my machine. Just trying to reload the udev rules didn’t work for me, and I thought I did something wrong, but it worked on reboot.

If the symlink worked running ‘ls /dev/ttyACM10’ should work without an error.

1 Like

Hi,
Here is a follow-up question because I dont think I will get time to test this and discover all devices again during this weekend: The ConBee2 stick was found by HA GUI after a reboot earlier like below:
ConBee2
Where is this adress stored, because I did not enter it manually in any .yaml file?

My question summerized, can I find this adress somewhere and change it from /dev/ttyACM0 to /dev/ttyACM10 and keep all my devices and entities intact if our .rules file works as we think?

I run the container in Priviledged mode because my knowledge is limited and got it working like this

Thanks,
AseKarlsson

It’s in your config directory, “.storage/core.config_entries”

                "domain": "zha",
                "title": "BV 2010/10, s/n: xxx - Silicon Labs",
                "data": {
                    "radio_type": "ezsp",
                    "device": {
                        "path": "/dev/ttyUSB0",
                        "baudrate": 57600
                    }
                },

If “path” doesn’t exists, add it. “/dev/ttyACM0” is the default, I think.
Then restart HA.