A few people have asked so I figured I’d share this method to use the new Zooz ZAC93 800-series GPIO module with an ESP32 running esphome and UART stream server component. This is effectively a zwave-serial-to-IP-over-WiFi bridge. The ESP32 does not process any zwave packets, it just presents the raw UART as a TCP serial connection which is used by zwave-js-ui running on a server elsewhere on the LAN.
First off, I know there are WiFi haters out there who will think this is nuts, but (a) sometimes you just can’t put a wired Z-wave hub where you want in your house and this solution gives you the flexibility to put one almost anywhere you want, for under $20, and (b) my WiFi is quite solid, with 50+ devices in a downtown apartment seeing dozens of networks. Friends don’t let friends use their ISP router for WiFi.
Another bonus: this solution gives the added option of bluetooth proxying on the ESP32, whereas if used atop a raspberry pi, bluetooth has to be disabled in the kernel to enable the GPIO UART. (there might be a workaround for this, but none of the Zooz docs mention it).
For background, the Zooz ZAC93 GPIO module is a UART (serial) module specifically designed to sit atop a raspberry pi. I had it on an old Pi Zero W for a while, and it worked fine running zwave-js-ui under docker, but the OS on sdcard was painfully slow (and a failure waiting to happen). A new Zero 2 would be better, but they are extremely hard to get lately, and frankly I got tired of running a full separate OS for a zwave hub. I already had a few ESP32s sitting around looking for work so I thought I’d give this a try. Disclaimer that I am not using this for my production network yet, but I’ve been testing it for a few weeks and haven’t seen any dropouts or issues.
Basic wiring diagram is just to connect four pins from the ESP32 to the ZAC93: 3.3V, ground, Tx and Rx. Unfortunately the pins don’t perfectly lineup for a module-on-board match, so I used Dupont cables. I used GPIO1 for Tx and GPIO3 for Rx, which is the existing UART0, meaning it’s best to move the esphome logging to uart1 (or disable) to avoid conflict. I’ve attached some images for wiring.
In esphome, here are the relevant details for the firmware configuration. Note the baud rate worked best as 115200. A binary sensor is also created, thanks to the stream_server component, to let you know when the serial stream has an active TCP connection.
logger:
hardware_uart: UART1
uart:
id: uart_zwave
tx_pin: GPIO1
rx_pin: GPIO3
baud_rate: 115200
external_components:
- source: github://oxan/esphome-stream-server
stream_server:
id: zac93
uart_id: uart_zwave
port: 6638
binary_sensor:
- platform: stream_server
connected:
name: Connected
After compiling and installing the ESP32 firmware, it should be ready to use. In zwave-js-ui, just enter tcp://ip:port
as the location of the zwave serial module, and it will open a connection and cause the the binary sensor (which I renamed zwave server) to be Connected
. You should be able to open the debug logs and see the driver polling the card for details like RSSI readings.
For added peace of mind, you can create an automation that alerts you if the binary sensor becomes disconnected for more than, say, 30 seconds.