14.2.3.5.4 Sending a Cluster-specific command

To send a cluster specific command the ZCL_CommandReq() function is used with the pointer to an instance of the ZCL_Request_t type as an argument that is used very similar as in ZCL_AttributeReq() function for general cluster commands described in Section Sending a General cluster command

Argument’s fields include command ID, source endpoint, destination addressing information, command payload and command payload’s length, pointers to a confirmation callback function, and a field configuring default response. These paremters are defined in ZCL_Request_t structure.

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

Command payload formatting

For cluster-specific commands the command’s payload is set to the pointer to 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 sizeof operator applied to this type.

The following example shows the usage of ZCL_CommandReq() API to send a 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 that for a cluster-specific command the application shall use the ZCL_GetNextSeqNumber() function to obtain ZCL sequence numbers set it to the sequenceNumber field in the dstAddressing structure of the argument of ZCL_CommandReq().