So, this was a lot harder than it really should have been, especially because rtl_433 is a bit thingie about where the device appears in the /dev/ file system as an added sting in the tail…
In my specific scenario, I was given a Vevor 7-in-1 wireless weather station for Christmas. They seem fairly solid and full featured for a $130 AUD device, so no complaints there. The device is also natively supported by rtl_433 which is a RTL SDR package, although its not supported in the version shipped by Debian 12. That’s awesome, although it would have been nice if the command line to use was documented better. I’ll talk more about those bits in a later post though. In this one I want to focus on the fun I had getting a USB device reliably passed through to a Docker container on my QNAP NAS.
First off, I am using a Realtek USB TV tuner for rtl_433, which appears like this one the NAS:
$ lsusb
Bus 001 Device 002: ID 0bda:2838 Realtek Semiconductor Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Specifically that first device is the lucky winner here. First off, I want that to appear reliably in /dev/ so that I can find it to pass it through to Docker. By reliably, I mean that its bus and device ID might change if you plugged it into a different USB port, or added a USB hub to the NAS. The way I’d usually do that is with a udev rule, which didn’t work at all how I expected on the QNAP Linux distribution.
This is because of two things — the udev version on the QNAP is a bit broken, and the configuration of the NAS in /etc/ and /lib/udev is clobbered on boot from a known good version. So first off we need to tweak that known good version to provide the configuration we want. This is in fact documented on the QNAP site, but took a while to find. Specifically in my case, I needed to mount the configuration in /tmp/config…
$ sudo bash
# mount $(/sbin/hal_app --get_boot_pd port_id=0)6 /tmp/config
And then I could create a file called /tmp/config/autorun.sh which contained this:
#!/bin/bash
cat <<EOF > /lib/udev/rules.d/60-rtlsdr.rules
ATTR{product}=="RTL2838UHIDIR",ATTR{serial}=="00000001",SYMLINK+="rtl433"
EOF
udevadm control --reload-rules
# This is horrid, but the udev in QNAP land is a bit broken...
usb_device=$(lsusb | grep Realtek | sed -e 's|^Bus |/dev/bus/usb/|' -e 's| Device |/|' -e 's|: .*$||')
pci_device=$(udevadm info -q path -n ${usb_device})
udevadm test --action="change" ${pci_device}
What this does is create a udev rule which matches the product and serial number of my RTL TV tuner, creating a symlink at /dev/rtl433 to the correct device file. You then need to have udev reload its rules, and thenĀ trick udev into running the new rule by running a test action against the correct PCI device (which you find by looking up the correct USB device). Lovely.
We then need to make that script executable, and unmount the config file system so that our changes are flushed to disk:
# chmod +x /tmp/config/autorun.sh
# umount /tmp/config
Finally, we also need to turn on support for the autorun.sh script in the QNAP control panel:
Now on reboot the USB device should be detected and symlinked to the right place.