Zigbee cluster read multiple attribute values

I am using custom clusters on ZED that report attributes. I am able to read these values from the CLI on my coordinator. 

I have modified the CLI (zigbee_cli_cmd_attr.c)  to read attributes scheduled by a timer and setting all the parameters of the read macros to read the attributes on the clusters. The CLI no longer parses any commands. 

Issue:

I am able to read these values via the method below, however I am limited to 10 attribute reads before the buffer has no more attributes to read. I would get a "Value type 0x%x unsupported" message for the default switch case of . zcl_attr_to_str() when requesting more than 10 attributes.

when requesting ~>13, results in a hard fault:

E7FE b 0x0000035E <HardFault_Handler>
--- ses_startup_nrf52840.s -- 73 ---------------------------
.thumb_func
.weak MemoryManagement_Handler
MemoryManagement_Handler:
b .

Most of the attributes are type U32. There is some type bool and s32 as well. I have tried briefly changing the types to see if that has any effect, and I have not noticed anything different. 

Method of attribute reading: 

I am using ZB_ZCL_GENERAL_INIT_READ_ATTR_REQ, 

looping : ZB_ZCL_GENERAL_ADD_ID_READ_ATTR_REQ for all the attributes to report, and ending with

ZB_ZCL_GENERAL_SEND_READ_ATTR_REQ.

then using a loop as before for each attribute to report, containing:

 ZB_ZCL_GENERAL_GET_NEXT_READ_ATTR_RES with zcl_attr_to_str(); to convert data to a string. zcl_attr_to_str() uses a 2d character array to store the attributes. I was not able to reuse this as a 1D array in a loop and reuse the buffer. 

#define max_buffers (20) //this should be index for each attribute
#define max_buffer_len (40) //this should be the character array for each attribute.

char attr_buffers [max_buffers][max_buffer_len];

and then just reading it out for now : NRF_LOG_INFO("attribute %d: %s",i,attr_buffers[i]);

Thanks,

Anderw

  • Hi,

    Can you provide your modified application, for us to have a look at the code and being able to reproduce the issue?

    Can you include the HardFault handling library in your application, to see the source of the hardfault?

    Best regards,
    Jørgen

  • /**
     * Copyright (c) 2018 - 2022, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    #include "nrf_cli.h"
    #include "zboss_api.h"
    #include "zb_error_handler.h"
    #include "zigbee_cli.h"
    #include "zigbee_cli_utils.h"
    #include "zigbee_helpers.h"
    
    #include "globals.h"
    //#include "nrf_delay.h"
    
    
    /**
     * @defgroup zb_cli_cmd_zcl ZCL commands
     * @ingroup zb_cli
     *
     * @{
     */
    
    //#define ATTRIBUTE_TABLE_SIZE     40
    //#define ATTRIBUTE_ROW_TIMEOUT_S  20
    
    //typedef enum attr_type_e
    //{
    //    ATTR_READ_REQUEST,
    //    ATTR_WRITE_REQUEST
    //} attr_req_type_t;
    
    int number_of_attrs_to_report = 0;
    int starting_attr = 0;
    
    
    /**@brief The row of the table which holds the requests which were sent.
     *
     * @details We compare the incoming responses with the rows contents to determine
     *          if it is the answer. The structure corresponds to both read and write
     *          requests.
     *          The key parameter is the sequence number.
     */
    //typedef struct attr_query_s
    //{
    //    zb_bool_t                  taken;
    //    zb_uint8_t                 seq_num;
    //    attr_req_type_t            req_type;
    //    zb_addr_u                  remote_node;
    //    zb_uint8_t                 remote_addr_mode;
    //    zb_uint8_t                 remote_ep;
    //    zb_uint16_t                profile_id;
    //    zb_uint16_t                cluster_id;
    //    zb_uint16_t                attr_id;
    //    zb_uint8_t                 attr_type;
    //    zb_uint8_t                 attr_value[32];
    //    zb_zcl_frame_direction_t   direction;
    //    nrf_cli_t                * p_cli;
    //} attr_query_t;
    
    //static attr_query_t m_attr_table[ATTRIBUTE_TABLE_SIZE];
    
    
    
    
    
    /**@brief Get the first free row in the attributes table, return -1 if none
     */
    //static zb_int8_t get_free_row_attr_table()
    //{
    //    int i;
    //    for (i = 0; i < ATTRIBUTE_TABLE_SIZE; i++)
    //    {
    //        if (m_attr_table[i].taken == ZB_FALSE)
    //        {
    //            return i;
    //        }
    //    }
    //    return -1;
    //}
    
    /**@brief Get the taken row with the selected seq_num, return -1 if none
     * @param sernum Sequence Number to look for
     */
    //static zb_int8_t get_attr_table_row_by_sn(zb_uint8_t sernum)
    //{
    //    int i;
    //    for (i = 0; i < ATTRIBUTE_TABLE_SIZE; i++)
    //    {
    //        if (m_attr_table[i].taken == ZB_TRUE)
    //        {
    //            if (m_attr_table[i].seq_num == sernum)
    //            {
    //                return i;
    //            }
    //        }
    //    }
    //    return -1;
    //}
    
    /**@brief Invalidate row after the timeout.
     *
     * @param row     Number of row to invalidate
     */
    //static void invalidate_row(zb_uint8_t row)
    //{
    //    if (row < ATTRIBUTE_TABLE_SIZE)
    //    {
    //        ZB_MEMSET(&(m_attr_table[row]), 0x00, sizeof(attr_query_t));
    //    }
    //}
    
    ///**@brief Invalidate row after the timeout - ZBOSS callback
    // *
    // * @param row     Number of row to invalidate
    // */
    //static void invalidate_row_cb(zb_uint8_t row)
    //{
    //    print_error(m_attr_table[row].p_cli, "Request timed out", ZB_TRUE);
    //    invalidate_row(row);
    //}
    
    static void frame_acked_cb(zb_bufid_t bufid)
    {
        if (bufid)
        {
            zb_buf_free(bufid);
        }
    }
    
    /**@brief Check if the frame we received is the response to our request in the table
     *
     * @param p_hdr  Pointer to the parsed header of the frame
     * @param p_row  Pointer to the row in the table to check against
     *
     * @return Whether it is response or not
     */
    //static zb_bool_t is_response(zb_zcl_parsed_hdr_t * p_hdr, attr_query_t * p_row)
    //{
    //    zb_uint16_t remote_node_short = 0;
    //    if (p_row->remote_addr_mode == ZB_APS_ADDR_MODE_64_ENDP_PRESENT)
    //    {
    //        remote_node_short = zb_address_short_by_ieee(p_row->remote_node.addr_long);
    //    }
    //    else
    //    {
    //        remote_node_short = p_row->remote_node.addr_short;
    //    }
    
    //    if (p_hdr->cluster_id != p_row->cluster_id)
    //    {
    //        return ZB_FALSE;
    //    }
    
    //    if (p_hdr->profile_id != p_row->profile_id)
    //    {
    //        return ZB_FALSE;
    //    }
    
    //    if (p_hdr->addr_data.common_data.src_endpoint != p_row->remote_ep)
    //    {
    //        return ZB_FALSE;
    //    }
    
    //    if (p_hdr->addr_data.common_data.source.addr_type == ZB_ZCL_ADDR_TYPE_SHORT)
    //    {
    //        if (p_hdr->addr_data.common_data.source.u.short_addr != remote_node_short)
    //        {
    //            return ZB_FALSE;
    //        }
    //    }
    //    else
    //    {
    //        return ZB_FALSE;
    //    }
    
    //    if (p_hdr->cmd_id != ZB_ZCL_CMD_DEFAULT_RESP &&
    //        p_hdr->cmd_id != ZB_ZCL_CMD_READ_ATTRIB_RESP &&
    //        p_hdr->cmd_id != ZB_ZCL_CMD_WRITE_ATTRIB_RESP)
    //    {
    //        return ZB_FALSE;
    //    }
    
    //    return ZB_TRUE;
    //}
    
    
    
    /**@brief Print the Read Attribute Response
     *
     * @param bufid     Zigbee buffer ID with Read Attribute Response packet.
     */
    #define max_buffers (20)
    #define max_buffer_len 40
    
    static void print_read_attr_resp (zb_bufid_t bufid)
    {
    NRF_LOG_INFO("Device report:%x = (%d)",dev_long_addr_g[dev_active],dev_active);
        zb_zcl_read_attr_res_t * p_attr_resp;
    
    for (int i = starting_attr; i < (number_of_attrs_to_report + starting_attr); i++){
        ZB_ZCL_GENERAL_GET_NEXT_READ_ATTR_RES(bufid, p_attr_resp);
          if (p_attr_resp->status == ZB_ZCL_STATUS_SUCCESS){
            char attr_buffers [max_buffers][max_buffer_len];
             zcl_attr_to_str(attr_buffers[i], sizeof(attr_buffers[i]), p_attr_resp->attr_type, p_attr_resp->attr_value);
             NRF_LOG_INFO("attribute %d: %s",i,attr_buffers[i]);
             
          }
          else{
          NRF_LOG_INFO(">>issue with reporting on attribute %d",i)
          }
        
        }
    }
    
    /**@brief Print the Write Attribute Response
     *
     * @param bufid     Zigbee buffer ID with Write Attribute Response packet.
     * @param p_row     Pointer to a row in attr table
     */
    //static void print_write_attr_response(zb_bufid_t bufid, attr_query_t * p_row)
    //{
    //    zb_zcl_write_attr_res_t * p_attr_resp;
    //    /* Get the contents of Write Attribute Response frame */
    //    ZB_ZCL_GET_NEXT_WRITE_ATTR_RES(bufid, p_attr_resp);
    
    //    if (!p_attr_resp)
    //    {
    //        print_error(p_row->p_cli, "No attribute could be retrieved", ZB_TRUE);
    //        return;
    //    }
    
    //    if (p_attr_resp->status != ZB_ZCL_STATUS_SUCCESS)
    //    {
    //        nrf_cli_fprintf(p_row->p_cli, NRF_CLI_NORMAL, "\r\nError: Status %d\r\n",
    //                        p_attr_resp->status);
    //        return;
    //    }
    
    //    print_done(p_row->p_cli, ZB_FALSE);
    //}
    
    /**@brief The Handler to 'intercept' every frame coming to the endpoint
     *
     * @param bufid    ZBOSS buffer id.
     */
    //static zb_uint8_t cli_agent_ep_handler_attr_orginal(zb_bufid_t bufid)
    //{
    //    zb_zcl_parsed_hdr_t * p_cmd_info = ZB_BUF_GET_PARAM(bufid, zb_zcl_parsed_hdr_t);
    //    zb_int8_t row;
    
    //    /* Get the row in the requests table according by the sequence number */
    //    row = get_attr_table_row_by_sn(p_cmd_info->seq_number);
    //    if (row == -1)
    //    {
    //        return ZB_FALSE;
    //    }
    
    //    attr_query_t * p_row = &(m_attr_table[row]);
    //    if (!is_response(p_cmd_info, p_row))
    //    {
    //        return ZB_FALSE;
    //    }
    
    //    if (p_cmd_info->cmd_id == ZB_ZCL_CMD_DEFAULT_RESP)
    //    {
    //        zb_zcl_default_resp_payload_t * p_def_resp;
    //        p_def_resp = ZB_ZCL_READ_DEFAULT_RESP(bufid);
    //        nrf_cli_fprintf(p_row->p_cli, NRF_CLI_ERROR, "\r\nError: Default Response received; ");
    //        nrf_cli_fprintf(p_row->p_cli, NRF_CLI_ERROR, "Command: %d, Status: %d ",
    //                        p_def_resp->command_id, p_def_resp->status);
    //    }
    //    else
    //    {
    //        if (p_row->req_type == ATTR_READ_REQUEST)
    //        {
    //            print_read_attr_resp(bufid);
    //        }
    //        else
    //        {
    //            print_write_attr_response(bufid, p_row);
    //        }
    //    }
    //    /* Cancel the ongoing alarm which was to erase the row... */
    //    UNUSED_RETURN_VALUE(ZB_SCHEDULE_APP_ALARM_CANCEL(invalidate_row_cb, row));
    //    /* ...and erase it manually */
    //    invalidate_row(row);
    
    //    zb_buf_free(bufid);
    //    return ZB_TRUE;
    //}
    
    static zb_uint8_t cli_agent_ep_handler_attr(zb_bufid_t bufid)
    {
        print_read_attr_resp(bufid);
        //zb_buf_free(bufid);
        return ZB_TRUE;
    }
    
    
    union zb_addr_u_t dev_addr;
    
    struct{
      int attr_id;
      int profile_id;
      int cluster_id;
      int send_ep;
      int dest_ep;
      int address_mode;
      zb_uint64_t long_addr;
    }redir;
    
    void readattr_send(zb_bufid_t bufid,zb_uint8_t attr_start)
    {
    number_of_attrs_to_report = 11;
    
    starting_attr = 0;
      redir.attr_id = attr_start; // starting attr to report. The loop counts from here
      redir.profile_id = 260;
      redir.cluster_id = 0x0413;
      redir.send_ep = 64;
      redir.dest_ep = 10;
      redir.address_mode = 3;
    
      redir.long_addr = dev_long_addr_g [dev_active];
      zb_uint8_t * p_cmd_buf;
    
      zb_uint8_t *p = (uint8_t *)&redir.long_addr;
      zb_uint8_t long_addr_array[8];
    
      for(int i = 0; i < 8; i++) {//this code satisfies the union for addressing used in ZB_ZCL_GENERAL_SEND_READ_ATTR_REQ (3rd parameter). I am only using the long address. I am changing the 64bit address into an unit8_t array[8]
        long_addr_array[i] = p[i];
        }
        for(int i = 0; i<8;i++){dev_addr.addr_long[i] = long_addr_array [i];}
    
      if (dev_comm_flag == true){// flag to check if there is atleaset 1 ep connected
        ZB_ZCL_GENERAL_INIT_READ_ATTR_REQ(bufid, p_cmd_buf, ZB_ZCL_ENABLE_DEFAULT_RESPONSE); //init the read
        for (redir.attr_id; redir.attr_id < (number_of_attrs_to_report + starting_attr); redir.attr_id++){
          ZB_ZCL_GENERAL_ADD_ID_READ_ATTR_REQ(p_cmd_buf, redir.attr_id); //loop for all the zigbee clusters to report
          }
    
        ZB_ZCL_GENERAL_SEND_READ_ATTR_REQ(bufid, p_cmd_buf, dev_addr, redir.address_mode, redir.dest_ep, redir.send_ep, redir.profile_id, redir.cluster_id, frame_acked_cb);//send the read 
        NRF_LOG_INFO("\nstarting attr: %d \nnumber of requested attr ids :%d",starting_attr,number_of_attrs_to_report);
    
            
      } else {
      NRF_LOG_INFO("device offline");
      }
    }
    
    
    //static void writeattr_send(zb_bufid_t bufid, zb_uint16_t cb_param)
    //{
    //    zb_ret_t zb_err_code;
    //    zb_uint8_t row = cb_param;
    //    zb_uint8_t * p_cmd_buf;
    //    attr_query_t * p_row = &(m_attr_table[row]);
    //    p_row->seq_num = ZCL_CTX().seq_number;
    
    //    zb_err_code = ZB_SCHEDULE_APP_ALARM(invalidate_row_cb, row,
    //                                        ATTRIBUTE_ROW_TIMEOUT_S * ZB_TIME_ONE_SECOND);
    //    if (zb_err_code != RET_OK)
    //    {
    //        print_error(p_row->p_cli, "No frame left - wait a bit", ZB_FALSE);
    //        /* Invalidate row so that we can reuse it */
    //        invalidate_row(row);
    //        zb_buf_free(bufid);
    //        return;
    //    }
    
    //    ZB_ZCL_GENERAL_INIT_WRITE_ATTR_REQ_A(bufid, p_cmd_buf, p_row->direction, ZB_ZCL_ENABLE_DEFAULT_RESPONSE);
    //    ZB_ZCL_GENERAL_ADD_VALUE_WRITE_ATTR_REQ(p_cmd_buf, p_row->attr_id, p_row->attr_type,
    //                                            p_row->attr_value);
    //    ZB_ZCL_GENERAL_SEND_WRITE_ATTR_REQ(bufid, p_cmd_buf, p_row->remote_node,
    //                                       p_row->remote_addr_mode, p_row->remote_ep,
    //                                       zb_get_cli_endpoint(), p_row->profile_id,
    //                                       p_row->cluster_id, frame_acked_cb);
    //}
    
    /**@brief Retrieve the attribute value of the remote node.
     *
     * @code
     * zcl attr read <h:dst_addr> <d:ep> <h:cluster> [-c] <h:profile> <h:attr_id>
     * @endcode
     *
     * Read the value of the attribute `attr_id` in the cluster `cluster`.
     * The cluster belongs to the profile `profile`, which resides on the endpoint
     * `ep` of the remote node `dst_addr`. If the attribute is on the client role
     * side of the cluster, use the `-c` switch.
     */
    //void cmd_zb_readattr_original(nrf_cli_t const * p_cli, size_t argc, char **argv)
    //{
    //    zb_ret_t zb_err_code;
    //    zb_int8_t row = get_free_row_attr_table();
    
    //    if (nrf_cli_help_requested(p_cli))
    //    {
    //        nrf_cli_help_print(p_cli, NULL, 0);
    //        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "  h: is for hex, d: is for decimal, -c switches the server-to-client direction\r\n");
    //        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "  readattr <h:dst_addr> <d:ep> <h:cluster> [-c] ");
    //        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "<h:profile> <h:attr ID>\r\n");
    //        return;
    //    }
    
    //    bool is_direction_present = ((argc == 7) && !strcmp(argv[4], "-c"));
    
    //    if (argc != 6 && !is_direction_present)
    //    {
    //        print_error(p_cli, "Wrong number of arguments", ZB_FALSE);
    //        return;
    //    }
    
    //    if (row == -1)
    //    {
    //        print_error(p_cli, "Request pool empty - wait a bit", ZB_FALSE);
    //        return;
    //    }
    
    //    attr_query_t * p_row = &(m_attr_table[row]);
    
    //    p_row->remote_addr_mode = parse_address(*(++argv), &(p_row->remote_node), ADDR_ANY);
    //    if (p_row->remote_addr_mode == ADDR_INVALID)
    //    {
    //        print_error(p_cli, "Invalid address", ZB_FALSE);
    //        return;
    //    }
    
    //    UNUSED_RETURN_VALUE(sscan_uint8(*(++argv), &(p_row->remote_ep)));
    
    //    if (!parse_hex_u16(*(++argv), &(p_row->cluster_id)))
    //    {
    //        print_error(p_cli, "Invalid cluster id", ZB_FALSE);
    //        return;
    //    }
    
    //    if (is_direction_present)
    //    {
    //        p_row->direction = ZB_ZCL_FRAME_DIRECTION_TO_CLI;
    //        ++argv;
    //    }
    //    else
    //    {
    //        p_row->direction = ZB_ZCL_FRAME_DIRECTION_TO_SRV;
    //    }
    
    //    if (!parse_hex_u16(*(++argv), &(p_row->profile_id)))
    //    {
    //        print_error(p_cli, "Invalid profile id", ZB_FALSE);
    //        return;
    //    }
    
    //    if (!parse_hex_u16(*(++argv), &(p_row->attr_id)))
    //    {
    //        print_error(p_cli, "Invalid attribute id", ZB_FALSE);
    //        return;
    //    }
    
    //    p_row->req_type = ATTR_READ_REQUEST;
    //    p_row->taken = ZB_TRUE;
    //    /* Put the CLI instance to be used later */
    //    p_row->p_cli = (nrf_cli_t*)p_cli;
    
    //    //zb_err_code = zb_buf_get_out_delayed(readattr_send);
    //    //zb_err_code = zb_buf_get_out_delayed_ext(readattr_send, 0, 0);
    //    if (zb_err_code != RET_OK)
    //    {
    //        print_error(p_cli, "No frame left - wait a bit", ZB_FALSE);
    //        /* Invalidate row so that we can reuse it */
    //        invalidate_row(row);
    //    }
    //}
    
    //void cmd_zb_readattr(nrf_cli_t const * p_cli, size_t argc, char **argv)
    //{
    //    zb_ret_t zb_err_code;
    
    //    //zb_err_code = zb_buf_get_out_delayed(readattr_send);
    //    if (zb_err_code != RET_OK)
    //    {
    //        print_error(p_cli, "No frame left - wait a bit", ZB_FALSE);
    //    }
    //}
    
    /**@brief Write the attribute value to the remote node.
     *
     * @code
     * zcl attr write <h:dst_addr> <d:ep> <h:cluster> <h:profile> <h:attr_id> <h:attr_type> <h:attr_value>
     * @endcode
     *
     * Write the `attr_value` value of the attribute `attr_id` of the type
     * `attr_type` in the cluster `cluster`. The cluster belongs to the profile
     * `profile`, which resides on the endpoint `ep` of the remote node `dst_addr`.
     *
     * @note The `attr_value` value must be in hexadecimal format, unless it is a
     * string (`attr_type == 42`), then it must be a string.
     *
     */
    //void cmd_zb_writeattr(nrf_cli_t const * p_cli, size_t argc, char **argv)
    //{
    //    zb_ret_t zb_err_code;
    //    zb_int8_t row = get_free_row_attr_table();
    
    //    if (nrf_cli_help_requested(p_cli))
    //    {
    //        nrf_cli_help_print(p_cli, NULL, 0);
    //        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "  h: is for hex, d: is for decimal, -c switches the server-to-client direction\r\n");
    //        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "  writeattr <h:dst_addr> <d:ep> <h:cluster> [-c] ");
    //        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "<h:profile> <h:attr ID> <h:attr type> ");
    //        nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "<h:attr value>\r\n");
    //        return;
    //    }
    
    //    bool is_direction_present = ((argc == 9) && !strcmp(argv[4], "-c"));
    
    //    if (argc != 8 && !is_direction_present)
    //    {
    //        print_error(p_cli, "Wrong number of arguments", ZB_FALSE);
    //        return;
    //    }
    
    //    if (row == -1)
    //    {
    //        print_error(p_cli, "Request pool empty - wait a bit", ZB_FALSE);
    //        return;
    //    }
    
    //    attr_query_t * p_row = &(m_attr_table[row]);
    
    //    p_row->remote_addr_mode = parse_address(*(++argv), &(p_row->remote_node), ADDR_ANY);
    //    if (p_row->remote_addr_mode == ADDR_INVALID)
    //    {
    //        print_error(p_cli, "Invalid address", ZB_FALSE);
    //        return;
    //    }
    
    //    UNUSED_RETURN_VALUE(sscan_uint8(*(++argv), &(p_row->remote_ep)));
    
    //    if (!parse_hex_u16(*(++argv), &(p_row->cluster_id)))
    //    {
    //        print_error(p_cli, "Invalid cluster id", ZB_FALSE);
    //        return;
    //    }
    
    //    if (is_direction_present)
    //    {
    //        p_row->direction = ZB_ZCL_FRAME_DIRECTION_TO_CLI;
    //        ++argv;
    //    }
    //    else
    //    {
    //        p_row->direction = ZB_ZCL_FRAME_DIRECTION_TO_SRV;
    //    }
    
    //    if (!parse_hex_u16(*(++argv), &(p_row->profile_id)))
    //    {
    //        print_error(p_cli, "Invalid profile id", ZB_FALSE);
    //        return;
    //    }
    
    //    if (!parse_hex_u16(*(++argv), &(p_row->attr_id)))
    //    {
    //        print_error(p_cli, "Invalid attribute id", ZB_FALSE);
    //        return;
    //    }
    
    //    if (!parse_hex_u8(*(++argv), &(p_row->attr_type)))
    //    {
    //        print_error(p_cli, "Invalid attribute type", ZB_FALSE);
    //        return;
    //    }
    
    //    uint8_t len = strlen(*(++argv));
    //    if (p_row->attr_type == ZB_ZCL_ATTR_TYPE_CHAR_STRING)
    //    {
    //        p_row->attr_value[0] = len;
    //        strncpy((zb_char_t*)(p_row->attr_value + 1), *argv, sizeof(p_row->attr_value) - 1);
    //    }
    //    else if (!parse_hex_str(*argv, len, p_row->attr_value, sizeof(p_row->attr_value), true))
    //    {
    //        print_error(p_cli, "Invalid attribute value", ZB_FALSE);
    //        return;
    //    }
    
    //    p_row->req_type = ATTR_WRITE_REQUEST;
    //    p_row->taken = ZB_TRUE;
    //    /* Put the CLI instance to be used later */
    //    p_row->p_cli = (nrf_cli_t*)p_cli;
    
    //    zb_err_code = zb_buf_get_out_delayed_ext(writeattr_send, row, 0);
    //    if (zb_err_code != RET_OK)
    //    {
    //        print_error(p_cli, "No frame left - wait a bit", ZB_FALSE);
    //        /* Invalidate row so that we can reuse it */
    //        invalidate_row(row);
    //    }
    //}
    
    
    
    
    
    /**@brief Endpoint handlers
     */
    NRF_ZIGBEE_EP_HANDLER_REGISTER(attr, cli_agent_ep_handler_attr);
    
    /** @} */
    

    attached is the modified zigbee_cli_cmd_attr.c

    I am calling readattr_send from main.c using: 

    zb_buf_get_out_delayed_ext(readattr_send,0,0);

    from a 5 second repeated timer

    this is the linker configuration:

    FLASH_PH_START=0x0
    FLASH_PH_SIZE=0x100000
    RAM_PH_START=0x20000000
    RAM_PH_SIZE=0x40000
    FLASH_START=0x0
    FLASH_SIZE=0x100000
    RAM_START=0x20000000
    RAM_SIZE=0x40000

    the nrf chip is NRF52840

    changing the U32 to U8 on the ZED allowed for more than 10 attributes. I am thinking this might be a memory buffer issue.

    this is my log from terminal:

    Types from ZED

    attr 0: u32

    attr 1: BOOL

    attr 2: BOOL

    attr 3: S32

    attr 4: u32

    attr 5: u32

    attr 6: u32

    attr 7: u32

    attr 8: u32

    attr 9: u32

    attr 10: u32

    attr 11: u32

    attr 12: u32

    Let me know if you need more information.

    -Andrew

  • Hi,

    Did you manage to resolve this issue, or do you still need assistance from us?

    Best regards,
    Jørgen

  • This is not resolved. I have changed my data types, and it was able to have more attributes. This works for most clusters I need, but it is still limited to some memory allocation limit.

Related