Home automation comes with plenty of potential to make our lives easier. But in order to succeed in its task, it often requires you to fill your house with bridges that can connect your smart devices to your Wi-Fi network. Unless you buy a smart device that communicates directly over Wi-Fi (like a TP-Link or Belkin smart plug), odds are that many of your favourite smart devices use either Bluetooth, Zigbee or Z-Wave to communicate. These protocols solve some of the issues of Wi-Fi when it comes to smart devices — like latency, centralised topology and relatively high power requirements — but they do require some physical hardware in between to do the smart protocol <-> Wi-Fi translation and make the devices actually controllable from a Wi-Fi-connected client.
The bad thing is that you’ll probably need a different bridge or hub for each class of devices you want to use. Philips Hue lights come with their own bridge, same for Lutron, same for HomeKit, same for Belkin, same for Switchbot, and the list goes on. What’s ironic is that most of these devices actually speak the same protocol (either Zigbee or Z-Wave) but, in most of the cases, they can only control their own devices. Try to imagine an alternative reality where all the ethernet cards can send and receive TCP/IP packets, but you’ll need an adapter just for HTTP traffic, one for FTP, one for SMTP, and so on: that’s more or less the reality today when it comes to smart bridges and hubs.
In order to solve the problem, many companies are throwing on the market even more hubs and bridges (from Samsung SmartThings, to the plethora of Amazon Echo, Google and Apple devices etc.), often compatible only with a subset of the devices out there and incompatible with one another, often incompatible by design with devices produced by competitors: that only brings even more fragmentation to the current smart home hell.
Moreover, many hubs can usually talk only to their smartphone app, adding an app hell to the bridge hell.
One of the most sought goals nowadays when it comes to home automation is (or it should be) to find consistent ways to communicate with as many devices as possible using the same tool, the same box and the same interface.
I’ve recently worked on achieving this goal in platypush. Other platforms have tackled the issue too (from HASS.io to Openhab) but, in my opinion, they all still require a certain degree of user configuration (like specifying what each device is and what it’s supposed to do) that in my opinion shouldn’t be required. In this article, we’ll go through what Zigbee and Z-Wave actually are, what you need to set up a universal bridge for them using just a Raspberry Pi and a USB dongle, and how to permanently move your existing smart bridges to the storage room.
Zigbee and Z-Wave have arguably risen to become the dominant communication protocols in the smart home and IoT industries. They share some common features, such as:
When it comes to the differences:
That should cover most of the knowledge you need when it comes to the theory of Zigbee and Z-Wave. You’ll find many Zigbee and Z-Wave compatible smart devices around. Some examples of Zigbee devices are the Philips Hue and Ikea smart bulbs, Honeywell thermostats, Belkin smart plugs and bulbs, Bosch sensors and Osram products. Z-Wave includes around 65,000 compatible devices out there, including many garage doors, presence and temperature sensors, thermostats, dimmers, remote controls, smoke detectors and so on.
We’ll use a RaspberryPi in the following examples as a DIY bridge (any model and any distribution should work fine), and platypush as a home automation platform that also runs the Zigbee and Z-Wave integrations.
On the hardware side you’ll need:
On the software side:
platypush uses zigbee2mqtt as a backend to interact with the Zigbee dongle. Install the zigbee2mqtt firmware on the dongle by following the instructions (for Windows, macOS and Linux) on their website. You can check a list of the compatible devices here.Install, start and enable an MQTT instance on the local machine, if you don’t have a server already running in your network. If you’re running Debian/Ubuntu/Raspbian and want to use Mosquitto, for example:
[sudo] apt-get install mosquitto
[sudo] systemctl start mosquitto.service
[sudo] systemctl enable mosquitto.service
Install zigbee2mqtt:
[sudo] apt-get install nodejs git make g++ gcc
git clone https://github.com/Koenkk/zigbee2mqtt
cd zigbee2mqtt
npm install
vi data/configuration
# Change mqtt.server and serial.port to respectively
# match your MQTT server and USB dongle device.
npm start
You can also make a systemd service out of it:
[Unit]
Description=zigbee2mqtt
After=network.target
[Service]
ExecStart=/usr/bin/npm start
WorkingDirectory=/path/to/zigbee2mqtt
StandardOutput=inherit
StandardError=inherit
Restart=always
[Install]
WantedBy=multi-user.target
Note that the zigbee2mqtt configuration file also includes a permit_join option. Set this to true while you’re pairing your Zigbee devices for the first time, and set it to false afterwards to prevent other devices from accidentally or malignantly join the network — you can always temporarily allow joins later.
Once started and in permit_join mode, you can start pairing Zigbee devices to your new network. That is usually done by doing a factory reset of the device. The procedure varies with the device: Philips Hue bulbs, for example, can be reset either from the app (if they are paired to a bridge) or by pressing the ON/OFF buttons of a Hue dimmer simultaneously for 10 seconds while keeping the dimmer within 10 cm from the lightbulb. Other Zigbee devices may include a reset button instead.Once a Zigbee device joins the network, the zigbee2mqtt logs should show a trace like the following:
Successfully interviewed '0x00158d0001dc126a', device has successfully been paired
Install Redis and platypush with the Zigbee, HTTP and MQTT extensions:
[sudo] apt-get install redis-server
[sudo] systemctl start redis.service
[sudo] systemctl enable redis.service
pip install 'platypush[zigbee,http,mqtt]'
Edit your
~/.config/platypush/config.yaml
file to enable the Zigbee and HTTP services:backend.http:
port: 8008
zigbee.mqtt:
host: localhost
backend.zigbee.mqtt:
enabled: true
Start platypush (either by running platypush or starting the platypush.service systemd service).Open http://host-or-ip:8008/ in a browser. The web panel should include the Zigbee icon in the navigation bar, you’ll be able to control your network from there.
You can send requests through the supported API over HTTP, Python code or through whichever platypush backend you have configured:
# HTTP request
curl -XPOST -H 'Content-Type: application/json' -d '
{
"type":"request",
"action":"zigbee.mqtt.device_set",
"args": {
"device":"White Bulb",
"property":"state",
"value":"ON"}
}' http://localhost:8008/execute
# Python usage
from platypush.context import get_plugin
get_plugin('zigbee.mqtt').device_set(device='White Bulb', property='state', value='ON')
Or hook any custom logic to the supported events:
event.hook.OnLightBulbOn:
if:
type: platypush.message.event.zigbee.mqtt.ZigbeeMqttDevicePropertySetEvent
device: White Bulb
then:
- if ${properties.get('state') == 'ON'}:
- action: tts.say
args:
text: "The light went on"
Congratulations, you’re now ready to use your Zigbee devices and build automation without bridges!
Making a DIY Z-Wave bridge is even simpler than making a Zigbee bridge, as you won’t need a debugger to flash a custom firmware nor an MQTT service in between.
You’ll need a Z-Wave USB adapter dongle. I use this one, but any compatible dongle should work. Take note of where the adapter is mapped on your system — e.g. /dev/ttyUSB0.
Install Redis and platypush with the Z-Wave and HTTP extensions:
[sudo] apt-get install redis-server
[sudo] systemctl start redis.service
[sudo] systemctl enable redis.service
pip install 'platypush[zwave,http]'
Configure your integrations in
~/.config/platypush/config.yaml
:backend.http:
port: 8008
zwave:
device: /dev/ttyUSB0
backend.zwave:
enabled: true
Start platypush (by running platypush or through systemd service) and point your browser to http://host-or-ip:8008/. You’ll see a new tab for the Z-Wave integration.Some screenshots from the Z-Wave web panel.
Each Z-Wave compatible device has its own way of pairing to a network. All you need to do is to press on the + button to put the network in pairing mode and then pair your devices within one minute through the procedure referred in the user manual. Since Z-Wave has a stricter protocol and all the compliant devices publish their values using the same format, the Z-Wave interface is much more granular and detailed compared to Zigbee.
You can, of course, send commands to the new network through the available API and subscribe custom hooks on Z-Wave events:
# HTTP request
curl -XPOST -H 'Content-Type: application/json' -d '
{
"type":"request",
"action":"zwave.get_value",
"args": {
"value_label":"Temperature",
"node_name":"Kitchen Sensor"
}
}' http://localhost:8008/execute
# Python usage
from platypush.context import get_plugin
get_plugin('zwave').get_value(value_label='Temperature', node_name='Kitchen Sensor')
# Example output
{
"type": "response"
"target": "http",
"response": {
"errors": [],
"output": {
"command_class": 49,
"data": 26.799999237060547,
"data_items": "Read only",
"genre": "User",
"index": 1,
"is_read_only": true,
"is_write_only": false,
"label": "Temperature",
"node_id": 3,
"type": "Decimal",
"units": "C",
"value_id": 72057594093256722
}
},
}
# Trigger a custom action when motion is detected
event.hook.OnZWaveValueEvent:
if:
type: platypush.message.event.zwave.ZwaveValueChangedEvent
then:
- if ${node['name'] == 'Motion Sensor' and value['label'] == 'Sensor' and value['data'] is True}:
- action: tts.say
args:
text: Motion has been detected
You should now have all the ingredients to build your custom IoT networks and ditch those bridges for good!
Previously published at https://medium.com/the-monolith/transform-a-raspberrypi-into-a-universal-zigbee-and-z-wave-bridge-b686cdd1849e