An introduction to Z-Wave programming in C#

November 30th, 2009 by Henrik Leidecker Jørgensen | Edit this entry Leave a reply »

Z-Wave is a protocol for wireless communication with home appliances e.g. lamps and sensors. Z-Wave can be used for switching on, switching off, monitoring etc.
It is possible to learn more about Z-Wave by reading one of the previous articles (in Danish) on this site or at Z-Waves.dk.

zwaves-logo-new2

It is easy to get started with Z-Wave programming. One important note here is that the specifications aren’t publicly available. The example in this article can be used for switching a lamp on or off.

AeonZStick

A Z-Wave USB stick from Aeon Labs is required for running the example in this article. It can be bought at HOMEe.dk.
The driver makes the Z-Wave unit available as a seriel port for the operating system. The serial port communication protocol is specified by Zensys. Several other Z-Wave USB sticks utilize the same approach. Similar units from other manufacturers will most likely be compatible with the example in this article. The Aeon Labs Z-Wave USB stick is by the way the same unit as the one bundled with the MiCasaVerde master.

A switch or dimmer unit is also neededSmartPowere.g. the Innovus SmartPower, but any switch unit will work.

A number of requirements needs to be fulfilled in order to be able to run the example from this article.

  • The Z-Wave USB stick must be installed the linked COM port must be known.
  • The node id of the switch unit must be known.
  • The switch unit and the Z-Wave USB stick controller must be linked together.
  • Basic knowledge about C# programming.

In the below example the Z-Wave USB stick is installed as the ‘COM4′ port and the node id of the switch is ‘6′.

First, the serial port has to be initialized with the correct parameters and then opened.

SerialPort sp = new SerialPort();
 
sp.PortName = "COM4";
sp.BaudRate = 115200;
sp.Parity = Parity.None;
sp.DataBits = 8;
sp.StopBits = StopBits.One;
sp.Handshake = Handshake.None;
sp.DtrEnable = true;
sp.RtsEnable = true;
sp.NewLine = System.Environment.NewLine;
 
sp.Open();

12 bytes must be send to the Z-Wave USB Stick to either switch on or turn off the unit.

/*
    0x01, 0x09, 0x00, 0x13, nodeId, 0x03, 0x20, 0x01, state, 0x05, checksum
*/

The ‘nodeId’ is referencing the node in question. ’state’ defines the state (on/off) of the unit. ‘checksum’ is a calculation based on the message data.

In this case the node id is ‘6′ and as the unit will be switched on the state value must be set to 0xFF.

byte nodeId = 0x06;
// Set state to 0xFF to turn the device on and 0x00 to turn it off
byte state = 0xFF; // On

The checksum is calculated by making an XOR of all the message bytes except for the first one. A bit-wise NOT is then executed on the result.

private static byte GenerateChecksum(byte[] data)
{
    int offset = 1;
    byte ret = data[offset];
    for (int i = offset + 1; i < data.Length - 1; i++)
    {
        // Xor bytes
        ret ^= data[i];
    }
    // Not result
    ret = (byte)(~ret);
    return ret;
}

The message can now be created.

byte[] message = new byte[] { 0x01, 0x09, 0x00, 0x13, nodeId, 0x03, 0x20, 0x01, state, 0x05, 0x00 };
message[message.Length - 1] = GenerateChecksum(message);

The message is send to the Z-Wave USB stick and the serial port closed by executing the following commands.

sp.Write(message, 0, message.Length);
 
sp.Close();

As the above example shows then it is relatively simple to get started with Z-Wave development in C#. Alternatives to making the implementation from scratch exist e.g. the development platform from Zensys‘ or the SDK from ControlThink.
In the upcoming article about Z-Wave programming in C# the program will be modified in order to allow it to switch the unit on and then off. The modified example will require some additional insights to the signalling at the serial port.

The source code can be downloaded via this link. You are free to use the code in any manner you like.

Advertisement

3 comments

  1. Vullisbak says:

    Excellent article, I’ll be keeping a close eye on your follow-ups

  2. nomail says:

    Thank you for the great article.
    I have one comment on how to improve receiving messages from COM port. Instead of using separate thread that uses function ReceiveMessage I used handler for SerialPort:

    sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);

    And then created handler:

    void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
    int bytesToRead = sp.BytesToRead;
    if ((bytesToRead != 0) & (sp.IsOpen == true))
    {
    byte[] message = new byte[bytesToRead];
    sp.Read(message, 0, bytesToRead);
    System.Console.WriteLine(“Message received: ” + ByteArrayToString(message));

    byte[] msg = message;
    int length = msg.Length;
    if (messageHandler != null)
    {
    if (msg[0] == 0×06)
    {
    if (msg.Length > 1)
    {
    SendACKMessage();
    byte[] tmp = new byte[length - 1];
    System.Array.Copy(msg, 1, tmp, 0, length – 1);
    msg = tmp;
    }
    messageHandler(sentMessage, MSG_ACKNOWLEDGE);
    }
    else
    {
    SendACKMessage();
    }
    }
    messageHandler(sentMessage, msg);
    }
    }

    Tried to register on the site to post this on the forum but it said it’s not possible at the moment.
    Keep these articles coming :)

  3. Ricky says:

    Nice article. Is there a way to poll the status of a device? Before we send a status update.