Step 3a: ZWave - Inclusion and Exclusion

 

The code for this step is found here.

 

The hardware is working, it's time to add ZWave support. Our primary goal is to implement CC_SENSOR_MULTILEVEL for both the humidity and temperature channels. We'll implement Version 11 of the command class, with GET/REPORT and SUPPORTED_GET/REPORT for sensors and scales. We'll use CC_CONFIGURATION to control the logger, supporting three parameters: #1, a 4 byte integer with the time between samples in seconds (the size chosen to allow 86400, or once per day); #2, a 1 byte integer with the number of samples (0 to run without stopping); and #3, a 1 byte start/stop (non-zero/zero) flag. We'll store at most 64 samples, based on the width of the LCD graphs, so we can statically allocate arrays and the back stores for the graphs. Logging will not persist over a power loss, so we don't need to worry about storing state in NVM, and we'll ignore configuration changes while the logger is running.

 

We are not trying to build a device that will pass certification. We will be ignoring many required command classes, including ZWave+, Indicator, Association, Basic, Device Reset, Firmware Update, and Supervision. We will not implement Smart Start, nor S2 Security. For reference, ZWave+ requires us to use GENERIC_TYPE_SENSOR_MULTILEVEL and SPECIFIC_TYPE_ROUTING_MULTILEVEL_SENSOR, and Sensor Multilevel instead of Basic. It also requires Association, Association Group Info, Device Reset, Firmware Update Meta-Data, Indicator, Manufacturer Specific, Multi-Channel Association, Power Level, S2, Supervision, Transport Service, Version, and Zwave Plus Info; Multi-Command would be recommended. Many of these are easily supported using the full framework, which we'll discuss in Step 4.

 

As a first step, implementing inclusion and exclusion is enough work, as it will force us to deal with the application framework parts we simplified back in Step 2a. You'll remember we removed association groups from the ZAF_TSE.c source file and multichannels from ZW_TransportEndpoint.c. We linked in many files to use them unchanged, including application_properties.c, AppTimer.c, board_indicator.c, board.c, ZAF_command_class_utils.c, zaf_event_helper.c, ZAF_uart_utils.c, ZW_TransportMulticast.c, and ZW_TransportSecProtocol.c. All these should be under the ZAF_AppUtil/ directory.

 

We start by cleaning up the configuration files for the framework. Include ZW_product_id_enum.h in src/config_app.h and remove the _PRODUCT_TYPE_ID_ENUM_ type. Move MAX_TXPWR and MEASURED_0DBM_TXPWR into src/config_rf.h, include ZW_radio_api.h, and define RADIO_REGION as REGION_US, also replacing the use of REGION_US in the application code. In ApplicationInit() we need to start the radio by calling BRD420xBoardInit(). Call this, and setup_display(), after starting the UART, as it includes debug prints that we don't want to lose. (The initialization function from Step 3b shows these changes, as well as edits for the NIF.)

 

When we created our event handlers in Step 2a, we left two placeholders that we now have to implement. The ZwCommandStatusQueue will handle events from the framework to the application, and ZWRxQueue will handle incoming frames. There is also a pZwTxQueue for outbound frames and pZWCommandQueue for commands to the framework, neither of which we'll use. Events in the command status queue have payloads of type SZwaveCommandStatusPackage; they are processed in handle_cmdstatus(). Its first byte/member, called eStatusType, is a enumeration EZwaveCommandStatusType. The second member, called Content, is a type-specific structure of varying length. For example and assuming the payload variable is called 'status', during inclusion we'll get a EZWAVECOMMANDSTATUS_LEARN_MODE_STATUS packet for status.eStatusType with the detailed state in status.Content.LearnModeStatus.Status. Frame events, processed in handle_frame(), also have two members in their structures, the first called eReceiveType and the second with type-specific details called uReceiveParams. All of these are defined in ${SDK}/ZWave/API/ZW_application_transport_interface.h. The event handlers will switch on the first member, either eStatusType or eReceiveType, and then process the details in the second. For this step, we do not need to do anything with frame events, and only must consider EZWAVECOMMANDSTATUS_LEARN_MODE_STATUS and EZWAVECOMMANDSTATUS_NETWORK_LEARN_MODE_START.

 

The demo programs define five states for the application. STARTUP means they are setting up non-volatile memory. During INIT they read what's stored in NVM, set up association groups, start the event scheduler, and begin Smart Start scanning. While IDLE they handle button presses, either entering learn mode or sending the NIF, or sending a message to the lifeline. They mark LEARN_MODE with LEDs and allow canceling the operation. RESET does just that, for the board and NVM.

 

We will simplify this. Our application state will contain a flag indicating if we're in learn mode or not. Progress will translate into an enumeration LEARN_[EXCLUDED|INCLUDED|UNDERWAY|FAILED] summary which we will pass to a set_indicator() function to control LED1, which we set aside back in Step 2a for this purpose. The LED will turn on if included, blink slowly while underway, and blink quickly for a while after a failure. Both the flag and LED are set in handle_cmdstatus().

 

While learning our button press event handler will ignore Button1 events. Otherwise it will call ZAF_setNetworkLearnMode() depending on the current inclusion state (available as app->pNetworkInfo->eInclusionState where app is cached and retrieved from ZAF_getAppHandle(). See handle_event().

 

These modifications require surprisingly few changes to files linked to the project; just getting a project to compile within the framework, without using it, has pulled in most of the dependencies. There are no changes to the project's (build) properties.

  1. Link ${SDK}/ZAF/⁠⁠ApplicationUtilities/board_BRD420x.c under ZAF_AppUtil⁠/.

  2. Link ${SDK}/ZAF/ApplicationUtilities/ZAF_network_learn.c under ZAF_AppUtil⁠/.

 

Only a handful of functions change for this functionality. Any not listed here are the same as in Step 2c.

function

status

role

description

handle_event

edit

button press

implement button 1

handle_dummy

remove

 

 

set_indicator

new

LED1

show learn status on LED

ApplicationInit

edit

ZAF

use config_rf.h, init radio

ApplicationTask

edit

ZAF

extra handlers

handle_frame

new

ZAF

frame event handler

handle_cmdstatus

new

ZAF

command status event handler

 

The directory listing has just three new entries, the RF configuration file and the two ZAF source links.

hw/

src/

ZAF_AppUtil/

ZAF_CC/

displayconfigapp.h

config_app.h

ZAF_TSE.c

 

displayfont16x20HT.h

config_rf.h

ZW_TransportEndpoint.c

 

em_types.h

HTSensor1.c

 

 

graphdisplay.c

i2cspmconfig.h

 

 

graphdisplay.h

 

 

 

textdisplay.c

 

 

 

testdisplayconfig.h

 

 

 

textdisplay.h

 

 

 

linked within Simplicity Studio

display.c

 

application_properties.c

 

displayls013b7dh03.c

 

AppTimer.c

 

displaypalemlib.c

 

board_BRD420x.c

 

em_i2c.c

 

board_indicator.c

 

em_letimer.c

 

board.c

 

em_prs.c

 

ZAF_command_class_utils.c

 

gpiointerrupts.c

 

zaf_event_helper.c

 

i2cspm.c

 

ZAF_network_learn.c

 

startup_zgm13.S

 

ZAF_uart_utils.c

 

system_zgm13.c

 

ZW_TransportMulticast.c

 

 

 

ZW_TransportSecProtocol.c

 

 

With this we have the basic functionality we wanted. If you press Button1 without having a controller waiting for the node, you will eventually see a failure indicator. If there is a controller waiting, you'll see a success indicator and console message. The controller will see the some correct values in the NIF, including the right device classes, and some incorrect, like the command class list. We'll fix that next. Sending commands from the controller to the devkit will do nothing, but you will see console messages for the framework events it generates.

step3A_zipgw

zipgateway information after inclusion. Command classes 0x68 (ZIP Naming) and 0x23 (ZIP) are added by the gateway. Device classes are correct.

zpiffer trace of inclusion

zpiffer trace of inclusion. AppUpdate in left (blue) window includes no command classes. Other NIF components in right (red) window.