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
