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

How to receive acknowledgment at switch - Zigbee light control example

Hi,

I am looking where can I get the ACK from the light bulb, in Zigbee light control  example. I am using the latest sdk nRF5_SDK_for_Thread_and_Zigbee_v4.1.0_32ce5f8. 

what I am actually trying to achieve is to measure the network latency. I have already done that in Bluetooth Mesh as the light switch example can send a reliable message and I get the ACK if the packet is really delayed then a timeout. so is there a way to do the same in Zigbee light control example. For now I am not receiving any kind of ACK from the bulb. The switch just says

"Send ON/OFF command:"

and I can also see that on the bulb

"app: Set ON/OFF value: 1
<info> app: Set level value: 255
<info> app: zcl_device_cb status: 0
<info> app: zcl_device_cb id 0"  

p.s. I am using nRF 52840 dk (pca10056) as bulb & switch and a nRF 52840 dongle (pca10059) as a coordinator

Thanks

  • Hi,

    I am assuming you are talking about the APS ACKs. When you send a command where APS ACK is enabled in the data request packet, you will get an APS ACK (end-to-end acknowledge), as you can see in the following sniffer trace:

    Each frame is also acknowledge by the 802.15.4 (MAC) layer between frames.

    You can parse the APS ACK if you register a callback when calling ZB_ZCL_ON_OFF_SEND_REQ(). The callback can look something like this:

    static zb_void_t on_off_cmd_cb(zb_bufid_t param)
    {
        // Parse APS ACK.
        zb_bufid_t                     p_asdu = param;
        zb_zcl_command_send_status_t * p_cmd_ping_status = ZB_BUF_GET_PARAM(p_asdu, zb_zcl_command_send_status_t);
        zb_uint16_t                    short_addr;
        zb_ret_t                       zb_err_code;
    
    
        if (param == 0)
        {
            return;
        }
    
    
        // Resolve received address to the short address.
        if (p_cmd_ping_status->dst_addr.addr_type == ZB_ZCL_ADDR_TYPE_SHORT)
        {
            short_addr = p_cmd_ping_status->dst_addr.u.short_addr;
        }
        else if (p_cmd_ping_status->dst_addr.addr_type == ZB_ZCL_ADDR_TYPE_IEEE)
        {
            short_addr = zb_address_short_by_ieee(p_cmd_ping_status->dst_addr.u.ieee_addr);
        }
        else
        {
            //Just checking we have a valid address type
            NRF_LOG_ERROR("on_off cmd acknowledged with an unknown destination address type: %d", p_cmd_ping_status->dst_addr.addr_type);
            zb_buf_free(param);
            return;
        }
    
    
        NRF_LOG_INFO("on_off cmd acknowledge by destination address: %x, endpoint %d and status %d ", short_addr, p_cmd_ping_status->dst_endpoint, p_cmd_ping_status->status);
        zb_buf_free(param);
        return;
    }

    Just remember to free the buffer used when sending the command in this callback when you are finish parsing the APS ACK, if no callback is set (cb=NUL) the stack will free the buffer upon receibing the APS ACK automatically.

    And you can register the callback by passing it as the last parameter in ZB_ZCL_ON_OFF_SEND_REQ():

        ZB_ZCL_ON_OFF_SEND_REQ(bufid,
                               m_device_ctx.bulb_params.short_addr,
                               ZB_APS_ADDR_MODE_16_ENDP_PRESENT,
                               m_device_ctx.bulb_params.endpoint,
                               LIGHT_SWITCH_ENDPOINT,
                               ZB_AF_HA_PROFILE_ID,
                               ZB_ZCL_DISABLE_DEFAULT_RESPONSE,
                               cmd_id,
                               on_off_cmd_cb);

    The log output of the switch device will now look like this after sending an ON/OFF command:

    <info> app: Send ON/OFF command: 1
    <info> app: on_off cmd acknowledge by destination address: E00B, endpoint 10 and status 0 found.
    <info> app: Send ON/OFF command: 0
    <info> app: on_off cmd acknowledge by destination address: E00B, endpoint 10 and status 0 found.
    

    You can use a similar approach for getting the timing between the command and the APS ACK and thus the latency in your application.

    The good news is that we already have a benchmark example which does everything for you and you can use it to measure latency in a network (echo mode): https://infocenter.nordicsemi.com/topic/sdk_tz_v4.1.0/benchmark.html

    In the benchmark example we used zb_zcl_finish_and_send_packet() to send a control command packet and zigbee_benchmark_frame_error_handler is registered as a callback for handling incoming benchmark command APS ACKs.

    Best regards,

    Marjeris

  • Thanks a lot for pointing me towards the right direction (benchmark example), I will implement it and will get back to you for further queries if any

    p.s. do we also have a benchmark application example for BT mesh, I have seen it for BLE but not for mesh, I do have an implementation already but I could then compare it with something. Thanks again

    Cheers,
    Awais

  • Hi Awais,

    Unfortunately we don't have any specific example to do a benchmark in BLE Mesh, but it's possible to use any of the BT Mesh examples to measure latency.

    To measure latency you can make a client node to send acknowledged SET message to a specific server node in the network and ait for Status response. The difference between the timestamps of outgoing message (capture using TX_COMPLETE event) and incoming message (access metadata parameter of the status callback timestamp when the message PDU was received) will give you a round trip latency.

    Best regards,

    Marjeris

  • Hi Marjeris,

    I am measuring latency exactly like you told, thanks anyways.

    Cheers,
    Awais

Related