The Z-Wave protocol in C# – Part 2

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

In the previous article the client had to control the timing of the message sending. This responsibility is now moved away from the client. A new set of classes are introduced to represent the Z-Wave devices that the client is communicating with.

The functionality of the implementation remains the same as for the previous article. The Z-Wave device is switched off and then on.

Switch s = new Switch(nodeId, zwavePort)
s.Off();
s.On();

It is important to understand the previous articles to get the most out of this example.

The same devices and configurations are used as in ‘The Z-Wave protocol in C#‘.

The Switch class is responsible for building the messages for switching the Z-Wave device on and off and handling the incoming messages from the Z-Wave controller.

class Switch : ZWaveNode
{
    public void On()
    {
        ...
    }
 
    public void Off()
    {
        ...
    }
 
    public void MessageHandler(byte[] message)
    {
        ...
    }
}

The Switch class is inherited from the ZWaveNode class.

abstract class ZWaveNode
{
    public byte NodeId { get; private set; }
    private ZWavePort zp;
    ...
}

The ZWaveNode class include a number of common attributes for Z-Wave devices and a reference to the ZWavePort object – to make it possible to send/receive messages to/from the Z-Wave controller.

One of the objectives with this implementation is to move the control of the message sequencing from the client to the core implementation – avoid the implementation of a break.

Thread.Sleep(5000); // Wait for 5 seconds

The message sequence is initiated and terminated by the Switch object. A variable has been introduced into the ZWavePort class for tracking whether or not a message sequence is ongoing.

private Boolean messagingLock;

If the variable is true a message sequence is ongoing.  A dedicated function SetMessagingLock has been implemented to make sure that only one thread can access this variable.

private Boolean SetMessagingLock(Boolean state)
{
    lock (messagingLocker)
    {
        if (state)
        {
            if (this.messagingLock)
            {
                return false;
            }
            else
            {
                this.messagingLock = true;
                return true;
            }
        }
        else
        {
            this.messagingLock = false;
            return true;
        }
    }
}

The function is called by SendMessage in the ZWavePort class. The is done to ensure that a message sequence isn’t ongoing before a new message sequence is initiated.

public void SendMessage(byte[] message)
{
    if (sp.IsOpen == true)
   {
        if (message != MSG_ACKNOWLEDGE)
        {
            if (!SetMessagingLock(true)) return false;
            sendACK = false;
            message[message.Length - 1] = GenerateChecksum(message); // Insert checksum
        }
        System.Console.WriteLine("Message sent: " + ByteArrayToString(message));
        sp.Write(message, 0, message.Length);
        return true;
}

No message is sent if a message sequence is ongoing and SendMessage returns false. ACK messages are sent independently of this system.
If SendMessage succeeds in setting the variable to true another message sequence can’t be started before the variable is set back to false . The variable will later be set to false by the Switch object.
The Switch object needs to know about incoming messages from the Z-Wave controller to be able to set the variable to false correctly. It is possible to subscribe to the messages from the Z-Wave controller by calling the SubscribeToMessages function in the ZWavePort class. In the constructor of the ZWaveNode class the SubscribeToMessages function is called with the MessageHandler function of the Switch object as the call back function.

public ZWaveNode(byte nodeId, ZWavePort zp)
{
    this.NodeId = nodeId;
    this.zp = zp;
    ZWavePort.MessageHandler messageHandler = new ZWavePort.MessageHandler(MessageHandler);
    zp.SubscribeToMessages(messageHandler);
}

Only two types of messages are received from the Z-Wave controller in this example

  • ACK – the message sequence is not completed. This is confirmation of the request sent by the C# client.
  • Response – the message sequence is completed. This is the response to the request sent by the C# client (The ACK for the response is sent automaticly before the MessageHandler function is called.)

The MessageHandler function in the Switch object calls the MessagingCompleted function except if the incoming message is an ACK message.

public override void MessageHandler(byte[] message)
{
    if (message != MSG_ACKNOWLEDGE)
    {
        MessagingCompleted();
    }
}

The MessagingCompleted function sets the messagingLock variable in the ZWavePort object to false – signaling that a new message sequence can be initiated.

The following function has been implemented in the ZWaveNode class to ensure that a message is sent even if it gets rejected initially by the SendMessage function in the ZWavePort object.

protected Boolean SendMessage(byte[] message)
{
    while (!zp.SendMessage(message)) Thread.Sleep(100);
    return true;
}

A delay of 100 ms is inserted if the message is rejected by the SendMessage function in the ZWavePort object before another try is made. This repeats until the message is send.

With the implementation in this article it is now possible to send several messages without implementing delays in between.

Switch s = new Switch(nodeId, zwavePort)
s.Off();
s.On();

In the upcoming article a Dimmer is added as a new device class and a weakness in the design is removed – with the current design all the device classes will release the messaging when they receive a response.

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

Advertisement

2 comments

  1. Tony says:

    Great article, I searched all over to find a getting started article like this. I’m still struggling to find where to find information on the protocol. Can you point me to any documents? The first thing I’m looking for is how to enumerate all zwave connected devices.

    I’d appreciate any help.

  2. Henrik Leidecker Jørgensen says:

    The thing is that the specification is closed but you can find a lot of information on the Internet if you really want to. One good source of information is the LinuxMCE Wiki pages. A few documents seems to be available to the public from Zensys, so you can try to Google those but they only have little value. Using a serial port sniffer for ‘reverse engineering’ is another approach. Participating in online discussions is also a good source. Looking in the source code of some of the available implementations can also provide some insights to the protocol. Bottom line is that it is a big puzzle. And finally … you can buy the development kit from Zensys.

    The enumeration of devices will be covered in one of the next articles. If you can’t wait then you can go to the LinuxMCE Wiki pages and find the information there.

Leave a Reply