This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Unable to configure attribute reporting on custom cluster

Greetings.

I am trying to implement a custom cluster with attribute reporting, however, for some reason, i am unable to start reporting of such attributes.


I have started by copying the Template sample and modifying it in the following ways:

  1. Created the following header files in a new folder (/inc): zb_zcl_shake_tracker.h and zb_ha_shaker.h , the former being my custom cluster and the latter my custom endpoint.
    The custom cluster has been defined following the guide for declaring custom cluster and using the Basic cluster as a guideline, whereas the custom endpoint was made by using the Template sample's Range Extender endpoint as a guideline
  2. Created zb_zcl_shake_tracker.c in /src as the Basic cluster i used as a guide for the custom cluster had two functions declared (init_server and init_client), in my .c file. These functions are defined but do nothing at all as i wasn't sure whether or not such functions were of any use in this case.
  3. Modified the main.c to add my custom cluster attributes to the device context structure, declare the attribute list, declare the cluster list of my custom endpoint, declare my custom endpoint and custom device context and finally add a infinite loop to toggle one of my custom attributes once every 2 seconds for testing purposes.
  4. Modified the CMakeList appropriately

Building the application didn't cause any issue and flashing the firmware on a testing board showed that it was working perfectly, with another board running the Shell sample in a coordinator role successfully allowing me to read the attribute via zcl attr read, using the zdo bind on command also returned without error, however, using the subscribe on command returned me with an error message: Error: Unable to configure attribute 1 reporting. Status: 1 
Trying the same with the On/Off attribute of the On/Off cluster of the Light Bulb sample however returned no such error and the reporting was working appropriately.

At this point i still do not understand what i am doing wrong or how can i fix this, especially as other seem to have had success in implementing their custom clusters with attribute reporting.

Follows the source code of the various files:

main.c

/*
 * Copyright (c) 2021 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
 */

/** @file
 *
 * @brief Zigbee application template.
 */

#include <zephyr.h>
#include <logging/log.h>
#include <dk_buttons_and_leds.h>
#include <device.h>
#include <drivers/sensor.h>
#include <zboss_api.h>
#include <zigbee/zigbee_error_handler.h>
#include <zigbee/zigbee_app_utils.h>
#include <zb_nrf_platform.h>
#include <zb_zcl_shake_tracker.h>
#include <zb_ha_shaker.h>

/* Device endpoint, used to receive ZCL commands. */
#define APP_TEMPLATE_ENDPOINT               10

/* Type of power sources available for the device.
 * For possible values see section 3.2.2.2.8 of ZCL specification.
 */
#define TEMPLATE_INIT_BASIC_POWER_SOURCE    ZB_ZCL_BASIC_POWER_SOURCE_DC_SOURCE

/* LED indicating that device successfully joined Zigbee network. */
#define ZIGBEE_NETWORK_STATE_LED            DK_LED3

/* LED used for device identification. */
#define IDENTIFY_LED                        DK_LED4

/* Button used to enter the Identify mode. */
#define IDENTIFY_MODE_BUTTON                DK_BTN4_MSK


LOG_MODULE_REGISTER(app, LOG_LEVEL_INF);

/* Main application customizable context.
 * Stores all settings and static values.
 */
struct zb_device_ctx {
	zb_zcl_basic_attrs_t     basic_attr;
	zb_zcl_identify_attrs_t  identify_attr;
    zb_zcl_shake_tracker_attrs_t  shake_attr;
};

/* Zigbee device application context storage. */
static struct zb_device_ctx dev_ctx;

ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST(
	identify_attr_list,
	&dev_ctx.identify_attr.identify_time);

ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST(
	basic_attr_list,
	&dev_ctx.basic_attr.zcl_version,
	&dev_ctx.basic_attr.power_source);

ZB_ZCL_DECLARE_SHAKE_TRACKER_ATTRIB_LIST(
        shake_attribute_list,
        &dev_ctx.shake_attr.data,
        &dev_ctx.shake_attr.is_shaked);

ZB_HA_DECLARE_SHAKER_CLUSTER_LIST(
        app_template_clusters,
        basic_attr_list,
        identify_attr_list,
        shake_attribute_list);

ZB_HA_DECLARE_SHAKER_EP(
        app_template_ep,
        APP_TEMPLATE_ENDPOINT,
        app_template_clusters);

ZB_HA_DECLARE_SHAKER_CTX(
        app_template_ctx,
    app_template_ep);



/**@brief Function for initializing all clusters attributes. */
static void app_clusters_attr_init(void)
{
	/* Basic cluster attributes data */
	dev_ctx.basic_attr.zcl_version = ZB_ZCL_VERSION;
	dev_ctx.basic_attr.power_source = TEMPLATE_INIT_BASIC_POWER_SOURCE;

	/* Identify cluster attributes data. */
	dev_ctx.identify_attr.identify_time =
		ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE;

    /*Shake cluster attributes data*/

    ZB_ZCL_SET_STRING_VAL(dev_ctx.shake_attr.data, ZB_ZCL_SHAKE_TRACKER_DATA_DEFAULT_VALUE, strlen(ZB_ZCL_SHAKE_TRACKER_DATA_DEFAULT_VALUE)+1);
    dev_ctx.shake_attr.is_shaked = ZB_ZCL_SHAKE_TRACKER_IS_SHAKED_DEFAULT_VALUE;


}

/**@brief Function to toggle the identify LED
 *
 * @param  bufid  Unused parameter, required by ZBOSS scheduler API.
 */
static void toggle_identify_led(zb_bufid_t bufid)
{
	static int blink_status;

	dk_set_led(IDENTIFY_LED, (++blink_status) % 2);
	ZB_SCHEDULE_APP_ALARM(toggle_identify_led, bufid, ZB_MILLISECONDS_TO_BEACON_INTERVAL(100));
}

/**@brief Function to handle identify notification events on the first endpoint.
 *
 * @param  bufid  Unused parameter, required by ZBOSS scheduler API.
 */
static void identify_cb(zb_bufid_t bufid)
{
	zb_ret_t zb_err_code;

	if (bufid) {
		/* Schedule a self-scheduling function that will toggle the LED */
		ZB_SCHEDULE_APP_CALLBACK(toggle_identify_led, bufid);
	} else {
		/* Cancel the toggling function alarm and turn off LED */
		zb_err_code = ZB_SCHEDULE_APP_ALARM_CANCEL(toggle_identify_led, ZB_ALARM_ANY_PARAM);
		ZVUNUSED(zb_err_code);

		dk_set_led(IDENTIFY_LED, 0);
	}
}

/**@breif Starts identifying the device.
 *
 * @param  bufid  Unused parameter, required by ZBOSS scheduler API.
 */
static void start_identifying(zb_bufid_t bufid)
{
	zb_ret_t zb_err_code;

	ZVUNUSED(bufid);

	/* Check if endpoint is in identifying mode,
	 * if not put desired endpoint in identifying mode.
	 */
	if (dev_ctx.identify_attr.identify_time ==
	    ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE) {
		LOG_INF("Enter identify mode");
		zb_err_code = zb_bdb_finding_binding_target(
			APP_TEMPLATE_ENDPOINT);
		ZB_ERROR_CHECK(zb_err_code);
	} else {
		LOG_INF("Cancel identify mode");
		zb_bdb_finding_binding_target_cancel();
	}
}

/**@brief Callback for button events.
 *
 * @param[in]   button_state  Bitmask containing buttons state.
 * @param[in]   has_changed   Bitmask containing buttons
 *                            that have changed their state.
 */
static void button_changed(uint32_t button_state, uint32_t has_changed)
{
	/* Calculate bitmask of buttons that are pressed
	 * and have changed their state.
	 */
	uint32_t buttons = button_state & has_changed;

	if (buttons & IDENTIFY_MODE_BUTTON) {
		ZB_SCHEDULE_APP_CALLBACK(start_identifying, 0);
	}
}

/**@brief Function for initializing LEDs and Buttons. */
static void configure_gpio(void)
{
	int err;

	err = dk_buttons_init(button_changed);
	if (err) {
		LOG_ERR("Cannot init buttons (err: %d)", err);
	}

	err = dk_leds_init();
	if (err) {
		LOG_ERR("Cannot init LEDs (err: %d)", err);
	}
}

/**@brief Zigbee stack event handler.
 *
 * @param[in]   bufid   Reference to the Zigbee stack buffer
 *                      used to pass signal.
 */
void zboss_signal_handler(zb_bufid_t bufid)
{
	/* Update network status LED. */
	zigbee_led_status_update(bufid, ZIGBEE_NETWORK_STATE_LED);

	/* No application-specific behavior is required.
	 * Call default signal handler.
	 */
	ZB_ERROR_CHECK(zigbee_default_signal_handler(bufid));

	/* All callbacks should either reuse or free passed buffers.
	 * If bufid == 0, the buffer is invalid (not passed).
	 */
	if (bufid) {
		zb_buf_free(bufid);
	}
}

void main(void)
{
	LOG_INF("Starting Zigbee application template example");

	/* Initialize */
	configure_gpio();

	/* Register device context (endpoints). */
	ZB_AF_REGISTER_DEVICE_CTX(&app_template_ctx);

	app_clusters_attr_init();

	/* Register handlers to identify notifications */
	ZB_AF_SET_IDENTIFY_NOTIFICATION_HANDLER(APP_TEMPLATE_ENDPOINT, identify_cb);

	/* Start Zigbee default thread */
	zigbee_enable();

	LOG_INF("Zigbee application template started");

    zb_bool_t current_value=dev_ctx.shake_attr.is_shaked;
    printk("First value for is_shaked is %d \n",current_value);

    while(1){
      k_sleep(K_MSEC(2000));
      printk("is_shaked attribute was %d now setting it to",dev_ctx.shake_attr.is_shaked);
      current_value ^=0x01;
      ZB_ZCL_SET_ATTRIBUTE(10, ZB_ZCL_CLUSTER_ID_SHAKE_TRACKER,ZB_ZCL_CLUSTER_SERVER_ROLE,ZB_ZCL_ATTR_SHAKE_TRACKER_IS_SHAKED, (zb_uint8_t *)&current_value,ZB_FALSE);

      printk(" %d\n", dev_ctx.shake_attr.is_shaked);
    }

}


zb_zcl_shake_tracker.h
#ifndef ZB_ZCL_SHAKE_TRACKER_H
#define ZB_ZCL_SHAKE_TRACKER_H 1


#include "zcl/zb_zcl_common.h"
#include "zcl/zb_zcl_commands.h"


enum zb_zcl_shake_tracker_info_attr_e{
    ZB_ZCL_ATTR_SHAKE_TRACKER_DATA =0x0000,
    ZB_ZCL_ATTR_SHAKE_TRACKER_IS_SHAKED =0x0001
};

enum zb_zcl_is_shaked_is_shaked_e{
    ZB_ZCL_IS_SHAKED_IS_NOT_SHAKED = 0,
    ZB_ZCL_IS_SHAKED_IS_SHAKED = 1
};


#define ZB_ZCL_SHAKE_TRACKER_DATA_DEFAULT_VALUE "Hello"//{'H', 'e', 'l', 'l','o','\0'}
#define ZB_ZCL_SHAKE_TRACKER_DATA_SIZE sizeof(ZB_ZCL_SHAKE_TRACKER_DATA_DEFAULT_VALUE)
#define ZB_ZCL_SHAKE_TRACKER_IS_SHAKED_DEFAULT_VALUE (ZB_ZCL_IS_SHAKED_IS_NOT_SHAKED)

#define ZB_ZCL_CLUSTER_ID_SHAKE_TRACKER 0xABCDU


#define ZB_ZCL_DECLARE_SHAKE_TRACKER_ATTRIB_LIST(attr_list, data, is_shaked) \
    ZB_ZCL_START_DECLARE_ATTRIB_LIST(attr_list)                                \
    ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_SHAKE_TRACKER_DATA, (data))      \
    ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_SHAKE_TRACKER_IS_SHAKED, (is_shaked))    \
    ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST



#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_SHAKE_TRACKER_DATA(data_ptr) \
{                                                                         \
  ZB_ZCL_ATTR_SHAKE_TRACKER_DATA,                                       \
  ZB_ZCL_ATTR_TYPE_CHAR_STRING,                                                    \
  ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING,                                           \
  (void*) data_ptr                                                   \
}

#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_SHAKE_TRACKER_IS_SHAKED(data_ptr) \
{                                                                            \
  ZB_ZCL_ATTR_SHAKE_TRACKER_IS_SHAKED,                                       \
  ZB_ZCL_ATTR_TYPE_BOOL,                                                     \
  ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING,                                             \
  (void*) data_ptr                                                      \
}






typedef struct zb_zcl_shake_tracker_attrs_s
{
  zb_char_t data [ZB_ZCL_SHAKE_TRACKER_DATA_SIZE];
  zb_bool_t is_shaked;

} zb_zcl_shake_tracker_attrs_t;



#define ZB_ZCL_DECLARE_SHAKE_TRACKER_ATTR_LIST(attr_list, attrs) \
    ZB_ZCL_DECLARE_SHAKE_TRACKER_ATTRIB_LIST(attr_list, &attrs.data, &attrs.is_shaked)



void zb_zcl_shake_tracker_init_server(void);
void zb_zcl_shake_tracker_init_client(void);

#define ZB_ZCL_CLUSTER_ID_SHAKE_TRACKER_SERVER_ROLE_INIT zb_zcl_shake_tracker_init_server
#define ZB_ZCL_CLUSTER_ID_SHAKE_TRACKER_CLIENT_ROLE_INIT zb_zcl_shake_tracker_init_client


#endif

zb_zcl_shake_tracker.c

#include "zboss_api.h"





#include "zb_zcl_shake_tracker.h"


void zb_zcl_shake_tracker_init_server(){}
void zb_zcl_shake_tracker_init_client(){}


zb_ha_shaker.h
#ifndef ZB_HA_SHAKER_H
#define ZB_HA_SHAKER_H 1


#define ZB_HA_DEVICE_VER_SHAKER 0

#define ZB_HA_SHAKER_IN_CLUSTER_NUM 2
#define ZB_HA_SHAKER_OUT_CLUSTER_NUM 1

#define ZB_HA_SHAKER_CLUSTER_NUM                                       \
    (ZB_HA_SHAKER_IN_CLUSTER_NUM + ZB_HA_SHAKER_OUT_CLUSTER_NUM)


#define ZB_HA_SHAKER_REPORT_ATTR_COUNT    1

#define ZB_HA_DECLARE_SHAKER_CLUSTER_LIST(                  \
    cluster_list_name,                                      \
    basic_attr_list,                                        \
    identify_attr_list,                                     \
    shake_attribute_list)                                   \
zb_zcl_cluster_desc_t cluster_list_name[] =                 \
{                                                           \
    ZB_ZCL_CLUSTER_DESC(                                    \
    ZB_ZCL_CLUSTER_ID_IDENTIFY,                             \
    ZB_ZCL_ARRAY_SIZE(identify_attr_list, zb_zcl_attr_t),   \
    (identify_attr_list),                                   \
    ZB_ZCL_CLUSTER_SERVER_ROLE,                             \
    ZB_ZCL_MANUF_CODE_INVALID                               \
    ),                                                      \
    ZB_ZCL_CLUSTER_DESC(                                    \
    ZB_ZCL_CLUSTER_ID_BASIC,                                \
    ZB_ZCL_ARRAY_SIZE(basic_attr_list, zb_zcl_attr_t),      \
    (basic_attr_list),                                      \
    ZB_ZCL_CLUSTER_SERVER_ROLE,                             \
    ZB_ZCL_MANUF_CODE_INVALID                               \
    ),                                                       \
    ZB_ZCL_CLUSTER_DESC(                                    \
    ZB_ZCL_CLUSTER_ID_SHAKE_TRACKER,                        \
    ZB_ZCL_ARRAY_SIZE(shake_attribute_list, zb_zcl_attr_t), \
    (shake_attribute_list),                                 \
    ZB_ZCL_CLUSTER_SERVER_ROLE,                             \
    ZB_ZCL_MANUF_CODE_INVALID                               \
    )                                                       \
}                                                           \



#define ZB_ZCL_DECLARE_SHAKER_SIMPLE_DESC(ep_name, ep_id, in_clust_num, out_clust_num) \
  ZB_DECLARE_SIMPLE_DESC(in_clust_num, out_clust_num);                                         \
  ZB_AF_SIMPLE_DESC_TYPE(in_clust_num, out_clust_num) simple_desc_##ep_name =                  \
  {                                                                                            \
    ep_id,                                                                                     \
    ZB_AF_HA_PROFILE_ID,                                                                       \
    0xDEAD,                                                                                    \
    ZB_HA_DEVICE_VER_SHAKER,                                                                   \
    0,                                                                                         \
    in_clust_num,                                                                              \
    out_clust_num,                                                                             \
    {                                                                                          \
      ZB_ZCL_CLUSTER_ID_BASIC,                                                                 \
      ZB_ZCL_CLUSTER_ID_IDENTIFY,                                                               \
      ZB_ZCL_CLUSTER_ID_SHAKE_TRACKER                                                          \
    }                                                                                          \
  }


#define ZB_HA_DECLARE_SHAKER_EP(ep_name, ep_id, cluster_list)                           \
  ZB_ZCL_DECLARE_SHAKER_SIMPLE_DESC(ep_name, ep_id,                                     \
      ZB_HA_SHAKER_IN_CLUSTER_NUM, ZB_HA_SHAKER_OUT_CLUSTER_NUM);               \
  ZB_AF_DECLARE_ENDPOINT_DESC(ep_name, ep_id, ZB_AF_HA_PROFILE_ID, 0, NULL,                              \
                          ZB_ZCL_ARRAY_SIZE(cluster_list, zb_zcl_cluster_desc_t), cluster_list, \
                              (zb_af_simple_desc_1_1_t*)&simple_desc_##ep_name,                 \
                              0, NULL, /* No reporting ctx */                                   \
                              0, NULL) /* No CVC ctx */


#define ZB_HA_DECLARE_SHAKER_CTX(device_ctx, ep_name)           \
  ZBOSS_DECLARE_DEVICE_CTX_1_EP(device_ctx, ep_name)



#endif


Thank you in advance.

Isaia

  • Addendum: the commands sent via CLI to subscribe to the reported attribute and relative responses, if they can be of any use

    uart:~$ bdb role zc
    Zigbee stack has been configured in the past.
    Please use the same role or disable NVRAM to change the Zigbee role.
    Coordinator set
    Done
    uart:~$ bdb start
    Started coordinator
    Done
    [00:00:13.114,746] <inf> zigbee_app_utils: Production configuration is not present or invalid (status: -1)
    [00:00:13.115,936] <inf> zigbee_app_utils: Zigbee stack initialized
    [00:00:13.158,203] <inf> zigbee_app_utils: Joined network successfully on reboot signal (Extended PAN ID: f4ce36bc41dcdf74, PAN ID: 0x6012)
    uart:~$ zdo mg
      mgmt_bind   mgmt_leave  mgmt_lqi
    uart:~$ zdo mgmt_lqi 0000
    [idx] ext_pan_id       ext_addr         short_addr flags permit_join depth lqi
    [  0] f4ce36bc41dcdf74 f4ce364145c4c951 0x2541     0x15  0           1   172
    ZDO request 1 complete
    Done
    uart:~$ zdo bind on f4ce364145c4c951 10 f4ce36bc41dcdf74 64 0xabcd
    on: wrong parameter count
    on - Create bind entry.
         Usage: on <h:source_eui64> <d:source_ep> <h:destination_addr>
         <d:destination_ep> <h:source_cluster_id> <h:request_dst_addr>
    uart:~$ zdo bind on f4ce364145c4c951 10 f4ce36bc41dcdf74 64 0xabcd 0x2541
    Done
    uart:~$ zcl subscribe on 0x2541 
    on: wrong parameter count
    on - Subscribe to an attribute.
         Usage: on <h:addr> <d:ep> <h:cluster> <h:profile> <h:attr_id> <d:attr_type>
         [<d:min_interval (s)>] [<d:max_interval (s)>]
    uart:~$ zcl subscribe on 0x2541 10 0xabcd 0x0104 0x0001 16
    Error: Unable to configure attribute 1 reporting. Status: 1
    
    Error: One or more attributes reporting were not configured successfully[00:01:59.041,778] <inf> zigbee.eprxzcl: Received ZCL command (0): src_addr=0x2541(short) src_ep=10 dst_ep=64 cluster_id=0xabcd profile_id=0x0104 cmd_dir=1 common_cmd=1 cmd_id=0x07 cmd_seq=0 disable_def_resp=1 manuf_code=void payload=[01000100] (0)
    

  • Hi,

    I am so sorry for the late reply. I have forwarded this case to one of our Zigbee experts who will take a closer look at this soon.

  • Hi Isaia,

    Sorry for the delay.

    It seems like you have forgotten to add the reporting context to your shaker device. You need to declare the context with ZBOSS_DEVICE_DECLARE_REPORTING_CTX and add the number of reporting attributes on the device to the endpoint descriptor:

    #define ZB_HA_DECLARE_SHAKER_EP(ep_name, ep_id, cluster_list)                                    \
      ZB_ZCL_DECLARE_SHAKER_SIMPLE_DESC(ep_name, ep_id,                                              \
          ZB_HA_SHAKER_IN_CLUSTER_NUM, ZB_HA_SHAKER_OUT_CLUSTER_NUM);                                \
          ZBOSS_DEVICE_DECLARE_REPORTING_CTX(reporting_info## device_ctx_name,                       \
                                         ZB_HA_SHAKER_REPORT_ATTR_COUNT);                            \
      ZB_AF_DECLARE_ENDPOINT_DESC(ep_name, ep_id, ZB_AF_HA_PROFILE_ID, 0, NULL,                      \
                              ZB_ZCL_ARRAY_SIZE(cluster_list, zb_zcl_cluster_desc_t), cluster_list,  \
                                  (zb_af_simple_desc_1_1_t*)&simple_desc_##ep_name,                  \
                                  ZB_HA_SHAKER_REPORT_ATTR_COUNT, reporting_info## device_ctx_name,  \
                                  0, NULL) /* No CVC ctx */

    Define ZB_HA_SHAKER_REPORT_ATTR_COUNT to be the number of attributes your device should report.

    Best regards,

    Marte

  • That did it, thank you.

    This should be added to the guide however as i don't think there is any reference to this in the documentation.

Related