Fork me on GitHub

Blog

Talking to a ZWave Switch using open-zwave

Z-Wave is a wireless communications protocol designed for home automation, specifically to remotely control applications in residential and light commercial environments. The technology uses a low-power RF radio embedded or retrofitted into electronics devices and systems, such as lighting, home access control, entertainment systems and household appliances.

The are many devices that have these RF chips embedded inside them. In this post you can see an example on how you can program Z-Wave switches using some OpenSource tools. We will use the open-zwave library. You can use it to interface with all available Z-Wave PC controllers. We have the Aeon Labs Z-Stick S2 and a Raspberry Pi.

The open-zwave library is great because it is OpenSource, you can easily build it for Raspberry and use the Raspberry as a hub for your home automation system. In this way with one Raspberry you can remotely control all your Z-Wave enabled devices at home - things like light switches, open/closed sensors, power meters, etc.

The first step is to download and build the open-zwave library on your Raspberry. Great Tutorial for more details. Here is a recap of what you need to do:

sudo apt-get install subversion libudev-dev make build-essential git-core
svn checkout http://open-zwave.googlecode.com/svn/trunk/ open-zwave-read-only
~/open-zwave-read-only/cpp/build/linux $ make

Then you’re ready to build the MinOZW example:

~/open-zwave-read-only/cpp/examples/linux/MinOZW $ make

Check if everything is alright by running the test:

./test

Make sure that the Z-Wave controller is connected to the USB drive of the Raspberry. If everything goes alright the MinOZW example will scan for new Hadrware and generate some debug files that list all discovered devices. Note that the controller can discover a device only if they have previously been paired together. Pairing devices together means that they would belong to the same network.

Now, we’re going to write our own test application! We’re going to first pair the controller with a Z-Wave Switch. Then in the test application we will turn the switch on and off from the code running on the Raspberry Pi. First after we have paired the devices we have to run the MinOZW executable like we did above and explore the generated zwcfg_0xYOUR_HOMEID.xml config file. It contains detailed information about all the sensors and controllers in the local ZWave network

Digging into the code of the examples/linux/MinOZW/Main.cpp file we can see that it uses the Manager class as the main public interface to OpenZWave.

First you need to say something like:

Manager::Create();
Manager::Get()->AddWatcher( OnNotification, NULL );
Manager::Get()->AddDriver( this->port );

Where port is the device address of your Z-Wave controller - for example: /dev/ttyUSB0

All Z-Wave functionality is accessed via the Manager class. It is a singleton class that exposes all the functionality required to add Z-Wave support to an application. It handles the sending and receiving of Z-Wave messages as well as the configuration of a Z-Wave network and its devices, freeing the library user from the burden of learning the low-level details of the Z-Wave protocol.

There can be only one instance of the Manager class, and all applications will start by calling Manager::Create static method to create that instance. From then on, a call to the Manager::Get static method will return the pointer to the Manager object. On application exit, Manager::Destroy should be called to allow OpenZWave to clean up and delete any other objects it has created.

Manager::Get()->AddWatcher( OnNotification, NULL );

Once the Manager has been created, a call should be made to Manager::AddWatcher to install a notification callback handler. This handler will receive notifications of Z-Wave network changes and updates to device values, and is an essential element of OpenZWave.

Manager::Get()->AddDriver( this->port );

Next, a call should be made to Manager::AddDriver for each Z-Wave controller attached to the PC. Each Driver will handle the sending and receiving of messages for all the devices in its controller's Z-Wave network.

Finally we want to set the value of the Z-Wave Switch. We will do this with the following code:

    
void SetValue(bool value)
{
    int nodeid = 3;
    pthread_mutex_lock( &g_criticalSection );
    for( list<NodeInfo*>::iterator it = g_nodes.begin(); it != g_nodes.end(); ++it )
    {
                NodeInfo nodeInfo = it;
                if( nodeInfo->m_nodeId != nodeid ) continue;
        for( list<ValueID>::iterator it2 = nodeInfo->m_values.begin();
it2 != nodeInfo->m_values.end(); ++it2 ) { ValueID v = *it2; if( v.GetCommandClassId() == 0x25 ) { Manager::Get()->SetValue(v, value); break; } } } pthread_mutex_unlock( &g_criticalSection ); }

You can see the Command Classes Ids here 0x25 is the Id of the COMMAND_CLASS_SWITCH_BINARY command. Therefore in the if statement we check that we set the value using the Manager class only when GetCommandClassId() is 0x25.
Note the if statement:

if( nodeInfo->m_nodeId != nodeid) continue;

You need to determine the right node id number of the Z-Wave Switch in your Z-Wave network. To do this you can have a look at the zwgcfg file. It would say something like:

<Node id="3" type="Binary Power Switch">
    <Manufacturer id="0086" name="Aeon Labs">
        <Product type="0003" id="0012" name="Unknown: type=0003, id=0012" />
    </Manufacturer>
    <CommandClasses>
        <CommandClass id="32" name="COMMAND_CLASS_BASIC" version="1" request_flags="4" mapping="37">
            <Instance index="1" />
        </CommandClass>
        <CommandClass id="37" name="COMMAND_CLASS_SWITCH_BINARY" version="1" request_flags="4">
            <Instance index="1" />
            <Value type="bool" label="Switch" units="" value="True" />
        </CommandClass>
    </CommandClasses>
</Node>

In the next post you will see how we used all of this to create a Z-Wave Switch Driver, build it on the Raspberry Pi and load it into Agilart.

Add a Comment