A Z-Wave network in Home Assistant has four parts: an adapter plugged into the server, a Z-Wave server (on Home Assistant OS, the Z-Wave JS app, formerly an add-on), the Z-Wave integration, and the devices. The first device usually joins within minutes. Most problems show up later and trace back to a few early decisions: which adapter you bought, where it sits, whether you kept the security keys, and how chatty your devices are allowed to be.
Z-Wave runs below 1 GHz, away from the 2.4 GHz band that Wi-Fi, Bluetooth, Zigbee and Thread share. The exact frequency depends on the region. In the EU, classic Z-Wave uses 868.4 and 869.85 MHz, in the US 908.42 and 916 MHz. A 700 or 800 series adapter can be switched between regions, but end devices cannot, so buy devices made for your region.
Pick an 800 series adapter and check its firmware
Home Assistant's documentation recommends an 800 series adapter for anyone starting out. The officially recommended one is the Home Assistant Connect ZWA-2. The documentation also lists the HomeSeer SmartStick G8 and the Zooz ZST39 LR as 800 series adapters reported to work. A 700 series adapter is generally not recommended, and the EU version of the Aeotec Z-Stick 7 is singled out for poor RF performance.
Firmware matters as much as the model. Some 700 and 800 series firmware has bugs that destabilise the mesh or make the adapter stop responding, and no version is known to be completely fixed. For 800 series adapters, the documentation suggests:
- prefer SDK 7.23.x or newer (the integration page asks for firmware 7.23.2 or later when buying new);
- 7.22.x and 7.17.2 to 7.19.x are okay;
- avoid anything before 7.17.2 and versions 7.20 to 7.21.3.
The SDK version does not have to match the firmware version the manufacturer prints, so ask the manufacturer if in doubt. Choose carefully: according to Z-Wave JS, controllers generally can't be downgraded. And prefer a USB adapter over a module, which is harder to pass through to Docker.
The ZWA-2 is a large antenna on a base rather than a stick, with one version for the whole world (recommended price 69 USD or 59 EUR). It ships set to the European region, and Home Assistant switches it to the region of the location in your settings. Keep it upright: it has an accelerometer and blinks its top light quickly when placed at a poor angle.
Put the adapter on a USB extension cable
According to the Home Assistant documentation, many reported Z-Wave problems come from RF interference from the server's own USB ports. Devices won't join, join without encryption, report corrupted values or react late. The first fix the developers ask for is a short USB 2.0 extension cable, followed by rebuilding the network routes.
The Z-Wave JS troubleshooting guide adds: keep the adapter away from other USB ports (USB 3 ports in particular), away from metal surfaces, out of the back of a server rack, and somewhere central. The adapter statistics show background RSSI, the noise level the radio hears. It should stay close to the radio's sensitivity limit, which for an 800 series adapter is around -110 dBm.
Install the Z-Wave JS app and save the keys
- Plug the adapter into the machine running Home Assistant. In most cases it is discovered automatically. In the dialog, choose Recommended installation, which installs the Z-Wave JS app, then assign an area and select Finish.
- Depending on the Home Assistant version, you may be asked for network security keys. On a first Z-Wave setup, leave the fields empty and submit: keys are generated for you. If the adapter has been used before with secure devices, enter the old network key as the S0 key.
- Wait for the app to start. The adapter's device page means the integration is ready.
Copy the keys somewhere safe straight away. They are in Settings > Apps > Z-Wave JS, on the Configuration tab: three S2 keys and one S0 key. Securely added devices only work with the keys they were added with. Lose the keys while moving to a new server, and the fix Z-Wave JS gives for a lock with mismatched keys is to remove it, possibly factory reset it, and add it again.
If the adapter isn't discovered, add the Z-Wave integration by hand in Settings > Devices & services > Add Integration, and check that the USB cable carries data and not only power.
On Home Assistant Container there are no apps. The recommended route there is the Z-Wave JS UI Docker container with its WS Server enabled, with the adapter given by its /dev/serial/by-id/... path so it doesn't change after a reboot. The older Z-Wave JS UI app on Home Assistant OS is being phased out, and the documentation describes a migration to the Z-Wave JS app that keeps the paired devices.
The radio region follows the location in Settings > System > General. To override it, pick a Radio Frequency Region on the app's Configuration tab, choosing the Long Range variant where there is one, such as Europe (Long Range). Devices without Long Range still work with it.
Back up the network, not only Home Assistant
The list of devices in the mesh is stored on the adapter. Everything else Z-Wave JS knows about them is not, so on first start the integration interviews every device. Battery devices make this slow: the Z-Wave JS documentation says a first interview can take several hours unless you wake the device by hand, usually with a button press described in its manual.
In Settings > Connectivity > Z-Wave you can Download backup. The file contains the adapter's non-volatile memory, including the paired devices. Download one before you migrate to a new adapter or reset the old one, and keep it with the security keys. The same page has Restore from backup and Migrate adapter, which moves the network to a new adapter without re-pairing devices.
Add devices with SmartStart and S2
Go to Settings > Connectivity > Z-Wave and select Add device.
With SmartStart (look for the SmartStart label and a QR code on the box or the device): keep the device switched off, select Scan QR code, scan it, and then power the device on or put it into inclusion mode. QR scanning in the browser needs HTTPS. Without it, read the code with another app and paste its content as text. A SmartStart device on the list is added automatically within about 10 minutes of being switched on near the network.
Without SmartStart: put the device into inclusion mode as its manual describes. For S2 you'll be asked for a PIN, the first five digits of the device's DSK key. It is often printed on the device and in its documentation. Photograph the label before the device disappears into a wall box.
Two old habits no longer apply. Don't carry the adapter to the device to add it, because that leaves broken routes. And don't start inclusion with a button on the adapter, which Home Assistant no longer supports.
Z-Wave JS groups encryption into security classes:
- S2 Access Control for locks, garage doors and similar;
- S2 Authenticated for alarm systems, sensors, lighting;
- S2 Unauthenticated, the same encryption without verifying that you added the right device;
- S0, the legacy class.
Home Assistant prefers S2 whenever a device supports it and falls back to S0 only when it has to. S0 adds a lot of traffic: the Z-Wave JS guide counts three commands per report, and advises against S0 for sensors altogether. A lock is different. Its main functions require encryption, so if it ended up added without it, remove it and add it again.
Entities appear when the interview finishes, usually after seconds to minutes. Some devices, such as button remotes, create no entities at all and only fire events (zwave_js_value_notification for scene buttons) that you use as automation triggers.
If a device won't join, the usual causes are:
- It is still paired with another network. Exclude it first. If you don't have the old adapter, use Options > Remove foreign device on the Z-Wave page. A factory reset also works.
- The region doesn't match the device.
- It is too far away. Some older devices lower their transmit power during inclusion. Bring them closer for pairing, then rebuild routes once everything is back in place.
Mesh or Long Range
In a classic Z-Wave mesh, always-on mains-powered devices repeat traffic for others. Battery devices such as locks, sensors and many thermostats do not. A network with only an adapter and a door lock has no mesh at all. A classic network holds up to 232 devices.
Z-Wave Long Range is a separate star network on the same adapter. Every Long Range device talks straight to the adapter, and none of them route traffic for classic devices. A network can hold up to 4000 of them. They can only be added with SmartStart and only with S2 Access Control or S2 Authenticated. When you scan a device that supports both, Home Assistant asks which network it should join:
- Long Range if it sits far from other devices or in a spot with past connection problems. It may also help the battery last longer.
- Mesh if you already have a mesh, because a new mains-powered device makes it stronger.
The choice isn't final. Remove the device and add it again to switch. The Z-Wave JS developers recommend making Long Range an opt-in choice rather than the default.
In Europe, Long Range is recent. The Z-Wave Alliance completed the European specification in February 2024, and Silicon Labs' SDK 7.23.1 shifted the European Long Range frequencies, making them incompatible with earlier implementations (7.22.x and 7.23.0). One more reason to keep the adapter firmware current.
Keep the network quiet
The Z-Wave JS guide is blunt: a direct link can carry 10 to 20 messages per second in good conditions, and a constant load like that across several hops is "absolutely devastating". Many devices ship with chatty reporting settings, multisensors and power meters most of all. Change them under Configure on the device's page:
- turn off reports you don't use, for example voltage and current on every socket of a power strip when you only need kWh;
- report on change instead of on a timer, with a threshold that fits the load, such as 1 W for an LED bulb and 50 W or more for a washing machine;
- keep timed reports only as a fallback, at a long interval such as once an hour;
- turn off supervision for reports that don't need confirmation.
Poll only as a last resort. Z-Wave does not poll devices on its own, and the zwave_js.refresh_value action is for targeted use, for example refreshing one value when there is motion in the room.
After moving a device, use Rebuild routes on its page. The network-wide Options > Discover and assign new routes generates a lot of traffic, so run it sparingly. Show map draws the routes, and Statistics gives per-device numbers: a device with thousands of incoming reports while others have a handful is probably misconfigured or poorly connected.
When something misbehaves
A node that keeps going dead and coming back, with "NoAck" in the log, has a weak connection to the adapter: go back to placement, the extension cable and reporting. A device shown as Unknown Manufacturer either hasn't finished its interview or has no device file in Z-Wave JS yet, and may still work fine. For a bug report, use Enable debug logging in the integration menu, reproduce the problem and switch logging off again. Home Assistant then offers the log for download.