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 !!!
Best Regards,
Deepika B