Event Handling
This chapter describes the event handling framework which allows the ZCL to deal with stack-related and timer-related events (including cluster-specific events).
A message arriving in a message queue triggers a stack event whereas a timer event is triggered when a software timer expires (for more information on timer events, refer to Section 5.2).
The event must be wrapped in a tsZCL_CallBackEvent
structure by the application (see Section 3.1 below), which then passes this event structure into the ZCL using the function vZCL_EventHandler(), described in Section 5.1. The ZCL processes the event and, if necessary, invokes the relevant endpoint callback function. Refer to Section 3.2 for more details of event processing.
Event Structure
The tsZCL_CallBackEvent
structure, in which an event is wrapped, is as follows:
typedef struct
{
teZCL_CallBackEventType eEventType;
uint8 u8TransactionSequenceNumber;
uint8 u8EndPoint;
teZCL_Status eZCL_Status;
union {
tsZCL_IndividualAttributesResponse sIndividualAttributeResponse;
tsZCL_DefaultResponse sDefaultResponse;
tsZCL_TimerMessage sTimerMessage;
tsZCL_ClusterCustomMessage sClusterCustomMessage;
tsZCL_AttributeReportingConfigurationRecord
sAttributeReportingConfigurationRecord;
tsZCL_AttributeReportingConfigurationResponse
sAttributeReportingConfigurationResponse;
tsZCL_AttributeDiscoveryResponse sAttributeDiscoveryResponse;
ZCL_AttributeStatusRecord sReportingConfigurationResponse;
tsZCL_ReportAttributeMirror sReportAttributeMirror;
uint32 u32TimerPeriodMs;
tsZCL_CommandDiscoveryIndividualResponse
sCommandsReceivedDiscoveryIndividualResponse;
tsZCL_CommandDiscoveryResponse sCommandsReceivedDiscoveryResponse;
tsZCL_CommandDiscoveryIndividualResponse
sCommandsGeneratedDiscoveryIndividualResponse;
tsZCL_CommandDiscoveryResponse sCommandsGeneratedDiscoveryResponse;
tsZCL_AttributeDiscoveryExtendedResponse
sAttributeDiscoveryExtenedResponse;
}uMessage ;
ZPS_tsAfEvent *pZPSevent;
tsZCL_ClusterInstance *psClusterInstance;
} tsZCL_CallBackEvent;
The fields of this structure are fully described Section 6.2.
In the tsZCL_CallBackEvent
structure, the eEventType
field defines the type of event being posted - the various event types are described in Section 3.3 below. The union and remaining fields are each relevant to only specific event types.
Parent topic:Event Handling
Processing Events
This section outlines how the application should deal with stack events and timer events that are generated externally to the ZCL. A cluster-specific event initially arrives as one of these events.
The occurrence of an event in the ZCL queue activates a ZCL user function. The following actions must then be performed in the application:
The task checks whether the event that has occurred is a timer event (timer messages are collected by a user-defined function).
The task sets fields of the event structure
tsZCL_CallBackEvent
(see Section 3.1), as follows (all other fields are ignored):
For a timer event, sets the field
eEventType
to E_ZCL_CBET_TIMER.For a millisecond timer event, sets the field
eEventType
to E_ZCL_CBET_TIMER_MS.For a stack event, sets the field
eEventType
to E_ZCL_ZIGBEE_EVENT and sets the fieldpZPSevent
to point to theZPS_tsAfEvent
structure received by the application. This structure is defined in the ZigBee 3.0 Stack User Guide (JNUG3130).
The task passes this event structure to the ZCL using vZCL_EventHandler() - the ZCL then identifies the event type (see Section 3.3) and invokes the appropriate endpoint callback function.
Note: For a cluster-specific event (which arrives as a stack event or a timer event), the cluster normally contains its own event handler which is invoked by the ZCL. If the event requires the attention of the application, the ZCL replaces the eEventType
field with E_ZCL_CBET_CLUSTER_CUSTOM and populates the tsZCL_ClusterCustomMessage
structure with the event data. The ZCL then invokes the user-defined endpoint callback function to perform any application-specific event handling that is required.
Parent topic:Event Handling
Events
The events that are not cluster-specific are divided into four categories (Input, Read, Write, General), as shown in the following table. The ‘input events’ originate externally to the ZCL and are passed into the ZCL for processing (see Section 3.2). The remaining events are generated as part of this processing.
Note: Cluster-specific events are covered in the chapter for the relevant cluster.
Category |
Event |
---|---|
Input Events |
E_ZCL_ZIGBEE_EVENT |
E_ZCL_CBET_TIMER |
|
E_ZCL_CBET_TIMER_MS |
|
Read Events |
E_ZCL_CBET_READ_REQUEST |
E_ZCL_CBET_READ_INDIVIDUAL_ATTRIBUTE_RESPONSE |
|
E_ZCL_CBET_READ_ATTRIBUTES_RESPONSE |
|
Write Events |
E_ZCL_CBET_CHECK_ATTRIBUTE_RANGE |
E_ZCL_CBET_WRITE_INDIVIDUAL_ATTRIBUTE |
|
E_ZCL_CBET_WRITE_ATTRIBUTES |
|
E_ZCL_CBET_WRITE_INDIVIDUAL_ATTRIBUTE_RESPONSE |
|
E_ZCL_CBET_WRITE_ATTRIBUTES_RESPONSE |
|
General Events |
E_ZCL_CBET_LOCK_MUTEX |
E_ZCL_CBET_UNLOCK_MUTEX |
|
E_ZCL_CBET_DEFAULT_RESPONSE |
|
E_ZCL_CBET_UNHANDLED_EVENT |
|
E_ZCL_CBET_ERROR |
|
E_ZCL_CBET_CLUSTER_UPDATE |
The above events are described below.
Input Events
The ‘input events’ are generated externally to the ZCL. Such an event is received by the application, which wraps the event in a tsZCL_CallBackEvent
structure and passes it into the ZCL using the function vZCL_EventHandler() - for further details of event processing, refer to Section 3.2.
E_ZCL_ZIGBEE_EVENT
All ZigBee PRO stack events to be processed by the ZCL are designated as this type of event by setting the
eEventType
field in thetsZCL_CallBackEvent
structure to E_ZCL_ZIGBEE_EVENT.
E_ZCL_CBET_TIMER
A timer event (indicating that a timer has expired) which is to be processed by the ZCL is designated as this type of event by setting the
eEventType
field in thetsZCL_CallBackEvent
structure to E_ZCL_CBET_TIMER.
E_ZCL_CBET_TIMER_MS
A millisecond timer event (indicating that a timer has expired) which is to be processed by the ZCL is designated as this type of event by setting the
eEventType
field in thetsZCL_CallBackEvent
structure to E_ZCL_CBET_TIMER_MS.
Read Events
The ‘read events’ are generated as the result of a ‘read attributes’ request (see Section2.3.2). Some of these events are generated on the remote node and some of them are generated on the local (requesting) node, as indicated in the table below.
Generated on local node (client): |
Generated on remote node (server): |
---|---|
E_ZCL_CBET_READ_REQUEST |
|
E_ZCL_CBET_READ_INDIVIDUAL_ATTRIBUTE_RESPONSE |
|
E_ZCL_CBET_READ_ATTRIBUTES_RESPONSE |
The circumstances surrounding the generation of the ‘read events’ are outlined below:
E_ZCL_CBET_READ_REQUEST
When a ‘read attributes’ request has been received and passed to the ZCL (as a stack event), the ZCL generates the event E_ZCL_CBET_READ_REQUEST for the relevant endpoint to indicate that the endpoint’s shared device structure is going to be read. This gives an opportunity for the application to access the shared structure first, if required - for example, to update attribute values before they are read. This event may be ignored if the application reads the hardware asynchronously - for example, driven by a timer or interrupt.
E_ZCL_CBET_READ_INDIVIDUAL_ATTRIBUTE_RESPONSE
When a ‘read attributes’ response has been received by the requesting node and passed to the ZCL (as a stack event), the ZCL generates the event E_ZCL_CBET_READ_INDIVIDUAL_ATTRIBUTE_RESPONSE for each individual attribute in the response. Details of the attribute are incorporated in the structure
tsZCL_ReadIndividualAttributesResponse
, described in Section 6.2.Note that this event is often ignored by the application, while the event E_ZCL_CBET_READ_ATTRIBUTES_RESPONSE (see next event) is handled.
E_ZCL_CBET_READ_ATTRIBUTES_RESPONSE
When a ‘read attributes’ response has been received by the requesting node and the ZCL has completed updating the local copy of the shared device structure, the ZCL generates the event E_ZCL_CBET_READ_ATTRIBUTES_RESPONSE. The transaction sequence number and cluster instance fields of the
tsZCL_CallBackEvent
structure are used by this event.
Write Events
The ‘write events’ are generated as the result of a ‘write attributes’ request (see Section 2.3.3). Some of these events are generated on the remote node and some of them are generated on the local (requesting) node, as indicated in the table below.
Generated on local node (client): |
Generated on remote node (server): |
---|---|
E_ZCL_CBET_CHECK_ATTRIBUTE_RANGE |
|
E_ZCL_CBET_WRITE_INDIVIDUAL_ATTRIBUTE |
|
E_ZCL_CBET_WRITE_ATTRIBUTES |
|
E_ZCL_CBET_WRITE_INDIVIDUAL_ATTRIBUTE_RESPONSE |
|
E_ZCL_CBET_WRITE_ATTRIBUTES_RESPONSE |
During the process of receiving and processing a ‘write attributes’ request, the receiving application maintains a tsZCL_IndividualAttributesResponse
structure for each individual attribute in the request:
typedef struct PACK {
uint16 u16AttributeEnum;
teZCL_ZCLAttributeType eAttributeDataType;
teZCL_CommandStatus eAttributeStatus;
void *pvAttributeData;
tsZCL_AttributeStatus *psAttributeStatus;
} tsZCL_IndividualAttributesResponse;
The u16AttributeEnum
field identifies the attribute.
The field eAttributeDataType
is set to the ZCL data type of the attribute in the request, which is checked by the ZCL to ensure that the attribute type in the request matches the expected attribute type.
The above structure is fully detailed in Section 6.2.
The circumstances surrounding the generation of the ‘write events’ are outlined below:
E_ZCL_CBET_CHECK_ATTRIBUTE_RANGE
When a ‘write attributes’ request has been received and passed to the ZCL (as a stack event), for each attribute in the request the ZCL generates the event E_ZCL_CBET_CHECK_ATTRIBUTE_RANGE for the relevant endpoint. This indicates that a ‘write attributes’ request has arrived and gives an opportunity for the application to do either or both of the following:
Check that the attribute value to be written falls within the valid range (range checking is not performed in the ZCL because the range may depend on application-specific rules).
Decide whether the requested write access to the attribute in the shared structure is allowed or not allowed.
The value to be written is pointed to by
pvAttributeData
in the above structure (this does not point to the field of the shared structure containing this attribute, as the shared structure field still has its existing value).The attribute status field
eAttributeStatus
in the above structure is initially set to E_ZCL_SUCCESS. The application should set this field to E_ZCL_ERR_ATTRIBUTE_RANGE if the attribute value is out-of-range or to E_ZCL_DENY_ATTRIBUTE_ACCESS if it decides to disallow the write. Also note the following:If a conventional ‘write attributes’ request is received and an attribute value fails the range check or write access to an attribute is denied, this attribute is left unchanged in the shared structure but other attributes are updated.
If an ‘undivided write attributes’ request is received and any attribute fails the range check or write access to any attribute is denied, no attribute values are updated in the shared structure.
E_ZCL_CBET_WRITE_INDIVIDUAL_ATTRIBUTE
Following an attempt to write an attribute value to the shared structure, the ZCL generates the event E_ZCL_CBET_WRITE_INDIVIDUAL_ATTRIBUTE for the relevant endpoint. The field
eAttributeStatus
in the structuretsZCL_IndividualAttributesResponse
indicates to the application whether the attribute value was updated successfully:If the write is successful, this status field is left as E_ZCL_SUCCESS.
If the write is unsuccessful, this status field is set to a suitable error status (see Section 7.1.4).
E_ZCL_CBET_WRITE_ATTRIBUTES
Once all the attributes in a ‘write attributes’ request have been processed, the ZCL generates the event E_ZCL_CBET_WRITE_ATTRIBUTES for the relevant endpoint.
E_ZCL_CBET_WRITE_INDIVIDUAL_ATTRIBUTE_RESPONSE
The E_ZCL_CBET_WRITE_INDIVIDUAL_ATTRIBUTE_RESPONSE event is generated for each attribute that is listed in an incoming ‘write attributes’ response message. Only attributes that have failed to be written are contained in the message. The field
eAttributeStatus
of the structuretsZCL_IndividualAttributesResponse
indicates the reason for the failure (see Section 7.1.4).
E_ZCL_CBET_WRITE_ATTRIBUTES_RESPONSE
The E_ZCL_CBET_WRITE_ATTRIBUTES_RESPONSE event is generated when the parsing of an incoming ‘write attributes’ response message is complete. This event is particularly useful following a write where all the attributes have been written without errors since, in this case, no E_ZCL_CBET_WRITE_INDIVIDUAL_ATTRIBUTE_RESPONSE event is generated.
General Events
E_ZCL_CBET_LOCK_MUTEX and E_ZCL_CBET_UNLOCK_MUTEX
When an application task accesses the shared device structure of an endpoint, a mutex should be used by the task to protect the shared structure from conflicting accesses. Thus, the ZCL may need to lock or unlock a mutex in handling an event - for example, when a “read attributes” request has been received and passed to the ZCL (as a stack event). In these circumstances, the ZCL generates the following events:
E_ZCL_CBET_LOCK_MUTEX when a mutex is to be locked
E_ZCL_CBET_UNLOCK_MUTEX when a mutex is to be unlocked
The ZCL specifies one of the above events in invoking the callback function for the endpoint. Thus, the endpoint callback function must include the necessary code to lock and unlock a mutex - for further information, refer to Appendix A.
The locking and unlocking of a mutex are useful if the tasks in the application are non-cooperative while sharing the same resource. To optimize the code, the above events are not generated when the tasks are in a cooperative group. Tasks are cooperative by default and, if not required, this feature can be disabled in the zcl_options.h file (see Section 1.3).
E_ZCL_CBET_DEFAULT_RESPONSE
The E_ZCL_CBET_DEFAULT_RESPONSE event is generated when a ZCL default response message has been received. These messages indicate that either an error has occurred or a message has been processed. The payload of the default response message is contained in the structure
tsZCL_DefaultResponseMessage
below:
typedef struct PACK {
uint8 u8CommandId;
uint8 u8StatusCode;
} tsZCL_DefaultResponseMessage;
u8CommandId
is the ZCL command identifier of the command which triggered the default response message.u8StatusCode
is the status code from the default response message. It is set to 0x00 for OK or to an error code defined in the ZCL Specification.E_ZCL_CBET_UNHANDLED_EVENT and E_ZCL_CBET_ERROR
The E_ZCL_CBET_UNHANDLED_EVENT and E_ZCL_CBET_ERROR events indicate that a stack message has been received which cannot be handled by the ZCL. The
*pZPSevent
field of thetsZCL_CallBackEvent
structure points to the stack event that caused the event.E_ZCL_CBET_CLUSTER_UPDATE
The E_ZCL_CBET_CLUSTER_UPDATE event indicates that one or more attribute values for a cluster on the local device may have changed.
Note: ZCL error events and default responses (see Section 6.1.9) may be generated when problems occur in receiving commands. The possible ZCL status codes contained in the events and responses are detailed in Section 4.2.
Parent topic:Event Handling