RaZberry - smart home based on Z-Wave and Raspberry Pi
- Tutorial
Many are trying to build a "smart home" with their own hands. When choosing a system, it is worth considering not only the range and cost of end devices, but also the capabilities of the controller. Most controllers are immediately ready to work “out of the box”, but present limited capabilities. However, it is often the flexibility and the possibility of easy integration that is the fundamental criterion for selection.
And now, the long-awaited “Lego cube” for automation systems based on Z-Wave technology has appeared, which has the desired flexibility and at the same time great functionality and low price.
The RaZberry expansion board for the Raspberry Pi turns the most popular and cheapest mini-computer into a Z-Wave home automation controller.
RaZberry is a three in one solution:
On Linux, RaZberry is seen as a com-port / dev / ttyAMA0. The board essentially consists of a ZM3102 transceiver, EEPROM memory for storing Z-Wave network data, a PCBA antenna, and a UART connector for GPIO Raspberry Pi legs. Only the legs Vcc, Gnd, TX and RX are actually used. The remaining legs are not used for the board and only help to fix it more firmly. In theory, these legs can be used for other needs.
The board provides an interface fully compatible with the Sigma Designs Serial API, which makes it possible to use not only the supplied Z-Way software, but also any other Z-Wave software (Open Z-Wave, LinuxMCE, FHEM or self-written), as well as the Z cloud service -Cloud (see instructions ). The board also provides an extension of the Sigma Designs Serial API protocol from Z-Wave.Me, which is necessary for the Z-Way software to work.
The firmware also allows you to update yourself by UART, which will not only fix possible bugs in the future, but also change the firmware version from the one installed by default (SDK 4.54.01) to the older 5.03, which does not have useful NWI, Explorer Frame and Random HomeId, but including SUC / SIS functionality. (For the attentive: yes, I was not mistaken, 4> 5;)
Z-Way is installed on top of Raspbian wheezy by running the command.
The installation script will put Z-Way in / opt / z-way-server, write the script to run in /etc/init.d/Z-Way, add it to the auto start and configure the port ttyAMA0. After rebooting (to apply kernel settings for ttyAMA0 - by default, Raspbian uses UART for the console), the server is ready to work. In a browser, open
Let's take a closer look at the Z-Way software bundled with RaZberry. It consists of several parts:
This structure allows you to use different levels of integration with the components of Z-Way. For projects where performance is important, a C-level API is available (there are .h header files for libzway included), for projects where operational development is needed, it is easier to use the JS API. It is important that both interfaces have a similar structure, which allows you to simply port the code from JavaScript to C after quick prototyping.
Next, I will describe the JavaScript level APIs and show how to create simple automation rules. The C-level interface is beyond the scope of this article. It is worth noting that the syntax in the server-side Z-Way JavaScript engine is similar to what was implemented for the Z-Cloud on the client side - see the Z-Cloud API description. For further reading, it is assumed that the reader is already familiar with the features of the Z-Wave protocol (see the detailed description of the Z-Wave protocol ).
Everything related to Z-Wave in the JavaScript namespace is located in the global zway object, which provides a complete tree of data and methods on Z-Wave devices.
The child object of controller, contains data specific to the Z-Wave controller, as well as a list of devices devices. Each device contains a data structure, as well as a list of device channels (instances). Each channel has a list of Z-Wave Command Classes supported by the device. The Command Class has methods for calling functions (Set, Get, ...), as well as a data tree (data), where all information about the Class is stored.
Graphically, this can be illustrated like this (picture from the documentation):
The API structure is asynchronous and is divided into two parts:
Sending commands is carried out by requests of the form
Teams queue for sending appropriate packets. Sending is carried out through the Sigma Designs Serial API, implemented on the RaZberry expansion board. All the magic of Z-Wave is hidden under this level of abstraction: for battery-powered devices, these packets are marked as awaiting awakening, a preliminary key exchange is in progress, to save battery power and airtime, some packets are bundled together and much more ... As with any protocol , Z-Wave has a lot of its cockroaches, which are all under the Z-Way API carpet and do not crawl out of there.
All data received from devices is recorded in the data tree related to the device or the Class of Commands. Each element of the data tree has the attributes value (element value), updateTime and invalidateTime (timestamp of date of update and expiration of the value), name (name). The tree structure is also described in detail in the documentation. To receive notifications about changes in tree values, there is a system of subscriptions to events. The bind function for each element of the tree allows you to bind a callback function to data changes.
The optional arg argument passed to bind will be passed to the callback function and useful for passing additional parameters to separate different events that share a common callback handler. The watchChildren parameter (true or false) allows you to track not only changes to this tree element, but also child ones. The this object in the callback function is an element of the data tree on which bind is launched: this.value is the value, this.updateTime is the date of the last update, etc. Type argument contains a bit mask of the change type (changed, updated, deleted, deprecated, ... - all values are described in detail in ZDefsPublic.h, which is included in the software package).
Similarly, there is a bind function on the global zway object, which allows you to track changes in the arrays of devices, instances and commandClasses:
The type argument indicates the nature of the change (a device / channel / command class has been added / deleted, or a file with a data tree to disk (ZDDX file) has been saved. The nodeId, instanceId, commandClassId triplet points to an object
that has been changed. Unbind can unsubscribe from events.
To simplify this, use the unbind function. syntax, you can omit the words commandClasses , instances [0] (exactly the zero channel!), .value (
It is worth noting that the zway global object is native in v8, i.e. This is not an ordinary JavaScript object: you can only change the data of tree elements. All other changes in the tree are ignored.
Here are a few examples:
Running shell commands when the controller receives Basic Set events from other network devices (for example, a switch is associated with a controller with channel 1 using MultiChannelAssociation)
Automatically turn off the light dimmer 10 seconds after switching on (for relays, use SwitchBinary instead of SwitchMultilevel). (Here it is assumed that the device is able to send reports and is associated with the controller)
(here it is worth paying attention that to run this code several times you need to enter the _tmr array for each device / channel)
Where to embed this JavaScript code? There are several ways to execute this code:
This interface of interaction with the Z-Way server uses the HTTP protocol and JSON format for data transfer. Using it is not difficult to create your own graphical interface for the automation server.
Commands are encoded directly in the URL request, and the responses come in the usual JSON format for ajaxers.
Request / ZWaveAPI / Data / provides the JSON structure of a complete update tree since time . It looks like
Here pathN is the path to the changed element of the tree, objectN is the new value of this element. updateTime - update generation time (it must be specified in the next request in order to receive updates)
If you request / ZWaveAPI / Data / 0 , then the server will return the full data structure.
Request / ZWaveAPI / Run /
runs JavaScript code . This request is similar to the more general / JS / Run / and was created for compatibility with the Z-Cloud service API.
Request / JS / Run /
performs in the v8 engine and returns the result of this command in the form of JSON.
Other commands are described in the documentation.
A few examples:
Recall that instances [0] , commandClasses, and value can be omitted.
! Remember that some characters must be explicitly encoded before sending (url encode): for example, + {}.
Along with the software comes the basic interface for the browser. It also uses the Z-Way JSON API to interact with the server. Its code is conveniently used to study the operation of the API. An extension for jQuery to track tree updates received by request / ZWaveAPI / Data / may also be useful .
This is how the interaction of different layers of the system looks like (picture from the documentation):
After some time, it is planned to write JS scripts for automation intended for ordinary users (workpiece curves already lie in the automation folder). They can be used in conjunction with your own user scripts, i.e. own scripts can already be started to be written and used in your projects.
Raspberry Pi are sold on the RS components or Farnell sites .
The RaZberry board and other Z-Wave equipment are available in the online store Z-Wave.Me and others.
I am sure that RaZberry will be a convenient solution for building budget automation systems based on Z-Wave.
And now, the long-awaited “Lego cube” for automation systems based on Z-Wave technology has appeared, which has the desired flexibility and at the same time great functionality and low price.
The RaZberry expansion board for the Raspberry Pi turns the most popular and cheapest mini-computer into a Z-Wave home automation controller.
RaZberry is a three in one solution:
- board with a transceiver Z-Wave ZM3102
- firmware for ZM3102, expanding the capabilities of standard firmware for sticks
- Z-Way software
Iron
On Linux, RaZberry is seen as a com-port / dev / ttyAMA0. The board essentially consists of a ZM3102 transceiver, EEPROM memory for storing Z-Wave network data, a PCBA antenna, and a UART connector for GPIO Raspberry Pi legs. Only the legs Vcc, Gnd, TX and RX are actually used. The remaining legs are not used for the board and only help to fix it more firmly. In theory, these legs can be used for other needs.
Firmware
The board provides an interface fully compatible with the Sigma Designs Serial API, which makes it possible to use not only the supplied Z-Way software, but also any other Z-Wave software (Open Z-Wave, LinuxMCE, FHEM or self-written), as well as the Z cloud service -Cloud (see instructions ). The board also provides an extension of the Sigma Designs Serial API protocol from Z-Wave.Me, which is necessary for the Z-Way software to work.
The firmware also allows you to update yourself by UART, which will not only fix possible bugs in the future, but also change the firmware version from the one installed by default (SDK 4.54.01) to the older 5.03, which does not have useful NWI, Explorer Frame and Random HomeId, but including SUC / SIS functionality. (For the attentive: yes, I was not mistaken, 4> 5;)
Software
Z-Way is installed on top of Raspbian wheezy by running the command.
wget ‐q ‐O ‐ razberry.z-wave.me/install | sudo bash
The installation script will put Z-Way in / opt / z-way-server, write the script to run in /etc/init.d/Z-Way, add it to the auto start and configure the port ttyAMA0. After rebooting (to apply kernel settings for ttyAMA0 - by default, Raspbian uses UART for the console), the server is ready to work. In a browser, open
IP_OF_RASPBERRY:8083
and start building a Z-Wave network. Let's take a closer look at the Z-Way software bundled with RaZberry. It consists of several parts:
- libzway library is the basis of the Z-Wave engine, which provides the C API for simple work with Z-Wave (depends on pthreads, zlib, openssl)
- libzwayjs library - binding between C and JavaScript engine of Google V8. Provides a simple JS API for working with the Z-Wave network (depends on libv8 and libzway)
- libzwayhttp library - HTTP service for serving external clients, including user interfaces. Provides JSON API (depends on libmicrohttpd, openssl, libzwayjs and libzway)
- main.cpp - binding for starting all services together, reading configs and command line parameters
This structure allows you to use different levels of integration with the components of Z-Way. For projects where performance is important, a C-level API is available (there are .h header files for libzway included), for projects where operational development is needed, it is easier to use the JS API. It is important that both interfaces have a similar structure, which allows you to simply port the code from JavaScript to C after quick prototyping.
Next, I will describe the JavaScript level APIs and show how to create simple automation rules. The C-level interface is beyond the scope of this article. It is worth noting that the syntax in the server-side Z-Way JavaScript engine is similar to what was implemented for the Z-Cloud on the client side - see the Z-Cloud API description. For further reading, it is assumed that the reader is already familiar with the features of the Z-Wave protocol (see the detailed description of the Z-Wave protocol ).
Everything related to Z-Wave in the JavaScript namespace is located in the global zway object, which provides a complete tree of data and methods on Z-Wave devices.
The child object of controller, contains data specific to the Z-Wave controller, as well as a list of devices devices. Each device contains a data structure, as well as a list of device channels (instances). Each channel has a list of Z-Wave Command Classes supported by the device. The Command Class has methods for calling functions (Set, Get, ...), as well as a data tree (data), where all information about the Class is stored.
Graphically, this can be illustrated like this (picture from the documentation):
The API structure is asynchronous and is divided into two parts:
- sending commands and requests
- receiving state change events
Sending commands is carried out by requests of the form
zway.devices[2].instances[0].commandClasses.Basic.Set(0)
(this example turns off the light). The .Get () function will send a value request to the device. zway.devices[2].RequestNodeNeighbourUpdate()
asks the device to update its neighbors, and the team zway.AddNodeToNetwork(1)
starts the process of adding a new device to the network. All commands are described in more detail in the documentation on the RaZberry project documentation page . Two additional parameters can be added to each request: callback functions for successful and unsuccessful sending.Teams queue for sending appropriate packets. Sending is carried out through the Sigma Designs Serial API, implemented on the RaZberry expansion board. All the magic of Z-Wave is hidden under this level of abstraction: for battery-powered devices, these packets are marked as awaiting awakening, a preliminary key exchange is in progress, to save battery power and airtime, some packets are bundled together and much more ... As with any protocol , Z-Wave has a lot of its cockroaches, which are all under the Z-Way API carpet and do not crawl out of there.
All data received from devices is recorded in the data tree related to the device or the Class of Commands. Each element of the data tree has the attributes value (element value), updateTime and invalidateTime (timestamp of date of update and expiration of the value), name (name). The tree structure is also described in detail in the documentation. To receive notifications about changes in tree values, there is a system of subscriptions to events. The bind function for each element of the tree allows you to bind a callback function to data changes.
zway.devices[2].instances[0].commandClasses.Basic.data.level.bind(function (type[, arg]) {}, [arg, [watchChildren=false]]);
The optional arg argument passed to bind will be passed to the callback function and useful for passing additional parameters to separate different events that share a common callback handler. The watchChildren parameter (true or false) allows you to track not only changes to this tree element, but also child ones. The this object in the callback function is an element of the data tree on which bind is launched: this.value is the value, this.updateTime is the date of the last update, etc. Type argument contains a bit mask of the change type (changed, updated, deleted, deprecated, ... - all values are described in detail in ZDefsPublic.h, which is included in the software package).
Similarly, there is a bind function on the global zway object, which allows you to track changes in the arrays of devices, instances and commandClasses:
zway.bind(function(type, nodeId, instanceId, commandClassId) {}, [mask = 0xffff])
The type argument indicates the nature of the change (a device / channel / command class has been added / deleted, or a file with a data tree to disk (ZDDX file) has been saved. The nodeId, instanceId, commandClassId triplet points to an object
that has been changed. Unbind can unsubscribe from events.
To simplify this, use the unbind function. syntax, you can omit the words commandClasses , instances [0] (exactly the zero channel!), .value (
level == 0
similarly level.value == 0
, but with JSON serialization without .value, the entire element of the tree with its attributes will be serialized, not just the value).It is worth noting that the zway global object is native in v8, i.e. This is not an ordinary JavaScript object: you can only change the data of tree elements. All other changes in the tree are ignored.
Here are a few examples:
Running shell commands when the controller receives Basic Set events from other network devices (for example, a switch is associated with a controller with channel 1 using MultiChannelAssociation)
var instanceId = 1;
var ctrlNodeId = zway.controller.data.nodeId.value; // Get controler Node Id
if (zway.devices[ctrlNodeId] && zway.devices[ctrlNodeId].instances[instanceId]) { // Check that instance object exists
var basicCC = zway.devices[ctrlNodeId].instances[instanceId].Basic;
if (basicCC) { // check that Basic exists
basicCC.data.level.bind(function() { // bind to Basic level value
system("echo " + this.value);
});
}
}
Automatically turn off the light dimmer 10 seconds after switching on (for relays, use SwitchBinary instead of SwitchMultilevel). (Here it is assumed that the device is able to send reports and is associated with the controller)
var nodeId = 2;
var instanceId = 0;
var _tmr = null
zway.devices[nodeId].instances[instanceId].SwitchMultilevel.data.level.bind(function() {
var node = args[0];
var instance = args[1];
if (_tmr) {
clearTimeout(_tmr);
}
_tmr = null;
if (this.value > 0) {
_tmr = setTimeout(function () {
zway.devices[nodeId].instances[instanceId].SwitchMultilevel.Set(0);
_tmr = null;
}, 10*1000);
}
});
(here it is worth paying attention that to run this code several times you need to enter the _tmr array for each device / channel)
JavaScript code execution
Where to embed this JavaScript code? There are several ways to execute this code:
- Write the code to a file and put it on the Raspberry Pi SD card in the / opt / z-way-server / [your folder] folder. Further, this code can be executed from automation / main.js: executeFile (pathToJavaScriptFile).
- You can also write your own JavaScript file in config.xml instead of the native RaZberry file.
- Send it over HTTP through the Z-Way JSON API
Now we will describe the Z-Way HTTP / JSON API
This interface of interaction with the Z-Way server uses the HTTP protocol and JSON format for data transfer. Using it is not difficult to create your own graphical interface for the automation server.
Commands are encoded directly in the URL request, and the responses come in the usual JSON format for ajaxers.
Request / ZWaveAPI / Data /
{
path1: object1,
path2: object2,
...
updateTime:
}
zway.
Other commands are described in the documentation.
A few examples:
localhost:8083/ZWaveAPI/Run/devices[2].SwitchMultilvel.data.level.value
- returns the last brightness level received from the device (it is worth reading SwitchMultilevel.Get () before reading)localhost:8083/ZWaveAPI/Run/devices[3].instances[1].SensorMultilvel.data.level.value
- returns the last sensor value received from the device (it is worth reading SensorMultilevel.Get () before reading)localhost:8083/ZWaveAPI/Run/devices[2].Basic.Set(0)
- turns off the device
Recall that instances [0] , commandClasses, and value can be omitted.
! Remember that some characters must be explicitly encoded before sending (url encode): for example, + {}.
Along with the software comes the basic interface for the browser. It also uses the Z-Way JSON API to interact with the server. Its code is conveniently used to study the operation of the API. An extension for jQuery to track tree updates received by request / ZWaveAPI / Data / may also be useful .
This is how the interaction of different layers of the system looks like (picture from the documentation):
After some time, it is planned to write JS scripts for automation intended for ordinary users (workpiece curves already lie in the automation folder). They can be used in conjunction with your own user scripts, i.e. own scripts can already be started to be written and used in your projects.
Where to get?
Raspberry Pi are sold on the RS components or Farnell sites .
The RaZberry board and other Z-Wave equipment are available in the online store Z-Wave.Me and others.
It's time to automate!
I am sure that RaZberry will be a convenient solution for building budget automation systems based on Z-Wave.