Heads up for Home Assistant OS users: the HA docs say the Z-Wave JS UI app is being phased out, because its UI is now built into the Z-Wave JS app. If you run HA OS, use the Z-Wave JS app. This project is for Container/Core installs, or for people who want the controller on a different machine.
What you need
- A Z-Wave adapter for ANZ (see the buying guide in this forum), on a USB extension cable.
- A Docker host that can see the stick.
- Home Assistant with the Z-Wave integration.
Do not use /dev/ttyUSB0 or /dev/ttyACM0 because the numbering can change. The compose example says to use the /dev/serial/by-id/... path:
Code: Select all
ls -l /dev/serial/by-id/Based on the project's example:
Code: Select all
services:
zwave-js-ui:
container_name: zwave-js-ui
image: zwavejs/zwave-js-ui:latest
restart: always
tty: true
stop_signal: SIGINT
environment:
- SESSION_SECRET=change-me-to-a-long-random-string
- TZ=Australia/Sydney
devices:
- '/dev/serial/by-id/YOUR-STICK-ID:/dev/zwave'
volumes:
- zwave-config:/usr/src/app/store
ports:
- '8091:8091' # web interface
- '127.0.0.1:3000:3000' # Z-Wave JS websocket server
volumes:
zwave-config:
name: zwave-config- Set SESSION_SECRET to your own random value; the example uses a placeholder.
- Port 8091 is the web UI, port 3000 is the Z-Wave JS WebSocket server that Home Assistant connects to. If Home Assistant runs on a different machine you cannot bind 3000 to localhost: publish it to the LAN instead, and firewall it to the Home Assistant host only. As far as I know the WebSocket server does not require a login by default (check the docs), so treat port 3000 as trusted-network only. The 127.0.0.1 binding in the example only works if Home Assistant runs on the same host with host networking; otherwise publish it normally and firewall it.
- Pin the image tag to a release number rather than latest once it is working, so an update does not surprise you.
- Keep the UI and WebSocket ports off the internet. Use a VPN if you need remote access, and check the Z-Wave JS UI settings for its authentication option.
Code: Select all
docker compose up -d- Open http://your-host:8091. In Settings, Z-Wave, set the serial port to /dev/zwave.
- Generate the security keys (S0 and the three S2 keys) in the same section and copy them somewhere safe, such as a password manager. Losing them makes a restore or migration painful.
- Set the RF region to ANZ if it does not match automatically.
- In Settings, Home Assistant, enable the WS Server.
In Home Assistant, add the Z-Wave integration. If asked, untick the option to use the Z-Wave JS app, then enter the server URL: ws://your-docker-host:3000. Wording may differ across Home Assistant versions.
Step 5: include devices and test
- Include devices from the Z-Wave JS UI or from Home Assistant's Z-Wave page, not from the stick's button. Use S2 where offered, and S0 only where it is the only choice, such as older door locks.
- Once a device is in, only rebuild routes when you need to (for example after moving devices). It generates traffic, so do it overnight on a larger network and not over and over.
- Wake battery devices (button press) so they finish their interview.
- Some devices do not create entities: button remotes send events, so use them as automation triggers.
- Back up the /usr/src/app/store volume. It holds the Z-Wave JS UI settings including your keys.
- Download an NVM backup of the adapter itself (Z-Wave JS UI has a backup option) before firmware updates, migrating, or any reset.
- Test the restore path once while nothing depends on it.
Question for the group: are you running Z-Wave JS UI separately from Home Assistant, or using the built-in Z-Wave JS app, and what made you choose that? Any tips on keeping the WebSocket link reliable across hosts?