This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Detecting and exposing multiple Zigbee endpoints on remote device.

Hello everyone,

Some info about my setup:
OS: Windows 10
IDE: SEGGER Embedded Studio v4.22 (64bit)
HW: nRF52840 Dongle rev 1.2.0 as Coordinator,
nRF52840 DK rev 1.1.0 as Light Switch and Light Bulb

To give a high level overview of my task, I am trying to create multiple endpoints on a device (light bulb), detect those endpoints via another device (light switch), and be able to populate an array that holds various information about the light bulb device. As a simple test, I would then use the light switch Button 1 to send a toggle command to endpoint 10 on the bulb in order to control LED 1, and have Button 2 on the switch send a toggle command to endpoint 11 on the bulb in order to control LED 2. My issue is that I am unable to detect endpoint 11 as a numeric value in my light switch code, thus preventing me from sending a on_off_toggle command to LED 2.

I am using a modified version of the zigbee_light_control example. The modified changes are as follows:

  • Coordinator (nRF52840 Dongle rev 1.2.0) - No changes have been made to the original coordinator code.

  • Light Bulb (nRF52840 DK rev 1.1.0) - I have 2 endpoints (10 and 11) which implement the ON_OFF_OUTPUT clusters. The basis for the dual endpoint segment of code is taken from the ble_zigbee_dynamic_color_light_bulb_thingy example. Modifications had to be made to the ZB_DECLARE_SIMPLE_DESC and ZB_AF_SIMPLE_DESC_TYPE macros in order to allow 2 endpoints of similar cluster ID in my code.

    /********************* Declare variables **************************/
    /* Define bulb struct */
    typedef struct
    {
        uint8_t			    ep_id;
    
        zb_zcl_basic_attrs_ext_t        basic_attr;
        zb_zcl_identify_attrs_t         identify_attr;
        zb_zcl_on_off_attrs_ext_t       on_off_attr;
        zb_zcl_scenes_attrs_t           scenes_attr;
        zb_zcl_groups_attrs_t           groups_attr;
    } bulb_device_ctx_t;
    
    static bulb_device_ctx_t m_dev_ctx_1;
    static bulb_device_ctx_t m_dev_ctx_2;
    
    /********************* Declare attribute lists **************************/
    /* On/Off cluster attributes additions data */
    ZB_ZCL_DECLARE_ON_OFF_ATTRIB_LIST(m_dev_ctx_1_on_off_attr_list,
                                      &m_dev_ctx_1.on_off_attr.on_off);
    
    /* Basic cluster attributes data */
    ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST(m_dev_ctx_1_basic_attr_list,
                                     &m_dev_ctx_1.basic_attr.zcl_version,
                                     &m_dev_ctx_1.basic_attr.ph_env);
    
    /* Identify cluster attributes data */
    ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST(m_dev_ctx_1_identify_attr_list, &m_dev_ctx_1.identify_attr.identify_time);
    
    /* Groups cluster attributes data */
    ZB_ZCL_DECLARE_GROUPS_ATTRIB_LIST(m_dev_ctx_1_groups_attr_list, &m_dev_ctx_1.groups_attr.name_support);
    
    /* Scenes cluster attribute data */
    ZB_ZCL_DECLARE_SCENES_ATTRIB_LIST(m_dev_ctx_1_scenes_attr_list,
                                      &m_dev_ctx_1.scenes_attr.scene_count,
                                      &m_dev_ctx_1.scenes_attr.current_scene,
                                      &m_dev_ctx_1.scenes_attr.current_group,
                                      &m_dev_ctx_1.scenes_attr.scene_valid,
                                      &m_dev_ctx_1.scenes_attr.name_support);
    
    /* On/Off cluster attributes additions data */
    ZB_ZCL_DECLARE_ON_OFF_ATTRIB_LIST(m_dev_ctx_2_on_off_attr_list,
                                      &m_dev_ctx_2.on_off_attr.on_off);
    
    /* Basic cluster attributes data */
    ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST(m_dev_ctx_2_basic_attr_list,
                                     &m_dev_ctx_2.basic_attr.zcl_version,
                                     &m_dev_ctx_2.basic_attr.ph_env);
    
    /* Identify cluster attributes data */
    ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST(m_dev_ctx_2_identify_attr_list, &m_dev_ctx_2.identify_attr.identify_time);
    
    /* Groups cluster attributes data */
    ZB_ZCL_DECLARE_GROUPS_ATTRIB_LIST(m_dev_ctx_2_groups_attr_list, &m_dev_ctx_2.groups_attr.name_support);
    
    /* Scenes cluster attribute data */
    ZB_ZCL_DECLARE_SCENES_ATTRIB_LIST(m_dev_ctx_2_scenes_attr_list,
                                      &m_dev_ctx_2.scenes_attr.scene_count,
                                      &m_dev_ctx_2.scenes_attr.current_scene,
                                      &m_dev_ctx_2.scenes_attr.current_group,
                                      &m_dev_ctx_2.scenes_attr.scene_valid,
                                      &m_dev_ctx_2.scenes_attr.name_support);
    
    
    /********************* Declare cluster lists **************************/
    ZB_HA_DECLARE_ON_OFF_OUTPUT_CLUSTER_LIST(m_dev_ctx_1_on_off_output_clusters,
                                              m_dev_ctx_1_on_off_attr_list,
                                              m_dev_ctx_1_basic_attr_list,
                                              m_dev_ctx_1_identify_attr_list,
                                              m_dev_ctx_1_groups_attr_list,
                                              m_dev_ctx_1_scenes_attr_list);
    
    ZB_HA_DECLARE_ON_OFF_OUTPUT_CLUSTER_LIST(m_dev_ctx_2_on_off_output_clusters,
                                              m_dev_ctx_2_on_off_attr_list,
                                              m_dev_ctx_2_basic_attr_list,
                                              m_dev_ctx_2_identify_attr_list,
                                              m_dev_ctx_2_groups_attr_list,
                                              m_dev_ctx_2_scenes_attr_list);
    
    /********************* Declare endpoints **************************/
    /* Declare on/off endpoint */
    ZB_ZCL_DECLARE_ON_OFF_OUTPUT_EP_VA(on_off_output_ep_10,
    				    HA_OUTPUT_ENDPOINT_10,
    				    m_dev_ctx_1_on_off_output_clusters);
    
    ZB_ZCL_DECLARE_ON_OFF_OUTPUT_EP_VA(on_off_output_ep_11,
    				    HA_OUTPUT_ENDPOINT_11,
    				    m_dev_ctx_2_on_off_output_clusters);
    
    /********************* Declare device context **************************/
    /* Declare device context */
    ZBOSS_DECLARE_DEVICE_CTX_2_EP(on_off_bulb_ctx,
                                  on_off_output_ep_10,
                                  on_off_output_ep_11);
    

  • Light Switch (nRF52840 DK rev 1.1.0) - I have modified the code to change the find request in the function static zb_void_t find_light_bulb(zb_uint8_t param). I am looking for 2 input clusters, with the cluster list set to ZB_ZCL_CLUSTER_ID_ON_OFF.

        /* We are searching for 2 clusters: On/Off and Level Control Server */
        p_req->num_in_clusters  = 2;
        p_req->num_out_clusters = 0;
        /*lint -save -e415 // Suppress warning 415 "likely access of out-of-bounds pointer" */
        p_req->cluster_list[0]  = ZB_ZCL_CLUSTER_ID_ON_OFF;
        /*lint -restore */
        UNUSED_RETURN_VALUE(zb_zdo_match_desc_req(param, find_light_bulb_cb));


    Upon finding the bulb in question, I search struct member p_resp->match_len to determine how many endpoints have been found that match the search description, and it correctly reads 2. I have also tried using the light_switch_groups example, with the exact same results.

    zb_zdo_match_desc_resp_t   * p_resp = (zb_zdo_match_desc_resp_t *) ZB_BUF_BEGIN(p_buf);
    NRF_LOG_INFO("Match Length: %d", p_resp->match_len);

I know both endpoints on the bulb are functioning normally, because if I send a ZB_ZCL_ON_OFF_SEND_TOGGLE_REQ to the bulb by manually hard-coding either 10 or 11 in the dst_ep parameter of the macro, LED 1 and 2 light up respectively.

    ZB_ZCL_ON_OFF_SEND_TOGGLE_REQ(p_buf,
                                  dst_addr,
                                  dst_addr_mode,
                                  dst_ep,
                                  LIGHT_SWITCH_ENDPOINT,
                                  ZB_AF_HA_PROFILE_ID,
                                  ZB_ZCL_DISABLE_DEFAULT_RESPONSE,
                                  NULL);

My issue however is that during the search, while p_resp->match_len correctly states there are 2 endpoints on the device, the light switch is only able to detect endpoint 10 as a numeric value, and not endpoint 11.

I would like to know how to expose all the endpoints of a discovered device. Any example code would also be welcome in pointing me to the right direction.

Thank you in advance,
Angry Oatmeal

  • Hello,

    The issue is resolved, I managed to find the section of code needed to detect all endpoints. It is located in the zigbee_cli_cmd_zdo.c source file, I used the code in the function static void cmd_zb_match_desc_cb(zb_uint8_t param).

    if (p_resp->status == ZB_ZDP_STATUS_SUCCESS)
        {
            zb_uint8_t * p_match_ep = (zb_uint8_t *)(p_resp + 1);
    
            while (p_resp->match_len > 0)
            {
                /* Match EP list follows right after response header */
                nrf_cli_fprintf(p_tsn_ctx->p_cli,
                                NRF_CLI_NORMAL,
                                "src_addr=%0hx ep=%d\r\n",
                                p_ind->src_addr,
                                *p_match_ep);
    
                p_match_ep += 1;
                p_resp->match_len -= 1;
            }

    Hope this helps others,
    Angry Oatmeal

Related