4.5.2 Read or Write a Remote Attribute

To read or write an attribute on a remote device, use the ZCL_AttributeReq() function. A single request can access values of several attributes from the same cluster.

The argument is of ZCL_Request_t* type.
  • To read the attribute’s value - Set the ID field of the argument to ZCL_READ_ATTRIBUTES_COMMAND_ID
  • To write the attribute’s value – Set the ID field of the argument to ZCL_WRITE_ATTRIBUTES_COMMAND_ID
The user can fill the requestPayload and requestLength fields of the ZCL_Request_t instance as described in following sections.

Payload for Read Attributes Command

To form the payload for the read attributes command, use the ZCL_PutNextElement() function. This function attribute allows the user to write the attribute IDs to the buffer one by one correctly and calculates the overall payload length. The user can, then, use the buffer as the payload for the read attribute command. The following the are the instructions:

  1. Define variables of ZCL_NextElement_t and ZCL_ReadAttributeReq_t types. For example:
    ZCL_NextElement_t element;
    ZCL_ReadAttributeReq_t readAttrReqElement;
  2. Define a sufficiently large buffer. The user must define the buffer globally and can be a variable of the uint8_t* type.
    Note: It must only include attribute IDs
  3. The user can configure element in the following way:
    element.payloadLength = 0;
    element.payload = buffer;
    element.id = ZCL_READ_ATTRIBUTES_COMMAND_ID;
    element.content = &readAttrReqElement;
    Note: Assume that the application defines the buffer variable elsewhere to use as the buffer.
  4. The user must repeat the following steps for each requested attribute:
    1. Set the readAttrReqElement.id to the target attributes identifier.
    2. Call the ZCL_PutNextElement()(&element).
  5. Set the requestLength field of the ZCL_Request_t instance to element.payloadLength.
  6. Set the requestPayload field of the ZCL_Request_t instance in the request to buffer.

Payload for Write Attributes Command

Forming the payload for a write attributes command involves nearly the same steps as those for the read attributes command:

  1. Define a variable of the ZCL_NextElement_t type and a request element. Which can be of the ZCL_WriteAttributeReq_t type. For example:
    ZCL_NextElement_t element;
    ZCL_WriteAttributeReq_t writeAttrReqElement;
    To set the type field of the ZCL_WriteAttributeReq_t instance, the user must assign it to the constant that specifies the attribute’s data type, such as ZCL_U64BIT_DATA_TYPE_ID. The ZCL specification determines the data type for each attribute, and the user must ensure that it matches the data type assigned to the attribute on the destination devices. The user must also write the attribute’s value to the value field. However, this field is actually of the uint8_t[1] type. The user can assign a 1-byte value to value[0], but the user cannot directly write values that occupy more than one byte in memory. To work around this, the user can allocate a sufficiently long buffer and cast it to the ZCL_WriteAttributeReq_t type. As an alternative, the user can define a custom structure that includes subsequent ID, type and value fields, with the value field being the actual size of the attribute.
    • For instance, for a 64-bit unsigned type, the user can define the structure in the following way:
      typedef struct PACK
      {
       ZCL_AttributeId_t id;
       uint8_t type;
       uint64_t value;
      } APP_Write64BitAttributeReq_t;
    • For instance, for a 64-bit unsigned type, the user can define the request element in the following way:
      APP_Write64BitAttributeReq_t writeAttrReqElement;
  2. The uset can configure the element in the following way:
    element.payloadLength = 0;
    element.payload = buffer;
    element.id = ZCL_WRITE_ATTRIBUTES_COMMAND_ID;
    element.content = &writeAttrReqElement;
    Note: Assume that the application defines the buffer variable elsewhere to use as the buffer.
  3. For each requested attribute, repeat the following steps:
    1. Set writeAttrReqElement.id to the target attribute’s ID.
    2. Write the attribute’s value to the writeAttrReqElement.value field. For a ZCL_WriteAttributeReq_t instance, cast this field to a pointer to the attribute’s data type and de-reference it. For example:
      *(uint64_t*)writeAttrReqElement->value = VALUE;
    3. Call ZCL_PutNextElement()(&element) and check the returned value. The function returns ZCL_END_PAYLOAD_REACHED_STATUS after the last element that fits into the payload is written.
  4. Set the requestLength field of the ZCL_Request_t instance to element.payloadLength.
  5. Set the requestPayload field of the ZCL_Request_t instance in the request to buffer.