I am trying to send a OnOff output cluster information to Co-ordinator when a button is pressed in the nrf52840 DK. The problem is the during the initial registration, the OnOff command is correctly sent, but after the button is pressed, I am unable to find the correct method to send the readresponse
Here is the complete program
#include <zephyr/types.h> #include <zephyr.h> #include <device.h> #include <soc.h> #include <drivers/pwm.h> #include <logging/log.h> #include <dk_buttons_and_leds.h> #include <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> /* Switch endpoint */ #define HA_SWITCH_ENDPOINT 12 /* Version of the application software (1 byte). */ #define SWITCH_INIT_BASIC_APP_VERSION 01 /* Version of the implementation of the Zigbee stack (1 byte). */ #define SWITCH_INIT_BASIC_STACK_VERSION 10 /* Version of the hardware of the device (1 byte). */ #define SWITCH_INIT_BASIC_HW_VERSION 11 /* Manufacturer name (32 bytes). */ #define SWITCH_INIT_BASIC_MANUF_NAME "DongleNordic" /* Model number assigned by manufacturer (32-bytes long string). */ #define SWITCH_INIT_BASIC_MODEL_ID "DongleSwitch" /* First 8 bytes specify the date of manufacturer of the device * in ISO 8601 format (YYYYMMDD). The rest (8 bytes) are manufacturer specific. */ #define SWITCH_INIT_BASIC_DATE_CODE "202201207777" /* Type of power sources available for the device. * For possible values see section 3.2.2.2.8 of ZCL specification. */ #define SWITCH_INIT_BASIC_POWER_SOURCE ZB_ZCL_BASIC_POWER_SOURCE_BATTERY /* Describes the physical location of the device (16 bytes). * May be modified during commisioning process. */ #define SWITCH_INIT_BASIC_LOCATION_DESC "Home" /* Describes the type of physical environment. * For possible values see section 3.2.2.2.10 of ZCL specification. */ #define SWITCH_INIT_BASIC_PH_ENV ZB_ZCL_BASIC_ENV_UNSPECIFIED #define TOGGLE_SWITCH DK_BTN3_MSK /* Nordic PWM nodes don't have flags cells in their specifiers, so * this is just future-proofing. */ #define FLAGS_OR_ZERO(node) \ COND_CODE_1(DT_PHA_HAS_CELL(node, pwms, flags), \ (DT_PWMS_FLAGS(node)), (0)) #ifndef ZB_ED_ROLE #error Define ZB_END_DEVICE_ROLE to compile enddevice source code. #endif static void switch_send_on_off(zb_bufid_t bufid, zb_uint16_t on_off); LOG_MODULE_REGISTER(app); /** * Placeholder for the bulb 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; } on_off_device_ctx_t; /* Zigbee device application context storage. */ static on_off_device_ctx_t dev_ctx; ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST( identify_attr_list, &dev_ctx.identify_attr.identify_time); ZB_ZCL_DECLARE_GROUPS_ATTRIB_LIST( groups_attr_list, &dev_ctx.groups_attr.name_support); 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); 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); ZB_HA_DECLARE_ON_OFF_OUTPUT_CLUSTER_LIST(on_off_output_clusters, on_off_attr_list, basic_attr_list, identify_attr_list, groups_attr_list, scenes_attr_list); ZB_HA_DECLARE_ON_OFF_OUTPUT_EP(on_off_output_ep, HA_SWITCH_ENDPOINT, on_off_output_clusters); ZB_HA_DECLARE_ON_OFF_OUTPUT_CTX(on_off_output_ctx, on_off_output_ep); /**@brief Callback for button events. * * @param[in] button_state Bitmask containing buttons state. * @param[in] has_changed Bitmask containing buttons * that have changed their state. */ static void button_changed(uint32_t button_state, uint32_t has_changed) { zb_ret_t zb_err_code; zb_uint16_t cmd_id = ZB_ZCL_CMD_ON_OFF_ON_ID; zb_err_code = zb_buf_get_out_delayed_ext(switch_send_on_off, cmd_id, 0); ZB_ERROR_CHECK(zb_err_code); } /**@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); } } /**@brief Function for sending ON/OFF requests to the network / co-ordinator. * * @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 switch_send_on_off(zb_bufid_t bufid, zb_uint16_t cmd_id) { LOG_INF("Send ON/OFF command: %d", cmd_id); zb_uint16_t coordinator_address = 0x0000; dev_ctx.on_off_attr.on_off = (zb_bool_t)ZB_ZCL_ON_OFF_IS_ON; ZB_ZCL_ON_OFF_SEND_REQ(bufid, coordinator_address, ZB_APS_ADDR_MODE_16_ENDP_PRESENT, HA_SWITCH_ENDPOINT, HA_SWITCH_ENDPOINT, ZB_AF_HA_PROFILE_ID, ZB_ZCL_ENABLE_DEFAULT_RESPONSE, cmd_id, NULL); } /**@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_uint8_t endpoint_invoked; zb_zcl_device_callback_param_t *device_cb_param = ZB_BUF_GET_PARAM(bufid, zb_zcl_device_callback_param_t); endpoint_invoked = device_cb_param->endpoint; LOG_INF("%s id %hd", __func__, device_cb_param->device_cb_id); LOG_INF("EndPoint Called is %d ", endpoint_invoked); /* Set default response value. */ device_cb_param->status = RET_OK; LOG_INF("ZB Callback started %c", bufid); 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) { /* 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 error(void) { while (true) { /* Spin forever */ k_sleep(K_MSEC(1000)); } } void main(void) { int err; LOG_INF("Starting Switch example"); /* Initialize */ configure_gpio(); err = settings_subsys_init(); if (err) { LOG_ERR("settings initialization failed"); } LOG_INF("Registering Device"); /* Register callback for handling ZCL commands. */ ZB_ZCL_REGISTER_DEVICE_CB(zcl_device_cb); LOG_INF("Setting Switch Context"); /* Register dimmer switch device context (all the endpoints). */ ZB_AF_REGISTER_DEVICE_CTX(&on_off_output_ctx); /* 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("Switch example started"); while (1) { // k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL)); } }
1. When the image is flashed in DK, it properly registers to the Zigbee2MQTT and send the correct response - please see the the Part 1 in the snapshot below. The Cluster is 'genOnOff, type 'readResponse' and json data {'OnOff':0}
2. After button is clicked - DK BTN3 in this case, the type changes to 'commandOn' with json data being empty - please see the Part 2 in the snapshot below. It is obviously due to the macro ZB_ZCL_ON_OFF_SEND_REQ. But I would need the cluster and the payload sent just like # 1. Which macro should I use to retain the type 'readResponse' for cluster 'genOnOff' and fill in the json data? This is for the OnOff Output ZCL