QUERY - [nRF52840][ZIGBEE] getting issue with reporting attribute while sending Temperature Measurement Value From Bulb To switch?

Hello Team,

I am using nrf52840 board which supports ZIGBEE .

Setup Details:
Zigbee_LIGHT_BULB (nRF52840 DK)
Zigbee_LIGHT_SWITCH(nRF52840 DK)

Light Bulb Example

I am currently implementing the Temperature Measurement Cluster in the Light Bulb example. I want to send the temperature measurement value to the Light Switch example. On the bulb side, I am using the report attribute to send the temperature value but switch is not receiving the temperature report why?

LIGHT_BULB EXAMPLE CODE (TEMPERATURE MEASUREMENT)


 /** @file
 *
 * @brief TODO: Write actual implementation details here
 */

#include <zephyr/types.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <soc.h>
#include <zephyr/drivers/pwm.h>
#include <zephyr/logging/log.h>
#include <dk_buttons_and_leds.h>
#include <zephyr/settings/settings.h>

#include <zboss_api.h>
#include <zboss_api_addons.h>
#include <zb_mem_config_med.h>
#include <zigbee/zigbee_app_utils.h>
#include <zigbee/zigbee_error_handler.h>
#include <zigbee/zigbee_zcl_scenes.h>
#include <zb_nrf_platform.h>
#include "zb_dimmable_light.h"
#include "zb_zcl_time.h"
#include "zb_zcl_temp_measurement.h"
#include "zcl/zb_zcl_temp_measurement_addons.h"
#include  <time.h>
#include <stdlib.h>
#include "stdint.h"
#include <limits.h>
#include "zcl/zb_zcl_reporting.h"
#include "zboss_api_core.h"


// Define RAND_MAX if not already defined
#ifndef RAND_MAX
#define RAND_MAX INT_MAX
#endif

#define RUN_STATUS_LED                  DK_LED1
#define RUN_LED_BLINK_INTERVAL          1000

/* Device endpoint, used to receive light controlling commands. */
#define LEVEL_CONTROL_ENDPOINT         11

/* Version of the application software (1 byte). */
#define BULB_INIT_BASIC_APP_VERSION     01

/* Version of the implementation of the Zigbee stack (1 byte). */
#define BULB_INIT_BASIC_STACK_VERSION   10

/* Version of the hardware of the device (1 byte). */
#define BULB_INIT_BASIC_HW_VERSION      11

/* Manufacturer name (32 bytes). */
#define BULB_INIT_BASIC_MANUF_NAME      "Nordic"

/* Model number assigned by manufacturer (32-bytes long string). */
#define BULB_INIT_BASIC_MODEL_ID        "light_v0.1"

/* First 8 bytes specify the date of manufacturer of the device
 * in ISO 8601 format (YYYYMMDD). The rest (8 bytes) are manufacturer specific.
 */
#define BULB_INIT_BASIC_DATE_CODE       "20230404"

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

/* Describes the physical location of the device (16 bytes).
 * May be modified during commissioning process.
 */
#define BULB_INIT_BASIC_LOCATION_DESC   "Office desk"

/* Describes the type of physical environment.
 * For possible values see section 3.2.2.2.10 of ZCL specification.
 */
#define BULB_INIT_BASIC_PH_ENV          ZB_ZCL_BASIC_ENV_UNSPECIFIED

/* LED indicating that light switch successfully joind Zigbee network. */
#define ZIGBEE_NETWORK_STATE_LED        DK_LED3

/* LED immitaing light bulb - define for informational
 * purposes only.
 */
#define BULB_LED                        DK_LED4

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

/* Use onboard led4 to act as a light bulb.
 * The app.overlay file has this at node label "pwm_led3" in /pwmleds.
 */
#define PWM_DK_LED4_NODE                DT_NODELABEL(pwm_led3)

/* Led PWM period, calculated for 100 Hz signal - in microseconds. */
#define LED_PWM_PERIOD_US               (USEC_PER_SEC / 100U)

#ifndef ZB_ROUTER_ROLE
#error Define ZB_ROUTER_ROLE to compile router source code.
#endif

/* Button to start Factory Reset */
#define FACTORY_RESET_BUTTON IDENTIFY_MODE_BUTTON

#if DT_NODE_HAS_STATUS(PWM_DK_LED4_NODE, okay)
static const struct pwm_dt_spec led_pwm = PWM_DT_SPEC_GET(PWM_DK_LED4_NODE);
#else
#error "Choose supported PWM driver"
#endif

/*Register the logging module with a specific log level */
LOG_MODULE_REGISTER(app, LOG_LEVEL_INF);

/* Attribute Values for temperature measurement */
static int16_t measuredValue = 0;  // Default to 0 (0.00°C)
static const int16_t minMeasuredValue = -27315;  // -273.15°C in MeasuredValue format
static const int16_t maxMeasuredValue = 32767;   // 327.67°C in MeasuredValue format
static uint16_t tolerance = 0;     // Default tolerance

/* Seed for the linear congruential generator (LCG) */
static uint32_t lcg_seed = 1;

/* Function to seed the random number generator */
void srand(unsigned int seed) {
    lcg_seed = seed;
}

/* Function to generate a random number using LCG algorithm */
int rand(void) {
    lcg_seed = (lcg_seed * 1664525 + 1013904223) % 0xFFFFFFFF;
    return (int)(lcg_seed & RAND_MAX);
}

static struct k_timer temperature_timer;
static bool bulb_on = false;


/* Main application customizable context.
 * Stores all settings and static values.
 */
typedef struct {
	zb_zcl_basic_attrs_ext_t basic_attr;
	zb_zcl_identify_attrs_t identify_attr;
	zb_zcl_scenes_attrs_t scenes_attr;
	zb_zcl_groups_attrs_t groups_attr;
	zb_zcl_on_off_attrs_t on_off_attr;
	zb_zcl_level_control_attrs_t level_control_attr;
	zb_zcl_time_attrs_t time_attr;
	zb_zcl_temp_measurement_attrs_t temp_measurement_attr;
} bulb_device_ctx_t;

/* Zigbee device application context storage. */
static bulb_device_ctx_t dev_ctx;

/* Declare attribute lists for different Zigbee clusters */

/* Identify cluster attributes additions data */
ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST(
	identify_attr_list,
	&dev_ctx.identify_attr.identify_time);

/* Groups cluster attributes additions data */
ZB_ZCL_DECLARE_GROUPS_ATTRIB_LIST(
	groups_attr_list,
	&dev_ctx.groups_attr.name_support);

/* Scenes cluster attributes additions data */
ZB_ZCL_DECLARE_SCENES_ATTRIB_LIST(
	scenes_attr_list,
	&dev_ctx.scenes_attr.scene_count,
	&dev_ctx.scenes_attr.current_scene,
	&dev_ctx.scenes_attr.current_group,
	&dev_ctx.scenes_attr.scene_valid,
	&dev_ctx.scenes_attr.name_support);

/* Basic cluster attributes additions data */
ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST_EXT(
	basic_attr_list,
	&dev_ctx.basic_attr.zcl_version,
	&dev_ctx.basic_attr.app_version,
	&dev_ctx.basic_attr.stack_version,
	&dev_ctx.basic_attr.hw_version,
	dev_ctx.basic_attr.mf_name,
	dev_ctx.basic_attr.model_id,
	dev_ctx.basic_attr.date_code,
	&dev_ctx.basic_attr.power_source,
	dev_ctx.basic_attr.location_id,
	&dev_ctx.basic_attr.ph_env,
	dev_ctx.basic_attr.sw_ver);

/* On/Off cluster attributes additions data */
ZB_ZCL_DECLARE_ON_OFF_ATTRIB_LIST(
	on_off_attr_list,
	&dev_ctx.on_off_attr.on_off);

/* Level Control cluster attributes additions data */
ZB_ZCL_DECLARE_LEVEL_CONTROL_ATTRIB_LIST(
	level_control_attr_list,
	&dev_ctx.level_control_attr.current_level,
	&dev_ctx.level_control_attr.remaining_time);

/* Time cluster attributes additions data */
ZB_ZCL_DECLARE_TIME_ATTRIB_LIST(
	time_attr_list,
	&dev_ctx.time_attr.dst_end,
	&dev_ctx.time_attr.dst_shift,
	&dev_ctx.time_attr.dst_start,
	&dev_ctx.time_attr.last_set_time,
	&dev_ctx.time_attr.local_time,
	&dev_ctx.time_attr.standard_time,
	&dev_ctx.time_attr.time,
	&dev_ctx.time_attr.time_status,
	&dev_ctx.time_attr.time_zone,
	&dev_ctx.time_attr.valid_until_time);

/* Temperature Measurement cluster attributes additions data */
ZB_ZCL_DECLARE_TEMP_MEASUREMENT_ATTRIB_LIST(
	temp_measurement_attr_list,
	&dev_ctx.temp_measurement_attr.max_measure_value,
	&dev_ctx.temp_measurement_attr.measure_value,
	&dev_ctx.temp_measurement_attr.min_measure_value,
	&dev_ctx.temp_measurement_attr.tolerance);

/* Declare Zigbee endpoint and cluster list for on/off light*/
ZB_DECLARE_ON_OFF_LIGHT_CLUSTER_LIST(
    on_off_light_clusters,
    basic_attr_list,
    identify_attr_list,
    groups_attr_list,
    scenes_attr_list,
    on_off_attr_list,
    level_control_attr_list,
	time_attr_list,
	temp_measurement_attr_list);

ZB_DECLARE_LEVEL_CONTROL_EP(
    level_control_ep,
    LEVEL_CONTROL_ENDPOINT,
    on_off_light_clusters);

ZBOSS_DECLARE_DEVICE_CTX_1_EP(
	on_off_light_ctx,
	level_control_ep);

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

	if (ZB_JOINED()) {
		/* 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) {

			zb_ret_t zb_err_code = zb_bdb_finding_binding_target(
				LEVEL_CONTROL_ENDPOINT);

			if (zb_err_code == RET_OK) {
				LOG_INF("Enter identify mode");
			} else if (zb_err_code == RET_INVALID_STATE) {
				LOG_WRN("RET_INVALID_STATE - Cannot enter identify mode");
			} else {
				ZB_ERROR_CHECK(zb_err_code);
			}
		} else {
			LOG_INF("Cancel identify mode");
			zb_bdb_finding_binding_target_cancel();
		}
	} else {
		LOG_WRN("Device not in a network - cannot enter identify mode");
	}
}

/**@brief Callback for button events.
 *
 * @param[in]   button_state  Bitmask containing the state of the buttons.
 * @param[in]   has_changed   Bitmask containing buttons that have changed their state.
 */
static void button_changed(uint32_t button_state, uint32_t has_changed)
{
	if (IDENTIFY_MODE_BUTTON & has_changed) {
		if (IDENTIFY_MODE_BUTTON & button_state) {
			/* Button changed its state to pressed */
			reset_temperature_data();
		} else {
			/* Button changed its state to released */
			if (was_factory_reset_done()) {
				/* The long press was for Factory Reset */
				LOG_DBG("After Factory Reset - ignore button release");
			} else   {
				/* Button released before Factory Reset */

				/* Start identification mode */
				ZB_SCHEDULE_APP_CALLBACK(start_identifying, 0);
			}
		}
	}

	check_factory_reset_button(button_state, has_changed);
}


// Function to reset temperature data
void reset_temperature_data() {
    // Reset the seed for the random number generator
    srand(time(NULL)); 
    // ... (Clear any other temperature-related data if needed)
    LOG_INF("Temperature data reset!");
}

/**@brief Function for initializing additional PWM leds. */
static void pwm_led_init(void)
{
	if (!device_is_ready(led_pwm.dev)) {
		LOG_ERR("Error: PWM device %s is not ready",
			led_pwm.dev->name);
	}
}

/**@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);
	}

	pwm_led_init();
}

/**@brief Sets brightness of bulb luminous executive element
 *
 * @param[in] brightness_level Brightness level, allowed values 0 ... 255,
 *                             0 - turn off, 255 - full brightness.
 */
static void light_bulb_set_brightness(zb_uint8_t brightness_level)
{
	uint32_t pulse = brightness_level * LED_PWM_PERIOD_US / 255U;

	if (pwm_set_dt(&led_pwm, PWM_USEC(LED_PWM_PERIOD_US), PWM_USEC(pulse))) {
		LOG_ERR("Pwm led 4 set fails:\n");
		return;
	}

	LOG_INF("Level value is %d", brightness_level);
}


/**@brief Function for setting the light bulb brightness.
 *
 * @param[in] new_level   Light bulb brightness value.
 */
static void level_control_set_value(zb_uint16_t new_level)
{
	LOG_INF("Set level value: %i", new_level);

	ZB_ZCL_SET_ATTRIBUTE(
		LEVEL_CONTROL_ENDPOINT,
		ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL,
		ZB_ZCL_CLUSTER_SERVER_ROLE,
		ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID,
		(zb_uint8_t *)&new_level,
		ZB_FALSE);

	light_bulb_set_brightness(new_level);
}

void temperature_timer_handler(struct k_timer *dummy)
{
	 if (!bulb_on) {
        return; // Stop updating temperature if bulb is off
    }
	int16_t new_temperature = 2200 + (rand() % 50);/* Read or simulate new temperature */
    update_temperature_measurement(new_temperature);
}

static const char* get_formatted_temperature(void) {
    static char temp_str[16];
    int16_t temp_value = dev_ctx.temp_measurement_attr.measure_value;
    snprintf(temp_str, sizeof(temp_str), "%d.%02d°C", temp_value / 100, temp_value % 100);
    return temp_str;
}


/**@brief Function for turning ON/OFF the light bulb.
 *
 * @param[in]   on   Boolean light bulb state.
 */
static void on_off_set_value(zb_bool_t on)
{
	LOG_INF("Set ON/OFF value: %i", on);

	const char* temp_str = get_formatted_temperature();

	ZB_ZCL_SET_ATTRIBUTE(
		LEVEL_CONTROL_ENDPOINT,
		ZB_ZCL_CLUSTER_ID_ON_OFF,
		ZB_ZCL_CLUSTER_SERVER_ROLE,
		ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID,
		(zb_uint8_t *)&on,
		ZB_FALSE);

	// if (on) {
	// 	LOG_INF("bulb is ON. \t Current temperature : %s ", temp_str);
	// }else {
	// 	LOG_INF("Bulb is OFF. \t Current Temperature : %s ", temp_str);
	// }

	if (on) {
    bulb_on = true;
	/* Start periodic temperature measurement updates */
    //k_timer_init(&temperature_timer, temperature_timer_handler, NULL);
    //k_timer_start(&temperature_timer, K_SECONDS(5), K_SECONDS(5));
    dk_set_led_on(DK_LED4);
    LOG_INF("Light ON - current temperature measurement: %s", temp_str);
	} else {
    bulb_on = false;
    //k_timer_stop(&temperature_timer);
    dk_set_led_off(DK_LED4);
    LOG_INF("Light OFF - current temperature measurement: %s", temp_str);
	}

}

/**@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 restore current Zigbee LED state. */
		//zb_err_code = ZB_SCHEDULE_APP_ALARM_CANCEL(toggle_identify_led, ZB_ALARM_ANY_PARAM);
		ZVUNUSED(zb_err_code);
	}
}

/**@brief Function for initializing all clusters attributes.
 */
static void bulb_clusters_attr_init(void)
{
	/* Basic cluster attributes data */
	dev_ctx.basic_attr.zcl_version = ZB_ZCL_VERSION;
	dev_ctx.basic_attr.app_version = BULB_INIT_BASIC_APP_VERSION;
	dev_ctx.basic_attr.stack_version = BULB_INIT_BASIC_STACK_VERSION;
	dev_ctx.basic_attr.hw_version = BULB_INIT_BASIC_HW_VERSION;

	ZB_ZCL_SET_STRING_VAL(
		dev_ctx.basic_attr.mf_name,
		BULB_INIT_BASIC_MANUF_NAME,
		ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_MANUF_NAME));

	ZB_ZCL_SET_STRING_VAL(
		dev_ctx.basic_attr.model_id,
		BULB_INIT_BASIC_MODEL_ID,
		ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_MODEL_ID));

	ZB_ZCL_SET_STRING_VAL(
		dev_ctx.basic_attr.date_code,
		BULB_INIT_BASIC_DATE_CODE,
		ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_DATE_CODE));

	dev_ctx.basic_attr.power_source = BULB_INIT_BASIC_POWER_SOURCE;

	ZB_ZCL_SET_STRING_VAL(
		dev_ctx.basic_attr.location_id,
		BULB_INIT_BASIC_LOCATION_DESC,
		ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_LOCATION_DESC));

	dev_ctx.basic_attr.ph_env = BULB_INIT_BASIC_PH_ENV;

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

	/* Groups cluster attributes data. */
	dev_ctx.groups_attr.name_support = ZB_ZCL_ATTR_GROUPS_NAME_SUPPORT_ID;

	/* Scenes cluster attributes data. */
	dev_ctx.scenes_attr.current_group = ZB_ZCL_ATTR_SCENES_CURRENT_GROUP_ID;
	dev_ctx.scenes_attr.current_scene = ZB_ZCL_ATTR_SCENES_CURRENT_SCENE_ID;
	dev_ctx.scenes_attr.name_support  = ZB_ZCL_ATTR_SCENES_NAME_SUPPORT_ID;
	dev_ctx.scenes_attr.scene_count   = ZB_ZCL_ATTR_SCENES_SCENE_COUNT_ID;
	dev_ctx.scenes_attr.scene_valid   = ZB_ZCL_ATTR_SCENES_SCENE_VALID_ID;


    /* On/Off cluster attributes data. */
	dev_ctx.on_off_attr.on_off = (zb_bool_t)ZB_ZCL_ON_OFF_IS_ON;

	/* Level Control Cluster attributes data. */
	dev_ctx.level_control_attr.current_level =
		ZB_ZCL_LEVEL_CONTROL_LEVEL_MAX_VALUE;
	dev_ctx.level_control_attr.remaining_time =
		ZB_ZCL_LEVEL_CONTROL_REMAINING_TIME_DEFAULT_VALUE;	

	/* Temperature Measurement cluster attributes data. */
	dev_ctx.temp_measurement_attr.max_measure_value = ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID;
	dev_ctx.temp_measurement_attr.measure_value     = ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID;
	dev_ctx.temp_measurement_attr.min_measure_value = ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID;
	dev_ctx.temp_measurement_attr.tolerance         = ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID;

	
	ZB_ZCL_SET_ATTRIBUTE(
		LEVEL_CONTROL_ENDPOINT,
		ZB_ZCL_CLUSTER_ID_ON_OFF,
		ZB_ZCL_CLUSTER_SERVER_ROLE,
		ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID,
		(zb_uint8_t *)&dev_ctx.on_off_attr.on_off,
		ZB_FALSE);

	ZB_ZCL_SET_ATTRIBUTE(
		LEVEL_CONTROL_ENDPOINT,
		ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL,
		ZB_ZCL_CLUSTER_SERVER_ROLE,
		ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID,
		(zb_uint8_t *)&dev_ctx.level_control_attr.current_level,
		ZB_FALSE);

	ZB_ZCL_SET_ATTRIBUTE(
        LEVEL_CONTROL_ENDPOINT,
        ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT,
        ZB_ZCL_CLUSTER_SERVER_ROLE,
        ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID,
        (zb_uint8_t *)&dev_ctx.temp_measurement_attr.measure_value,
        ZB_FALSE);

    ZB_ZCL_SET_ATTRIBUTE(
        LEVEL_CONTROL_ENDPOINT,
        ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT,
        ZB_ZCL_CLUSTER_SERVER_ROLE,
        ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID,
        (zb_uint8_t *)&dev_ctx.temp_measurement_attr.min_measure_value,
        ZB_FALSE);

    ZB_ZCL_SET_ATTRIBUTE(
        LEVEL_CONTROL_ENDPOINT,
        ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT,
        ZB_ZCL_CLUSTER_SERVER_ROLE,
        ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID,
        (zb_uint8_t *)&dev_ctx.temp_measurement_attr.max_measure_value,
        ZB_FALSE);

    ZB_ZCL_SET_ATTRIBUTE(
        LEVEL_CONTROL_ENDPOINT,
        ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT,
        ZB_ZCL_CLUSTER_SERVER_ROLE,
        ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID,
        (zb_uint8_t *)&dev_ctx.temp_measurement_attr.tolerance,
        ZB_FALSE);

}

// // Function to initialize the random number generator
void initialize_random() {
    srand(gmtime(NULL)); // Seed the random number generator with the current time
}

// Function to read temperature from the sensor (simulated here)
int16_t read_temperature_sensor(void) {
    static int counter = 0;
    counter++;
    return 2200 + (rand() % 50); // Simulate temperature change
}
// Function to configure temperature reporting
void configure_temperature_reporting() {
    zb_zcl_reporting_info_t temp_rep_info;
    memset(&temp_rep_info, 0, sizeof(temp_rep_info));
    // Set up reporting configuration (adjust values as needed)
    temp_rep_info.direction = ZB_ZCL_CONFIGURE_REPORTING_SEND_REPORT;
    temp_rep_info.ep = LEVEL_CONTROL_ENDPOINT;
    temp_rep_info.cluster_id = ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
    temp_rep_info.cluster_role = ZB_ZCL_CLUSTER_SERVER_ROLE;
    temp_rep_info.attr_id = ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID;
    temp_rep_info.dst.profile_id = ZB_AF_HA_PROFILE_ID;
    temp_rep_info.u.send_info.min_interval = 30;      // 30 seconds
    temp_rep_info.u.send_info.max_interval = 300;    // 5 minutes
    temp_rep_info.u.send_info.delta.s16 = 0x0032;     // 0.5 degrees
    zb_ret_t ret = zb_zcl_put_reporting_info(&temp_rep_info, ZB_TRUE);
    if (ret == RET_OK) {
        LOG_INF("Temperature reporting configured successfully.\n");
    } else {
        LOG_ERR("Failed to configure temperature reporting.\n");
    }
}
// Function to start attribute reporting
void start_reporting() {
    zb_ret_t ret = zb_zcl_start_attr_reporting(LEVEL_CONTROL_ENDPOINT,
                                                ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT,
                                                ZB_ZCL_CLUSTER_SERVER_ROLE,
                                                ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID);
    if (ret == RET_OK) {
        LOG_INF("Temperature reporting started successfully.\n");
    } else {
        LOG_ERR("Failed to start temperature reporting.\n");
    }
}
// Function to update the temperature measurement attribute and trigger a report
void update_temperature_measurement() {
    int16_t new_temperature = read_temperature_sensor();
    // Update the attribute and trigger a report
    ZB_ZCL_SET_ATTRIBUTE(
						LEVEL_CONTROL_ENDPOINT,
						ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT,
						ZB_ZCL_CLUSTER_SERVER_ROLE,
						ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID,
						(zb_uint8_t *)&new_temperature,
						ZB_FALSE);

    zb_zcl_start_attr_reporting(LEVEL_CONTROL_ENDPOINT,
                       ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT,
                       ZB_ZCL_CLUSTER_SERVER_ROLE,
                       ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID);
    LOG_INF("Reported temperature: %d.%02d°C", new_temperature / 100, new_temperature % 100);
}

/**@brief Callback function for handling ZCL commands.
 *
 * @param[in]   bufid   Reference to Zigbee stack buffer
 *                      used to pass received data.
 */
static void zcl_device_cb(zb_bufid_t bufid)
{
	zb_uint8_t cluster_id;
	zb_uint8_t attr_id;
	zb_zcl_device_callback_param_t  *device_cb_param =
		ZB_BUF_GET_PARAM(bufid, zb_zcl_device_callback_param_t);

	LOG_INF("%s id %hd", __func__, device_cb_param->device_cb_id);

	/* Set default response value. */
	device_cb_param->status = RET_OK;

	switch (device_cb_param->device_cb_id) {

	case ZB_ZCL_LEVEL_CONTROL_SET_VALUE_CB_ID:
		LOG_INF("Level control setting to %d",
			device_cb_param->cb_param.level_control_set_value_param
			.new_value);
		level_control_set_value(
			device_cb_param->cb_param.level_control_set_value_param
			.new_value);
		
		break;

	case ZB_ZCL_SET_ATTR_VALUE_CB_ID:
		cluster_id = device_cb_param->cb_param.
			     set_attr_value_param.cluster_id;
		attr_id = device_cb_param->cb_param.
			  set_attr_value_param.attr_id;

		if (cluster_id == ZB_ZCL_CLUSTER_ID_ON_OFF) {
			uint8_t value =
				device_cb_param->cb_param.set_attr_value_param
				.values.data8;

			LOG_INF("on/off attribute setting to %hd", value);
			if (attr_id == ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID) {
				on_off_set_value((zb_bool_t)value);
				// int16_t new_temperature = 2200 + (rand() % 50);/* Read or simulate new temperature */;
        		// update_temperature_measurement(new_temperature);

				if(value == 1) {
					dk_set_led_on(DK_LED4);
				} else {
					dk_set_led_off(DK_LED4);
				}
				
			}
		} else {
			/* Other clusters can be processed here */
			LOG_INF("Unhandled cluster attribute id: %d",
				cluster_id);
			device_cb_param->status = RET_NOT_IMPLEMENTED;
		}
		break;
	default:
		if (zcl_scenes_cb(bufid) == ZB_FALSE) {
			device_cb_param->status = RET_NOT_IMPLEMENTED;
		}
		break;
	}

	LOG_INF("%s status: %hd", __func__, device_cb_param->status);
}


/**@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)
{
	int blink_status = 0;
	int err;

	// Seed the random number generator with the current time
    srand(gmtime(NULL));

	LOG_INF("Starting On Off Cluster Example");
 
	/* Initialize */
	configure_gpio();
	err = settings_subsys_init();
	if (err) {
		LOG_ERR("settings initialization failed");
	}
	register_factory_reset_button(FACTORY_RESET_BUTTON);

	/* Register callback for handling ZCL commands. */
	ZB_ZCL_REGISTER_DEVICE_CB(zcl_device_cb);
	

	/* Register on off switch device context (endpoints). */
	ZB_AF_REGISTER_DEVICE_CTX(&on_off_light_ctx);

	bulb_clusters_attr_init();
	LOG_INF("after cluster initialization");
	level_control_set_value(dev_ctx.level_control_attr.current_level);

	/* Register handler to identify notifications. */
	ZB_AF_SET_IDENTIFY_NOTIFICATION_HANDLER(LEVEL_CONTROL_ENDPOINT, identify_cb);

	/* Initialize ZCL scene table */
	zcl_scenes_init();

	/* Settings should be loaded after zcl_scenes_init */
	err = settings_load();
	if (err) {
		LOG_ERR("settings loading failed");
	}

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

	LOG_INF("On off cluster example started");

	

	while (1) {

		// Update temperature and trigger a report
			update_temperature_measurement(); 
			k_sleep(K_SECONDS(5)); // Update every 5 seconds (adjust as needed)
	}
}

Light Switch Example

In the Light Switch example, how can I receive the temperature value?

Is a Bind Request required? If so, on which side do I need to implement bind_and_configuring_reporting?

Can you please help me with this? I am getting confused. Additionally, can you please let me know whether the implementation of the code on both sides is correct?

In switch side i wrote functions 

LIGHT_SWITCH EXAMPLE (TEMPERATURE MEASUREMENT)


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

/** @file
 * @brief Dimmer switch for HA profile implementation.
 */

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/logging/log.h>
#include <dk_buttons_and_leds.h>
#include <ram_pwrdn.h>

#include <zboss_api.h>
#include <zboss_api_addons.h>
#include <zigbee/zigbee_app_utils.h>
#include <zigbee/zigbee_error_handler.h>
#include <zb_nrf_platform.h>
#include "zb_mem_config_custom.h"
#include "zb_dimmer_switch.h"
#include "zb_zcl_commands.h"
#include "zb_zcl_common.h"
#include "zb_zcl_temp_measurement.h"
//#include "zb_zcl_common.h"
// #include "zcl/zb_zcl_common.h"
#include <stdio.h>

#include "zboss_api_zcl.h"
#include "zboss_api_nwk.h"

#if CONFIG_ZIGBEE_FOTA
#include <zigbee/zigbee_fota.h>
#include <zephyr/sys/reboot.h>
#include <zephyr/dfu/mcuboot.h>

/* LED indicating OTA Client Activity. */
#define OTA_ACTIVITY_LED          DK_LED2
#endif /* CONFIG_ZIGBEE_FOTA */

#if CONFIG_BT_NUS
#include "nus_cmd.h"


/* LED which indicates that Central is connected. */
#define NUS_STATUS_LED            DK_LED1
/* UART command that will turn on found light bulb(s). */
#define COMMAND_ON                "n"
/**< UART command that will turn off found light bulb(s). */
#define COMMAND_OFF               "f"
/**< UART command that will turn toggle found light bulb(s). */
#define COMMAND_TOGGLE            "t"
/**< UART command that will increase brightness of found light bulb(s). */
#define COMMAND_INCREASE          "i"
/**< UART command that will decrease brightness of found light bulb(s). */
#define COMMAND_DECREASE          "d"
#endif /* CONFIG_BT_NUS */

/* Source endpoint used to control light bulb. */
#define LIGHT_SWITCH_ENDPOINT      1
/* Delay between the light switch startup and light bulb finding procedure. */
#define MATCH_DESC_REQ_START_DELAY K_SECONDS(2)
/* Timeout for finding procedure. */
#define MATCH_DESC_REQ_TIMEOUT     K_SECONDS(5)
/* Find only non-sleepy device. */
#define MATCH_DESC_REQ_ROLE        ZB_NWK_BROADCAST_RX_ON_WHEN_IDLE

/* Do not erase NVRAM to save the network parameters after device reboot or
 * power-off. NOTE: If this option is set to ZB_TRUE then do full device erase
 * for all network devices before running other samples.
 */
#define ERASE_PERSISTENT_CONFIG    ZB_FALSE
/* LED indicating that light switch successfully joind Zigbee network. */
#define ZIGBEE_NETWORK_STATE_LED   DK_LED3
/* LED used for device identification. */
#define IDENTIFY_LED               ZIGBEE_NETWORK_STATE_LED
/* LED indicating that light witch found a light bulb to control. */
#define BULB_FOUND_LED             DK_LED4
/* Button ID used to switch on the light bulb. */
#define BUTTON_ON                  DK_BTN1_MSK
/* Button ID used to switch off the light bulb. */
#define BUTTON_OFF                 DK_BTN2_MSK
/* Dim step size - increases/decreses current level (range 0x000 - 0xfe). */
#define DIMM_STEP                  15
/* Button ID used to enable sleepy behavior. */
#define BUTTON_SLEEPY              DK_BTN3_MSK

/* Button to start Factory Reset */
#define FACTORY_RESET_BUTTON       DK_BTN4_MSK

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

/* Transition time for a single step operation in 0.1 sec units.
 * 0xFFFF - immediate change.
 */
#define DIMM_TRANSACTION_TIME      2

/* Time after which the button state is checked again to detect button hold,
 * the dimm command is sent again.
 */
#define BUTTON_LONG_POLL_TMO       K_MSEC(500)

#if !defined ZB_ED_ROLE
#error Define ZB_ED_ROLE to compile light switch (End Device) source code.
#endif



LOG_MODULE_REGISTER(app, LOG_LEVEL_INF);

// Simulated temperature value
static int16_t temperatureValue = 2350; // 23.50°C


struct bulb_context {
	zb_uint8_t endpoint;
	zb_uint16_t short_addr;
	struct k_timer find_alarm;
};

struct buttons_context {
	uint32_t state;
	atomic_t long_poll;
	struct k_timer alarm;
};

struct zb_device_ctx {
	zb_zcl_basic_attrs_t basic_attr;
	zb_zcl_identify_attrs_t identify_attr;
	zb_zcl_temp_measurement_attrs_t temp_measurement_attr;
};

static struct bulb_context bulb_ctx;
static struct buttons_context buttons_ctx;
static struct zb_device_ctx dev_ctx;
static zb_bool_t ready_to_bind = 0;

/* Declare attribute list for Basic cluster (server). */
ZB_ZCL_DECLARE_BASIC_SERVER_ATTRIB_LIST(
	basic_server_attr_list,
	&dev_ctx.basic_attr.zcl_version,
	&dev_ctx.basic_attr.power_source);

/* Declare attribute list for Identify cluster (client). */
ZB_ZCL_DECLARE_IDENTIFY_CLIENT_ATTRIB_LIST(
	identify_client_attr_list);

/* Declare attribute list for Identify cluster (server). */
ZB_ZCL_DECLARE_IDENTIFY_SERVER_ATTRIB_LIST(
	identify_server_attr_list,
	&dev_ctx.identify_attr.identify_time);

/* Declare attribute list for Scenes cluster (client). */
ZB_ZCL_DECLARE_SCENES_CLIENT_ATTRIB_LIST(
	scenes_client_attr_list);

/* Declare attribute list for Groups cluster (client). */
ZB_ZCL_DECLARE_GROUPS_CLIENT_ATTRIB_LIST(
	groups_client_attr_list);

/* Declare attribute list for On/Off cluster (client). */
ZB_ZCL_DECLARE_ON_OFF_CLIENT_ATTRIB_LIST(
	on_off_client_attr_list);

/* Declare attribute list for Level control cluster (client). */
ZB_ZCL_DECLARE_LEVEL_CONTROL_CLIENT_ATTRIB_LIST(
	level_control_client_attr_list);

ZB_ZCL_DECLARE_TEMP_MEASUREMENT_SERVER_ATTRIB_LIST(
	temp_measurement_server_attr_list,
	&dev_ctx.temp_measurement_attr.measure_value,
	&dev_ctx.temp_measurement_attr.max_measure_value,
	&dev_ctx.temp_measurement_attr.min_measure_value,
	&dev_ctx.temp_measurement_attr.tolerance);

ZB_ZCL_DECLARE_TEMP_MEASUREMENT_CLIENT_ATTRIB_LIST(
	temp_measurement_client_attr_list);

/* Declare cluster list for Dimmer Switch device. */
ZB_DECLARE_DIMMER_SWITCH_CLUSTER_LIST(
	dimmer_switch_clusters,
	basic_server_attr_list,
	identify_client_attr_list,
	identify_server_attr_list,
	scenes_client_attr_list,
	groups_client_attr_list,
	on_off_client_attr_list,
	level_control_client_attr_list,
	temp_measurement_server_attr_list,
	temp_measurement_client_attr_list);

/* Declare endpoint for Dimmer Switch device. */
ZB_DECLARE_DIMMER_SWITCH_EP(
	dimmer_switch_ep,
	LIGHT_SWITCH_ENDPOINT,
	dimmer_switch_clusters);

/* Declare application's device context (list of registered endpoints)
 * for Dimmer Switch device.
 */
#ifndef CONFIG_ZIGBEE_FOTA
ZBOSS_DECLARE_DEVICE_CTX_1_EP(dimmer_switch_ctx, dimmer_switch_ep);
#else

  #if LIGHT_SWITCH_ENDPOINT == CONFIG_ZIGBEE_FOTA_ENDPOINT
    #error "Light switch and Zigbee OTA endpoints should be different."
  #endif

extern zb_af_endpoint_desc_t zigbee_fota_client_ep;
ZBOSS_DECLARE_DEVICE_CTX_2_EP(dimmer_switch_ctx,
			      zigbee_fota_client_ep,
			      dimmer_switch_ep);
#endif /* CONFIG_ZIGBEE_FOTA */

/* Forward declarations. */
static void light_switch_button_handler(struct k_timer *timer);
static void find_light_bulb_alarm(struct k_timer *timer);
static void find_light_bulb(zb_bufid_t bufid);
static void light_switch_send_on_off(zb_bufid_t bufid, zb_uint16_t on_off);

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

	if (ZB_JOINED()) {
		/* 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) {

			zb_ret_t zb_err_code = zb_bdb_finding_binding_target(LIGHT_SWITCH_ENDPOINT);

			if (zb_err_code == RET_OK) {
				LOG_INF("Enter identify mode");
			} else if (zb_err_code == RET_INVALID_STATE) {
				LOG_WRN("RET_INVALID_STATE - Cannot enter identify mode");
			} else {
				ZB_ERROR_CHECK(zb_err_code);
			}
		} else {
			LOG_INF("Cancel identify mode");
			zb_bdb_finding_binding_target_cancel();
		}
	} else {
		LOG_WRN("Device not in a network - cannot enter identify mode");
	}
}

/**@brief Callback for button events.
 *
 * @param[in]   button_state  Bitmask containing buttons state.
 * @param[in]   has_changed   Bitmask containing buttons that has
 *                            changed their state.
 */
static void button_handler(uint32_t button_state, uint32_t has_changed)
{
	zb_uint16_t cmd_id;
	zb_ret_t zb_err_code;

	/* Inform default signal handler about user input at the device. */
	user_input_indicate();

	check_factory_reset_button(button_state, has_changed);

	if (bulb_ctx.short_addr == 0xFFFF) {
		LOG_DBG("No bulb found yet.");
		return;
	}

	switch (has_changed) {
	case BUTTON_ON:
		LOG_DBG("ON - button changed");
		cmd_id = ZB_ZCL_CMD_ON_OFF_ON_ID;
		break;
	case BUTTON_OFF:
		LOG_DBG("OFF - button changed");
		cmd_id = ZB_ZCL_CMD_ON_OFF_OFF_ID;
		break;
	case IDENTIFY_MODE_BUTTON:
		if (IDENTIFY_MODE_BUTTON & button_state) {
			/* Button changed its state to pressed */
		} else {
			/* Button changed its state to released */
			if (was_factory_reset_done()) {
				/* The long press was for Factory Reset */
				LOG_DBG("After Factory Reset - ignore button release");
			} else   {
				/* Button released before Factory Reset */

				/* Start identification mode */
				ZB_SCHEDULE_APP_CALLBACK(start_identifying, 0);
			}
		}
		return;
	default:
		LOG_DBG("Unhandled button");
		return;
	}

	switch (button_state) {
	case BUTTON_ON:
	case BUTTON_OFF:
		LOG_DBG("Button pressed");
		buttons_ctx.state = button_state;

		/* Alarm can be scheduled only once. Next alarm only resets
		 * counting.
		 */
		k_timer_start(&buttons_ctx.alarm, BUTTON_LONG_POLL_TMO,
			      K_NO_WAIT);
		break;
	case 0:
		LOG_DBG("Button released");

		k_timer_stop(&buttons_ctx.alarm);

		if (atomic_set(&buttons_ctx.long_poll, ZB_FALSE) == ZB_FALSE) {
			/* Allocate output buffer and send on/off command. */
			zb_err_code = zb_buf_get_out_delayed_ext(
				light_switch_send_on_off, cmd_id, 0);
			ZB_ERROR_CHECK(zb_err_code);
		}
		break;
	default:
		break;
	}
}

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

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

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

static void alarm_timers_init(void)
{
	k_timer_init(&buttons_ctx.alarm, light_switch_button_handler, NULL);
	k_timer_init(&bulb_ctx.find_alarm, find_light_bulb_alarm, NULL);
}

/**@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 = ZB_ZCL_BASIC_POWER_SOURCE_UNKNOWN;

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

/**
 * @brief Configures attribute reporting for temperature measurement.
 *
 * @param[in]   bufid   Reference to Zigbee stack buffer used for communication.
 */
void configure_attr_reporting(zb_bufid_t bufid)
{
    zb_uint8_t * cmd_ptr;

    // Initialize configure reporting request
    ZB_ZCL_GENERAL_INIT_CONFIGURE_REPORTING_CLI_REQ(bufid,
                                                    cmd_ptr,
                                                    ZB_ZCL_ENABLE_DEFAULT_RESPONSE);

    // Add request to configure reporting for temperature attribute
    ZB_ZCL_GENERAL_ADD_RECV_REPORT_CONFIGURE_REPORTING_REQ(cmd_ptr,
                                                           ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID,
                                                           0);

    // Send configure reporting request to the specified endpoint
    ZB_ZCL_GENERAL_SEND_CONFIGURE_REPORTING_REQ(bufid,
                                                cmd_ptr,
                                                bulb_ctx.short_addr,
                                                ZB_APS_ADDR_MODE_16_ENDP_PRESENT,
                                                bulb_ctx.endpoint, 
                                                LIGHT_SWITCH_ENDPOINT,
                                                ZB_AF_HA_PROFILE_ID, 
                                                ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, 
                                                NULL);

    LOG_INF("Attribute reporting configured");
}

/**@brief Simulates receiving a temperature report and handles it.
 *
 * @param[in]   temperature   Temperature value to handle.
 */
void handle_temperature_measurement(int16_t temperature)
{
    // Update device context with the new temperature value
    dev_ctx.temp_measurement_attr.measure_value = temperature;

    // Implement logic to handle temperature value as needed
    LOG_INF("Received temperature measurement: %d", temperature);

    // Trigger attribute reporting configuration
    zb_bufid_t bufid = zb_buf_get_out();
    configure_attr_reporting(bufid);
}


/**@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);

		/* Update network status/idenitfication LED. */
		if (ZB_JOINED()) {
			dk_set_led_on(ZIGBEE_NETWORK_STATE_LED);
		} else {
			dk_set_led_off(ZIGBEE_NETWORK_STATE_LED);
		}
	}
}

/**@brief Function for sending ON/OFF requests to the light bulb.
 *
 * @param[in]   bufid    Non-zero reference to Zigbee stack buffer that will be
 *                       used to construct on/off request.
 * @param[in]   cmd_id   ZCL command id.
 */
static void light_switch_send_on_off(zb_bufid_t bufid, zb_uint16_t cmd_id)
{
	LOG_INF("Send ON/OFF command: %d", cmd_id);

	ZB_ZCL_ON_OFF_SEND_REQ(bufid,
			       bulb_ctx.short_addr,
			       ZB_APS_ADDR_MODE_16_ENDP_PRESENT,
			       bulb_ctx.endpoint,
			       LIGHT_SWITCH_ENDPOINT,
			       ZB_AF_HA_PROFILE_ID,
			       ZB_ZCL_DISABLE_DEFAULT_RESPONSE,
			       cmd_id,
			       NULL);
}

/**@brief Function for sending step requests to the light bulb.
 *
 * @param[in]   bufid        Non-zero reference to Zigbee stack buffer that
 *                           will be used to construct step request.
 * @param[in]   cmd_id       ZCL command id.
 */
static void light_switch_send_step(zb_bufid_t bufid, zb_uint16_t cmd_id)
{
	LOG_INF("Send step level command: %d", cmd_id);

	ZB_ZCL_LEVEL_CONTROL_SEND_STEP_REQ(bufid,
					   bulb_ctx.short_addr,
					   ZB_APS_ADDR_MODE_16_ENDP_PRESENT,
					   bulb_ctx.endpoint,
					   LIGHT_SWITCH_ENDPOINT,
					   ZB_AF_HA_PROFILE_ID,
					   ZB_ZCL_DISABLE_DEFAULT_RESPONSE,
					   NULL,
					   cmd_id,
					   DIMM_STEP,
					   DIMM_TRANSACTION_TIME);
}

/**
 * @brief Callback function for handling ZDO bind response.
 *
 * @param[in]   bufid   Reference to Zigbee stack buffer containing response.
 */
static void zb_bind_callback(zb_bufid_t bufid)
{
    zb_zdo_bind_resp_t * p_resp = (zb_zdo_bind_resp_t *)zb_buf_begin(bufid);

    if (p_resp->status == ZB_ZDP_STATUS_SUCCESS)
    {
        LOG_INF("Bind ok");
    }
    else {
        // Log error if binding modification failed
        LOG_INF("Error: Unable to modify binding. Status %d", p_resp->status);
    }
}


/**
 * @brief Initiates a ZDO bind request.
 *
 * @param[in]   bufid   Reference to Zigbee stack buffer for the request.
 */
static void bind_req(zb_bufid_t bufid)
{
    zb_ieee_addr_t               src_nwk_addr;
    zb_zdo_bind_req_param_t    * p_req;
    zb_ret_t                     zb_err_code;

    zb_osif_get_ieee_eui64(src_nwk_addr);
    
    // Initialize bind request parameters
    p_req = ZB_BUF_GET_PARAM(bufid, zb_zdo_bind_req_param_t);
    ZB_MEMCPY(p_req->src_address, ZB_PIBCACHE_NETWORK_ADDRESS(), sizeof(zb_ieee_addr_t));
    p_req->src_endp = LIGHT_SWITCH_ENDPOINT;
    p_req->cluster_id = ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
    p_req->dst_addr_mode = ZB_BIND_DST_ADDR_MODE_64_BIT_EXTENDED;
    ZB_MEMCPY(p_req->dst_address.addr_long, src_nwk_addr, sizeof(zb_ieee_addr_t));
    p_req->dst_endp = bulb_ctx.endpoint;
    p_req->req_dst_addr = bulb_ctx.short_addr;

    // Send the bind request
    zb_err_code = zb_zdo_bind_req(bufid, zb_bind_callback);
    ZB_ERROR_CHECK(zb_err_code);
}


/**@brief Callback function receiving finding procedure results.
 *
 * @param[in]   bufid   Reference to Zigbee stack buffer used to pass
 *                      received data.
 */
static void find_light_bulb_cb(zb_bufid_t bufid)
{
	/* Get the beginning of the response. */
	zb_zdo_match_desc_resp_t *resp =
		(zb_zdo_match_desc_resp_t *) zb_buf_begin(bufid);
	/* Get the pointer to the parameters buffer, which stores APS layer
	 * response.
	 */
	zb_apsde_data_indication_t *ind = ZB_BUF_GET_PARAM(bufid,
							   zb_apsde_data_indication_t);
	zb_uint8_t *match_ep;
	 zb_ret_t zb_err_code;

	if ((resp->status == ZB_ZDP_STATUS_SUCCESS) &&
	    (resp->match_len > 0) &&
	    (bulb_ctx.short_addr == 0xFFFF)) {

		/* Match EP list follows right after response header. */
		match_ep = (zb_uint8_t *)(resp + 1);

		/* We are searching for exact cluster, so only 1 EP
		 * may be found.
		 */
		bulb_ctx.endpoint = *match_ep;
		bulb_ctx.short_addr = ind->src_addr;

		LOG_INF("Found bulb addr: %d ep: %d",
			bulb_ctx.short_addr,
			bulb_ctx.endpoint);

		k_timer_stop(&bulb_ctx.find_alarm);
		dk_set_led_on(BULB_FOUND_LED);
		
	} else {
		LOG_INF("Bulb not found, try again");
	}

	if (bufid) {
		zb_buf_free(bufid);
	}
	ready_to_bind = 1;
}


/**@brief Find bulb allarm handler.
 *
 * @param[in]   timer   Address of timer.
 */
static void find_light_bulb_alarm(struct k_timer *timer)
{
	ZB_ERROR_CHECK(zb_buf_get_out_delayed(find_light_bulb));
}


/**@brief Function for sending ON/OFF and Level Control find request.
 *
 * @param[in]   bufid   Reference to Zigbee stack buffer that will be used to
 *                      construct find request.
 */
static void find_light_bulb(zb_bufid_t bufid)
{
	zb_zdo_match_desc_param_t *req;
	zb_uint8_t tsn = ZB_ZDO_INVALID_TSN;

	/* Initialize pointers inside buffer and reserve space for
	 * zb_zdo_match_desc_param_t request.
	 */
	req = zb_buf_initial_alloc(bufid,
				   sizeof(zb_zdo_match_desc_param_t) + (1) * sizeof(zb_uint16_t));

	req->nwk_addr = MATCH_DESC_REQ_ROLE;
	req->addr_of_interest = MATCH_DESC_REQ_ROLE;
	req->profile_id = ZB_AF_HA_PROFILE_ID;

	/* We are searching for 2 clusters: On/Off and Level Control Server. */
	req->num_in_clusters = 2;
	req->num_out_clusters = 0;
	req->cluster_list[0] = ZB_ZCL_CLUSTER_ID_ON_OFF;
	req->cluster_list[1] = ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL;

	/* Set 0xFFFF to reset short address in order to parse
	 * only one response.
	 */
	bulb_ctx.short_addr = 0xFFFF;
	tsn = zb_zdo_match_desc_req(bufid, find_light_bulb_cb);

	/* Free buffer if failed to send a request. */
	if (tsn == ZB_ZDO_INVALID_TSN) {
		zb_buf_free(bufid);

		LOG_ERR("Failed to send Match Descriptor request");
	}
}

/**@brief Callback for detecting button press duration.
 *
 * @param[in]   timer   Address of timer.
 */
static void light_switch_button_handler(struct k_timer *timer)
{
	zb_ret_t zb_err_code;
	zb_uint16_t cmd_id;

	if (dk_get_buttons() & buttons_ctx.state) {
		atomic_set(&buttons_ctx.long_poll, ZB_TRUE);
		if (buttons_ctx.state == BUTTON_ON) {
			cmd_id = ZB_ZCL_LEVEL_CONTROL_STEP_MODE_UP;
		} else {
			cmd_id = ZB_ZCL_LEVEL_CONTROL_STEP_MODE_DOWN;
		}

		/* Allocate output buffer and send step command. */
		zb_err_code = zb_buf_get_out_delayed_ext(light_switch_send_step,
							 cmd_id,
							 0);
		if (!zb_err_code) {
			LOG_WRN("Buffer is full");
		}

		k_timer_start(&buttons_ctx.alarm, BUTTON_LONG_POLL_TMO,
			      K_NO_WAIT);
	} else {
		atomic_set(&buttons_ctx.long_poll, ZB_FALSE);
	}
}

#ifdef CONFIG_ZIGBEE_FOTA
static void confirm_image(void)
{
	if (!boot_is_img_confirmed()) {
		int ret = boot_write_img_confirmed();

		if (ret) {
			LOG_ERR("Couldn't confirm image: %d", ret);
		} else {
			LOG_INF("Marked image as OK");
		}
	}
}

static void ota_evt_handler(const struct zigbee_fota_evt *evt)
{
	switch (evt->id) {
	case ZIGBEE_FOTA_EVT_PROGRESS:
		dk_set_led(OTA_ACTIVITY_LED, evt->dl.progress % 2);
		break;

	case ZIGBEE_FOTA_EVT_FINISHED:
		LOG_INF("Reboot application.");
		/* Power on unused sections of RAM to allow MCUboot to use it. */
		if (IS_ENABLED(CONFIG_RAM_POWER_DOWN_LIBRARY)) {
			power_up_unused_ram();
		}

		sys_reboot(SYS_REBOOT_COLD);
		break;// // Simulate receiving a temperature report
    // int16_t simulatedTemperature = 2350; // Simulated temperature data
    // handleIncomingMessage(&simulatedTemperature);


	case ZIGBEE_FOTA_EVT_ERROR:
		LOG_ERR("OTA image transfer failed.");
		break;

	default:
		break;
	}
}

/**@brief Callback function for handling ZCL commands.
 *
 * @param[in]   bufid   Reference to Zigbee stack buffer
 *                      used to pass received data.
 */
static void zcl_device_cb(zb_bufid_t bufid)
{
	zb_zcl_device_callback_param_t *device_cb_param =
		ZB_BUF_GET_PARAM(bufid, zb_zcl_device_callback_param_t);

	if (device_cb_param->device_cb_id == ZB_ZCL_OTA_UPGRADE_VALUE_CB_ID) {
		zigbee_fota_zcl_cb(bufid);
	} else {
		device_cb_param->status = RET_NOT_IMPLEMENTED;
	}
}
#endif /* CONFIG_ZIGBEE_FOTA */

/**@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)
{
	zb_zdo_app_signal_hdr_t *sig_hndler = NULL;
	zb_zdo_app_signal_type_t sig = zb_get_app_signal(bufid, &sig_hndler);
	zb_ret_t status = ZB_GET_APP_SIGNAL_STATUS(bufid);

	/* Update network status LED. */
	zigbee_led_status_update(bufid, ZIGBEE_NETWORK_STATE_LED);

#ifdef CONFIG_ZIGBEE_FOTA
	/* Pass signal to the OTA client implementation. */
	zigbee_fota_signal_handler(bufid);
#endif /* CONFIG_ZIGBEE_FOTA */

	switch (sig) {
	case ZB_BDB_SIGNAL_DEVICE_REBOOT:
	/* fall-through */
	case ZB_BDB_SIGNAL_STEERING:
		/* Call default signal handler. */
		ZB_ERROR_CHECK(zigbee_default_signal_handler(bufid));
		if (status == RET_OK) {
			/* Check the light device address. */
			if (bulb_ctx.short_addr == 0xFFFF) {
				k_timer_start(&bulb_ctx.find_alarm,
					      MATCH_DESC_REQ_START_DELAY,
					      MATCH_DESC_REQ_TIMEOUT);
			}
		}
		break;
	case ZB_ZDO_SIGNAL_LEAVE:
		/* If device leaves the network, reset bulb short_addr. */
		if (status == RET_OK) {
			zb_zdo_signal_leave_params_t *leave_params =
				ZB_ZDO_SIGNAL_GET_PARAMS(sig_hndler, zb_zdo_signal_leave_params_t);

			if (leave_params->leave_type == ZB_NWK_LEAVE_TYPE_RESET) {
				bulb_ctx.short_addr = 0xFFFF;
			}
		}
		/* Call default signal handler. */
		ZB_ERROR_CHECK(zigbee_default_signal_handler(bufid));
		break;

	default:
		/* Call default signal handler. */
		ZB_ERROR_CHECK(zigbee_default_signal_handler// // Simulate receiving a temperature report
    // int16_t simulatedTemperature = 2350; // Simulated temperature data
    // handleIncomingMessage(&simulatedTemperature);
(bufid));
		break;
	}

	if (bufid) {
		zb_buf_free(bufid);
	}
}

#if CONFIG_BT_NUS

static void turn_on_cmd(struct k_work *item)
{
	ARG_UNUSED(item);
	zb_buf_get_out_delayed_ext(light_switch_send_on_off,
				   ZB_ZCL_CMD_ON_OFF_ON_ID, 0);
}

static void turn_off_cmd(struct k_work *item)
{
	ARG_UNUSED(item);
	zb_buf_get_out_delayed_ext(light_switch_send_on_off,
				   ZB_ZCL_CMD_ON_OFF_OFF_ID, 0);	
}

static void toggle_cmd(struct k_work *item)
{
	ARG_UNUSED(item);
	zb_buf_get_out_delayed_ext(light_switch_send_on_off,
				   ZB_ZCL_CMD_ON_OFF_TOGGLE_ID, 0);void
}

static void increase_cmd(struct k_work *item)
{
	ARG_UNUSED(item);
	zb_buf_get_out_delayed_ext(light_switch_send_step,
				   ZB_ZCL_LEVEL_CONTROL_STEP_MODE_UP, 0);
}

static void decrease_cmd(struct k_work *item)
{
	ARG_UNUSED(item);
	zb_buf_get_out_delayed_ext(light_switch_send_step,
				   ZB_ZCL_LEVEL_CONTROL_STEP_MODE_DOWN, 0);
}

static void on_nus_connect(struct k_work *item)
{
	ARG_UNUSED(item);
	dk_set_led_on(NUS_STATUS_LED);
}

static void on_nus_disconnect(struct k_work *item)
{
	ARG_UNUSED(item);
	dk_set_led_off(NUS_STATUS_LED);
}

static struct nus_entry commands[] = {
	NUS_COMMAND(COMMAND_ON, turn_on_cmd),
	NUS_COMMAND(COMMAND_OFF, turn_off_cmd),
	NUS_COMMAND(COMMAND_TOGGLE, toggle_cmd),
	NUS_COMMAND(COMMAND_INCREASE, increase_cmd),
	NUS_COMMAND(COMMAND_DECREASE, decrease_cmd),
	NUS_COMMAND(NULL, NULL),
};

#endif /* CONFIG_BT_NUS */

void main(void)
{

	
	//zb_ret_t          zb_err_code;
    zb_ieee_addr_t    ieee_addr;
    static zb_bool_t  bind_on = 0;
    static zb_bool_t  reporting_configured = 0;

	LOG_INF("Starting ZBOSS Light Switch example");

	/* Initialize. */
	configure_gpio();
	alarm_timers_init();
	register_factory_reset_button(FACTORY_RESET_BUTTON);

	zigbee_erase_persistent_storage(ERASE_PERSISTENT_CONFIG);
	zb_set_ed_timeout(ED_AGING_TIMEOUT_64MIN);
	zb_set_keepalive_timeout(ZB_MILLISECONDS_TO_BEACON_INTERVAL(3000));

	/* Set default bulb short_addr. */
	bulb_ctx.short_addr = 0xFFFF;
	

	/* If "sleepy button" is defined, check its state during Zigbee
	 * initialization and enable sleepy behavior at device if defined button
	 * is pressed.
	 */
#if defined BUTTON_SLEEPY
	if (dk_get_buttons() & BUTTON_SLEEPY) {
		zigbee_configure_sleepy_behavior(true);
	}
#endif

	/* Power off unused sections of RAM to lower device power consumption. */
	if (IS_ENABLED(CONFIG_RAM_POWER_DOWN_LIBRARY)) {
		power_down_unused_ram();
	}

#ifdef CONFIG_ZIGBEE_FOTA
	/* Initialize Zigbee FOTA download service. */
	zigbee_fota_init(ota_evt_handler);

	/* Mark the current firmware as valid. */
	confirm_image();

	/* Register callback for handling ZCL commands. */
	ZB_ZCL_REGISTER_DEVICE_CB(zcl_device_cb);
#endif /* CONFIG_ZIGBEE_FOTA */


	/* Register dimmer switch device context (endpoints). */
	ZB_AF_REGISTER_DEVICE_CTX(&dimmer_switch_ctx);

	app_clusters_attr_init();

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

#ifdef CONFIG_ZIGBEE_FOTA
	ZB_AF_SET_IDENTIFY_NOTIFICATION_HANDLER(CONFIG_ZIGBEE_FOTA_ENDPOINT, identify_cb);
#endif /* CONFIG_ZIGBEE_FOTA */

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

#if CONFIG_BT_NUS
	/* Initialize NUS command service. */
	nus_cmd_init(on_nus_connect, on_nus_disconnect, commands);
#endif /* CONFIG_BT_NUS */

	LOG_INF("ZBOSS Light Switch example started");

// Example of handling incoming temperature measurement
		int16_t simulatedTemperature = 2350; // Simulated temperature data
		handle_temperature_measurement(simulatedTemperature);

	while (1) {
		// k_sleep(K_FOREVER);
		zboss_main_loop_iteration();


        if (ready_to_bind && !bind_on) {
            LOG_INF("Ready to bind");
            zb_buf_get_out_delayed(bind_req);
            bind_on = 1;
        }
        else if (bind_on && !reporting_configured)
        {
            LOG_INF("Ready to configure reporting");
            zb_buf_get_out_delayed(configure_attr_reporting);
            reporting_configured = 1;
        }
    
	}
} 

As I am new to this, please help here get the above information.

Thanks a lot Slight smile!!!

Best Regards,
Deepika B




Parents
  • Hello again,

    This case from last year has some information on how to add ZCL clusters to an application. It can help you to get started. You can start with the light bulb and light switch samples as the base (instead of the Zigbee template) and add the clusters fror temperature measurement. Follow the guide, but use my reply from the ticket when you see any references to "ZB_HA"-macros.

    Next week I'll be able to provide more specific support. Thank you for your patience and best of luck.

    Best regards,

    Maria

Reply
  • Hello again,

    This case from last year has some information on how to add ZCL clusters to an application. It can help you to get started. You can start with the light bulb and light switch samples as the base (instead of the Zigbee template) and add the clusters fror temperature measurement. Follow the guide, but use my reply from the ticket when you see any references to "ZB_HA"-macros.

    Next week I'll be able to provide more specific support. Thank you for your patience and best of luck.

    Best regards,

    Maria

Children
No Data
Related