Command Handling and Generation#
Sending Commands and Command Responses#
The Zigbee Application Framework API includes many useful macros for sending and responding to ZCL commands. All of the macros are defined in the file zap-command.h. This file is generated for each project. For example, after building project Z3Light the file can be found in <user workspace>/Z3Light/zap-command.h.
To send a command, do the following.
Sending a command:
Construct a command using a fill macro from the zap-command.h file:
For example:
sl_zigbee_af_fill_command_identify_cluster_identify(identifyTime);
identifyTime
is an int16u defined in the spec as the number of seconds the device should continue to identify itself.This macro fills the command buffer with the appropriate values.
Retrieve a pointer to the command
sl_zigbee_aps_frame_t
and populate it with the appropriate source and destination endpoints for your command. Other values in the ApsFrame such as sequence number are handled by the framework, so you do not need to worry about them.Once the command has been constructed, the command can be sent as a unicast, multicast, or broadcast using one of the following functions:
sl_status_t sl_zigbee_af_send_command_multicast(sl_zigbee_multicast_id_t multicastId, sl_802154_short_addr_t alias, uint8_t sequence); sl_status_t sl_zigbee_af_send_command_unicast(sl_zigbee_outgoing_message_type_t type, uint16_t indexOrDestination); sl_status_t sl_zigbee_af_send_command_broadcast(sl_802154_short_addr_t destination, sl_802154_short_addr_t alias, uint8_t sequence);
Sending a response to an incoming command:
Use a similar mechanism to send a response to an incoming command.
Fill the response command buffer using the command response macros included in autogen/zap-command.h such as:
sl_zigbee_af_fill_command_identify_cluster_identify_query_response(identifyTime)
identifyTime
is an int16u representing the number of seconds the device will continue to identify itself.You do not need to worry about the endpoints set in the response
sl_zigbee_aps_frame_t
since these are handled by the framework.Send the response command by calling
sl_zigbee_af_send_response()
.
ZCL Command Processing#
When the Zigbee Application Framework receives a ZCL command, it is passed off for command processing inside the utility function sl_zigbee_af_process_message
, located within app/framework/util/util.c. The process message function parses the command and populates a local struct of the type sl_zigbee_af_cluster_command_t
. Once this struct is populated, it is assigned to the global pointer sli_zigbee_af_current_command
so that it is available to every function called during command processing.
sl_zigbee_af_process_message
first calls sl_zigbee_af_pre_command_received_cb
to give the application a chance to handle the command. If the command is a global command, it is passed to process-global-message.c for processing; otherwise, it is passed to process-cluster-message.c for processing.
Note: For more information on command processing flow, see the message flowcharts in Callback Flow for Message Processing. Also, for more information on ZCL command runtime subscription, refer to ZCL Command Handling Callbacks
app/framework/util/process-global-message.c#
process-global-message.c handles all global commands, such as reading and writing attributes. Global commands do not currently have associated command callbacks the way cluster-specific commands do.
app/framework/util/process-cluster-message.c#
process-cluster-message.c handles all cluster-specific commands and passes them on to software modules that have subscribed to a specific cluster using the sl_zigbee_subscribe_to_zcl_commands()
API. The subscribed callback is passed the actual ZCL command in the form of an sl_zigbee_af_cluster_command_t
struct. The zap-cluster-command-parser.[c,h] generated files provide command-specific structs and APIs to further parse the ZCL command into a specific ZCL command. For example, for the “stop” command provided by the “level control” cluster, the following struct contains the exact fields of such command:
sl_zcl_level_control_cluster_stop_command_t cmd_data;
The following API can be invoked to parse out the specific ZCL command into the corresponding struct:
zcl_decode_level_control_cluster_stop_command(cmd, &cmd_data);
Where cmd is a pointer to a EmberAfClusterCommand struct passed to the subscribed callback.
Note: Since the cluster-specific command callbacks are called within the command handling context, all of the metadata associated with any command handled in one of these callbacks is available from the global pointer
sli_zigbee_af_current_command
.
Always access the global pointer sli_zigbee_af_current_command
by using the convenient macro provided in app/framework/include/af.h called sl_zigbee_af_current_command()
.
Sending a Default Response#
The Zigbee Application Framework does not automatically send a default response for command handled by the application. In order to improve system reliability and flexibility, Silicon Labs has handed all the default response handling over to the application. This means that, while you now have complete control over sending default responses for commands that you handle, you also are responsible for sending default responses for all those commands. A default response must be sent for any unicast message that does not have a specific response and is not itself a default response. For more information on when default response should and should not be sent, please refer to the Zigbee documentation.
The Zigbee-created components handle sending default responses for all the commands that they handle. Any commands that the components do not handle automatically return SL_ZIGBEE_ZCL_STATUS_UNSUP_COMMAND, or something like it. Your application needs to do the same for all the commands it handles that do not themselves have a specific command response.
Silicon Labs has created a default response API to make this is simple as possible. The sl_zigbee_af_send_default_resonse()
command takes two arguments: the current command, and the status byte. The current command can be retrieved from the Zigbee Application Framework using sl_zigbee_af_current_command()
. The ZCL status bytes used for default response are enumerated in app/framework/gen/enum.h.
sl_status_t sl_zigbee_af_send_default_response(const sl_zigbee_af_cluster_command_t *cmd, sl_zigbee_af_status_t status);
A typical use of this function looks like:
sl_zigbee_af_send_default_response( sl_zigbee_af_curent_command(), SL_ZIGBEE_ZCL_STATUS_SUCCESS );