cancel
Showing results for 
Search instead for 
Did you mean: 

Why is a STM32WB55-based ZigBee APS coordinator kicking out my router after 15 seconds?

m4l490n
Associate III

I'm working on a project using the STM32WB55 Nucleo Board with the Zigbee_APS_Coord example. I need this specific example because my application communicates at the APS level and doesn't use ZCL.

My application also requires a custom encryption key, and we don't use or support install codes. The system works by having the coordinator create a network with a known, configurable extended PAN ID, to which all router devices (no end devices, only routers) connect. Communication is then established using the custom encryption key.

I’m providing this background because I’m unsure if I’m misconfiguring the Zigbee_APS_Coord example for my coordinator. My goal is to allow my existing non-STM32 routers to connect to the STM32WB55 Nucleo Board acting as a coordinator. If anyone has insights or can point out potential issues, I'd appreciate the help.

FWIW, the routers already connect and work perfectly fine with my existing non-STM32 coordinator. I'm just trying to substitute the non-STM32 coordinator with an STM32WB55-based one.

I have only made these changes to the original example.

 

FIRST

I'm calling ZbChangeExtAddr in APP_ZIGBEE_StackLayersInit to configure my custom EPID:

 

 

/**
 * @brief  Initialize Zigbee stack layers
 *   None
 * @retval None
 */
static void APP_ZIGBEE_StackLayersInit(void)
{
    APP_DBG("APP_ZIGBEE_StackLayersInit");

    zigbee_app_info.zb = ZbInit(0U, NULL, NULL);
    assert(zigbee_app_info.zb != NULL);

    /********************* Configure Custon EPID *******************/
    ZbChangeExtAddr(zigbee_app_info.zb, ZIGBEE_DEFAULT_EPID);

    /* Create the endpoint and cluster(s) */
    APP_ZIGBEE_ConfigEndpoints();

    BSP_LED_Off(LED_RED);
    BSP_LED_Off(LED_GREEN);
    BSP_LED_Off(LED_BLUE);

    /* Configure the joining parameters */
    zigbee_app_info.join_status = (enum ZbStatusCodeT)0x01; /* init to error status */
    zigbee_app_info.join_delay = HAL_GetTick(); /* now */

    /* Initialization Complete */
    zigbee_app_info.has_init = true;

    /* run the task */
    UTIL_SEQ_SetTask(1U << CFG_TASK_ZIGBEE_NETWORK_FORM, CFG_SCH_PRIO_0);
} /* APP_ZIGBEE_StackLayersInit */

 

 

 

SECOND

I added code to get and print the EPID to verify that the network is using it and I changed this line memcpy(config.security.preconfiguredLinkKey, sec_key_ha, ZB_SEC_KEYSIZE); to memcpy(config.security.preconfiguredLinkKey, sec_key, ZB_SEC_KEYSIZE); so the code uses my custom key instead of the one it came with the original project. I did this in the APP_ZIGBEE_NwkForm function:

 

 

/**
 * @brief  Handle Zigbee network forming and joining
 *   None
 * @retval None
 */
static void APP_ZIGBEE_NwkForm(void)
{
    if ((zigbee_app_info.join_status != ZB_STATUS_SUCCESS) && (HAL_GetTick() >= zigbee_app_info.join_delay))
    {
        struct ZbStartupT config;
        enum ZbStatusCodeT status;

        /* Configure Zigbee Logging (only need to do this once, but this is a good place to put it) */
        ZbSetLogging(zigbee_app_info.zb, ZB_LOG_MASK_LEVEL_5, NULL);

        /* Attempt to join a zigbee network */
        ZbStartupConfigGetProDefaults(&config);

        /* Set the centralized network */
        APP_DBG("Network config : \e[93mAPP_STARTUP_CENTRALIZED_COORD\e[0m");
        config.startupControl = ZbStartTypeForm;

        /******************************* Verify EPID ********************************/
        zigbee_uint64_t local_epid;
        local_epid.val = ZbExtendedAddress(zigbee_app_info.zb);
        char epid_string[EUI64_SIZE * 3 + 1] = {0};
        for (int i = 0; i < EUI64_SIZE; i++)
        {
            sprintf(&epid_string[i * 3], "%02X ", local_epid.arr[EUI64_SIZE - 1 - i]);
        }
        APP_DBG("EPID: \e[93m%s\e[0m", epid_string);

        /******************************* Using custom key ********************************/
        memcpy(config.security.preconfiguredLinkKey, sec_key, ZB_SEC_KEYSIZE);

        config.channelList.count = 1;
        config.channelList.list[0].page = 0;
        config.channelList.list[0].channelMask = 1 << CHANNEL; /*Channel in use */

        /* Using ZbStartupWait (blocking) here instead of ZbStartup, in order to demonstrate how to do
         * a blocking call on the M4. */
        status = ZbStartupWait(zigbee_app_info.zb, &config);

        APP_DBG("ZbStartup Callback (status = 0x%02x)", status);
        zigbee_app_info.join_status = status;

        if (status == ZB_STATUS_SUCCESS)
        {
            zigbee_app_info.join_delay = 0U;
            BSP_LED_On(LED_GREEN);
        }
        else
        {
            APP_DBG("Startup failed, re-attempting to form a network after a short delay (%d ms)",
                    APP_ZIGBEE_STARTUP_FAIL_DELAY);
            zigbee_app_info.join_delay = HAL_GetTick() + APP_ZIGBEE_STARTUP_FAIL_DELAY;
        }
    }

    /* If Network forming/joining was not successful reschedule the current task to retry the process */
    if (zigbee_app_info.join_status != ZB_STATUS_SUCCESS)
    {
        UTIL_SEQ_SetTask(1U << CFG_TASK_ZIGBEE_NETWORK_FORM, CFG_SCH_PRIO_0);
    }
    else
    {
        /* Starting application init task */
        UTIL_SEQ_SetTask(1U << CFG_TASK_ZIGBEE_APP_START, CFG_SCH_PRIO_0);
    }
} /* APP_ZIGBEE_NwkForm */

 

 

 

I compile and flash the code and I can see this in the terminal:

m4l490n_0-1729285009752.png

Which confirms the use of my Extended PAN ID.

Then, after some seconds, my router seems to be connecting perfectly fine but it is kicked out after 15 seconds. Then it connects again only to be kicked out again and so on.

m4l490n_2-1729285330664.png

 

What is going on? What am I missing?

_________________________________________________________________________________

EDIT:

Once I configured the correct cluster and profile I was able to see the packet my router was sending upon connection. So the encryption key and network joining in general are working well, my only problem is that the coordinator is still kicking out the router after 15 seconds and I have no idea why.

m4l490n_0-1729293890931.png

 

1 ACCEPTED SOLUTION

Accepted Solutions
Ouadi
ST Employee

Hi @m4l490n ,

After reviewing your captures I noticed that the join procedure does not use the trust center link key exchange which should be initiated from the joined device with a Request Key frame which is expected by the coordinator, that's why it will be kicked out of network. 

To ignore the Trust Center Link Key at the join you have to add the following code on your application:

 


static void APP_ZIGBEE_StackLayersInit(void)
{
  APP_DBG("APP_ZIGBEE_StackLayersInit");

  zigbee_app_info.zb = ZbInit(0U, NULL, NULL);
  assert(zigbee_app_info.zb != NULL);

  /* Create the endpoint and cluster(s) */
  APP_ZIGBEE_ConfigEndpoints();

  /* Configure the joining parameters */
  zigbee_app_info.join_status = (enum ZbStatusCodeT) 0x01; /* init to error status */
  zigbee_app_info.join_delay = HAL_GetTick(); /* now */

  /* Initialization Complete */
  zigbee_app_info.has_init = true;

  /* Ignore Trust Center Key Exchange */
  bool val= FALSE;
  ZbBdbSet(zigbee_app_info.zb,ZB_BDB_TrustCenterRequiresKeyExchange,&val,sizeof(val));

  /* run the task */
  UTIL_SEQ_SetTask(1U << CFG_TASK_ZIGBEE_NETWORK_FORM, CFG_SCH_PRIO_0);
} /* APP_ZIGBEE_StackLayersInit */

 

From captures 253, the joining time allowed by default is expired, the coordinator sends a beacon response with a permit join set to false ( Zigbee Spec) that's why the router cannot join to your device anymore. To allow new devices to join the network for an extra amount of time you have to perform a ZbZdoPermitJoinReq.

Regards,

Ouadi

View solution in original post

10 REPLIES 10
Ouadi
ST Employee

Hello @m4l490n,

With only logs  it's not easy to analyze why the coordinator performs a leave after the association, a Wireshark capture would be more helpful to understand the reason. 

What kind of routers / non STM32 coordinator you are using ?

Best regards,

Ouadi

@Ouadi thank you for helping!

The nonSTM routers and coordinator I'm using are our custom devices. They are based on the EFR32MG24 SoC from Silicon Labs.

How can I use Wireshark for this? Can I use the USB dongle that comes with the STM32WB55 Nucleo Pack? if so, what firmware can I use with it?

Hi @m4l490n,

Please follow the procedure on the wiki page to configure the STM32WB as a 802.15.4 sniffer: https://wiki.stmicroelectronics.cn/stm32mcu/wiki/Connectivity:How_to_configure_sniffer_for_802.15.4 

Best regards,

Ouadi

Hello @Ouadi 

I have attached the Wireshark capture. It includes two instances of my nonSTM32 router device joining, being accepted, sending data to the STM32 APS Coordinator, and finally being kicked out of the network.

Thanks again for the support. I appreciate it!

Can you also provide the network key to decrypt the packets ? 

Thanks,

@Ouadi 

After sending the first capture, I let it run to see what happens. I observed that after several join-leave "cycles", in this case, 6, the STM32 APS Coordinator fails and my nonSTM router can't connect anymore. I know is the STM32 APS Coordinator the one that is failing because my nonSTM router device can connect just fine again after I reboot the STM32 APS Coordinator.

In the attached capture, you can see that something is wrong from captures 253 to 282. My nonSTM router device was not able to connect after capture 253 and it was able to connect again after capture 282 that is when I rebooted the STM32 APS Coordinator.

Please let me know your observations.

Thanks!

@Ouadi  Of course, the key is "MySuperSecureKey"

Ouadi
ST Employee

Hi @m4l490n ,

After reviewing your captures I noticed that the join procedure does not use the trust center link key exchange which should be initiated from the joined device with a Request Key frame which is expected by the coordinator, that's why it will be kicked out of network. 

To ignore the Trust Center Link Key at the join you have to add the following code on your application:

 


static void APP_ZIGBEE_StackLayersInit(void)
{
  APP_DBG("APP_ZIGBEE_StackLayersInit");

  zigbee_app_info.zb = ZbInit(0U, NULL, NULL);
  assert(zigbee_app_info.zb != NULL);

  /* Create the endpoint and cluster(s) */
  APP_ZIGBEE_ConfigEndpoints();

  /* Configure the joining parameters */
  zigbee_app_info.join_status = (enum ZbStatusCodeT) 0x01; /* init to error status */
  zigbee_app_info.join_delay = HAL_GetTick(); /* now */

  /* Initialization Complete */
  zigbee_app_info.has_init = true;

  /* Ignore Trust Center Key Exchange */
  bool val= FALSE;
  ZbBdbSet(zigbee_app_info.zb,ZB_BDB_TrustCenterRequiresKeyExchange,&val,sizeof(val));

  /* run the task */
  UTIL_SEQ_SetTask(1U << CFG_TASK_ZIGBEE_NETWORK_FORM, CFG_SCH_PRIO_0);
} /* APP_ZIGBEE_StackLayersInit */

 

From captures 253, the joining time allowed by default is expired, the coordinator sends a beacon response with a permit join set to false ( Zigbee Spec) that's why the router cannot join to your device anymore. To allow new devices to join the network for an extra amount of time you have to perform a ZbZdoPermitJoinReq.

Regards,

Ouadi

@Ouadi Thank you very much. That was the solution.

I just have another question. Where can I call ZbZdoPermitJoinReq? I don't see any tick function or any other place to call that periodically.