Z-Wave JS

Z-Wave JS

Serial over TCP with ser2net

Instead of using a local USB port on the same host, the Z-Wave JS drive can connect to a serial port over TCP, for example using ser2net1. Z-Wave sticks are basically Serial-over-USB devices.

Configuring ser2net on host with USB stick

First you need to determine which /dev file/serial port your stick gets mapped to.


The udev hwdb files are read from the text files located in the system hwdb directory /usr/lib/udev/hwdb.d.

Instead of using the default /dev/ttyUSB0 or /dev/ttyACM0 device /dev paths, you can use udev rules to automatically create a symlink under /dev with a predictable name for your Z-Wave stick, as well as set permission bits and group ownership.

ser2net has to be running as a user that can read and write to the device path.

The idVendor and idProduct are the ID's from udev's hardware database2. You can find these in several ways3, for example they get printed by dmesg when you plug it in, and you can also use lsusb.

For example, I am using an Aeotec Z-Stick:

$ lsusb | grep "ZW090"
Bus 001 Device 016: ID 0658:0200 Sigma Designs, Inc. Aeotec Z-Stick Gen5 (ZW090) - UZB

The udev ID of is 0658:0200, meaning that idVendor is 0658 and idProduct is 0200.

Create the rule a file /etc/udev/rules.d/10-zwave.rules:

SUBSYSTEM=="tty", ATTRS{idVendor}=="0658", ATTRS{idProduct}=="0200", MODE="0660", GROUP="dialout", SYMLINK+="zwave0"

This will symlink a device with id 0658:0200 to /dev/zwave0, with the file mode 0600 and owned by the dialout group.

And reload the udev rules:

$ sudo udevadm control --reload-rules

Now you can plug in the Z-Wave stick, and the /dev/zwave0 symlink should be created:

$ ls -l /dev/zwave0
lrwxrwxrwx 1 root root 7 Jan 31 08:15 /dev/zwave0 -> ttyACM0

The permissions and ownership will be reflected by the device file the symlink points to:

$ ls -l /dev/ttyACM0
crw-rw---- 1 root dialout 166, 0 Jan 31 08:15 /dev/ttyACM0

Edit /etc/ser2net.yaml:

define: &banner \r\nser2net port \p device \d [\B] (Debian GNU/Linux)\r\n\r\n

connection: &zwave0
    # Bind to TCP port
    accepter: tcp,30844
    enable: on
        kickolduser: true
        # Ensure mDNS is disabled
        mdns: false
    # Use the symlink from /etc/udev/rules.d/10-zwave.rules
    connector: serialdev, /dev/zwave0,115200N81,nobreak,local

The ser2net serial port has to be configured with 115200 as the baud rate followed by N81 for 8 data bits and 1 stop bit.

Z-Wave JS configuration


This also works with ZHA and zigbee2mqtt, since Zigbee devices are also USB-over serial devices.

For zigbee2mqtt, in configuration.yaml:

  port: tcp://${hostname}:${port}

For ZHA, it is (unfortunately) only possible to configure it in the UI. Configure it as socket://${host}:${port} (not tcp://).

In the Z-Wave JS settings, configure Serial Port as tcp://${host}:{port}.

Configuring Z-Wave JS to use the ser2net serial port

Settings -> Z-Wave

Or set it in settings.json:

  "zwave": {
    "port": "tcp://${host}:${port}"




See man hwdb.