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

Parents Reply Children
  • /**
     * 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