Hello Nordic support,
I have a Zigbee coordinator application which has declared the time cluster as a server. I have a zigbee end device which has a time cluster as a client. When I send binding request from the coordinator for the time cluster, I get the bind status as success in the bind request callback function. However, I do not receive any read commands from the device for the time cluster.
This is how I have declared the time cluster and the endpoint, which has some other clusters as well:
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_ext_t on_off_attr;
zb_zcl_level_control_attrs_t level_control_attr;
//time cluster attributes
zb_zcl_time_attrs_t time_attr;
}server_device_ctx_t;
/************************************************************************
server endpoint variable
*************************************************************************/
#define ZB_HA_SERVER_EP_IN_CLUSTER_NUM 0
#define ZB_HA_SERVER_EP_OUT_CLUSTER_NUM 7
#define SERVER_REPORTING_ATTR_NR 4 //max nr of reporting attribute for server endpoint
#define ZB_HA_DECLARE_SERVER_EP_CLUSTER_LIST_COORD( \
cluster_list_name, \
basic_attr_list, \
identify_attr_list, \
scenes_attr_list, \
groups_attr_list, \
on_off_attr_list, \
level_control_attr_list, \
time_attr_list) \
zb_zcl_cluster_desc_t cluster_list_name[] = \
{ \
ZB_ZCL_CLUSTER_DESC( \
ZB_ZCL_CLUSTER_ID_IDENTIFY, \
ZB_ZCL_ARRAY_SIZE(identify_attr_list, zb_zcl_attr_t), \
(identify_attr_list), \
ZB_ZCL_CLUSTER_SERVER_ROLE, \
ZB_ZCL_MANUF_CODE_INVALID \
), \
ZB_ZCL_CLUSTER_DESC( \
ZB_ZCL_CLUSTER_ID_BASIC, \
ZB_ZCL_ARRAY_SIZE(basic_attr_list, zb_zcl_attr_t), \
(basic_attr_list), \
ZB_ZCL_CLUSTER_SERVER_ROLE, \
ZB_ZCL_MANUF_CODE_INVALID \
), \
ZB_ZCL_CLUSTER_DESC( \
ZB_ZCL_CLUSTER_ID_SCENES, \
ZB_ZCL_ARRAY_SIZE(scenes_attr_list, zb_zcl_attr_t), \
(scenes_attr_list), \
ZB_ZCL_CLUSTER_SERVER_ROLE, \
ZB_ZCL_MANUF_CODE_INVALID \
), \
ZB_ZCL_CLUSTER_DESC( \
ZB_ZCL_CLUSTER_ID_GROUPS, \
ZB_ZCL_ARRAY_SIZE(groups_attr_list, zb_zcl_attr_t), \
(groups_attr_list), \
ZB_ZCL_CLUSTER_SERVER_ROLE, \
ZB_ZCL_MANUF_CODE_INVALID \
), \
ZB_ZCL_CLUSTER_DESC( \
ZB_ZCL_CLUSTER_ID_ON_OFF, \
ZB_ZCL_ARRAY_SIZE(on_off_attr_list, zb_zcl_attr_t), \
(on_off_attr_list), \
ZB_ZCL_CLUSTER_SERVER_ROLE, \
ZB_ZCL_MANUF_CODE_INVALID \
), \
ZB_ZCL_CLUSTER_DESC( \
ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, \
ZB_ZCL_ARRAY_SIZE(level_control_attr_list, zb_zcl_attr_t), \
(level_control_attr_list), \
ZB_ZCL_CLUSTER_SERVER_ROLE, \
ZB_ZCL_MANUF_CODE_INVALID \
), \
ZB_ZCL_CLUSTER_DESC( \
ZB_ZCL_CLUSTER_ID_TIME, \
ZB_ZCL_ARRAY_SIZE(time_attr_list, zb_zcl_attr_t), \
(time_attr_list), \
ZB_ZCL_CLUSTER_SERVER_ROLE, \
ZB_ZCL_MANUF_CODE_INVALID \
) \
}
#define ZB_HA_DECLARE_SERVER_EP_SIMPLE_DESC( \
ep_name, ep_id, in_clust_num, out_clust_num) \
ZB_DECLARE_SIMPLE_DESC(in_clust_num, out_clust_num); \
ZB_AF_SIMPLE_DESC_TYPE(in_clust_num, out_clust_num) \
simple_desc_##ep_name = \
{ \
ep_id, \
ZB_AF_HA_PROFILE_ID, \
ZB_HA_IAS_ZONE_ID, \
ZB_HA_IAS_ZONE_VER, \
0, \
in_clust_num, \
out_clust_num, \
{ \
ZB_ZCL_CLUSTER_ID_IDENTIFY, \
ZB_ZCL_CLUSTER_ID_BASIC, \
ZB_ZCL_CLUSTER_ID_SCENES, \
ZB_ZCL_CLUSTER_ID_GROUPS, \
ZB_ZCL_CLUSTER_ID_ON_OFF, \
ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, \
ZB_ZCL_CLUSTER_ID_TIME \
} \
}
#define ZB_HA_DECLARE_SERVER_EP(ep_name, ep_id, cluster_list) \
ZB_HA_DECLARE_SERVER_EP_SIMPLE_DESC( \
ep_name, \
ep_id, \
ZB_HA_SERVER_EP_IN_CLUSTER_NUM, \
ZB_HA_SERVER_EP_OUT_CLUSTER_NUM); \
ZBOSS_DEVICE_DECLARE_REPORTING_CTX(reporting_info## device_ctx_name, \
SERVER_REPORTING_ATTR_NR); \
ZB_AF_DECLARE_ENDPOINT_DESC( \
ep_name, \
ep_id, \
ZB_AF_HA_PROFILE_ID, \
0, \
NULL, \
ZB_ZCL_ARRAY_SIZE(cluster_list, zb_zcl_cluster_desc_t), \
cluster_list, \
(zb_af_simple_desc_1_1_t*)&simple_desc_##ep_name, \
SERVER_REPORTING_ATTR_NR, \
reporting_info## device_ctx_name, \
0, \
NULL)
static server_device_ctx_t m_dev_ctx;
ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST(client_identify_attr_list, &m_dev_ctx.identify_attr.identify_time);
ZB_ZCL_DECLARE_GROUPS_ATTRIB_LIST(groups_attr_list, &m_dev_ctx.groups_attr.name_support);
ZB_ZCL_DECLARE_SCENES_ATTRIB_LIST(scenes_attr_list,
&m_dev_ctx.scenes_attr.scene_count,
&m_dev_ctx.scenes_attr.current_scene,
&m_dev_ctx.scenes_attr.current_group,
&m_dev_ctx.scenes_attr.scene_valid,
&m_dev_ctx.scenes_attr.name_support);
ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST_EXT(client_basic_attr_list,
&m_dev_ctx.basic_attr.zcl_version,
&m_dev_ctx.basic_attr.app_version,
&m_dev_ctx.basic_attr.stack_version,
&m_dev_ctx.basic_attr.hw_version,
m_dev_ctx.basic_attr.mf_name,
m_dev_ctx.basic_attr.model_id,
m_dev_ctx.basic_attr.date_code,
&m_dev_ctx.basic_attr.power_source,
m_dev_ctx.basic_attr.location_id,
&m_dev_ctx.basic_attr.ph_env,
m_dev_ctx.basic_attr.sw_ver);
/* On/Off cluster attributes additions data */
ZB_ZCL_DECLARE_ON_OFF_ATTRIB_LIST_EXT(on_off_attr_list,
&m_dev_ctx.on_off_attr.on_off,
&m_dev_ctx.on_off_attr.global_scene_ctrl,
&m_dev_ctx.on_off_attr.on_time,
&m_dev_ctx.on_off_attr.off_wait_time);
ZB_ZCL_DECLARE_LEVEL_CONTROL_ATTRIB_LIST(level_control_attr_list,
&m_dev_ctx.level_control_attr.current_level,
&m_dev_ctx.level_control_attr.remaining_time);
ZB_ZCL_DECLARE_TIME_ATTR_LIST(time_attr_list,
m_dev_ctx.time_attr);
// Declare cluster list for Nordic server end point
ZB_HA_DECLARE_SERVER_EP_CLUSTER_LIST_COORD(server_ep_clusters,
client_basic_attr_list,
client_identify_attr_list,
groups_attr_list,
scenes_attr_list,
on_off_attr_list,
level_control_attr_list,
time_attr_list);
ZB_HA_DECLARE_SERVER_EP(server_ep,
HA_SERVER_ENDPOINT,
server_ep_clusters);
ZBOSS_DECLARE_DEVICE_CTX_2_EP(ZbDev_ctx, server_ep, second_ep); //Note second endpoint is a client endpoint
This is how I bind to the time cluster:
void APP_zigbeeBindTime(uint16_t type, uint16_t short_addr, zb_ieee_addr_t * long_addr, uint16_t ep)
{
zb_zdo_bind_req_param_t *req;
zb_bufid_t buf;
buf = zb_buf_get_out();
DB_EXCEPTION(buf == ZB_BUF_INVALID);
req = ZB_BUF_GET_PARAM(buf, zb_zdo_bind_req_param_t);
ZB_MEMCPY(&req->src_address, long_addr, sizeof(zb_ieee_addr_t));
req->src_endp = ep;
req->cluster_id = ZB_ZCL_CLUSTER_ID_TIME;
req->dst_addr_mode = ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
ZB_MEMCPY(&req->dst_address.addr_long, &ieee_addr, sizeof(zb_ieee_addr_t));
req->dst_endp = HA_SERVER_ENDPOINT;
req->req_dst_addr = short_addr;
zb_zdo_bind_req(buf, zb_bind_timecluster_callback);
}
void zb_bind_timecluster_callback(zb_uint8_t param)
{
zb_zdo_bind_resp_t * p_resp = (zb_zdo_bind_resp_t *)zb_buf_begin(param);
if (p_resp->status == ZB_ZDP_STATUS_SUCCESS)
{
PRINT(APP_ZB_DB_PRINT1, "bind_time SUCCESS\r\n");
//APP_mainSetEventFromISR(eventDvlcoWindowBound);
}
else
{
PRINT(APP_ZB_DB_PRINT1, "bind_time error 0x%02x\r\n",p_resp->status);
}
zb_buf_free(param);
}
This is the function to initialise the server attributes, which is called in main(),
static void server_ep_attr_init(void)
{
/* Basic cluster attributes data */
m_dev_ctx.basic_attr.zcl_version = ZB_ZCL_VERSION;
m_dev_ctx.basic_attr.app_version = BULB_INIT_BASIC_APP_VERSION;
m_dev_ctx.basic_attr.stack_version = BULB_INIT_BASIC_STACK_VERSION;
m_dev_ctx.basic_attr.hw_version = BULB_INIT_BASIC_HW_VERSION;
/* Use ZB_ZCL_SET_STRING_VAL to set strings, because the first byte should
* contain string length without trailing zero.
*
* For example "test" string will be encoded as:
* [(0x4), 't', 'e', 's', 't']
*/
ZB_ZCL_SET_STRING_VAL(m_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(m_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(m_dev_ctx.basic_attr.date_code,
BULB_INIT_BASIC_DATE_CODE,
ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_DATE_CODE));
m_dev_ctx.basic_attr.power_source = BULB_INIT_BASIC_POWER_SOURCE;
ZB_ZCL_SET_STRING_VAL(m_dev_ctx.basic_attr.location_id,
BULB_INIT_BASIC_LOCATION_DESC,
ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_LOCATION_DESC));
m_dev_ctx.basic_attr.ph_env = BULB_INIT_BASIC_PH_ENV;
ZB_ZCL_SET_STRING_VAL(m_dev_ctx.basic_attr.sw_ver,
BULB_INIT_BASIC_SW_VERSION,
ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_SW_VERSION));
/* Identify cluster attributes data */
m_dev_ctx.identify_attr.identify_time = ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE;
/* On/Off cluster attributes data */
m_dev_ctx.on_off_attr.on_off = (zb_bool_t)ZB_ZCL_ON_OFF_IS_ON;
m_dev_ctx.level_control_attr.current_level = ZB_ZCL_LEVEL_CONTROL_LEVEL_MAX_VALUE;
m_dev_ctx.level_control_attr.remaining_time = ZB_ZCL_LEVEL_CONTROL_REMAINING_TIME_DEFAULT_VALUE;
/* Time cluster attributes */
uint16_t time_reg;
ReadRegister(ADDR_TIME_LOW, SIZE_TIME_LOW, &time_reg, false, false, true);
m_dev_ctx.time_attr.time = (uint32_t)time_reg;
ReadRegister(ADDR_TIME_HIGH, SIZE_TIME_HIGH, &time_reg, false, false, true);
m_dev_ctx.time_attr.time |= ((uint32_t)time_reg)<<16;
m_dev_ctx.time_attr.time_status = 0x01;
}
Also, in the main(), the callback for the server endpoint is declared:
ZB_AF_SET_ENDPOINT_HANDLER(HA_SERVER_ENDPOINT, serverEpClusterCallBack);
However, even though the time cluster bind callback status is a success, I never see the serverEpClusterCallback being triggered. Could you please let me know if I'm missing something for binding time cluster and how to resolve this?
Regards,
Anusha