Designing a Custom Zigbee 3.0 Certifiable Product Using SampleApp#
Introduction#
The intention of this lab is to help developers create their own custom Zigbee 3.0 devices using Z-Stack. Topics that we will cover in this lab include:
Choosing a certifiable Zigbee device type from the Zigbee device type specifications
Gathering the required information about your chosen Zigbee device from the Zigbee documentation
Modifying the sample applications provided in the SimpleLink SDK to suit the needs of your chosen Zigbee device
Z-Stack is a component of the SimpleLink CC13xx / CC26xx Software Development Kit and is a complete Zigbee 3.0 software solution.
Note: This lab is intended to be a starting point for development, it does not go into details about how to test and verify the final product.
Note
Technical support For any questions you may have, please refer to the TI Zigbee & Thread E2E Forum.
Prerequisites#
Background#
Familiarity with the Zigbee 3.0 specification
More information about the changes in Zigbee 3.0 compared to older specifications can be found in SWRA615
Basic CCS knowledge
Some basic familiarity with embedded programming
Software#
Code Composer Studio (latest version) with support for CC13xx/CC26xx devices
SimpleLink CC13xx / CC26xx SDK (latest)
Recommended Reading#
Zigbee Documentation#
Zigbee Cluster Library v7 Specification (ZCL spec) - Zigbee Document number 07-5123-07
Zigbee Lighting and Occupancy Device Specification (ZLO spec) - Zigbee Document number 15-0014-05
Zigbee Home Automation Public Application Profile (ZHA spec) - Zigbee Document number 05-3520-29
Note
Note Zigbee documentation can be obtained from the Connectivity Standards Alliance
Gathering information from Zigbee documentation#
Before we jump into the software, our first task is to determine which type of Zigbee device we wish to create. Then we must determine which clusters that device must support and which attributes those clusters must support.
Choosing a Zigbee device type#
There are currently two specifications we can refer to for choosing a Zigbee device type, the Zigbee Lighting and Occupancy Device Specification (ZLO spec) and the Zigbee Home Automation Public Application Profile (ZHA spec).
Go to the “Device Descriptions” sections of both documents, Section 5 in the ZLO spec and Section 5.7 in the ZHA spec. At first glance you will notice that there is some overlap between these two specifications, namely Device ID 0x0100 through 0x0107. If you are creating one of these Zigbee Lighting devices, refer to the information in the ZLO spec instead of the ZHA spec. The ZLO spec is the newest device specification document that has been released by the Connectivity Standards Alliance, so the information in this document is newer and supersedes anything regarding these devices types in the ZHA spec. For all other non-overlapping device types between these two documents, the current instructions from the Zigbee Alliance website are to follow the guidelines in each corresponding document for each device type.
So, let’s say we want to create a Door Lock as our Zigbee device. In Section 5.7 of the ZHA spec, we can see in Table 5.1 below that this device has Device ID 0x000A.
ZHA Spec: Table 5.1 Devices Specified in the HA Profile
Determining which clusters our device support#
In the same document that we chose our Zigbee device out of, we can navigate to the section that defines what clusters our device supports. In our case, we need go to Section 7.4.10 of the ZHA spec for Door Lock. From here we can determine which clusters our device supports under the subsection ‘Supported Clusters’.
Here are all the important points from the images below:
Mandatory and Optional Clusters
All Zigbee devices must implement their mandatory clusters to pass Zigbee device certification. Zigbee device manufacturers may choose to implement certain optional clusters for their own application needs.
Note
If you choose to implement an optional cluster, even though it is marked as optional, you must still pass certification for that cluster if you wish to include it with your device
Server Side and Client Side cluster implementation
Implementing the Server vs. the Client side of a cluster is very important because it determines which attributes you support.
Common Clusters for all Zigbee devices
All Zigbee devices support a common set of mandatory and optional clusters, listed below in table 7.1. We can see in section 7.4.10.1 below that it mentions “In addition to those specified in Table 7.1”
ZHA Spec: Section 7.4.10.1 Supported Clusters for Door Lock
ZHA Spec: Table 7.1 Clusters Common to All Devices
Now, using the information from the tables above, let’s make new table that shows what clusters our Door Lock device is going to support. Only the mandatory clusters are selected for this example.
SLA Table 1: Cluster table for Door Lock device
Cluster ID |
Cluster Name |
Client/Server Side |
---|---|---|
0x0000 |
Basic |
Server |
0x0003 |
Identify |
Client + Server |
0x0004 |
Groups |
Server |
0x0005 |
Scenes |
Server |
0x0101 |
Door Lock |
Server |
Determining which attributes our clusters support#
Now that we have a list of clusters, we can refer to the Zigbee Cluster Library v7 Specification (ZCL spec). The ZCL spec will tell us which attributes our selected clusters support. Each section of the ZCL spec will give us a cluster and tell us which attributes the Server Side and Client Side implementations of that cluster support.
As of the ZCL v6 spec, it is mandatory for every cluster to support the ClusterRevision attribute.
ZCL Spec: Table 2-1 Global attributes for every cluster
Let’s start with the Basic Cluster. From the table we made in the previous section, we must support the Basic Cluster Server. Table 3-7 in Section 3.2.2.2 of the ZCL spec tells us which attributes the Basic Cluster Server supports.
ZCL Spec: Table 3-7 Attributes supported by Basic Cluster Server
Next we can find the Identify Cluster, for which we must support both Client and Server. Table 3-28 in section 3.5.2.2 of the ZCL spec tells us which attributes the Identify Cluster Server supports. Section 3.5.2.1 of the ZCL spec tells us that the Identify Cluster Client does not support any cluster specific attributes.
ZCL Spec: Table 3-31 Attributes supported by Identify Cluster Server
Next is the Groups Cluster, for which we must support both Client and Server. Table 3-36 of section 3.6.2.2 of the ZCL spec tells us which attributes the Groups Cluster Server supports. The same can be said of Table 3-40 of section 3.7.2.2.1 for the Scenes Cluster and Table 7-8 of section 7.3.2.10 for the Door Lock Cluster, all for the Server side.
ZCL Spec: Table 3-36 Attributes supported by Groups Cluster Server
ZCL Spec: Table 3-40 Attributes supported by Scenes Cluster Server
ZCL Spec: Table 7-8 Attributes supported by Door Lock Cluster Server
Once again, a new table is created using the information from the tables above that shows us which attributes our Door Lock device is going to support. Only the madatory attributes are selected for this example.
SLA Table 2: Attribute table for Door Lock device
Attribute |
Cluster |
Data Type |
Access |
Default Value |
---|---|---|---|---|
ZCLVersion |
Basic |
uint8 |
Read |
2 |
PowerSource |
Basic |
enum8 |
Read |
0 |
ClusterRevision |
Basic |
uint16 |
Read |
1 |
IdentifyTime |
Identify |
uint16 |
Read/Write |
0 |
ClusterRevision |
Identify |
uint16 |
Read |
1 |
NameSupport |
Groups |
map8 |
Read |
0 |
ClusterRevision |
Groups |
uint16 |
Read |
1 |
SceneCount |
Scenes |
uint8 |
Read |
0 |
CurrentScene |
Scenes |
uint8 |
Read |
0 |
CurrentGroup |
Scenes |
uint16 |
Read |
0 |
SceneValid |
Scenes |
bool |
Read |
0 |
NameSupport |
Scenes |
map8 |
Read |
0 |
ClusterRevision |
Scenes |
uint16 |
Read |
1 |
LockState |
Door Lock |
enum8 |
Read/Reportable |
0 |
LockType |
Door Lock |
enum8 |
Read |
0 |
ActuatorEnabled |
Door Lock |
bool |
Read |
0 |
ClusterRevision |
Door Lock |
uint16 |
Read |
1 |
Warning
Reportable Attributes: If any of the attributes you are supporting have an access type of Reportable, it is mandatory for your device to support ZCL reporting which means your device will need to include the compile flag BDB_REPORTING
which enables ZCL report sending capabilities. We will revisit this again later on in the lab.
Modifying the SampleApp project#
It’s finally time to start modifying the software to suit our needs. We will be referencing the SampleApp project to create a custom certifiable application using the SysConfig Application Builder. You can learn more about this feature in the TI Z-Stack User’s Guide. You can find the project in the following location:
C:\ti\simplelink_cc13xx_cc26xx_sdk_<version>\examples\rtos\<LaunchPad variant>\zstack\zr_sampleapp
Importing the project into Code Composer Studio#
Now we are ready to import the project into Code Composer Studio (CCS). Open CCS and go to File > Import > C/C++ Project > CCS Project
and then browse for the zr_sampleapp project path under Select search-directory
:
Import our modified SampleApp into CCS
At this point it is a good idea to try building the project just to make sure all the file paths resolve correctly, this will verify that we have a good starting point for our incoming code modifications.
Using the SysConfig Application Builder#
The SysConfig Application Builder will automate several ZCL configurations. This consists of defining compile flags in ti_zstack_config.h
along with including all attributes, server/client clusters, simple descriptors, callback definitions, and initialization code inside the zcl_config.c
file. First, open the zr_sampleapp.syscfg
> Z-Stack > Zigbee Application Endpoint menu and select Generic as the Zigbee Device Type. It is possible to change the Application Name to “Door Lock” or another suitable name of choice, however this lab will keep the default “Sample App” naming convention.
Zigbee Application Endpoint view in SysConfig
Note
Although a Door Lock is provided as a pre-configured certifiable Zigbee Device Type, we will build one from scratch for the purposes of this lab.
The following list details what all is configured inside the Zigbee Application Builder
Viewing Mandatory Clusters
Adding Additional Clusters
Choosing BDB Reporting and Advanced Settings
Viewing Mandatory Clusters#
We can select the Mandatory Clusters tab to see that only the Basic and Identify clusters are defined as the Server Clusters. This is the default requirement for a Generic Zigbee Device Type and no further changes are required towards these settings. Optional Attributes and Optional Commands Generated/Received can be added if necessary for the application. Groups is listed under Server Clusters from Recommended Optional Clusters and should be chosen accordingly.
Mandatory Clusters
Adding Additional Clusters#
Inside the Additional Clusters tab is where we will add the clusters from SLA Table 1, excluding Basic and Identify for the server side as they are already covered by the Mandatory Clusters. For Server Clusters, select Scenes and DoorLock. Client Clusters need only add Identify.
Additional Clusters
Doing this will prompt the Zigbee Application Builder to automatically fill the Mandatory Attributes tab with the attributes described in SLA Table 2. The Mandatory Commands Generated/Received are also populated. Optional Attributes and Optional Commands Generated/Received can also be added based on application needs.
Choosing BDB Reporting and Advanced Settings#
As SLA Table 2 identifies a reportable attribute which was added when configuring the Additional Clusters, the BDB Reporting tab becomes available. These values, alongside those of the Advanced Settings tab, can be chosen according to the developer’s requirements. More information can be obtained in the SysConfig section of the TI Z-Stack User’s Guide. For the purpose of this lab, however, the default values will be used.
BDB Reporting and Advanced Settings
After completing all configurations inside the SysConfig Zigbee Application Builder, we will build the project to generate the zcl_config.c/h
file which will be located in the default/sysconfig
folder. It is here that we can view the ZCL attribute variables/default values, attribute lists, command lists, callbacks, and simple descriptors that were created based on our previous selections. We also see that a zclConfigInit
function is created to initialize this code, and is called by sampleApp_Init
of sampleapp.c
.
Warning
SysConfig output: Files found in the default/sysconfig
folder must never be directly edited as they will be re-written each time the project is built. Changes can only be made by modifying the corresponding SysConfig module or copying files into the main project directory after de-selecting Include in build
from the SysConfig Generated File View.
All of the ZCL source code files are included in the SampleApp project by default, but the functionality contained in each file is compiled out via compile flags. The table below shows which compile flags will be added to ti_zstack_config.h
based on the clusters listed in SLA Table 1.
SLA Table 3: Compile Flag to Cluster correspondence
Cluster ID |
Cluster Name |
Compile Flags |
---|---|---|
0x0000 |
ZCL_CLUSTER_ID_GEN_BASIC |
ZCL_BASIC |
0x0001 |
ZCL_CLUSTER_ID_GEN_POWER_CFG |
N/A |
0x0002 |
ZCL_CLUSTER_ID_GEN_DEVICE_TEMP_CONFIG |
N/A |
0x0003 |
ZCL_CLUSTER_ID_GEN_IDENTIFY |
ZCL_IDENTIFY |
0x0004 |
ZCL_CLUSTER_ID_GEN_GROUPS |
ZCL_GROUPS |
0x0005 |
ZCL_CLUSTER_ID_GEN_SCENES |
ZCL_SCENES |
0x0006 |
ZCL_CLUSTER_ID_GEN_ON_OFF |
ZCL_ON_OFF |
0x0007 |
ZCL_CLUSTER_ID_GEN_ON_OFF_SWITCH_CONFIG |
N/A |
0x0008 |
ZCL_CLUSTER_ID_GEN_LEVEL_CONTROL |
ZCL_LEVEL_CTRL |
0x0009 |
ZCL_CLUSTER_ID_GEN_ALARMS |
ZCL_ALARMS |
0x000A |
ZCL_CLUSTER_ID_GEN_TIME |
N/A |
0x000B |
ZCL_CLUSTER_ID_GEN_LOCATION |
ZCL_LOCATION |
0x000C |
ZCL_CLUSTER_ID_GEN_ANALOG_INPUT_BASIC |
N/A |
0x000D |
ZCL_CLUSTER_ID_GEN_ANALOG_OUTPUT_BASIC |
N/A |
0x000E |
ZCL_CLUSTER_ID_GEN_ANALOG_VALUE_BASIC |
N/A |
0x000F |
ZCL_CLUSTER_ID_GEN_BINARY_INPUT_BASIC |
N/A |
0x0010 |
ZCL_CLUSTER_ID_GEN_BINARY_OUTPUT_BASIC |
N/A |
0x0011 |
ZCL_CLUSTER_ID_GEN_BINARY_VALUE_BASIC |
N/A |
0x0012 |
ZCL_CLUSTER_ID_GEN_MULTISTATE_INPUT_BASIC |
N/A |
0x0013 |
ZCL_CLUSTER_ID_GEN_MULTISTATE_OUTPUT_BASIC |
N/A |
0x0014 |
ZCL_CLUSTER_ID_GEN_MULTISTATE_VALUE_BASIC |
N/A |
0x0015 |
ZCL_CLUSTER_ID_GEN_COMMISSIONING |
N/A |
0x0016 |
ZCL_CLUSTER_ID_GEN_PARTITION |
N/A |
0x0019 |
ZCL_CLUSTER_ID_OTA |
OTA_CLIENT_INTEGRATED |
0x001A |
ZCL_CLUSTER_ID_GEN_POWER_PROFILE |
N/A |
0x001B |
ZCL_CLUSTER_ID_GEN_APPLIANCE_CONTROL |
N/A |
0x0020 |
ZCL_CLUSTER_ID_GEN_POLL_CONTROL |
N/A |
0x0021 |
ZCL_CLUSTER_ID_GREEN_POWER |
N/A |
0x0022 |
ZCL_CLUSTER_ID_MOBILE_DEVICE_CONFIGURATION |
N/A |
0x0023 |
ZCL_CLUSTER_ID_NEIGHBOR_CLEANING |
N/A |
0x0024 |
ZCL_CLUSTER_ID_NEAREST_GATEWAY |
N/A |
0x0100 |
ZCL_CLUSTER_ID_CLOSURES_SHADE_CONFIG |
N/A |
0x0101 |
ZCL_CLUSTER_ID_CLOSURES_DOOR_LOCK |
ZCL_DOORLOCK |
0x0102 |
ZCL_CLUSTER_ID_CLOSURES_WINDOW_COVERING |
ZCL_WINDOWCOVERING |
0x0200 |
ZCL_CLUSTER_ID_HVAC_PUMP_CONFIG_CONTROL |
ZCL_HVAC_CLUSTER |
0x0201 |
ZCL_CLUSTER_ID_HVAC_THERMOSTAT |
ZCL_HVAC_CLUSTER |
0x0202 |
ZCL_CLUSTER_ID_HVAC_FAN_CONTROL |
ZCL_HVAC_CLUSTER |
0x0203 |
ZCL_CLUSTER_ID_HVAC_DIHUMIDIFICATION_CONTROL |
ZCL_HVAC_CLUSTER |
0x0204 |
ZCL_CLUSTER_ID_HVAC_USER_INTERFACE_CONFIG |
ZCL_HVAC_CLUSTER |
0x0300 |
ZCL_CLUSTER_ID_LIGHTING_COLOR_CONTROL |
ZCL_LIGHT_LINK_ENHANCE |
0x0301 |
ZCL_CLUSTER_ID_LIGHTING_BALLAST_CONFIG |
ZCL_LIGHT_LINK_ENHANCE |
0x0400 |
ZCL_CLUSTER_ID_MS_ILLUMINANCE_MEASUREMENT |
N/A |
0x0401 |
ZCL_CLUSTER_ID_MS_ILLUMINANCE_LEVEL_SENSING_CONFIG |
N/A |
0x0402 |
ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT |
N/A |
0x0403 |
ZCL_CLUSTER_ID_MS_PRESSURE_MEASUREMENT |
N/A |
0x0404 |
ZCL_CLUSTER_ID_MS_FLOW_MEASUREMENT |
N/A |
0x0405 |
ZCL_CLUSTER_ID_MS_RELATIVE_HUMIDITY |
N/A |
0x0406 |
ZCL_CLUSTER_ID_MS_OCCUPANCY_SENSING |
N/A |
0x0500 |
ZCL_CLUSTER_ID_SS_IAS_ZONE |
ZCL_ZONE |
0x0501 |
ZCL_CLUSTER_ID_SS_IAS_ACE |
ZCL_ACE |
0x0502 |
ZCL_CLUSTER_ID_SS_IAS_WD |
ZCL_WD |
0x0600 |
ZCL_CLUSTER_ID_PI_GENERIC_TUNNEL |
N/A |
0x0601 |
ZCL_CLUSTER_ID_PI_BACNET_PROTOCOL_TUNNEL |
N/A |
0x0602 |
ZCL_CLUSTER_ID_PI_ANALOG_INPUT_BACNET_REG |
N/A |
0x0603 |
ZCL_CLUSTER_ID_PI_ANALOG_INPUT_BACNET_EXT |
N/A |
0x0604 |
ZCL_CLUSTER_ID_PI_ANALOG_OUTPUT_BACNET_REG |
N/A |
0x0605 |
ZCL_CLUSTER_ID_PI_ANALOG_OUTPUT_BACNET_EXT |
N/A |
0x0606 |
ZCL_CLUSTER_ID_PI_ANALOG_VALUE_BACNET_REG |
N/A |
0x0607 |
ZCL_CLUSTER_ID_PI_ANALOG_VALUE_BACNET_EXT |
N/A |
0x0608 |
ZCL_CLUSTER_ID_PI_BINARY_INPUT_BACNET_REG |
N/A |
0x0609 |
ZCL_CLUSTER_ID_PI_BINARY_INPUT_BACNET_EXT |
N/A |
0x060A |
ZCL_CLUSTER_ID_PI_BINARY_OUTPUT_BACNET_REG |
N/A |
0x060B |
ZCL_CLUSTER_ID_PI_BINARY_OUTPUT_BACNET_EXT |
N/A |
0x060C |
ZCL_CLUSTER_ID_PI_BINARY_VALUE_BACNET_REG |
N/A |
0x060D |
ZCL_CLUSTER_ID_PI_BINARY_VALUE_BACNET_EXT |
N/A |
0x060E |
ZCL_CLUSTER_ID_PI_MULTISTATE_INPUT_BACNET_REG |
N/A |
0x060F |
ZCL_CLUSTER_ID_PI_MULTISTATE_INPUT_BACNET_EXT |
N/A |
0x0610 |
ZCL_CLUSTER_ID_PI_MULTISTATE_OUTPUT_BACNET_REG |
N/A |
0x0611 |
ZCL_CLUSTER_ID_PI_MULTISTATE_OUTPUT_BACNET_EXT |
N/A |
0x0612 |
ZCL_CLUSTER_ID_PI_MULTISTATE_VALUE_BACNET_REG |
N/A |
0x0613 |
ZCL_CLUSTER_ID_PI_MULTISTATE_VALUE_BACNET_EXT |
N/A |
0x0614 |
ZCL_CLUSTER_ID_PI_11073_PROTOCOL_TUNNEL |
N/A |
0x0615 |
ZCL_CLUSTER_ID_PI_ISO7818_PROTOCOL_TUNNEL |
N/A |
0x0617 |
ZCL_CLUSTER_ID_PI_RETAIL_TUNNEL |
N/A |
0x0700 |
ZCL_CLUSTER_ID_SE_PRICE |
ZCL_SE_PRICE_SERVER, ZCL_SE_PRICE_CLIENT |
0x0701 |
ZCL_CLUSTER_ID_SE_DRLC |
ZCL_SE_DRLC_SERVER, ZCL_SE_DRLC_CLIENT |
0x0702 |
ZCL_CLUSTER_ID_SE_METERING |
ZCL_SE_METERING_SERVER, ZCL_SE_METERING_CLIENT |
0x0703 |
ZCL_CLUSTER_ID_SE_MESSAGING |
ZCL_SE_MESSAGING_SERVER, ZCL_SE_MESSAGING_CLIENT |
0x0704 |
ZCL_CLUSTER_ID_SE_TUNNELING |
ZCL_SE_TUNNELING_SERVER, ZCL_SE_TUNNELING_CLIENT |
0x0705 |
ZCL_CLUSTER_ID_SE_PREPAYMENT |
ZCL_SE_PREPAYMENT_SERVER, ZCL_SE_PREPAYMENT_CLIENT |
0x0706 |
ZCL_CLUSTER_ID_SE_ENERGY_MGMT |
ZCL_SE_ENERGY_MGMT_SERVER, ZCL_SE_ENERGY_MGMT_CLIENT |
0x0707 |
ZCL_CLUSTER_ID_SE_CALENDAR |
ZCL_SE_CALENDAR_SERVER, ZCL_SE_CALENDAR_CLIENT |
0x0708 |
ZCL_CLUSTER_ID_SE_DEVICE_MGMT |
ZCL_SE_DEVICE_MGMT_SERVER, ZCL_SE_DEVICE_MGMT_CLIENT |
0x0709 |
ZCL_CLUSTER_ID_SE_EVENTS |
ZCL_SE_EVENTS_SERVER, ZCL_SE_EVENTS_CLIENT |
0x070A |
ZCL_CLUSTER_ID_SE_MDU_PAIRING |
ZCL_SE_MDU_PAIRING_SERVER, ZCL_SE_MDU_PAIRING_CLIENT |
0x0800 |
ZCL_CLUSTER_ID_SE_KEY_ESTABLISHMENT |
ZCL_KEY_ESTABLISH |
0x0900 |
ZCL_CLUSTER_ID_TELECOMMUNICATIONS_INFORMATION |
N/A |
0x0904 |
ZCL_CLUSTER_ID_TELECOMMUNICATIONS_CHATTING |
N/A |
0x0905 |
ZCL_CLUSTER_ID_TELECOMMUNICATIONS_VOICE_OVER_ZIGBEE |
N/A |
0x0B00 |
ZCL_CLUSTER_ID_HA_APPLIANCE_IDENTIFICATION |
ZCL_APPLIANCE_IDENTIFICATION |
0x0B01 |
ZCL_CLUSTER_ID_HA_METER_IDENTIFICATION |
ZCL_METER_IDENTIFICATION |
0x0B02 |
ZCL_CLUSTER_ID_HA_APPLIANCE_EVENTS_ALERTS |
ZCL_APPLIANCE_EVENTS_ALERTS |
0x0B03 |
ZCL_CLUSTER_ID_HA_APPLIANCE_STATISTICS |
ZCL_APPLIANCE_STATISTICS |
0x0B04 |
ZCL_CLUSTER_ID_HA_ELECTRICAL_MEASUREMENT |
ZCL_ELECTRICAL_MEASUREMENT |
0x0B05 |
ZCL_CLUSTER_ID_HA_DIAGNOSTIC |
ZCL_DIAGNOSTIC |
0x1000 |
ZCL_CLUSTER_ID_TOUCHLINK |
N/A |
In addition to the compile flags in the table above, it is also considered whether any attributes have an access type of ‘Reportable’, which is information that we recorded in SLA Table 2. If there is an attribute that is ‘Reportable’, it is also included as the compile flag BDB_REPORTING
in the ti_zstack_config.h
file.
For our Door Lock device, the compile flags ZCL_BASIC
, ZCL_IDENTIFY
, ZCL_GROUPS
, ZCL_SCENES
, ZCL_DOORLOCK
and BDB_REPORTING
will be included in the SysConfig output once the corresponding Clusters and Attributes are added. They can be viewed in the default/syscfg/ti_zstack_config.h
after building the project.
ZCL Compile Flags generated by SysConfig
/* Cluster Flags */
#define ZCL_SYSCONFIG
#define ZCL_READ
#define ZCL_WRITE
#define ZCL_DISCOVER
#define ZCL_BASIC
#define ZCL_IDENTIFY
#define ZCL_GROUPS
#define ZCL_SCENES
#define ZCL_DOORLOCK
#define BDB_REPORTING
Making code changes to suit our selected Zigbee device#
As the SysConfig Zigbee Application Builder has automated setup of the ZCL layer inside zcl_config.h/c
, all that remains is to copy the command callback functions, attribute variables, and default values into sampleapp.c
and remove the WEAK
tags so that they are correctly re-defined outside of the generated SysConfig files.
ZCL command callback functions are where your hardware-specific actions are performed in relation to the state of your cluster attributes. For instance, if you receive a Zigbee command from another device that changes the state of your Door Lock Cluster “LockState” attribute, you can receive a callback to your application saying that something happened, and at this point you would update your global attribute variable with the value passed into the callback function as a parameter and perform your hardware-specific action such as toggling a GPIO pin to reflect the new state of your attribute.
To receive these callback functions in your application, you must register a list of function pointers with each corresponding ZCL module. By default, zcl_config.c
already does this with zclConfigInit
:
ZCL command callback registration
static void zclConfigInit( void )
{
...
zclGeneral_RegisterCmdCallbacks( SAMPLEAPP_ENDPOINT, &sampleApp_zclGeneralCmdCallbacks );
zclClosures_RegisterDoorLockCmdCallbacks( SAMPLEAPP_ENDPOINT, &sampleApp_zclClosuresCmdCallbacks );
...
}
The second parameter we pass into this function is the list of function pointers that we wish to register with the ZCL module. For every function present on this list we will receive a callback in our application when the corresponding action has been triggered, and we can set any callback we do not wish to receive to NULL
. To know which callback functions are available, you must look into the corresponding zcl<module>_AppCallbacks_t
struct in the ZCL header files. Since the Basic, Identify, Groups, and Scenes clusters are all part of the ZCL General group (i.e. check Chapter 3 of the ZCL spec), all of their callback function descriptions are in the struct zclGeneral_AppCallbacks_t
in zcl_general.h
. For the Door Lock cluster, this is part of the Closures group, so it is in the struct zclClosures_DoorLockAppCallbacks_t
in zcl_closures.h
. Each function in these structs has a typedef
associated with it so you can know how to implement the function prototype and definition in your application. For instance, for the Door Lock callback, it has the type zclClosures_DoorLock_t
in the struct zclClosures_DoorLockAppCallbacks_t
, and we can see the typedef
definition is as below:
typedef ZStatus_t (*zclClosures_DoorLock_t) ( zclIncoming_t *pInMsg, zclDoorLock_t *pInCmd );
And in zcl_config.c
the function is already defined as such:
WEAK ZStatus_t sampleApp_DoorLockCB( zclIncoming_t *pInMsg, zclDoorLock_t *pInCmd ) { return ((ZStatus_t) 0); }
However, this is an empty function which does not accomplish anything. To re-define it for application use, it must be copied into sampleapp.c
and remove the WEAK
tag. This directs the compiler to use the callback function declared inside this file instead.
ZCL command callback use
// Declaring the function at the top of the file
ZStatus_t sampleApp_DoorLockCB( zclIncoming_t *pInMsg, zclDoorLock_t *pInCmd );
...
// Implementing the function further in the file
ZStatus_t sampleApp_DoorLockCB( zclIncoming_t *pInMsg, zclDoorLock_t *pInCmd )
{
// Perform action based on application needs
return 0;
}
The same can be done for ZCL attribute variables, like sampleApp_DoorLock_LockState
.
As mentioned before, the ZCL command callback functions are where you, the developer, must implement your hardware-specific functionality in your application code based on the high-level intended action of each ZCL command. This is the part of the code where, aside from provided HAL drivers, there is no specific framework for how you should implement your actions since it is highly dependent on your custom hardware design. One thing you must do, however, is update the state of your global attribute(s) in these callback functions (if applicable).
As an example, in the Door Lock cluster “DoorLock” Callback, you would do at least 2 things:
Update the state of your global “LockState” attribute based on the function parameter of the callback function.
Perform a hardware-specific action that actually changes the state of your hardware, such as altering the door lock mechanism.