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

Zigbee communication failure

Hello Nordic!

I've been implementing some more commands in my endpoint handler but (I don't know how) it has stopped working. I have added the responses of the commands as shown in the code above but it just freezes the coordinator and makes the atribute reporting to stop. As a coordinator I am using a CC2531 with Zigbee2MQTT firmware flashed. 

As a guide for coding I am using this two links:

https://infocenter.nordicsemi.com/index.jsp?topic=%2Fsdk_tz_v4.1.0%2Fgroup__ha__door__lock.html

 https://infocenter.nordicsemi.com/index.jsp?topic=%2Fsdk_tz_v4.1.0%2Fusing_zigbee__z_c_l.html&anchor=register_zigbee_device

The code I am using is as follows, I have only pasted a part of the code because the callback is huge, but I could provide it if its needed:

    switch( cmd_info -> cluster_id )
    {
        case ZB_ZCL_CLUSTER_ID_DOOR_LOCK:
            if( cmd_info->is_common_command )
            {
                TRACE_MSG(TRACE_ZCL2, "Skip general command %hd", (FMT__H, cmd_info->cmd_id));
            }
            else
            {
                if (cmd_info -> cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV)
                {
                    switch (cmd_info->cmd_id) {
                        case ZB_ZCL_CMD_DOOR_LOCK_LOCK_DOOR:
                            bsp_board_led_off(LED_AUXILIAR);
                            set_estado_cerradura(ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_LOCKED);

                            // MANDAMOS LA RESPUESTA DEL COMANDO
                            ZB_ZCL_DOOR_LOCK_SEND_LOCK_DOOR_RES(bufferRespuesta,
                                                                ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr,
                                                                ZB_APS_ADDR_MODE_16_ENDP_PRESENT,
                                                                ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint,
                                                                ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint,
                                                                cmd_info->profile_id,
                                                                cmd_info->seq_number,
                                                                &status,
                                                                false);
                            cmd_processed = ZB_TRUE;
                            zb_buf_free(zigbeeBuffer);
                            //zb_buf_free(param);
                            zb_buf_free(bufferRespuesta);
                            return ZB_TRUE;
                            break;

                        case ZB_ZCL_CMD_DOOR_LOCK_UNLOCK_DOOR:
                            bsp_board_led_off(LED_AUXILIAR);
                            set_estado_cerradura(ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_UNLOCKED);

                            // MANDAMOS LA RESPUESTA DEL COMANDO
                            ZB_ZCL_DOOR_LOCK_SEND_UNLOCK_DOOR_RES(bufferRespuesta,
                                                                  ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr,
                                                                  ZB_APS_ADDR_MODE_16_ENDP_PRESENT,
                                                                  ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint,
                                                                  ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint,
                                                                  cmd_info->profile_id,
                                                                  cmd_info->seq_number,
                                                                  &status,
                                                                  false);
                            cmd_processed = ZB_TRUE;
                            zb_buf_free(zigbeeBuffer);
                            //zb_buf_free(param);
                            zb_buf_free(bufferRespuesta);
                            return ZB_TRUE;
                            break;
                    }
                }
            }
            break;

        default:
            TRACE_MSG(TRACE_ZCL1, "SRV role, cluster 0x%d is not supported", (FMT__D, cmd_info->cluster_id));
            break;
    }
return ZB_FALSE

Some strange issues I have came across:

- If I comment the response, the atribute reporting start working again. Can't figure out why, I need some explanation why.

- With the response uncommented, alhough the response is not sent, the atribute is set correctly but neither the response nor the atribute report is sent.

Cheers!

  • Hi,

    Are you implementing a door lock with the door lock server cluster on the nRF side? Have you taken a look at our BLE/Zigbee door lock example? https://infocenter.nordicsemi.com/topic/sdk_tz_v4.1.0/zigbee_multi_dynamic_door_lock_nus_example.html

    See how the ZCL callback function is implemented in the example:

    /**@brief Callback function for handling ZCL commands.
     *
     * @param[in]   bufid   Reference to Zigbee stack buffer used to pass received data.
     */
    static zb_void_t zcl_device_cb(zb_bufid_t bufid)
    {
        zb_zcl_device_callback_param_t * p_device_cb_param = ZB_BUF_GET_PARAM(bufid, zb_zcl_device_callback_param_t);
    
        /* Set default response value. */
        p_device_cb_param->status = RET_OK;
    
        switch (p_device_cb_param->device_cb_id)
        {
            case ZB_ZCL_DOOR_LOCK_UNLOCK_DOOR_CB_ID:
                set_lock_state(ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_UNLOCKED);
                break;
    
            case ZB_ZCL_DOOR_LOCK_LOCK_DOOR_CB_ID:
                set_lock_state(ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_LOCKED);
                break;
    
            default:
                p_device_cb_param->status = RET_ERROR;
                break;
        }
    }

    The only thing you should need to do is to intercept the command to set the status of the lock in your application, the response to the command should be send by the stack, see ZB_ZCL_DOOR_LOCK_LOCK_DOOR_CB_ID  and ZB_ZCL_DOOR_LOCK_UNLOCK_DOOR_CB_ID application callbacks.

    BR,

    Marjeris

  • Hello!

    Yes, I have checked the door_lock_nus example. In fact I am using it as a base for my code and I have modified a lot the example.

    I have to avoid the ZCL callback because it wasn't intercepting other commands such as Set Pin Code, Clear Pin Code and Get Pin Code and others. So I switched to an Endpoint Handler which effectively intercepts all commands. 

    Anyway, I could use the ZCL callback but I would need to add some more callbacks, for the previous commands (set, clear and get). Is there any way to add more application callbacks for other commands?

    The callback code is looking something similar to this:

    b_uint8_t ep_cb(zb_uint8_t param)
    {
        zb_bufid_t zigbeeBuffer = param;
        zb_zcl_parsed_hdr_t *cmd_info = ZB_BUF_GET_PARAM(zigbeeBuffer, zb_zcl_parsed_hdr_t);
        zb_bool_t cmd_processed = ZB_FALSE;
        zb_uint8_t cmd_length = zb_buf_len(zigbeeBuffer);
        zb_uint8_t *payload = (zb_uint8_t*) zb_buf_begin(zigbeeBuffer);
    
        zb_uint8_t status = ZB_ZCL_STATUS_SUCCESS;
        //zb_bufid_t* bufferRespuesta = zb_buf_get_out();
    
        switch( cmd_info -> cluster_id )
        {
            case ZB_ZCL_CLUSTER_ID_DOOR_LOCK:
                if( cmd_info->is_common_command )
                {
                    TRACE_MSG(TRACE_ZCL2, "Skip general command %hd", (FMT__H, cmd_info->cmd_id));
                }
                else
                {
                    if (cmd_info -> cmd_direction == ZB_ZCL_FRAME_DIRECTION_TO_SRV)
                    {
                        if (ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr == 0x0000)
                        {
                           coordinadorInfo.short_address = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).source.u.short_addr;
                           coordinadorInfo.source_endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).src_endpoint;
                           coordinadorInfo.destination_endpoint = ZB_ZCL_PARSED_HDR_SHORT_DATA(cmd_info).dst_endpoint;
                           coordinadorInfo.profile_id = cmd_info -> profile_id;
                        }
                        switch (cmd_info->cmd_id) {
                            case ZB_ZCL_CMD_DOOR_LOCK_LOCK_DOOR:
                                bsp_board_led_off(LED_AUXILIAR);
                                set_estado_cerradura(ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_LOCKED);
    
                                // MANDAMOS LA RESPUESTA DEL COMANDO
                                ZB_ZCL_DOOR_LOCK_SEND_LOCK_DOOR_RES(zigbeeBuffer,
                                                                   coordinadorInfo.short_address,
                                                                   ZB_APS_ADDR_MODE_16_ENDP_PRESENT,
                                                                   coordinadorInfo.source_endpoint,
                                                                   coordinadorInfo.destination_endpoint,
                                                                   coordinadorInfo.profile_id,
                                                                   cmd_info->seq_number,
                                                                   status,
                                                                   false);
                                cmd_processed = ZB_TRUE;
                                zb_buf_free(zigbeeBuffer);
                                //zb_buf_free(param);
                                // zb_buf_free(bufferRespuesta);
                                return ZB_TRUE;
                                break;
    
                            case ZB_ZCL_CMD_DOOR_LOCK_UNLOCK_DOOR:
                                bsp_board_led_off(LED_AUXILIAR);
                                set_estado_cerradura(ZB_ZCL_ATTR_DOOR_LOCK_LOCK_STATE_UNLOCKED);
    
                                // MANDAMOS LA RESPUESTA DEL COMANDO
                                ZB_ZCL_DOOR_LOCK_SEND_UNLOCK_DOOR_RES(zigbeeBuffer,
                                                                     coordinadorInfo.short_address,
                                                                     ZB_APS_ADDR_MODE_16_ENDP_PRESENT,
                                                                     coordinadorInfo.source_endpoint,
                                                                     coordinadorInfo.destination_endpoint,
                                                                     coordinadorInfo.profile_id,
                                                                     cmd_info->seq_number,
                                                                     status,
                                                                     false);
                                cmd_processed = ZB_TRUE;
                                zb_buf_free(zigbeeBuffer);
                                //zb_buf_free(param);
                                // zb_buf_free(bufferRespuesta);
                                return ZB_TRUE;
                                break;
    
                            case ZB_ZCL_CMD_DOOR_LOCK_SET_PIN_CODE:
                                bsp_board_led_off(LED_AUXILIAR);
                                // LEEMOS EL PAYLOAD DEL MENSAJE Y LO GUARDAMOS EN UNA CREDENCIAL TEMPORAL
                                tempCredencial.user_ID = (payload[1] << 8) + payload[0];
                                tempCredencial.user_status = payload[2];
                                tempCredencial.user_type = payload[3];
                                for (int i = 0; i < payload[4]; i++)
                                {
                                    tempCredencial.pin_code = (tempCredencial.pin_code << 8) + payload[5 + i];
                                }
                                // SETEAMOS EL USUARIO QUE HEMOS LEIDO
                                set_pin_code(tempCredencial.user_ID,
                                             tempCredencial.user_status,
                                             tempCredencial.user_type,
                                             tempCredencial.pin_code);
    
                                // MANDAMOS LA RESPUESTA DEL COMANDO
                                ZB_ZCL_DOOR_LOCK_SET_PIN_CODE_RES(zigbeeBuffer,
                                                                   coordinadorInfo.short_address,
                                                                   ZB_APS_ADDR_MODE_16_ENDP_PRESENT,
                                                                   coordinadorInfo.source_endpoint,
                                                                   coordinadorInfo.destination_endpoint,
                                                                   coordinadorInfo.profile_id,
                                                                  cmd_info->seq_number,
                                                                  status,
                                                                  false);
                                cmd_processed = ZB_TRUE;
                                zb_buf_free(zigbeeBuffer);
                                //zb_buf_free(param);
                                // zb_buf_free(bufferRespuesta);
                                return ZB_TRUE;
                                break;
    
                            case ZB_ZCL_CMD_DOOR_LOCK_GET_PIN_CODE:
                                bsp_board_led_on(LED_AUXILIAR);
                                tempCredencial.user_ID = (payload[1] << 8) + payload[0];
                                tempCredencial.pin_code = get_pin_code(tempCredencial.user_ID).pin_code;
                                // FIXME: HAY QUE PROBARLO
                                // RESPONDEMOS CON ESTA FUNCION
                                ZB_ZCL_DOOR_LOCK_GET_PIN_CODE_RES(zigbeeBuffer,
                                                                   coordinadorInfo.short_address,
                                                                   ZB_APS_ADDR_MODE_16_ENDP_PRESENT,
                                                                   coordinadorInfo.source_endpoint,
                                                                   coordinadorInfo.destination_endpoint,
                                                                   coordinadorInfo.profile_id,
                                                                  tempCredencial.user_ID,
                                                                  tempCredencial.user_status,
                                                                  tempCredencial.user_type,
                                                                  tempCredencial.pin_code,
                                                                  false);
                                cmd_processed = ZB_TRUE;
                                zb_buf_free(zigbeeBuffer);
                                //zb_buf_free(param);
                                // zb_buf_free(bufferRespuesta);
                                return ZB_TRUE;
                                break;
    
                            case ZB_ZCL_CMD_DOOR_LOCK_CLEAR_PIN_CODE:
                                bsp_board_led_off(LED_AUXILIAR);
                                // LEEMOS EL PAYLOAD Y LO GUARDAMOS COMO USER_ID
                                tempCredencial.user_ID = (payload[1] << 8) + payload[0];
                                clear_pin_code(tempCredencial.user_ID);
                                ZB_ZCL_DOOR_LOCK_CLEAR_PIN_CODE_RES(zigbeeBuffer,
                                                                   coordinadorInfo.short_address,
                                                                   ZB_APS_ADDR_MODE_16_ENDP_PRESENT,
                                                                   coordinadorInfo.source_endpoint,
                                                                   coordinadorInfo.destination_endpoint,
                                                                   coordinadorInfo.profile_id,
                                                                    cmd_info->seq_number,
                                                                    status,
                                                                    false);
                                cmd_processed = ZB_TRUE;
                                zb_buf_free(zigbeeBuffer);
                                //zb_buf_free(param);
                                // zb_buf_free(bufferRespuesta);
                                return ZB_TRUE;
                                break;
    
                            default:
                                //TRACE_MSG(TRACE_ZCL2, "Cluster command %hd, skip it", (FMT__H, cmd_info->cmd_id));
                                break;
                        }
                    }
                }
                break;
    
            default:
                break;
        }
        //if (cmd_processed == ZB_TRUE)
        //{
        //    zb_buf_free(zigbeeBuffer);
        //    zb_buf_free(param);
        //}
        //zb_buf_free(bufferRespuesta);
        return cmd_processed;
    }

    The code has a lot of commented lines because I am terribly lost and I have been testing different approaches.

    Cheers!

  • Hi,

    I am sorry I didn't come back to you on this one.

    mazis said:
    I have to avoid the ZCL callback because it wasn't intercepting other commands such as Set Pin Code, Clear Pin Code and Get Pin Code and others. So I switched to an Endpoint Handler which effectively intercepts all commands. 

    Do you still need help registering your ZCL command handler override cb?

    There is a small guide on how to intercept ZCL commands and overriding the handling of ZCL commands in the infocenter:
     https://infocenter.nordicsemi.com/topic/sdk_tz_v4.1.0/using_zigbee__z_c_l.html?cp=7_3_3_4_1_8_1#process_zcl_cmd_implementing

    Perhaps this will provide you with some help?

    Best regards,

    Marjeris

Related