Z-Way library is a middleware between Sigma Designs Z-Wave transceiver and your application. Z-Way offers pretty high level API to control Z-Wave devices and manage wireless network.

Interaction with the library covers three aspects:

  1. sending commands to Z-Wave devices;
  2. sending network management commands to the transceiver;
  3. receiving updates from the network.

Sending commands

Every command request generates an outgoing packet (job). Before generating a packet, library will validate parameters and check whether the command is supported by recipient. In case of failure command will return error immediately.

Once a job is generated, it is placed into outgoing queue for future send. The queued jobs are handled internally by Z-Way engine according to commands priorities, nodes states and capabilities, transceiver state etc.

Once the job is sent, it must be first confirmed it was successfully delivered to Z-Wave stack, and then confirmed it was delivered to recipient. All these operations are performed asynchronously, so command may provide a callback function to call in case of success or failure if it is needed to know delivery result.

After the delivery was confirmed, command is considered executed. If it was a state request command (i.e. SensorMultilevel Get), response packet may be delayed (or even not sent at all), so command’s success/failure callbacks cannot be used to get requested state immediately.

Receiving updates

All incoming packets from Z-Wave network are automatically parsed by Z-Way and stored in special variables called data holders. Data holder is a named variable that stores a value along with its data type and time the value was last updated and “invalidated”. Each data holder may also contain a set of child data holders, so they form a hierarchical data storage. Data holders also support callbacks, so custom code may be executed each time the value is updated.

For example, level data holder stores dimming level of a dimmer. Once application executes a Get command for that dimmer, Z-Way will update invalidateTime property on the level data holder, so application knows the current value is assumed to be outdated, but the new one was not received yet.

Once Z-Way received a packet with new value of the dimmer, it will store it in level data holder and update updateTime property. Since updateTime is greater that invalidateTime, the value is considered valid now.

Z-Wave device can also send unsolicited state reports to controller (without a request from controller’s side; e.g. due to local operation or periodically). Due to asynchronous nature of Z-Wave protocol, controller can’t tell whether the packet was sent unsolicited or it is a response to the previous command. So unsolicited packet will be handled the same way exactly.

Command Classes

Z-Way inherits structure of Z-Wave protocol and divides data holders and command on different Command Classes (CC). Command Classes are building blocks of Z-Wave functionality. For example, dimming is provided by Command Class SwitchMultilevel, relay operation by CC SwitchBinary, sensors by CCs SensorMultilevel and SensorBinary etc. Please consult Z-Wave protocol basics to understand Z-Wave Command Classes.

All Command Classes share a minimal subset of common data holders:

  • supported says if CC is supported by device (it implements that functionality) or only controlled (it can control other devices implementing that functionality).
  • version stores version of the CC. Used internally to know how to deal with that Command Class.
  • security tells if CC communications should be encrypted using Z-Wave AES security mechanism.
  • interviewDone and interviewCounter describe the status of initial interview process during which Z-Way asks the device about its CC capabilities. If the interview is incomplete, Z-Way might fail to use some Command Classes with this device. All Z-Wave certified devices MUST pass interview process.

All the other data holders are specific to each Command Class. For example, SwitchMultilevel Command Class contains level data holder, SensorBinary has two-level storage, grouping data by sensor types: 0 -> {sensorTypeString, level}, 5 -> {sensorTypeString, level}, ... where type identifiers are Z-Wave specific constants. Every Z-Wave specific constant value will have corresponding verbal description (in case of SensorBinary it is in sensorTypeString data holder).

Some Command Classes are hidden under the hood of Z-Way: MultiCmdSecurityCRC16MultiChannelApplicationStatus. They’re handled internally by Z-Way software, and shouldn’t be used directly.

Some Command Classes have no public APIs, but their data holders may be very useful in your application: AssociationGroupInformationDeviceResetLocallyManufacturerSpecificVersionZWavePlusInfo.

All the remaing Command Classes have their Get and Set commands specific to functionality of the Command Class. Consult CommandClassesPublic.h header file for more info about available commands for different Command Classes and their meaning.

Network management

Z-Way offers API for network management operations: include new devices, exclude devices, discover neighbor devices, remove failed nodes, frequency selection, controller reset etc. These functions are described in ZWayLib.h header file.

Z-Way also provides a low level access to Z-Wave transceiver functionality through Sigma Designs Serial API. These functions are provided by Function Classes. You should use them only if you have deep knowledge of Z-Wave networking. Check FunctionClassesPublic.h for more info.

Using Z-Way

To use Z-Way one need to include few header files:

#include <ZWayLib.h>
#include <ZLogging.h>

Z-Way will need to know where to write the log to, so first of all you need to create logging context using zlog_create() call. You can disable logging by passing NULL instead of logging context to Z-Way.

Then create new Z-Way context using zway_init(). It will only allocate memory, read log files, initialize internal structures. At this point you can already attach your handlers on new device/instance/Command Class creation (you will also be able to do it at any time later). Do it using zway_device_add_callback() call. Warning: you should initialize ZWay pointer with NULL before passing it to zway_init!

Executing zway_start() will open serial port and start a new thread that will handle all communications with the transceiver. From now Z-Way can receive packets from the network, but can not parse them yet, since devices were not discovered yet. All received packets will just be queued to be parsed later after discovery process.

Last step to run Z-Way is zway_discover() call. It will start communications with the Z-Wave transceiver and ask about devices in the network, their capabilities, network state etc. During discovery phase Z-Way will create structures for all devices and load saved data from file stored in config/zddx folder.

From now on, Z-Way is ready to operate. Incoming events will trigger callback functions attached by application, and executing commands will put new packets in the queue.

You will also need few other functions zway_is_running()zway_is_idle()zway_stop()zway_terminate() to handler termination process.

We suggest you to check z-way-test project and look on comments in header files.