Turris Omnia: Zigbee2mqtt im LXC-Container

Nachdem ich deCONZ im LXC-Container auf dem Turris zum Laufen bekommen habe, musste ich feststellen, dass einige Geräte der tint Serie von Müller Licht von deCONZ noch nicht unterstützt werden. Da mir grundsätzlich das Konzept gefällt, dass ich das Zigbee-Netzwerk getrennt von Home Assistant verwalte, kommt Zigbee2mqtt als alternative Lösung in Betracht. Außerdem werden bei Zigbe2mqtt neue Zigbee-Geräte schneller unterstützt. Zumindest ist die Seite mit den unterstützten Zigbee-Geräten ziemlich umfangreich. 

Hardware auswählen

Leider lässt sich Zigbee2mqtt nicht mit einem ConBee-Adapter von Dresden Elektronik nutzen. Es werden aber einige Adapter von Texas Instruments von Zigbee2mqtt unterstützt (siehe Zigbee2mqtt - Supported Adapters). Die kostengünstigste Variante ist dabei wohl der CC2531. Allerdings ist der Funktionsumfang dieses Sticks auch etwas eingeschränkt. Es können nur ca. 30 Zigbee-Geräte angebunden werden und die Reichweite ist wohl ebenfalls beschränkt. Außerdem eignet sich der Stick für Zigbee 3.0 nur bedingt. 

Der deutlich teurere CC1352P-2 ist zwar deutlich teurer unterstützt aber angeblich 100+ Zigbee-Devices bei deutlich besserer Reichweite und Zigbee 3.0 Unterstützung. Daher habe ich mich für diesen Adapter als Zigbee-Controller entschieden. 

Firmware auswählen und flashen

Die Firmware für die Zigbee-Controller kann auf GitHub heruntergeladen werden (siehe Z-Stack-firmware auf GitHub). Es ist lediglich die passende Coordinator-Firmware auszuwählen. Für den CC1352P-2 ist die Firmware Z-Stack_3.x.0 auszuwählen. 

Einen Überblick welche Firmware mit welchem Adapter verwendet werden kann findet sich im README.md des Repositories.

Wie die Firmware zu flashen ist, wird auf der Zigbee2mqtt-Seite erklärt (siehe Flashing the firmware on the CC2531 USB stick und Flashing via UNIFLASH) und hat bei mir ohne Probleme funktioniert. Ich habe die Prozedur aber auch im Artikel Zigbee2mqtt inkl. Coordinator-Firmware aktualisieren beschrieben.

Turris Omnia vorbereiten

Bevor Zigbee2mqtt in einem LXC-Container installiert werden kann, muss zunächst das TurrisOS angepasst werden.

Hotplug einrichten

Ich habe in dem Artikel Turris Omnia: USB-Devices per Hotplug-Daemon einrichten bereits beschrieben, wie per Hotplug-Script die Berechtigungen des USB-Devices angepasst und ein eindeutiger Link auf das entsprechende Device angelegt werden kann.  Für den hier verwendeten CC1352P-2-Controller nutze ich folgendes Hotplug-Script:

cat <<\EOF > /etc/hotplug.d/usb/20-zigbee2mqtt
PRODID="451/bef3/100"
SYMLINK="zigbee2mqtt"

if [ "${PRODUCT}" = "${PRODID}" ]; then
    if [ "${ACTION}" = "add" ]; then
        DEVICE_NAME=$(find /sys/${DEVPATH}/tty/ -name ttyACM* | grep -Eo "ttyACM.*$")
        if [ -z ${DEVICE_NAME} ]; then
            logger -t hotplug "20-zigbee2mqtt: Device ${DEVICENAME} not relevant - skipping "
            exit
        fi
        logger -t hotplug "20-zigbee2mqtt: determined ${DEVICE_NAME} as device name for ${DEVICENAME}"

        /bin/chown root:plugdev /dev/${DEVICE_NAME}
        /bin/chmod 664 /dev/${DEVICE_NAME}
        logger -t hotplug "20-zigbee2mqtt: Changed access rights for /dev/${DEVICE_NAME}"

        [ "${DEVICENAME: -1}" = 0 ] && SYMLINK="${SYMLINK}0"
        [ "${DEVICENAME: -1}" = 3 ] && SYMLINK="${SYMLINK}1"

        ln -s /dev/${DEVICE_NAME} /dev/${SYMLINK}
        logger -t hotplug "20-zigbee2mqtt: Symlink /dev/${SYMLINK} -> /dev/${DEVICE_NAME} created"
    fi

    if [ "${ACTION}" = "remove" ]; then
        rm /dev/${SYMLINK}[01]
        logger -t hotplug "20-zigbee2mqtt: Symlink /dev/${SYMLINK}[01] removed"
    fi
fi
EOF

Und damit der das Device bei einem Reboot ebenfalls korrekt initialisiert wird, müssen folgende Kommandos beim Systemstart des Turris ausgeführt werden (z.B. per rc.local):

#!/bin/bash

ID_CC1352P_2="451/bef3/100"

# Devices werden beim Booten quasi eingesteckt...
ACTION="add"

# Init cdc_acm devices
for i in $(dmesg | grep -Eo "cdc_acm.*ttyACM.*$" | cut -d " " -f 2); do

        DEVICENAME=${i%:}
        DEVPATH="bus/usb/devices/${DEVICENAME}"
        PRODUCT=$(grep PRODUCT /sys/bus/usb/devices/${DEVICENAME}/uevent | cut -d "=" -f 2)

        case "${PRODUCT}" in
                ${ID_CC1352P_2})
                        . /etc/hotplug.d/usb/20-zigbee2mqtt
                        ;;
        esac
done

Device im LXC-Container bereitstellen

Jetzt muss das USB-Device mit ein paar kleinen Ergänzungen an der LXC-Konfiguration an den Container durchgereicht werden:

#
# USB-Devices für LXC-Container bereitstellen
#############################################

# /dev/bus/usb für lsusb im LXC-Container bereitstellen
# beseitigt Fehlermeldung "unable to initialize libusb: -99"
lxc.mount.entry = /dev/bus/usb dev/bus/usb  none bind,optional,create=dir 0 0

# Zugriff auf CC1352P-2 (zigbee2mqtt) erlauben
lxc.cgroup.devices.allow = c 166:* rwm
lxc.mount.entry = /dev/ttyACM0 dev/ttyACM0  none bind,optional,create=file 0 0
lxc.mount.entry = /dev/ttyACM1 dev/ttyACM1  none bind,optional,create=file 0 0
lxc.mount.entry = /dev/zigbee2mqtt0 dev/zigbee2mqtt0 none bind,optional,create=file 0 0
lxc.mount.entry = /dev/zigbee2mqtt1 dev/zigbee2mqtt1 none bind,optional,create=file 0 0

Änderungen im LXC-Container

Nachdem der Turris Omnia soweit vorbereitet ist, geht es in dem entsprechenden LXC-Container weiter. Ich gehe davon aus, dass hier bereits ein Container mit Debian 10 (Buster) grundsätzlich eingerichtet ist - inkl. automatischem Start bei Reboot des Turris Omnia. 

Es gibt mehrere Möglichkeiten wie Zigbee2mqtt installiert werden kann. Da die Software bei mit im gleichen LXC-Container wie Home Assistant läuft habe ich mich für die Installation im Python Virtual Environment entschieden.

Service Benutzer anlegen

Damit der Zigbee2mqtt-Dienst ohne administrative Berechtigungen ausgeführt werden kann, wird zunächst ein neuer Benutzer angelegt. Dabei sollte das Homeverzeichnis nicht direkt mit angelegt werden, da dies in einem späteren Schritt erfolgt:

adduser --system --home /srv/zigbee2mqtt --no-create-home --group --shell /bin/bash --disabled-login zigbee
adduser zigbee plugdev

Zigbee2mqtt Repository Clonen

Anschließend wird zigbee2mqtt per git in das Homeverzeichnis des neuen Benutzers gecloned und die Berechtigungen entsprechend angepasst:

git clone https://github.com/Koenkk/zigbee2mqtt.git /srv/zigbee2mqtt
chown -R zigbee:zigbee /srv/zigbee2mqtt

Zigbee2mqtt im Python Virtual Environment installieren

Jetzt wird zunächst in den Benutzerkontext von zigbee gewechselt und eine virtuelle Python-Umgebung angelegt und aktiviert. (Zeilen 1 - 7). Danach werden ein paar Module per pip aktualisiert (Zeile 10) und npm installiert und eingerichtet (Zeilen 13ff):

# Python venv einrichten
sudo -u zigbee -i
cd /srv/zigbee2mqtt
python3 -m venv .
  
# Python venv aktivieren
source bin/activate
  
# pip, wheel und setuptools aktualisieren
pip install --upgrade pip wheel setuptools
  
# node Umgebung installieren...
pip install nodeenv
  
# ... und einrichten
nodeenv -p -n 10.15.1
  
# Um sicherzugehen, einmal die Python venv verlassen und wieder aktivieren 
deactivate
source bin/activate
  
# Abhängigkeiten installieren
npm ci

# Python venv deaktivieren
deactivate

MQTT-Benutzer anlegen

Bevor die Konfiguration von Zigbee2mqtt angepasst werden kann, muss ggf. noch ein Benutzer im MQTT-Server angelegt werden. Für einen Mosquitto-Server werden dazu als root folgende Befehle ausgeführt:

$ mosquitto_passwd /etc/mosquitto/passwd zigbee2mqtt
Password:
Reenter password:
  
$ systemctl restart mosquitto

Da ich in meienr MQTT-Installation die Nutzer zusätzlich beschränke (nicht jeder Benutzer darf beliebige Topics-Posten), müssen dem Benutzer auch noch einige Zugriffsrechte eingeräumt werden:


# allow user zigbee2mqtt to read/write to necessary topics
user zigbee2mqtt
# Allow publishing and reading Device Status
topic readwrite zigbee2mqtt/#
# allow reading home Assitant Birth and Will messages
topic read hass/#
# allow publishing new device to Home Assistant (MQTT Discovery)
topic readwrite homeassistant/#

Damit die Änderungen übernommen werden, muss der MQTT-Dienst mit systemctl restart mosquitto neu gestartet werden.

Zigbee2mqtt Grundkonfiguration

Jetzt kann die Zigbee2mqtt Konfiguration unter /srv/zigbee2mqtt/data/configuration.yaml in den Abschnitten mqtt: und serial: entsprechend anpassen.

# MQTT settings
mqtt:
  # MQTT Base Topic for zigbee2mqtt MQTT messages
  base_topic: zigbee2mqtt
  # MQTT Server URL
  server: 'mqtt://localhost'
  # Benutzerdaten für den MQTT server eintragen, sofern erforderlich: 
  user: my_user
  password: my_password

# Serial settings
serial:
  # Hier das oben erstellte USB-Device eintragen:
  port: /dev/zigbee2mqtt0

Zigbee2mqtt starten

Für einen ersten Test, ob alles geklappt hat, kann der Server manuell gestartet werden:


# In den richtigen  Benutzerkontext wechseln
sudo -u zigbee -i

# Python3 Environment aktivieren
source bin/activate

# Dienst starten
npm start

# Der Dienst kann mit Strg+c beendet werden 

# Python Environment
deactivate

Wenn dabei kein Fehler auftritt, muss ein Startscript für systemd erstellt werden, damit der Dienst nach einem Reboot auch automtisch gestartet wird. Dazu reicht es die Datei /etc/systemd/system/zigbee2mqtt.service anzulegen:

sudo cat <<\EOF > /etc/systemd/system/zigbee2mqtt.service 
[Unit]
Description=zigbee2mqtt
After=network.target 
Wants=mosquitto.service

[Service]
User=zigbee
PermissionsStartOnly=true
ExecStartPre=/bin/chown root:plugdev /dev/zigbee2mqtt0
ExecStartPre=/bin/chmod 664 /dev/zigbee2mqtt0
ExecStart=/bin/bash -c 'source /srv/zigbee2mqtt/bin/activate; /srv/zigbee2mqtt/bin/npm start'
WorkingDirectory=/srv/zigbee2mqtt
StandardOutput=inherit
StandardError=inherit
Restart=always

[Install]
WantedBy=multi-user.target
EOF

Wenn das Startup-Script per systemctl daemon-reload eingelesen wurde, sollte sich der Dienst jetzt per systemctl start zigbee2mqtt starten lassen. systemctl status zigbee2mqtt zeigt, ob der Dients erfolgreicih gestartet wurde. Ist das der Fall, kann mit systemctl enable zigbee2mqtt.service der automatische Start des Dienstes aktiviert werden.

Hinweis: Wie die Installation später aktualisiert werden kann wird in dem Artikel Zigbee2mqtt inkl. Coordinator-Firmware aktualisieren beschrieben.

Damit sollte Zigbee2mqtt in der Grundkonfiguration funktionieren. Bevor aber die ersten Zigbee-Geräte angebunden werden, sollte dass Zigbee-Netzwerk noch abgesichert werden. Außerdem muss im Home Assistant auch noch sichergestellt werden, dass die neu gekoppelten Devices im Home Assistant auch automatisch erkannt werden. Das wird dann im nächsten Artikel beschrieben (siehe Zigbee2mqtt absichern und in Home Assistant einbinden). 

Quellen

[1] Zigbee2mqtt
[2] Zigbee2mqtt - Supported Devices
[3] Zigbee2mqtt - Supported AdaptersZigbee2mqtt - Supported Adapters
[4] GitHub - Z-Stack-Firmware
[5] Zigbee2mqtt - CC2531 flashen
[6] Zigbee2mqtt - Flashing via Uniflash
[7] Running Zigbee2mqtt
[8] Running Zigbee2mqtt in Virtual Environment

 

Kommentare

PostadresseE-MailadresseFestnetzMobiltelefonSMS/SignalThreemaTwitter DirektnachrichtFAXWeb Page