Z-Ware C API Training#

The purpose of this training is to explain how to use the Z-Ware C API and enable the user to modify the Z-Ware C API sample apps.

Topics covered:

  • Explanation of the sample app functionality

  • Brief overview of the sample app code

  • Documentation Resources

  • Building the library

  • Building the sample apps

  • How to modify a sample app

In the Lab Exercise, the following tasks will be performed.

  • Build library and apps

  • Connect the sample app to Z/IP gateway

  • Do basic control of Z-Wave devices

  • Modify the sample app to receive the notification command class

Introduction#

The Z-Ware C API is the lowest level way to use Z-Ware. After you build it, use sample apps to see how it works and how to use it.

The sample apps are located in the Z-Ware source tree. The path to the sample apps is zware/v7.xx/src/zwportal/zwave/hcapi/demos.

The C API abstracts Z-Wave command classes into a controllable and monitorable API. The C API uses callbacks to notify the upper level application about events and status changes.

Example Apps Included#

gw_discovery will find any Z/IP gateways on the network and display the IP address. zwnet_gw_discvr_start finds gateways and a callback, and zwnet_gw_discvr_cb is called upon completion.

add_node can be used to include a new node

rm_node can be used to exclude a node

nw_reset resets the network

basic sends the basic set command

bin_switch controls a binary switch

bin_sensor gets data from a binary sensor

controller_app combines many of these examples together and has a command line menu to access the many features

Most of these apps have a configuration file in the directory that should contain the IP address of Z/IP gateway and the DTLS key.

Mandatory Setup Functions#

To ensure that the Z-Ware C API functions properly, some functions must be called at initialization. For example, all the example apps call zwnet_init inside a local function called lib_init.

Additionally, the following functions must be called.

  • zwnet_local_addr_get gets the local IP address used by Z-Ware for communicating with Z/IP gateway

  • zwnet_listen_port_get gets the local port used by Z-Ware for incoming unsolicited communication from Z/IP gateway

  • zwif_gw_unsolicit_set push Z-Ware's IP address and listening port to Z/IP gateway as unsolicited destination

An example is included in the bin_sensor app and is shown below.

//Get local Z/IP client listening address and port
result = zwnet_local_addr_get(hl_appl->zwnet, hl_appl->zip_gw_ip, local_ip, hl_appl->use_ipv4);

if (result != 0)
{
    printf("Error: couldn't get local Z/IP client listening address: %d\n", result);
    return result;
}

local_port = zwnet_listen_port_get(hl_appl->zwnet);

if (hl_appl->use_ipv4)
{   //Convert to IPv4-mapped IPv6 address
    uint8_t unsolicit_ipv4[4];

    //Save the IPv4 address
    memcpy(unsolicit_ipv4, local_ip, 4);

    //Convert the IPv4 address to IPv4-mapped IPv6 address
    memset(local_ip, 0, 10);
    local_ip[10] = 0xFF;
    local_ip[11] = 0xFF;
    memcpy(&local_ip[12], unsolicit_ipv4, 4);
}

result = gw_intf_get(hl_appl->zwnet, &gw_ifd);
if (result != 0)
{
    printf("Error: couldn't find Z/IP gateway interface: %d\n", result);
    return result;
}

result = zwif_gw_unsolicit_set(&gw_ifd, local_ip, local_port);

if (result != 0)
{
    printf("Error: couldn't set unsolicited address: %d\n", result);
}

Enumerating Z-Ware Nodes#

In Z-Ware, you must iterate through the nodes to find the one you are looking for. To control Z-Wave devices, you iterate to find the interface in the device you want to control.

Nodes

Starting from the network, you must iterate through the list of nodes using the following functions.

  • zwnet_get_node

  • zwnode_get_next

  • zwnode_get_ep

  • zwep_get_next

  • zwep_get_if

  • zwif_get_next

Starting from an interface, you can iterate in reverse using the following functions.

  • zwif_get_ep

  • zwep_get_node

  • zwnode_get_net

For example, to find a binary switch interface you could iterate through the network as follows.

//Get first node (controller node)
result = zwnet_get_node(net, &node);
if (result != 0)
{
    return result;
}

while (!zwnode_get_next(&node, &node))//get next node
{
    if (!zwnode_get_ep(&node, &ep)) //get first endpoint of the node
    {
        do
        {
            if (!zwep_get_if(&ep, &intf)) //get first interface of the endpoint
            {
                do
                {
                    if (intf.cls == COMMAND_CLASS_SWITCH_BINARY)
                    {   //Found a binary switch so return
                        *bin_sw_if = intf;
                        return 0;
                    }

                }while (!zwif_get_next(&intf, &intf)); //get next interface
            }
        }while (!zwep_get_next(&ep, &ep)); //get next endpoint
    }
}

return  ZW_ERR_INTF_NOT_FOUND;

Controlling Z-Wave Devices#

These functions are described in detail in the C API reference but as a quick reminder of how to control Z-Wave nodes see the following functions.

zwif_xxx_rpt_set registers a callback for interface xxx. For example, to set up a callback for binary sensor data, see the following code. The callback is then called when data is received.

// set up binary sensor callback
zwif_bsensor_rpt_set(&bin_sensor_if, hl_bin_snsr_rep_cb);
// binary sensor callback function
void hl_bin_snsr_rep_cb(zwifd_p ifd, uint8_t state, uint8_t type, time_t ts)
{
    if (ts == 0)
    {
        printf("\nBinary sensor report: no cached data. Report get: type=%u\n", type);
        return;
    }

    if (type > ZW_BSENSOR_TYPE_GLASS_BRK)
    {
        type = 0;
    }

    printf("\nBinary sensor (%s) state :%s", bsensor_type_str[type], (state == 0)? "idle" : "event detected");
    printf("\nTime stamp:%s\n", ctime(&ts));

}

zwif_xxx_get issue a get command to interface xxx. This can be used to read sensor data. For example, see below.

zwif_bsensor_get(&bin_sensor_if, sensor_type, (choice == '3')? ZWIF_GET_BMSK_LIVE : ZWIF_GET_BMSK_CACHE);

zwif_xxx_set set a value to interface xxx. This is used to set values, such as to turn a switch on or off. For example, see below from the bin_switch app.

zwif_switch_set(&bin_sw_if, (choice == '1')? 1:0, 0, NULL, NULL);

Sample Apps Code#

gw_discovery is the first sample app a new user should run. It will display the detected gateway IP address, which can then be entered into the app.cfg file for the rest of the sample apps.

Z-Ware C API Documentation Resources#

For the Z-Ware C API, see the following documents:

Building the Library and Sample Apps#

See the Lab Exercise to build the library and modify a sample app on a Raspberry Pi. The steps to build the library are also listed in the gateway Getting Started Guide.