This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Zigbee SDK 4.1 -> Light Control Example -> Light Switch binding & finding button not working

Hello everyone,

In the Light Control Example of Zigbee SDK 4.1 there is a Light Switch with a couple of button assignments.

Used board: PCA10056

  • (Light switch) Button 1
    • When the light bulb has been turned off, pressing this button once turns it back on.
    • When pressed for a longer period of time, increases the brightness of the light bulb.
  • (Light switch) Button 2
    • After the successful commissioning (LED3 state), pressing this button once turns off the light bulb (LED4).
    • When pressed for a longer period of time, decreases the brightness of the light bulb.
  • (Light switch) Button 3 – When pressed while resetting the board, enables the Sleepy End Device behavior.
  • (Light switch) Button 4 – When pressed, toggles the Finding & Binding mode on the local endpoint on or off.

Button 1, 2 and 3 are working, however Button 4 is unassigned to start the Finding & Binding mode.

When I press Button 4 I get the error "<info> app: Unhandled BSP Event received: 17"

A quick look in the code does indeed show that it is unassigned, so how do I start the Finding & Binding mode on my Light Switch? I want to bind it to a light bulb that I put in identifying mode.

Parents
  • Hi,

    You are correct that button 4 is unassigned in the light switch code, and that Finding and Binding is not implemented there. You can add this functionality to your application with the following steps:

    Add a case for the button event for button 4 in buttons_handler(), BSP_EVENT_KEY_3.

    case BSP_EVENT_KEY_3:
        toggle_find_n_bind();
        return;

    You need a function to start the Finding and Binding procedure. This is the toggle_find_n_bind() function you call when button 4 is pressed, as shown above:

    /**@brief Function to start the Finding & Binding Procedure.
     *        If the Finding & Binding Procedure was already started, cancel it.
     */
    static zb_void_t toggle_find_n_bind(void)
    {
        zb_ret_t zb_err_code;
    
        zb_err_code = zb_bdb_finding_binding_initiator(LIGHT_SWITCH_ENDPOINT, finding_n_binding_cb);
        if (zb_err_code == RET_OK)
        {
            bsp_board_led_on(FINDING_N_BINDING_STATE_LED);
            NRF_LOG_INFO("F&B: Started Finding & Binding procedure.");
        }
        else if (zb_err_code == RET_BUSY)
        {
            zb_bdb_finding_binding_initiator_cancel();
        }
        else if (zb_err_code == RET_INVALID_STATE)
        {
            NRF_LOG_WARNING("Device not yet commissionned!");
        }
        else
        {
            ZB_ERROR_CHECK(zb_err_code);
        }
    }

    In toggle_find_n_bind, you initiate the Finding and Binding procedure with zb_bdb_finding_binding_initiator(), which takes in the user callback for the procedure as a parameter, finding_n_binding_cb(). This callback can be implemented like this:

    /**@brief Callback to finding and binding procedure.
     *
     * @param[IN]   status  Procedure status.
     * @param[IN]   addr    Found device address.
     * @param[IN]   ep      Found device endpoint.
     * @param[IN]   cluster Common cluster ID.
     *
     * @return      Returned boolean value is used to decide if found device's cluster (ID given as parameter) should be bound.
     */
    static zb_bool_t finding_n_binding_cb(zb_int16_t status, zb_ieee_addr_t addr, zb_uint8_t ep, zb_uint16_t cluster)
    {
        zb_bool_t ret = ZB_FALSE;
        zb_char_t addr_buf[2 * 8 + 1];    /* 8 bytes (2 characters) plus one byte for null-terminator. */
        
        UNUSED_RETURN_VALUE(ieee_addr_to_str(addr_buf, sizeof(addr_buf), addr));
    
        switch (status)
        {
            case ZB_BDB_COMM_BIND_SUCCESS:
                NRF_LOG_INFO("Successfully bound node %s ep %hd cluster %hd",  NRF_LOG_PUSH(addr_buf), ep, cluster);
                break;
    
            case ZB_BDB_COMM_BIND_FAIL:
                NRF_LOG_INFO("Failed to bind node %s ep %hd cluster %hd", NRF_LOG_PUSH(addr_buf), ep, cluster);
                break;
    
            case ZB_BDB_COMM_BIND_ASK_USER:
                switch (cluster)
                {
                    case ZB_ZCL_CLUSTER_ID_ON_OFF:
                    case ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL:
                    case ZB_ZCL_CLUSTER_ID_IDENTIFY:
                    case ZB_ZCL_CLUSTER_ID_COLOR_CONTROL:
                        NRF_LOG_INFO("Trying to bind node %s ep %hd cluster %hd", NRF_LOG_PUSH(addr_buf), ep, cluster);
                        ret = ZB_TRUE;
                        break;
                    default:
                        /* We are not interested in this cluster. */
                        break;
                }
                break;
    
            default:
                /* Should not happen */
                break;
        }
    
        return ret;
    }

    The Zigbee stack will generate the signal ZB_BDB_SIGNAL_FINDING_AND_BINDING_INITIATOR_FINISHED when the Finding and Binding initiator has completed. You do not need to do anything with this signal, but you can use it if you want to get the status of the Finding and Binding procedure, to see if it was successful. If you want to do this, you can handle the signal in the zboss_signal_handler. Inside the switch there, add a case for ZB_BDB_SIGNAL_FINDING_AND_BINDING_INITIATOR_FINISHED:

            case ZB_BDB_SIGNAL_FINDING_AND_BINDING_INITIATOR_FINISHED:
                {
                    zb_zdo_signal_fb_initiator_finished_params_t * f_n_b_status = ZB_ZDO_SIGNAL_GET_PARAMS(p_sg_p, zb_zdo_signal_fb_initiator_finished_params_t);
                    switch(f_n_b_status->status)
                    {
                        case ZB_ZDO_FB_INITIATOR_STATUS_SUCCESS:
                            NRF_LOG_INFO("F&B: Remote peer has been bound");
                            break;
    
                        case ZB_ZDO_FB_INITIATOR_STATUS_CANCEL:
                            NRF_LOG_INFO("F&B: Initiator process was canceled");
                            break;
    
                        case ZB_ZDO_FB_INITIATOR_STATUS_ALARM:
                            NRF_LOG_INFO("F&B: Initiator process was timed out");
                            break;
    
                        case ZB_ZDO_FB_INITIATOR_STATUS_ERROR:
                            NRF_LOG_ERROR("F&B: Error.");
                            break;
    
                        default:
                            NRF_LOG_ERROR("F&B: Unknown error (status %d)", f_n_b_status->status);
                            break;
                    }
                }
                break;

    Best regards,

    Marte

Reply
  • Hi,

    You are correct that button 4 is unassigned in the light switch code, and that Finding and Binding is not implemented there. You can add this functionality to your application with the following steps:

    Add a case for the button event for button 4 in buttons_handler(), BSP_EVENT_KEY_3.

    case BSP_EVENT_KEY_3:
        toggle_find_n_bind();
        return;

    You need a function to start the Finding and Binding procedure. This is the toggle_find_n_bind() function you call when button 4 is pressed, as shown above:

    /**@brief Function to start the Finding & Binding Procedure.
     *        If the Finding & Binding Procedure was already started, cancel it.
     */
    static zb_void_t toggle_find_n_bind(void)
    {
        zb_ret_t zb_err_code;
    
        zb_err_code = zb_bdb_finding_binding_initiator(LIGHT_SWITCH_ENDPOINT, finding_n_binding_cb);
        if (zb_err_code == RET_OK)
        {
            bsp_board_led_on(FINDING_N_BINDING_STATE_LED);
            NRF_LOG_INFO("F&B: Started Finding & Binding procedure.");
        }
        else if (zb_err_code == RET_BUSY)
        {
            zb_bdb_finding_binding_initiator_cancel();
        }
        else if (zb_err_code == RET_INVALID_STATE)
        {
            NRF_LOG_WARNING("Device not yet commissionned!");
        }
        else
        {
            ZB_ERROR_CHECK(zb_err_code);
        }
    }

    In toggle_find_n_bind, you initiate the Finding and Binding procedure with zb_bdb_finding_binding_initiator(), which takes in the user callback for the procedure as a parameter, finding_n_binding_cb(). This callback can be implemented like this:

    /**@brief Callback to finding and binding procedure.
     *
     * @param[IN]   status  Procedure status.
     * @param[IN]   addr    Found device address.
     * @param[IN]   ep      Found device endpoint.
     * @param[IN]   cluster Common cluster ID.
     *
     * @return      Returned boolean value is used to decide if found device's cluster (ID given as parameter) should be bound.
     */
    static zb_bool_t finding_n_binding_cb(zb_int16_t status, zb_ieee_addr_t addr, zb_uint8_t ep, zb_uint16_t cluster)
    {
        zb_bool_t ret = ZB_FALSE;
        zb_char_t addr_buf[2 * 8 + 1];    /* 8 bytes (2 characters) plus one byte for null-terminator. */
        
        UNUSED_RETURN_VALUE(ieee_addr_to_str(addr_buf, sizeof(addr_buf), addr));
    
        switch (status)
        {
            case ZB_BDB_COMM_BIND_SUCCESS:
                NRF_LOG_INFO("Successfully bound node %s ep %hd cluster %hd",  NRF_LOG_PUSH(addr_buf), ep, cluster);
                break;
    
            case ZB_BDB_COMM_BIND_FAIL:
                NRF_LOG_INFO("Failed to bind node %s ep %hd cluster %hd", NRF_LOG_PUSH(addr_buf), ep, cluster);
                break;
    
            case ZB_BDB_COMM_BIND_ASK_USER:
                switch (cluster)
                {
                    case ZB_ZCL_CLUSTER_ID_ON_OFF:
                    case ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL:
                    case ZB_ZCL_CLUSTER_ID_IDENTIFY:
                    case ZB_ZCL_CLUSTER_ID_COLOR_CONTROL:
                        NRF_LOG_INFO("Trying to bind node %s ep %hd cluster %hd", NRF_LOG_PUSH(addr_buf), ep, cluster);
                        ret = ZB_TRUE;
                        break;
                    default:
                        /* We are not interested in this cluster. */
                        break;
                }
                break;
    
            default:
                /* Should not happen */
                break;
        }
    
        return ret;
    }

    The Zigbee stack will generate the signal ZB_BDB_SIGNAL_FINDING_AND_BINDING_INITIATOR_FINISHED when the Finding and Binding initiator has completed. You do not need to do anything with this signal, but you can use it if you want to get the status of the Finding and Binding procedure, to see if it was successful. If you want to do this, you can handle the signal in the zboss_signal_handler. Inside the switch there, add a case for ZB_BDB_SIGNAL_FINDING_AND_BINDING_INITIATOR_FINISHED:

            case ZB_BDB_SIGNAL_FINDING_AND_BINDING_INITIATOR_FINISHED:
                {
                    zb_zdo_signal_fb_initiator_finished_params_t * f_n_b_status = ZB_ZDO_SIGNAL_GET_PARAMS(p_sg_p, zb_zdo_signal_fb_initiator_finished_params_t);
                    switch(f_n_b_status->status)
                    {
                        case ZB_ZDO_FB_INITIATOR_STATUS_SUCCESS:
                            NRF_LOG_INFO("F&B: Remote peer has been bound");
                            break;
    
                        case ZB_ZDO_FB_INITIATOR_STATUS_CANCEL:
                            NRF_LOG_INFO("F&B: Initiator process was canceled");
                            break;
    
                        case ZB_ZDO_FB_INITIATOR_STATUS_ALARM:
                            NRF_LOG_INFO("F&B: Initiator process was timed out");
                            break;
    
                        case ZB_ZDO_FB_INITIATOR_STATUS_ERROR:
                            NRF_LOG_ERROR("F&B: Error.");
                            break;
    
                        default:
                            NRF_LOG_ERROR("F&B: Unknown error (status %d)", f_n_b_status->status);
                            break;
                    }
                }
                break;

    Best regards,

    Marte

Children
No Data
Related