User Tools

Site Tools

This documentation is no longer maintained by the Turris team (although it can be used by the community to share content). The current official documentation is at docs.turris.cz.

Installing Phoscon/Deconz gateway on Turris Omnia in LXC container

work in progress. This how-to is meant to be as a hand-book for experienced user. Backup your router before playing with this. Unexpected things might happen.

Guys from deconz did great job when tuning their official raspberry Pi image - that's not the case with this manual. At least so far. If deConz is the only way to control your bathroom lights, ensure you have headlamps for your family members before you'll start with following experimental-graded procedure.

Bug/Issue list:

  • container doesn't want to start automatically
  • Conbee USB Stick has to bee in USB2 hub otherwise it's not visible in Turris Omnia at all
  • FIXME: https
  • FIXME: measure system load on omnia caused by this software “stack”

Deconz/Phoscon/Conbee system introduction

  • Conbee II, (vendor link) is USB Zigbee gateway dongle - acts as a bridge between Zigbee mesh network and Ethernet-enabled device. Lot of business logic is implemented in built-in MCU running proprietary firmware.
  • Deconz, (vendor link) is management software for ZigBee networks, able to work with Conbee II (and other adapters). One of its components, “deconz-rest-plugin” is open-source (github).
  • Phoscon (vendor link) is web application providing GUI to Deconz software. Phoscon is currently closed-source 1)

supported devices

main features

  • “cloud” free - it can work completely offline
  • integration with existing home-automation software like Home Assistant
  • European vendor
  • acceptable pricing
  • open and documented API
  • possibility to run affordable Zigbee bulbs/switches without need to install their “original” gateways, which are possible privacy/security disaster2)..
  • multiplatform.. at least if your platform is win[7,10],x86_64 Docker, current LTS Ubuntu, or Raspbian, aka armhf. And as Turris omnia is armhf too, it's multiplatform-enough :)

Turris Omnia tutorial

Ensure the external storage is configured

Using internal flash storage is not recommended by Turris Omnia makers!

Configure external (USB, msata) storage as described here. External storage should be mounted in /srv mountpoint.

Prepare Turris and LXC environment

install USB driver and utils

opkg install kmod-usb-acm
opkg install usbutils

install LXC environment using forris GUI and reboot

in forris GUI:

→ “updater” and in “Package lists” check “LXC utilities”.

Click on “Save and update” and wait for installation.

Plug in the Conbee II USB stick and reboot omnia to let luci load relevant plugin and load new kernel module. After reboot, we should see the device (VendorID: Dresden Elektronik ) with the proper driver (cdc_acm) loaded:

root@turris:/dev# lsusb
...
Bus 002 Device 081: ID 1cf1:0030 Dresden Elektronik 
...
root@turris:/dev#
root@turris:/dev# lsusb --tree
/:  Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
    |__ Port 1: Dev 2, If 0, Class=Mass Storage, Driver=usb-storage, 5000M
/:  Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
        |__ Port 1: Dev 81, If 0, Class=Communications, Driver=cdc_acm, 12M
        |__ Port 1: Dev 81, If 1, Class=CDC Data, Driver=cdc_acm, 12M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=orion-ehci/1p, 480M
root@turris:/dev#

There is watchdog inside a device, so if deCONZ is not talking to USB stick, device will reset itself after some time. Don't be surprised to see such reconnects in dmesg. (and related increasing DevID)

If USB device is not recognized by Turris Omnia OS, try to plug it into USB2 hub connected to USB3 Omnia port. As there is new Turris OS release in preparations, I don't want to spent time by debugging this.

create Debian Buster container

Vendor expects current raspbian, which is based on Debian Buster 3) of armv7l architecture. So let's create ABI-compatible LXC container:

root@turris:/srv/lxc# lxc-create -t download -n lxc_deconz
Setting up the GPG keyring
Downloading the image index

---
DIST    RELEASE ARCH    VARIANT BUILD
---
#.. additional OSs removed...
Debian  Stretch aarch64 default 2019-09-18
Debian  Buster  armv7l  default 2019-09-18
Debian  Buster  aarch64 default 2019-09-18
Gentoo  stable  armv7l  default 2019-09-18
#.. additional OSs removed...
---

Distribution: Debian
Release: Buster
Architecture: armv7l

Downloading the image index
Downloading the rootfs
Downloading the metadata
The image cache is now ready
Unpacking the rootfs

---
Distribution Debian version Buster was just installed as a container.

Content of the tarballs is provided by third party, thus there is no warranty of any kind nor support from Turris team.

Do not use containers on internal flash, they can wear it down really fast!!!
root@turris:/srv/lxc#

Install prerequisities

get the container CLI:

root@turris:/srv/lxc# lxc-ls 
lxc_deconz
root@turris:/srv/lxc# lxc-attach -n lxc_deconz
root@LXCNAME:/#

set some descriptive hostname:

root@LXCNAME:/# hostnamectl set-hostname lxc-deconz
root@LXCNAME:/#

“restart” container by clickin on “stop” and “start” in Luci gui. (Services → LXC Containers)

BUG: For unknown reason, in current Turris omnia OS, lxc_stop CLI command is hanging. Use Luci GUI instead.

attach back to the container and install dependencies and nice-to-have tools:

root@turris:/srv/lxc# lxc-attach -n lxc_deconz
root@lxc-deconz:/# apt install procps iputils-ping less wget curl gnupg lsb-release libatomic1 usbutils strace tree

download and install wiringpi - it is not directly needed, but it is dependency of deconz deb package. There is plan to remove this dependency from deconz. 4)

root@lxc-deconz:/# wget https://project-downloads.drogon.net/wiringpi-latest.deb
root@lxc-deconz:/# apt install ./wiringpi-latest.deb

Install deconz

get deconz repo key:

curl http://phoscon.de/apt/deconz.pub.key | apt-key add -

add deconz repository to the system:

sh -c "echo 'deb http://phoscon.de/apt/deconz \
    $(lsb_release -cs) main' > \
    /etc/apt/sources.list.d/deconz.list"

install deconz package:

apt update
apt install deconz

Configure /dev/ttyACM0 passthru

USB stick driver creates /dev/ttyACM0 block device there on host. We need to pass this device into LXC container.

In turris(host) shell, get the major cgroup number of /dev/ttyACM0:

root@turris:/srv/lxc# ls -la /dev/ttyACM0 
crw-r--r--    1 root     root      166,   0 Sep 21 22:22 /dev/ttyACM0
root@turris:/srv/lxc#

it's 166 - we'll need this number later.

Open containers config and configure /dev/ttyACM0 passthru with the path and number we found above:

append to /srv/lxc/lxc_deconz/config:

..
# usb devices:
lxc.cgroup.devices.allow = c 166:* rwm
lxc.mount.entry = /dev/ttyACM0 dev/ttyACM0              none bind,optional,create=file 0 0

stop & start container and check if device is present:

root@lxc-deconz:/# ls -lah /dev/ttyACM0 
crw-r--r-- 1 root root 166, 0 Sep 21 20:22 /dev/ttyACM0
root@lxc-deconz:/#

Tweak container environment

Now, try the vendors' utility if we can see the USB stick:

root@lxc-deconz:~# GCFFlasher_internal -l
GCFFlasher V3_06 (c) dresden elektronik ingenieurtechnik gmbh
Path             | Vendor | Product | Serial     | Type
-----------------+--------+---------+------------+-------
root@lxc-deconz:~#

no - it's missing, because deCONZ is internally calling function from libqt5serial, trying to use udev database in /run/udev/data/, usually created by systemd-udevd. That's not case in containerized OS from obvious reasons but we can steal the proper file from raspberryPi running systemd and having USB dongle plugged.. :)

so first, in container, create the right dir:

mkdir -p /run/udev/data/

and fill it with the required data:

cd /run/udev/data/
echo "E:ID_VENDOR_ID=1cf1
E:ID_MODEL_ID=0030" > c166\:0

now the USB stick should be recognized:

root@lxc-deconz:/run/udev/data# GCFFlasher_internal -l
GCFFlasher V3_06 (c) dresden elektronik ingenieurtechnik gmbh
Path             | Vendor | Product | Serial     | Type
-----------------+--------+---------+------------+-------
/dev/ttyACM0     | 0x1CF1 | 0x0030  |            | ConBee II 
root@lxc-deconz:/run/udev/data#

Run deconz

root@lxc-deconz:/run/udev/data# deCONZ -platform minimal

Operation not permitted when running deconz

Apparently, in the deconz deb package, cap_sys_time and cap_sys_boot are set in postinst for /usr/bin/deCONZ. Both caps are forbidden in lxc configuration (see /usr/share/lxc/config/common.conf ):

root@lxc-deconz:/# getcap /usr/bin/deCONZ
/usr/bin/deCONZ = cap_net_bind_service,cap_sys_boot,cap_sys_time+ep
root@lxc-deconz:/#

both caps can be removed with:

root@lxc-deconz:/# /sbin/setcap cap_net_bind_service+ep /usr/bin/deCONZ

file caps now looks like:

root@lxc-deconz:/# getcap /usr/bin/deCONZ
/usr/bin/deCONZ = cap_net_bind_service+ep
root@lxc-deconz:/#

Indeed, we'll fix that permanently in the systemd unit file, to be sure that package update will not break our setup.

deconz will start, listen on default port (8080) and USB firmware version should be visible in webGUI:

If USB firmware version is not visible, check if USB device is visible inside of container (lsusb, etc.)

Configure autostart of service

add regular user to run the service:

useradd deconz-user

make home dir and change the ownership:

mkdir /home/deconz-user
chown -R deconz-user:deconz-user /home/deconz-user

Add deconz-user into dialout group:

usermod -a -G dialout deconz-user

copy reference unit file into /etc/systemd/system:

root@lxc-deconz:~# cp /lib/systemd/system/deconz.service /etc/systemd/system/

..and tweak it to our needs:

[Unit]
Description=deCONZ: ZigBee gateway -- REST API
Wants=deconz-init.service deconz-update.service
StartLimitIntervalSec=0

[Service]
User=deconz-user
PermissionsStartOnly=true
ExecStartPre=/bin/chown root:dialout /dev/ttyACM0
ExecStartPre=/bin/chmod 664 /dev/ttyACM0
ExecStartPre=/bin/mkdir -p /run/udev/data
ExecStartPre=/sbin/setcap cap_net_bind_service+ep /usr/bin/deCONZ
ExecStartPre=/bin/bash -c "/bin/echo -e 'E:ID_VENDOR_ID=1cf1\nE:ID_MODEL_ID=0030' > /run/udev/data/c166:0"
ExecStart=/usr/bin/deCONZ -platform minimal --http-port=80
Restart=on-failure
StartLimitInterval=60
#AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_KILL CAP_SYS_BOOT CAP_SYS_TIME

[Install]
WantedBy=multi-user.target

explanation

  • User .. the regular user we created so deconz-user in our case
  • PermissionsStartOnly .. will execute ExecStartPre commands as root, but the service itself as deconz-user
  • ExecStartPre commands .. fixing permisions on /dev/ttyACM0 and tweaking the udev dir, also limiting the capabilities of the deconz binary.

configure autostart of container

as described in how-to, edit /etc/config/lxc-auto at Turris to automatically start our container:

root@turris:~# cat /etc/config/lxc-auto 
...
config container
  option name lxc_deconz
  option timeout 30
...
root@turris:~#

Tips & tricks

deCONZ secret debug options

deCONZ can be started directly from cli with several debug options5), e.g:

deCONZ -platform minimal --dbg-info=2 --dbg-zdp=2 --dbg-zcl=2 --db-aps=2 --dbg-http=2

References

3)
root@raspberrypi:/home/pi# lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 10 (buster)
Release:        10
Codename:       buster
root@raspberrypi:/home/pi#
4)
issue #1775 WiringPi will be depreceated soon https://github.com/dresden-elektronik/deconz-rest-plugin/issues/1775
5)
issue #295 How to specify command line parameters to deCONZ v2.04.93? https://github.com/dresden-elektronik/deconz-rest-plugin/issues/295