How to perform energy scan on Zigbee coordinator?

Hello Nordic Team,

I have an application for Zigbee coordinator running on nrf52840.  My use case is for the coordinator to move to another channel with less noise if the current channel is noisy. For this, I am trying to use this function zb_zdo_mgmt_nwk_update_req to perform energy scan. However, when the callback is triggered, I see the status as 133.

This is the code snippet on how I use the function zb_zdo_mgmt_nwk_update_req for energy scan.

bool EnergyScan(uint8_t channel)
{
  zb_bufid_t bufid;
  zb_zdo_mgmt_nwk_update_req_t *req;
  zb_uint8_t zb_ret;
  uint32_t channelMask = 1UL << channel;
  bool ret = false;

  bufid = zb_buf_get_out();
  if (bufid == ZB_BUF_INVALID)
  {
    PRINT("No Zigbee buffer available\r\n");
  }
  else
  {
    req = ZB_BUF_GET_PARAM(bufid, zb_zdo_mgmt_nwk_update_req_t);
    ZB_CHANNEL_PAGE_SET_PAGE(req->hdr.scan_channels, ZB_CHANNEL_LIST_PAGE0_IDX);
    ZB_CHANNEL_PAGE_SET_MASK(req->hdr.scan_channels, channelMask);
    req->hdr.scan_duration = ZB_ZDO_NEW_ACTIVE_CHANNEL;
    req->dst_addr = ZB_NWK_BROADCAST_ALL_DEVICES; 
 
    zb_ret = zb_zdo_mgmt_nwk_update_req(bufid, EnergyScan_cb);

    if (zb_ret != ZB_ZDO_INVALID_TSN)
    {
      ret = true;
    }
    else
    {
      zb_buf_free(bufid);
    }
  }
  return ret;
}

static void EnergyScan_cb(zb_uint8_t bufid)
{
  zb_zdo_mgmt_nwk_update_notify_param_t * p_resp = (zb_zdo_mgmt_nwk_update_notify_param_t *)zb_buf_begin(bufid);
  PRINT("cb status %d, scanned ch %d list count %d energy %d %d %d %d %d %d %d %d \r\n",p_resp->hdr.status, p_resp->hdr.scanned_channels, p_resp->hdr.scanned_channels_list_count, p_resp->energy_values[0], p_resp->energy_values[1], p_resp->energy_values[2], p_resp->energy_values[3], p_resp->energy_values[4], p_resp->energy_values[5], p_resp->energy_values[6], p_resp->energy_values[7]);
  zb_buf_free(bufid);
}

When the callback is executed, this is the kind of prints that I get:

cb status 133, scanned ch 1966080 list count 255 energy 198 0 34 140 112 197 0 8

I would like to know the following:

1. What does the value 133 for status mean? 

2. Am I following the right approach for performing energy scan?

Can you please help address these questions?

Thanks,

Anusha

  • Hello Anusha,

    I have asked our Zigbee team what the status code 133 means, and whether or not this is the correct approach (I have not tried it before).

    I see from some of your older tickets that it looks like you are using the nRF5 SDK for Thread and Zigbee. Is that still the case, or are you using the nRF Connect SDK (NCS)? And whether it is nRF5 or NCS, what release version of the SDK are you using?

    Best regards,

    Edvin

  • Hi Edvin,

    Thanks for your response. 

    I went through the Zigbee specification documentation and I modified the parameters to perform energy scan as follows:

    bool EnergyScan(uint8_t channel)
    {
    zb_bufid_t bufid;
    zb_zdo_mgmt_nwk_update_req_t *req;
    zb_uint8_t zb_ret;
    uint32_t channelMask = 0x3fff800; //To scan all channels from 11-25 - Changed
    bool ret = false;
    
    bufid = zb_buf_get_out();
    if (bufid == ZB_BUF_INVALID)
    {
    PRINT("No Zigbee buffer available\r\n");
    }
    else
    {
    req = ZB_BUF_GET_PARAM(bufid, zb_zdo_mgmt_nwk_update_req_t);
    ZB_CHANNEL_PAGE_SET_PAGE(req->hdr.scan_channels, ZB_CHANNEL_LIST_PAGE0_IDX);
    ZB_CHANNEL_PAGE_SET_MASK(req->hdr.scan_channels, channelMask);
    req->hdr.scan_duration = 3; //Changed
    req->scan_count = 1; //Changed
    req->dst_addr = 0xD530; //Short address of the device to which the request is to be sent--Changed
    
    zb_ret = zb_zdo_mgmt_nwk_update_req(bufid, EnergyScan_cb);
    
    if (zb_ret != ZB_ZDO_INVALID_TSN)
    {
    ret = true;
    }
    else
    {
    zb_buf_free(bufid);
    }
    }
    return ret;
    }
    
    static void EnergyScan_cb(zb_uint8_t bufid)
    {
    zb_zdo_mgmt_nwk_update_notify_param_t * p_resp = (zb_zdo_mgmt_nwk_update_notify_param_t *)zb_buf_begin(bufid);
    PRINT("cb status %d, scanned ch %d list count %d energy %d %d %d %d %d %d %d %d \r\n",p_resp->hdr.status, p_resp->hdr.scanned_channels, p_resp->hdr.scanned_channels_list_count, p_resp->energy_values[0], p_resp->energy_values[1], p_resp->energy_values[2], p_resp->energy_values[3], p_resp->energy_values[4], p_resp->energy_values[5], p_resp->energy_values[6], p_resp->energy_values[7]);
    zb_buf_free(bufid);
    }


    With these changes, I could get the energy scan result as I could see from the debug prints and also from nRF Sniffer as below:

    Debug print:

    cb status 0, scanned ch 67106816 list count 15 energy 201 197 196 205 203 201 216 219 


    Wireshark log:



    With these changes, I could get the Network Update Notify for routers that are bound to coordinator as seen above. So, I think I am framing the network update request for energy scan correctly. Please let me know if otherwise.

    However, for sleepy end devices, the response is Not Supported as seen here:



    So, is it not mandatory to implement this for Zigbee end devices, which are sleepy in nature?

    Regarding the SDK version, I am still using nRF5 SDK for Thread and Zigbee and the version used is 4.2.0.

    Regards,
    Anusha

  • Hello,

    Actually, can you try to use zb_zdo_mgmt_nwk_update_notify_hdr_t instead of zb_zdo_mgmt_nwk_update_notify_param_t? There is an example code for the callback in the documentation for zb_zdo_mgmt_nwk_update_req():

    {
      zb_uint8_t tsn;
      zb_zdo_mgmt_nwk_update_req_t *req;
     
      req = ZB_BUF_GET_PARAM(buf, zb_zdo_mgmt_nwk_update_req_t);
     
      req->hdr.scan_channels = ZB_MAC_ALL_CHANNELS_MASK;
      req->hdr.scan_duration = TEST_SCAN_DURATION;
      req->scan_count = TEST_SCAN_COUNT;
     
      req->dst_addr = 0;
     
      tsn = zb_zdo_mgmt_nwk_update_req(param, mgmt_nwk_update_ok_cb);
    }
     
     
    void mgmt_nwk_update_ok_cb(zb_uint8_t param)
    {
      zb_bufid_t buf = param;
      zb_uint8_t *zdp_cmd = zb_buf_begin(buf);
      zb_zdo_mgmt_nwk_update_notify_hdr_t *notify_resp = (zb_zdo_mgmt_nwk_update_notify_hdr_t *)zdp_cmd;
     
      TRACE_MSG(TRACE_APS3,
                "notify_resp status %hd, scanned_channels %x %x, total_transmissions %hd, "
                "transmission_failures %hd, scanned_channels_list_count %hd, buf len %hd",
                (FMT__H_D_D_H_H_H_H, notify_resp->status, (zb_uint16_t)notify_resp->scanned_channels,
                 *((zb_uint16_t*)&notify_resp->scanned_channels + 1),
                 notify_resp->total_transmissions, notify_resp->transmission_failures,
                 notify_resp->scanned_channels_list_count, zb_buf_len(buf)));
     
      if (notify_resp->status == ZB_ZDP_STATUS_SUCCESS)
      {
        TRACE_MSG(TRACE_APS3, "mgmt_nwk_update_notify received, Ok", (FMT__0));
      }
      else
      {
        TRACE_MSG(TRACE_ERROR, "mgmt_nwk_update_notify received, ERROR incorrect status %x",
                  (FMT__D, notify_resp->status));
      }
     
      zb_buf_free(buf);
    }

    Best regards,

    Edvin

  • Hi Edvin,

    Thanks for this information. I see that even using zb_zdo_mgmt_nwk_update_notify_param_t works. I am using this as I need the energy of each channel scanned. 

    In this example, there are macros named TEST_SCAN_DURATION and TEST_SCAN_COUNT but I could not find their values in their documentation or in the nRF SDK. Could you please let me know the values of these macros?

    Regards,

    Anusha

  • Hello Anusha,

    From the Zigbee specification, section 2.4.3.3.9:

    So duration is between 0 and 5, and it seems like scan_count should be set to 1.

    Best regards,

    Edvin

Related