Z-Wave

Z-Wave is a two-way wireless communication standard on the 868 MHz - 915 MHz band. It is very similar to Zigbee.

Z-Wave is built around a principle called Command Classes. A Command Class is a group of Commands, that each can make a device perform an action, or request data.

Commands usually belong to one of 3 categories:

  • "set" commands update a value

  • "report" commands to let devices know the current value

  • "get" commands are a request the current value, the device will send a report in response

As an example lets take a look at COMMAND_CLASS_BASIC, this Command Class is supported by all devices. It has a BASIC_SET command, which sets a boolean (usually on/off), a BASIC_GETcommand, and a BASIC_REPORT command. Sending a BASIC_GET to the device will make the device send a BASIC_REPORT to Homey. The BASIC_REPORT contains the boolean (on/off) value.

Sending a command to a device from Homey is simple:

/drivers/<driver_id>/device.js
const Homey = require('homey');

class Device extends Homey.Device {
  async onInit() {
    const node = await this.homey.zwave.getNode(this);

    await node.CommandClass.COMMAND_CLASS_BASIC.BASIC_SET({ Value: true });
  }
}

module.exports = Device;

You can view working examples of Homey Apps that use Z-Wave at: https://github.com/athombv/com.fibaro-example and https://github.com/athombv/com.danalock-example

Pairing

Tell Homey your driver supports a Z-Wave device by adding a zwave object to your driver manifest. To create a driver for a Z-Wave device you need to know the following properties of the device:

  • manufacturerId

  • productTypeId

  • productId

To find out your device's IDs, pair it as a Basic Z-Wave Device. After successfully pairing you can find these values in the device settings. All Z-Wave devices are paired using the built-in Z-Wave pair wizard. Upon pairing a Z-Wave device, an App will be selected if all three IDs match.

You can customize the built-in Z-Wave pair wizard by supplying more specific instructions and a custom image in the learnmode property.

/drivers/<driver_id>/driver.compose.json
{
  "name": { "en": "My Driver" },
  "class": "light",
  "capabilities": ["onoff"],
  "zwave": {
    "manufacturerId": 271,
    "productTypeId": [256],
    "productId": [260],
    "learnmode": {
      "image": "/drivers/<driver_id>/assets/learnmode.svg",
      "instruction": { "en": "Press the button on your device three times" }
    }
  }
}

It is possible to add multiple productTypeId and productId values in order to support multiple devices with the same Driver.

Most Z-Wave devices are unpaired in the same way as they are paired but in case the unpair wizard benefits from custom instructions or a different image it is possible to provide unlearnmode options to your Z-Wave driver manifest. unlearnmode accepts the same properties as learnmode.

Manifest

In addition to the essential driver zwave properties manifacturerId, productTypeId and productId there are properties allow you to configure the behaviour of your Z-Wave device.

Some of these properties configure the behaviour of your device while pairing, so changes to them will require you to remove and re-add your devices.

Device settings

Z-Wave devices often have configuration parameters, in Homey these can be set in the device settings. The only thing you need to do is tell Homey which setting corresponds to which Z-Wave configuration parameter of the device. You can do this by adding a zwave property to the device setting that controls the configuration parameter. Read the device setting guide for more information.

/drivers/<driver_id>/driver.settings.compose.json
[
  {
    "id": "minimum_brightness",
    "type": "number",
    "label": { "en": "Minimum brightness level" },
    "value": 1,
    "attr": { "min": 1,"max": 98 },
    "hint": { "en": "This parameter determines the minimal brightness." },
    "zwave": {
      "index": 13,
      "size": 1
    }
  }
]

Require secure communication

Z-Wave devices can use secure communication, this protects outsiders from interfering with your network. Homey supports the S0 and S2 Z-Wave security layers.

It is possible that devices only provide certain functionality when they are paired securely, for example a Z-Wave Doorlock can choose to only allow using COMMAND_CLASS_LOCK with secure communication. In this case your app should set the requireSecure property in your drivers zwave object to true. To find out what command classes require secure communication check your devices technical specifications.

/drivers/<driver_id>/driver.compose.json
{
  "name": { "en": "My Driver" },
  "class": "lock",
  "capabilities": ["locked"],
  "zwave": {
    "manufacturerId": 270,
    "productTypeId": [8],
    "productId": [2],
    "requireSecure": true
  }
}

By default Homey will use S2 if a device supports it. Due to the additional communication overhead of S0 your app needs to opt-into S0 by setting requireSecure to true.

Default device configuration

After pairing a device, Homey can write configuration parameters to ensure they are set to the correct value using the defaultConfiguration parameter of the devices zwave options.

Configuration parameters can be 1, 2 or 4 bytes long, use the size property to tell Homey how many bytes to write. The value is a signed integer and its range is determined by the size of the parameter:

  • -128, 127 for size=1

  • -32768, -32767 for size=2

  • -2147483648, 2147483647 for size=4

/drivers/<driver_id>/driver.compose.json
{
  "name": { "en": "My Driver" },
  "class": "light",
  "capabilities": ["onoff"],
  "zwave": {
    "manufacturerId": 271,
    "productTypeId": [256],
    "productId": [260],
    "defaultConfiguration": [
      {
        "id": 3,
        "size": 1,
        "value": 123
      }
    ]
  }
}

Association Groups

Association groups allow Z-Wave devices to be linked together (associated) so that they can communicate directly without needing a central controller, like Homey. For some devices, Homey needs to be added to their association group to be able to receive status updates. For example devices may choose to only send "central scene activation" commands to their "lifeline" (the node in association group 1).

By default Homey will always associate with group 1, this behaviour can be customized by adding a associationGroups property to the devices zwave options. Entering an empty array or leaving out the number 1 will cause Homey to remove the association with group 1.

Users can configure the associations from the device settings, use the associationGroupsOptions property to add hints explaining what the various association groups do and how to configure them correctly.

/drivers/<driver_id>/driver.compose.json
{
  "name": { "en": "My Driver" },
  "class": "light",
  "capabilities": ["onoff"],
  "zwave": {
    "manufacturerId": 271,
    "productTypeId": [256],
    "productId": [260],
    "associationGroups": [1, 3],
    "associationGroupsOptions": {
      "3": {
        "hint": { "en": "On/off signals from input 3" }
      }
    }
  }
}

In addition to "regular" (single-channel) associations devices with multiple endpoints can support "multi-channel association". It may be necessary to use multi-channel association to receive updates from a devices endpoints. This can be configured using the associationGroupsMultiChannel property in the devices zwave options:

/drivers/<driver_id>/driver.compose.json
{
  "name": { "en": "My Driver" },
  "class": "light",
  "capabilities": ["onoff"],
  "zwave": {
    "manufacturerId": 271,
    "productTypeId": [256],
    "productId": [260],
    "associationGroups": [],
    "associationGroupsMultiChannel": [1],
  }
}

Battery Device Wake Up Interval

Z-Wave battery devices can have special behaviour to conserve power. These devices will send messages at any time but they are not always listening for messages. The interval with which it is possible to send messages to such a device is called the "wake up interval". By default the manufacturer will have set the wake up interval to a duration they think is appropriate but it may be necessary to overwrite this default. In those cases you can set the wakeUpInterval property in the device's zwave options. This property controls the desired wake up interval in seconds. The range of allowed values is: 30-16777215 (30 seconds to 194 days)

/drivers/<driver_id>/driver.compose.json
{
  "name": { "en": "My Driver" },
  "class": "light",
  "capabilities": ["onoff"],
  "zwave": {
    "manufacturerId": 271,
    "productTypeId": [256],
    "productId": [260],
    "wakeUpInterval": 900
  }
}

Multi channel nodes

In Z-Wave a device can only implement a command class once. This means that technically a single Z-Wave device can only have a single switch, because it can only implement, for example, COMMAND_CLASS_SWITCH_BINARY once. In order to give devices the ability to implement a command class multiple times, Z-Wave has Multi Channel Nodes. A Multi Channel Node is a type of Z-Wave node that contains several "endpoints" which are each their own Z-Wave node. Each of these endpoints can individually implement, for example, COMMAND_CLASS_SWITCH_BINARY.

In Homey after pairing a Multi Channel node, several devices will be added to the devices overview.

/drivers/<driver_id>/driver.compose.json
{
  "name": { "en": "My Driver" },
  "class": "light",
  "capabilities": ["onoff"],
  "zwave": {
    "manufacturerId": 271,
    "productTypeId": [256],
    "productId": [260],
    "multiChannelNodes": {
      "1": {
        "name": { "en": "MultiChannel device 1" },
        "class": "socket",
        "capabilities": ["onoff", "measure_power", "meter_power"],
        "icon": "/drivers/<driver_id>/assets/icon-multichannelnode1.svg"
      }
    }
  }
}

It is possible to override the settings of the Multi Channel Node by providing the settings option. This option takes the same values as the regular Device Settings:

/drivers/<driver_id>/driver.compose.json
{
  "name": { "en": "My Driver" },
  "class": "light",
  "capabilities": ["onoff"],
  "zwave": {
    "manufacturerId": 271,
    "productTypeId": [256],
    "productId": [260],
    "multiChannelNodes": {
      "1": {
        "name": { "en": "MultiChannel device 1" },
        "class": "socket",
        "capabilities": ["onoff", "measure_power", "meter_power"],
        "icon": "/drivers/<driver_id>/assets/icon-multichannelnode1.svg",
        "settings": []
      }
    }
  }
}

homey-zwavedriver

A library named homey-zwavedriver has been developed to ease development of Z-Wave devices in Homey. It mainly maps Command Classes to Homey's capabilities. It is recommended for most app developers to use this library.

homey-zwavedriver is only compatible with SDK version 3. Its predecessor homey-meshdriver is available for SDK version 2.

npm install homey-zwavedriver

When you are using homey-zwavedriver your device should extend ZwaveDevice instead of Homey.Device. This class implements some useful helpers that you can use to integrate your Z-Wave device with Homey. When a new Device is initialized ZwaveDevice#onNodeInit() will be called. In this method you should register all the devices capabilities. homey-zwavedriver supplies a ZwaveDevice#registerCapability() method that you only need to tell what capability your device has and which associated command class implements the capability.

/drivers/<driver_id>/device.js
const { ZwaveDevice } = require('homey-zwavedriver');

class Device extends ZwaveDevice {
  async onNodeInit() {
    this.registerCapability('onoff', 'SWITCH_BINARY');
  }
}

module.exports = Device;

If you are implementing a light device you can extend ZwaveLightDevice instead. This class already implements all the expected behaviour for a Z-Wave light.

Z-Wave API

If possible you should use homey-zwavedriver instead, only use the built-in Z-Wave API if you absolutely need to.

/drivers/<driver_id>/device.js
const Homey = require('homey');

class Device extends Homey.Device {
  async onInit() {
    // get the node by our Device's instance
    const node = await this.homey.zwave.getNode(this);

    // get the BASIC status
    node.CommandClass.COMMAND_CLASS_BASIC.BASIC_GET()
      .then((result) => {
        if (result["Value"]) {
          this.log("Device is turned on");
        } else {
          this.log("Device is turned off");
        }
      })
      .catch(this.error);

    // battery nodes can emit an 'online' event when they're available
    // you can send commands within 10s of this event, before the node goes to sleep again
    node.on("online", (online) => {
      if (online) {
        this.log("Device is online");
      } else {
        this.log("Device is offline");
      }
    });

    // register for 'report' events
    node.CommandClass.COMMAND_CLASS_BASIC.on("report", (command, report) => {
      this.log(command.name); // e.g. BASIC_REPORT
      this.log(report); // e.g. { Value: true }
    });
  }
}

module.exports = Device;

Command Class Reference

The Command Classes are documented extensively by Sigma Designs, and are freely available.

Last updated