4.5.4 Sending a Cluster-specific Command

To send a cluster-specific command, use the ZCL_CommandReq() function and pass a pointer to an instance of the ZCL_Request_t type as an argument. This process is very similar to how the user can use the ZCL_AttributeReq() function for general cluster commands. For more details, refer to the Sending a General Cluster Command.

The following parameters are defined in the ZCL_Request_t structure. The fields of the argument include:
  • Command ID
  • Source endpoint
  • Destination addressing information
  • Command payload
  • Command payload’s length
  • Pointers to a confirmation callback function
  • A field configuring the default response

If a cluster-specific command requires a specific ZCL response command as per its specification in the cluster definition file, then the ZCL_Notify callback for the ZCL request is triggered only after such response command is received or until timeout for its reception expires. Immediately after such ZCL_Notify, the device calls the callback function for the ZCL response command as specified for supported cluster commands.

When a cluster-specific command requires a specific ZCL response command according to its specification in the cluster definition file, the system triggers the ZCL_Notify callback for the ZCL request only after receiving the required response command or when the timeout for its reception expires. Without any delay, following the ZCL_Notify, the system also calls the callback function for the ZCL response command as specified for supported cluster commands.

Command Payload Formatting

For cluster-specific commands, the command’s payload is set to the pointer of an instance of a special type defined for each command in the cluster header file. The payload length can be calculated with the help of the size of the operator applied to this type.

The following example demonstrates the usage of the ZCL_CommandReq() API to send an OTAU cluster-specific command:
ZCL_OtauImageBlockReq_t *tmpOtauReq = &zclReqMem.uImageBlockReq;
  ZCL_Request_t *tmpZclReq = &.zclCommandReq;

  // fill the ZCL_Request_t structure fields for outgoing request.
  tmpZclReq->dstAddressing.addrMode             = APS_SHORT_ADDRESS;

  tmpZclReq->dstAddressing.addr.shortAddress    = actvServer->serverShortAddress;
  tmpZclReq->dstAddressing.endpointId           = actvServer->serverEndpoint;

  tmpZclReq->dstAddressing.profileId            = zclOtauMem.initParam.profileId;
  tmpZclReq->dstAddressing.clusterId            = OTAU_CLUSTER_ID;
  tmpZclReq->dstAddressing.clusterSide          = ZCL_SERVER_CLUSTER_TYPE;
  tmpZclReq->dstAddressing.manufacturerSpecCode = 0;
  tmpZclReq->dstAddressing.sequenceNumber       = ZCL_GetNextSeqNumber();
  tmpZclReq->endpointId                         = zclOtauMem.initParam.otauEndpoint;
  tmpZclReq->id                                 = id;
  tmpZclReq->defaultResponse                    = ZCL_FRAME_CONTROL_ENABLE_DEFAULT_RESPONSE;
  tmpZclReq->requestLength                      = length;
  tmpZclReq->requestPayload                     = payload;
  tmpZclReq->responseWaitTimeout                = rspWaitTime;
  tmpZclReq->ZCL_Notify                         = otauSomeRequestConfirm;

  // fill the command structu/paremeters of the cluster command
  tmpOtauReq->controlField.blockRequestDelayPresent = 1;
  tmpOtauReq->controlField.reqNodeIeeeAddrPresent   = 0;
  tmpOtauReq->controlField.reserved                 = 0;
  tmpOtauReq->manufacturerId                        = csManufacturerId;
  tmpOtauReq->imageType                             = clientMem->downloadingImgType;
  memcpy(&tmpOtauReq->firmwareVersion,&clientMem->newFirmwareVersion,sizeof(ZCL_OtauFirmwareVersion_t));
  tmpOtauReq->fileOffset                            = clientMem->imageAuxParam.requestFileOffset;
  tmpOtauReq->maxDataSize                           = clientMem->imageAuxParam.requestBlockSize;
  tmpOtauReq->minimumBlockPeriod                    = otauClientAttributes.minimumBlockPeriod.value;

  ZCL_CommandReq(tmpZclReq);
Note: For a cluster-specific command, the application uses the ZCL_GetNextSeqNumber() function to obtain the ZCL sequence numbers to set to the sequenceNumber field in the destination addressing structure of the argument of the ZCL_CommandReq().