Developing with ZBOSS for Zigbee
|
This page provides an overview of the stack ZCL, commissioning, and security APIs.
The following table lists terms that are used in the Zigbee Cluster Library specification.
Term | Definition |
---|---|
Attribute | A data entity that represents a physical quantity or state. This data is communicated to other devices through commands. |
Cluster | A specification that defines one or more attributes, commands, behaviors, or dependencies. Cluster supports an independent utility or application function. The term can also be used for the implementation or the instance of the cluster specification on an endpoint. |
Device | A specification that defines a unique device identifier and a set of mandatory and optional clusters to be implemented on a single endpoint. The term can also be used for the implementation or the instance of the device specification on an endpoint. |
Endpoint | A device instance on a node. |
Node | A testable implementation of a Zigbee application on a single stack with a single network address, and on a single network. |
The Zigbee application implements a node that handles endpoints. Every endpoint implements a set of clusters. Clusters implement the device functionality, such as attributes to store the state and the commands for various operations.
The ZCL specification is designed to minimize the consumption of flash and RAM by the user application. The application uses the API to declare a Zigbee device and to construct and parse ZCL commands.
Zigbee devices are characterized by a set of clusters that have mandatory and optional attributes. To save memory, make sure that only the required attributes and clusters are declared.
Application can either use predefined device declaration (for example, IAS Zone device) or define its own set of clusters and endpoints.
At the highest level, the Zigbee end product implementation consists of the following parts:
ZCL attributes are described according to the ZCL specification. The library declares attribute lists according to the mandatory attribute sets of the clusters. The ZCL attributes are defined in a form that allows modification.
ZB_ZCL_START_DECLARE_ATTRIB_LIST
and ends with ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST. You can add any number of additional attributes between these lines.ZB_ZCL_DECLARE_ON_OFF_SWITCH_CONFIGURATION_ATTRIB_LIST
macro is defined in the zb_zcl_on_off_switch.h
file. This cluster supports two attributes: switch_type
and switch_actions
.The SDK provides more than 30 implemented Zigbee clusters that are ready for the user application.
To use a cluster, the application must declare it as part of the Zigbee device that is being implemented. Each cluster description is associated with a Zigbee device and includes the following data:
The cluster description data is stored using zb_zcl_cluster_desc_t type. The SDK provides several APIs to fill in cluster descriptors while creating the cluster list declaration.
When a non-standard cluster is required, implement it in the following manner:
zb_zcl_<cluster_name>.h
zb_zcl_<cluster_name>.c
All the available Zigbee device functions are defined by a set of supported clusters. The cluster list is an array of the zb_zcl_cluster_desc_t type. For standard Zigbee devices, the source code contains a set of declaration APIs for cluster lists. A cluster list can be modified by adding or removing clusters.
zb_ha_dimmable_light.h
. Whenever the dimmable light utilizes Basic, Identify, Groups, Scenes, On/Off, and Level Control clusters in a server role, the device takes attribute lists for all of them.An endpoint or a set of endpoints fully describes a Zigbee device. The endpoint declaration in the user application finalizes the logical description of the Zigbee device. To implement ZCL features, each Zigbee device must have at least one endpoint declared besides the built-in one (with ep_id
parameter value set to 0). This declared endpoint will be stored in the zb_af_endpoint_desc_t type endpoint list.
Each endpoint description includes the following data:
The endpoint description data is stored using the type zb_af_endpoint_desc_t. The SDK provides several APIs to fill in endpoint descriptors while performing a Zigbee device declaration for each supported Zigbee device. Additionally, the API declares a simple descriptor. The endpoint list declaration API is provided in the source code and can be modified depending on the application.
The simple descriptor contains specific information for each endpoint contained in a node. It is mandatory for each endpoint present in the node.
The API declares the simple descriptor for each standard Zigbee device and embeds the related calls into the endpoint declaration APIs. However, if modifications to the standard device are requested, the simple descriptor declaration is provided in the source code and you can modify it according to the application needs.
Technically speaking, the simple descriptor is a variable of the type ZB_AF_SIMPLE_DESC_TYPE(in_clust_count, out_clust_count). A pointer to this variable is stored in the endpoint descriptor. This macro is used to create a full type name at compilation time. This is because the simple descriptor contains a list of in and out (client/server) clusters, and the list size varies for different devices. To minimize the RAM usage, the specified values of in and out clusters are used to declare an array of a size required to store all cluster IDs.
There is a base type declared for the simple descriptor: ZB_AF_SIMPLE_DESC_TYPE(1, 1)
. This type is used to cast all the user-specific simple descriptor types at runtime.
The Zigbee device context aggregates the list of endpoints and runtime data, for example storage for reporting configuration information and Level Control context information. The application is responsible for providing enough storage for reporting and Level Control context data for all the endpoints that it declares. For standard Zigbee devices, it is the API that declares device context together with storage for all the context data.
The stack provides the ability to declare one or multiple endpoints for a device.
To declare a multiple endpoint device, the application must call ZBOSS_DECLARE_DEVICE_CTX_<N>_EP
, where N is the number of endpoints.
The stack provides the default macros for declaring not more than 4 endpoints for a device. If the application requires a higher number of endpoints, use one of the following elements for declaring the desired device context:
For instance, ZBOSS_DECLARE_DEVICE_CTX_2_EP(device_ctx_name, ep1_name, ep2_name) declares the device context with two different endpoint descriptors (ep1_name, ep2_name).
For more information on how to declare endpoint descriptors, refer to the section Declaring endpoint.
When the declaration procedures are finished, the device context must be registered with a call to ZB_AF_REGISTER_DEVICE_CTX. As part of this call, two callbacks can be registered in the application:
The stack implements the default handling of all the ZCL commands for all supported clusters, but is also provides a mechanism to override the default settings by intercepting the default ZCL command processing and implementing a custom, application-specific command handling.
To execute this mechanism, the ZCL packet handler callback must be first implemented and registered by the application (see Registering device context). After the ZCL packet handler is registered, it is called for each new incoming ZCL command. This happens before the default ZCL handler is called.
The most common commands processed by the application are responses to the requests sent, including Read attribute response, Write attribute response, and Configure reporting response.
Macro | Parameters | Return value | Description |
---|---|---|---|
ZB_AF_SET_ENDPOINT_HANDLER(endpoint, handler) | endpoint – Endpoint number.handler – Pointer to a function of the type zb_device_handler_t. | None. | Register ZCL packet handler for the specific endpoint. |
zb_device_handler_t(zb_uint8_t param) | zb_uint8_t param – ID of the buffer with the incoming ZCL command. | ZB_TRUE – If the ZCL command was processed by the application. ZB_FALSE – The ZCL command will be proceeded by the stack. | ZCL packet processing callback. |
To process an incoming ZCL command, implement the following algorithm in the ZCL packet handler callback:
cmd_direction
field of the zb_zcl_parsed_hdr_t
structure):is_common_command
field of the zb_zcl_parsed_hdr_t structure is set to 1.is_common_command
field is set to 0.cmd_info -> cluster_id
field of the zb_zcl_parsed_hdr_t structure.cmd_info -> cmd_id
field of the zb_zcl_parsed_hdr_t structure.If the incoming command was processed by the application:
Otherwise, return ZB_FALSE to indicate to the stack to perform the default command processing.
Zigbee device callback is an optional callback, but in case of usage ZCL clusters from the table below, implementing of the Zigbee device callback becomes mandatory. It is called by the stack's default ZCL cluster handlers to notify the application about a certain event. The event can be caused either by the incoming ZCL command or by the internal stack logic.
The "device" word in the callback name indicates that the application must react as a real device. For example, change the brightness level of the lamp on ZB_ZCL_LEVEL_CONTROL_SET_VALUE_CB_ID callback.
With a call to ZB_ZCL_REGISTER_DEVICE_CB(), the application can register a callback function that takes the reference to a buffer as the input parameter. This buffer carries the parameter zb_zcl_device_callback_param_t (see Zigbee stack memory management subsystem for information about how to get a parameter from the buffer).
To check what action triggered the callback, refer to the field device_cb_id
of the received parameter. All the cases are listed in the zb_zcl_device_callback_id_t enumeration. Do not perform any blocking operations during the Zigbee device callback implementation. The memory buffer passed as a parameter to this callback must neither be released nor reused by the application because it is managed by the ZCL subsystem.
The SDK provides API calls for sending and parsing ZCL packets for general command frames and cluster-specific commands.
Macro example | Cluster name | Action verb | Command |
---|---|---|---|
ZB_ZCL_ON_OFF_SEND_TOGGLE_REQ() | On/Off | Send | Toggle |
ZB_ZCL_IAS_ZONE_SEND_STATUS_CHANGE_NOTIFICATION_REQ() | IAS zone | Send | Zone notification |
ZB_ZCL_GENERAL_INIT_READ_ATTR_REQ() ZB_ZCL_GENERAL_ADD_ID_READ_ATTR_REQ() ZB_ZCL_GENERAL_SEND_READ_ATTR_REQ() | (general commands) | Initialize Add Send | Read Attribute |
To construct a manufacturer-specific command (or a standard command that is not supported by the API yet), use the low-level API:
Optionally, a callback can be initiated by including a callback function into a packet. On return, it contains the following parameters:
The API for parsing the received ZCL packets for general command frames and cluster-specific commands is similar to the API for Sending ZCL commands.
Macro example | Cluster name | Action verb | Command | Additional information |
---|---|---|---|---|
ZB_ZCL_IAS_ZONE_GET_STATUS_CHANGE_NOTIFICATION_REQ() | IAS zone | Get | Zone notification | Fills in a variable of the zb_zcl_ias_zone_status_change_not_t type. |
ZB_ZCL_GENERAL_GET_NEXT_READ_ATTR_RES() | (general command) | Get | Read Attribute | Parses the Read Attribute response. |
The commissioning logic is based on Zigbee BDB specification, and is divided into the following types:
Other types of commissioning like the legacy HA or the ZLL commissioning are supported, but not recommended.
You can configure commissioning by setting parameters before the start of the stack.
There are several commissioning parameters that can be assigned by the application or stored in NVRAM, or both. The default parameters are coded in the application firmware. Then they can be updated by the NVRAM content.
The commissioning configuration sequence is made of the following steps:
zb_set_long_address(g_ed_addr)
;zb_set_network_ed_role(1l<<21)
;The stack implements all Zigbee roles: a coordinator, a router, and an end device. Only one role can be defined in a Zigbee application. Switching Zigbee role at runtime is not supported.
Different libraries are provided for each role, and the application must be linked to them:
libzboss.a
,libzboss.ed.a
.See the following table for the overview of functions for setting the device role.
Macro | Parameters | Return value | Description |
---|---|---|---|
zb_set_network_coordinator_role(zb_uint32_t channel_mask) | channel_mask – mask used to define the primary channel set. | None. | Initiate device as a Zigbee coordinator. |
zb_set_network_router_role(zb_uint32_t channel_mask) | channel_mask – mask used to define the primary channel set. | None. | Initiate device as a Zigbee router. |
zb_set_network_ed_role(zb_uint32_t channel_mask) | channel_mask – mask used to define the primary channel set. | None. | Initiate device as a Zigbee end device. |
For the complete list of settings, see the Application structure & commissioning start section in the Zigbee stack API reference documentation.
The channel_mask
parameter is a bit field that defines the Zigbee channels to be used for the energy scan as the primary channel set. Bits from 11 to 26 are used to control the channel selection. Each bit enables or disables the corresponding channel. To set all channel masks (enable all channels), use the macro ZB_TRANSCEIVER_ALL_CHANNELS_MASK
.
BDB has an abstraction of primary and secondary channel mask. By default, the secondary channel mask is the same, but you can define it separately by using the call zb_set_bdb_secondary_channel_set(zb_uint32_t channel_mask).
For details on the abstraction of primary and secondary channel mask and the complete network configuration API, see the official Zigbee BDB specification.
The following functions can modify the settings of the BDB channel:
To start the implicit BDB commissioning after the zboss_start() call, use the zb_set_bdb_commissioning_mode() function. Its parameter is a bitmask that specifies the BDB commissioning mode. See the official Zigbee BDB specification for detailed description. For more details about the API, see the BDB commissioning API section in the Zigbee stack API documentation.
You can use one of the following functions for the stack initialization:
The zboss_start_no_autostart() function does only minimal initialization of the stack framework, enough to have the multitasking and the memory management. The stack initializes its base structures, reads NVRAM, starts the scheduler, but does not initialize Zigbee data structures and radio. It then calls zboss_signal_handler() with ZB_ZDO_SIGNAL_SKIP_STARTUP signal. The application should later call ZBOSS commissioning initiation – bdb_start_top_level_commissioning(ZB_BDB_NETWORK_STEERING) that will trigger further commissioning. To avoid triggering commissioning at this point, call bdb_start_top_level_commissioning() with mask 0 that makes the stack proceed with the initialization without steering and commissioning. This option is recommended if:
After starting zboss_main_loop or zboss_main_loop_iteration, the stack will interact with the user application using:
As the full-featured Zigbee stack is implemented, all Zigbee commands and events are processed. In addition, there are tools that allow the application to handle some Zigbee events, including network formation, association status, and leave indication. Due to its nature, different Zigbee events appear asynchronously and the stack informs the application with application signals. The application can handle or ignore these signals.
All application signals are processed in the application with a predefined callback function zboss_signal_handler(). Each application must implement this function, even if there is no need to process signals. The prototype for the signal handler function is:
In this function, param
is a reference to a memory buffer.
Take into account the following policies while implementing the zboss_signal_handler() function:
An application signal is described with the following parameters:
To get the signal description, the application calls zb_get_app_signal(). For example:
Where:
param
is the reference to a memory buffer,ev_p
is the pointer to store the extended event info; can be NULL
. The function returns an ID of the application signal.The stack implements procedures for the following BDB commissioning modes:
The implementation can use commissioning at any time. For example, network steering can be started at any time for the whole node, and finding and binding can be performed at any time on any application endpoint.
The commissioning procedure is initiated by triggering a top-level commissioning procedure with the bdb_start_top_level_commissioning function.
ZB_BDBC_MIN_COMMISSIONING_TIME_S
= 180 seconds.ZB_BDBC_MIN_COMMISSIONING_TIME_S
= 180 seconds.Macro | Parameters | Return value | Description |
---|---|---|---|
bdb_start_top_level_commissioning(zb_uint8_t mode_mask) | zb_uint8_t mode_mask – logical OR of values from zb_bdb_commissioning_mode_mask_t. | ZB_TRUE – in case the device starts successfully ZB_FALSE – in case an error occured (for example: the device has already been running) | Initiate BDB commissioning procedure defined by the mode_mask . |
zb_bdb_finding_binding_target(zb_uint8_t endpoint) | zb_uint8_t endpoint – endpoint to bind. | RET_OK if procedure was successfully started | Finding and binding interface. Set finding and binding target mode on the endpoint. |
zb_bdb_finding_binding_initiator(zb_uint8_t endpoint, zb_bdb_comm_binding_callback_t user_binding_cb) | zb_uint8_t endpoint – endpoint to bind.user_binding_cb - user callback function. | RET_OK, or the error code | Finding and binding interface. Initiate finding and binding on the endpoint. Pass result with user_binding_cb . |
typedef zb_bool_t (* zb_bdb_comm_binding_callback_t)(zb_int16_t status, zb_ieee_addr_t addr, zb_uint8_t ep, zb_uint16_t cluster) | status – status (ask user, success or fail).addr – extended address of a device to bindep – endpoint of a device to bind.cluster – cluster ID to bind. | zb_bool_t – agree or disagree to bind device. | Finding and binding interface. BDB finding and binding callback template. |
The Zigbee stack provides an interactive mechanism to reset any node implementation to the default factory settings, based on the requirements in the official Zigbee BDB specification. There are the following approaches for this process:
The resetting process of a Zigbee-based application includes persistent data cleanup and consists of the following steps:
The stack provides a feature to reset a device externally by sending ZB_ZCL_BASIC_SEND_RESET_REQ. The target device goes through all the steps mentioned above in Resetting to factory defaults. The reset can be performed at any time once the device is started (see Stack commissioning start sequence). The device initiates either ZB_ZCL_SET_DEFAULT_VALUE_CB in case it is predefined or the device user application callback with ZB_ZCL_BASIC_RESET_CB_ID.
The device can be reset to factory defaults with a local action. For instance, such a reset can be initiated by the device button press or internal application logics. To do this, use zb_bdb_reset_via_local_action(zb_uint8_t param). The device performs NLME leave and cleans all Zigbee persistent data, except the outgoing NWK frame counter and application datasets (if any).
The application can reset its datasets before starting the process or after its completion. The reset can be performed at any time once the device is started (see Stack commissioning start sequence).
After the reset, the application receives the ZB_ZDO_SIGNAL_LEAVE signal that notifies the user about the completion of the reset procedure.
The application has access to a selection of security measures in the stack. However, most options are invisible to the application, but the features provided by Zigbee network security API and Zigbee API for code security installation can be used to set up the necessary security measures.
Trust Center generates random network keys. This is the default behavior, according to Zigbee PRO core specification.
It is possible to predefine the network key by using zb_secur_setup_nwk_key(). You can use this API call for debugging purposes to simplify the analysis of traffic sniffing results. Do not use it in the production environment.
An application acting as a coordinator (Trust Center) can force the network key switch procedure by calling zb_secur_setup_nwk_key().
In accordance with the Zigbee 3.0 specifications, this SDK provides install code functionality. The following table provides an overview of the related API macros.
Macro | Parameters | Return value | Description |
---|---|---|---|
void zb_secur_ic_add(zb_ieee_addr_t address, zb_uint8_t ic_type, zb_uint8_t *ic, zb_secur_ic_add_cb_t cb); | zb_ieee_addr_t address – long address of the device.zb_uint8_t ic_type - install code type as enumerated in zb_ic_types_tzb_uint8_t *ic – pointer to the install code buffer.zb_secur_ic_add_cb_t cb – callback that will be called after installcode addition. | Does not have return value. | Add the install code for the device with the specified long address. Only for the coordinator. |
zb_ret_t zb_secur_ic_set(zb_uint8_t ic_type, zb_uint8_t *ic); | zb_uint8_t ic_type - install code type as enumerated in zb_ic_types_tzb_uint8_t *ic – pointer to the install code buffer. | zb_ret_t RET_OK on success. RET_CONVERSION_ERROR on error in install code CRC. | Add the install code for a device. Not for the coordinator. |
void zb_secur_ic_remove_req(zb_uint8_t param); | zb_uint8_t param – ID of the buffer with request parameters, it will be also used to store response. | Does not have return value. | Remove the install code for the device with the specified long address. Only for the coordinator. |
void zb_set_installcode_policy(zb_bool_t allow_ic_only); | zb_bool_t allow_ic_only – If True, Install code is required for adding a new device to the network. If False, the default commisioning is used. | n/a | Set Install code policy flag. |