Skip to main content

🟢 Z-Wave JS UI auf EOS ARM mit ioBroker

Z-Wave JS UI nativ auf EndeavourOS ARM headless mit ioBroker

Z-Wave JS UI als Vorbereitung für ioBroker.zwavews

Voraussetzungen für ioBroker

  • Eine laufende zwave-js-ui Umgebung
  • Aktivierte WS (Websocket) Kommunikation
  • Installation und Konfiguration des Adapters ioBroker.zwavews

ℹ️ Hinweis

  • Das Webinterface läuft standardmäßig auf Port 8091
  • Der Websocket-Server für ioBroker.zwavews läuft standardmäßig auf Port 3000

📋 Voraussetzungen

System

  • Raspberry Pi 4 oder 5
  • EndeavourOS ARM (Headless empfohlen)
  • ioBroker nativ installiert unter /opt/iobroker
  • NodeJS LTS 22 (nodejs-lts-jod), bei Artikelerstellung von ioBroker empfohlen
  • Funktionierender Z-Wave Controller
    • USB-Stick (z.B. /dev/ttyACM0 oder /dev/ttyUSB0)
    • oder RaZberry 7 (z.B. /dev/ttyAMA0)
  • SSH-Zugriff

Neuer Z-Wave Controller: ZWA-2

Aktuell (seit 2026-03-21) im Einsatz: Home Assistant Connect ZWA-2 (Nabu Casa)
Technische Details:

  • Controller: Z-Wave 800-Serie
  • Kompatibilität: Läuft stabil mit Z-Wave JS UI (11.15.0)
  • Info: Kein Home Assistant nötig
  • Firmware: 1.2.0 (stable)
  • Migration: NVM vom RaZberry 7 erfolgreich importiert

Wenn der ZWA-2 per USB angeschlossen ist, erscheint er unter Linux als serielles Gerät, z.B.:

/dev/ttyACM0

Für eine stabile Zuordnung empfiehlt sich der feste Gerätepfad unter:

/dev/serial/by-id/

Ein typischer Eintrag sieht dann etwa so aus:

ls -l /dev/serial/by-id/
lrwxrwxrwx 1 root root 13 07. Jan 21:42 usb-Nabu_Casa_ZWA-2_<SERIENWERT>-if00 -> ../../ttyACM0

Wenn du den ZWA‑2 als Controller einrichtest, trägst du genau diesen Pfad ein:

/dev/serial/by-id/usb-Nabu_Casa_ZWA-2_<SERIENWERT>-if00

zwa-2.jpg Verbaut ist ein Silicon Labs ZG23 mit ESP32-S3 als SoC. Der ZWA-2 nutzt den neuesten Chipsatz der 800er-Serie und unterstützt alle gängigen Z-Wave-Geräte – inklusive Mesh und Z-Wave Long Range (LR).

📌 Hinweise zum ZWA-2

  • Binary Switch: LED an/aus
  • Enable Tilt Indicator: Neigungsanzeige an/aus
  • Stromverbrauch (ca.): 5V / 0,182A (910mW)
  • Antenne: Große Antenne (erhoffte Reichweitenverbesserung)

⚙️ Wichtige Systemkonfiguration bei RaZberry 7

Die Konfiguration erfolgte bereits bei: "ioBroker auf Pi 4 mit EndeavourOS → Schritt 7: Vorbereitung für ioBroker"

Dort muss folgendes gesetzt sein:

/boot/config.txt
enable_uart=1
dtoverlay=disable-bt
/boot/cmdline.txt

Falls vorhanden, entfernen:

console=serial0,115200

🔎 System prüfen

node -v
npm -v

Empfohlen zum Zeitpunkt dieser Anleitung: Node.js 22 LTS (nodejs-lts-jod).
Bei Installation gemäß ioBroker-Anleitung ist diese Version bereits vorhanden.

Bei USB-Stick:

ls -l /dev/ttyACM* /dev/ttyUSB* 2>/dev/null

Bei RaZberry 7 (GPIO):

ls -l /dev/serial* /dev/ttyAMA* 2>/dev/null

meine Ausgabe:

crw-rw---- 1 root uucp 204, 64 10. Feb 18:42  /dev/ttyAMA0

Gerät gehört Gruppe uucp und nur root und Mitglieder der Gruppe uucp dürfen zugreifen.

In zwave-js-ui verwendest du später:

/dev/ttyAMA0

🚀 Installation

Z-Wave JS UI lokal in eigenes Verzeichnis installieren

Für eine bessere Übersicht nutze ich den Ordner /opt, da sich dort bereits ioBroker befinden.

Auch Z-Wave JS UI wird deshalb unter /opt/zwave-js-ui installiert.

Dabei werden Programm und Daten bewusst getrennt gespeichert.

/opt/zwave-js-ui
 ├─ app
 │   └─ node_modules
 └─ store

Der Vorteil:

  • Updates betreffen nur den Ordner "app".
  • Alle Einstellungen bleiben im Ordner "store" erhalten.

VERZEICHNISSE ANLEGEN

sudo mkdir -p /opt/zwave-js-ui/app
sudo mkdir -p /opt/zwave-js-ui/store/.config-db/devices

SERVICE-USER ANLEGEN
Mit eigenem Home-Verzeichnis anlegen und zur Gruppe uucp hinzufügen.

sudo useradd -r -m -d /opt/zwave-js-ui -s /usr/bin/nologin zwave
sudo usermod -aG uucp zwave

Überprüfen:

grep zwave /etc/passwd

Erwartete Ausgabe:

zwave:x:<UID>:<GID>::/opt/zwave-js-ui:/usr/bin/nologin

⚠️ Gruppenmitgliedschaft prüfen

id zwave

Erwartete Ausgabe:

uid=<UID>(zwave) gid=<GID>(zwave) Gruppen=<GID>(zwave),...(uucp)

Bedeutung:

  • uid(zwave) → Benutzer „zwave“ existiert
  • gid(zwave) → primäre Gruppe „zwave“
  • Gruppen=…(zwave),…(uucp) → Benutzer ist in der Gruppe „uucp“

RECHTE SETZEN

sudo chown -R zwave:zwave /opt/zwave-js-ui

INSTALLATION ALS USER "zwave"

cd /opt/zwave-js-ui/app
sudo -u zwave npm init -y
sudo -u zwave npm install zwave-js-ui@latest

Hinweis

npm init -y ist optional. Falls keine package.json existiert, legt npm install sie automatisch an.


OPTIONAL
Backup-Dateien zurückkopieren (falls vorhanden), Beispiel – Pfad ggf. anpassen:

sudo cp ~/tmp/nodes.json /opt/zwave-js-ui/store/
sudo cp ~/tmp/settings.json /opt/zwave-js-ui/store/
sudo cp ~/tmp/users.json /opt/zwave-js-ui/store/

Z-Wave Cache-Dateien (HomeID anpassen, z.B. a42bc123):

sudo cp ~/tmp/a42bc123.jsonl /opt/zwave-js-ui/store/
sudo cp ~/tmp/a42bc123.metadata.jsonl /opt/zwave-js-ui/store/
sudo cp ~/tmp/a42bc123.values.jsonl /opt/zwave-js-ui/store/

Rechte korrigieren:

sudo chown -R zwave:zwave /opt/zwave-js-ui/store

systemd Service anlegen

sudo nano /etc/systemd/system/zwave-js-ui.service

Inhalt:

[Unit]
Description=Z-Wave JS UI
After=network-online.target

[Service]
Type=simple
User=zwave
Group=zwave
SupplementaryGroups=uucp
WorkingDirectory=/opt/zwave-js-ui/app
Environment=NODE_ENV=production
Environment=STORE_DIR=/opt/zwave-js-ui/store
Environment=ZWAVEJS_EXTERNAL_CONFIG=/opt/zwave-js-ui/store/.config-db
ExecStart=/usr/bin/node --preserve-symlinks /opt/zwave-js-ui/app/node_modules/zwave-js-ui/server/bin/www.js
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Rechte anpassen, Service laden, aktivieren, starten:

sudo chown -R zwave:zwave /opt/zwave-js-ui
sudo systemctl daemon-reload
sudo systemctl enable zwave-js-ui
sudo systemctl start zwave-js-ui

Status und Ports prüfen:

systemctl status zwave-js-ui
sudo ss -tulpn | grep -E '8091|3000'

Port 3000 ist noch nicht offen, weil der Websocket-Server noch nicht aktiviert ist (kommt später im Webinterface).


🌐 Webinterface öffnen

http://<IP-deines-Pi>:8091

bei mir ist das:

http://192.168.0.164:8091

🔄 OPTIONAL: Migration von zwave2 zu zwave-js-ui

Einfache Migration: Cache-Datei von zwave2 übernehmen und Batteriegeräte einmal aufwecken.

Dieser Abschnitt ist nur bei einem Upgrade des Adapters ioBroker.zwave2 relevant und optional. In Einzelfällen kann es dennoch erforderlich sein, batteriebetriebene Geräte erneut zu interviewen. Bei einer Neuinstallation kann dieser Schritt übersprungen werden.

Für die Migration muss zwave-js-ui bereits installiert und betriebsbereit sein.
Der Adapter ioBroker.zwave2 darf währenddessen nicht aktiv sein, da der serielle Port nur exklusiv von einem Prozess geöffnet werden kann.

Die Übernahme der zwave2-Geräte ist möglich, da alle relevanten Informationen im Z-Wave-Koordinator (Controller) gespeichert sind.


Cache-Datei übernehmen

Der Z-Wave-Treiber speichert Informationen über das Netzwerk im Cache. Dieser Cache enthält die beim Interview ermittelte Struktur des Gerätes. Dadurch müssen Geräte nach einem Neustart nicht erneut vollständig interviewt werden.

Ohne Cache müssen die Geräte erneut interviewt werden. Batteriebetriebene Geräte müssen dafür meist manuell aufgeweckt werden, da sie sich normalerweise im Schlafmodus befinden.

Im zwave2-Ordner befinden sich mehrere controller-spezifische JSON-Dateien (*.jsonl). Der Dateiname basiert auf der Home ID des Z-Wave-Controllers (hexadezimal) und ist daher auf jedem System unterschiedlich.

Typischer Speicherort:

/opt/iobroker/iobroker-data/zwave2.0/cache

Zuerst den Ordnerinhalt prüfen:

ls -l /opt/iobroker/iobroker-data/zwave2.0/cache

Gesucht werden Dateien mit der Endung .jsonl, z.B.:

a42bc123.jsonl
a42bc123.metadata.jsonl
a42bc123.values.jsonl

Die Dateien dürfen nicht umbenannt werden.

Dateien mit der Endung .lock werden nicht benötigt und sollten nicht kopiert werden.


Zielverzeichnis (Store)

Bei dieser Installation liegt das Store-Verzeichnis hier:

/opt/zwave-js-ui/store/

Hauptdateien kopieren

sudo cp /opt/iobroker/iobroker-data/zwave2.0/cache/*.jsonl /opt/zwave-js-ui/store/

Rechte korrigieren

sudo chown zwave:zwave /opt/zwave-js-ui/store/*.jsonl

Dienst neu starten und den Status prüfen:

sudo systemctl restart zwave-js-ui
systemctl status zwave-js-ui

Hinweis zum weiteren Ablauf

Nach der Übernahme der Cache-Datei und dem Neustart erfolgt die normale Einrichtung (Serial Port, Security Keys und WebSocket) wie in den folgenden Abschnitten beschrieben.

Batteriebetriebene Geräte müssen einmal manuell aufgeweckt werden, damit sie vollständig eingelesen werden.


🔌 Serielles Device konfigurieren

Im Webinterface:

Settings → MQTT Gateway

Das MQTT Gateway wird für ioBroker.zwavews nicht benötigt und kann deaktiviert bleiben. Die Kommunikation mit ioBroker erfolgt ausschließlich über Websocket.

zwave-js-ui_settings1.png

Aktiviere die WS-Server-Einstellungen in zwave-js-ui. Diese findest du in den Einstellungen von Home Assistant.


Settings → Z-Wave → Serial Port

In meinem Beispiel:

/dev/ttyAMA0

Zusätzlich konfigurieren:

  • Bei einer Neuinstallation die Security Keys generieren lassen
  • Bei einem Upgrade von ioBroker.zwave2 die dort verwendeten Security Keys übernehmen
  • Bei meinem Upgrade mussten die „Security Keys (Long Range)“ neu generiert werden, da ioBroker.zwave2 diese nicht unterstützt
  • Default Radio Configuration: Europe

zwave-js-ui_settings2.png

Die im Bild gezeigten Keys sind nur Beispielwerte (Demo)!

zwave-js-ui_controlPanel.png

zwave-js-ui_networkGraph.png


Websocket für ioBroker.zwavews aktivieren

Im Webinterface:

Settings → Home Assistant

  • Websocket Server aktivieren
  • Server Host leer lassen (bindet auf allen Interfaces)
  • Standard-Port 3000 verwenden
  • DNS Discovery deaktivieren (bei fester IP und manueller URL im Adapter nicht erforderlich)

Speichern.

Du wirst gefragt, ob der Z-Wave JS Driver neu starten soll: YES

Alternativ:

sudo systemctl restart zwave-js-ui

Port prüfen:

sudo ss -tulpn | grep 3000

💡 Tipp

Die Einstellungen der zwave-js-ui Oberfläche können über Import / Export gesichert und wiederhergestellt werden.

⚠️ Wichtig

Ein Z-Wave Controller ist ein serielles Gerät. Der Port kann in der Regel nur von einem Prozess exklusiv geöffnet werden (Lock). Während du zwave-js-ui einrichtest, muss der zwave2 Adapter deaktiviert bleiben, sofern dieser genutzt wird. Später ersetzt zwave-js-ui den zwave2 Adapter vollständig.

Diese Einstellungen im ioBroker.zwavews Adapter eintragen:

ZwaveWS Verbindung

  • Scheme: WS
  • Websocket IP-Adresse: IP-deines-Pi
  • Websocket Port: 3000

ZwaveJS WebUI

  • Scheme: HTTP
  • WebUI IP-Adresse: IP-deines-Pi
  • WebUI Port: 8091

zwaveWS.png


🔄 Update von Z-Wave JS UI

Update installieren und kontrollieren:

sudo -u zwave npm install --prefix /opt/zwave-js-ui/app zwave-js-ui@latest

Dienst neu starten und prüfen:

sudo systemctl restart zwave-js-ui
systemctl status zwave-js-ui

Version prüfen (optional):

sudo -u zwave npm list --prefix /opt/zwave-js-ui/app zwave-js-ui

Ergebnis:

app@1.0.0 /opt/zwave-js-ui/app
└── zwave-js-ui@11.14.0

💡 Tipp

Alias-Stärken beim einfachen Austausch einer Komponente, ohne Scripts oder VIS anpassen zu müssen, liegen nicht nur in den eingebauten Konvertierungsfunktionen, sondern auch in der Möglichkeit, unterschiedliche IDs für Lesen und Schreiben zu nutzen. Das erspart euch zusätzliche Datenpunkte und/oder ein Script (z.B. per Blockly).

👉 Siehe auch: „Alias-Datenpunkte in ioBroker“ im Wiki.