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

Zigbee: Giving end device permission to join network

Hi,

I'm working with the nrf52840-DK and using the nRF5 SDK v15.2.0 Stack version.

I´ve got a working program for my coordinator (C) and my end device (ED). The C establishes the network successfully, the ED is able to join and they are both able to send messages to each other, by pressing one of the buttons on the nrf52840 DK. It also works to find out the short address and other information about the new joined device.
NOTE: I attached my coordinators main, buttons_handler_function, and zboss_signal_handler below.

As soon as the ED is switched on, it starts searching for a network, if it is in range of my C, it instantly joins the network. Now I want my C not to respond to the joining requests of the the ED unless one of the C buttons is pressed.

So far I couldn´t find a way to control the commissioning/joining procedure. Feels like Zigbee is managing all of this stuff by it self and is giving me just an interrupt in the zboss_signal_handler. It jumps correctly into the case ZB_ZDO_SIGNAL_DEVICE_ANNCE, which gives me the chance to get all the informations about the new device (as mentioned above) and call other functions. But at the time I get the interrupt in the zboss_signal_handler, the joining procedure is already done!

I already figured out that I could change -> ZB_DEFAULT_PRMIT_JOINING_DURATION   0xff  (in zb_config_common.h ). But I don´t know on which value I have to set ZB_DEFAULT_PRMIT_JOINING_DURATION in order to lower the permit time to a few seconds. But this still won´t enable me to control the commissioning/joining procedure.


So my two issues that I´m struggling with are:

1. How to control the commissioning/joining procedure?

2. Do I have to reduce the joining duration and how do I do that?

Thanks
Greetings Luke

#include "zboss_api.h"
#include "zboss_api_aps.h"
#include "zb_mem_config_med.h"
#include "zb_error_handler.h"

#include "zb_zcl_commands.h"
#include "zb_zcl_basic.h"
#include "bsp.h"
#include "boards.h"


#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"


#define MAX_CHILDREN                      2                                    /**< The maximum amount of connected devices. Setting this value to 0 disables association to this device.  */
#define IEEE_CHANNEL_MASK                 (1l << ZIGBEE_CHANNEL)                /**< Scan only one, predefined channel to find the coordinator. */
#define COORDINATOR_ENDPOINT              10                                    /**< Device endpoint, used to receive light controlling commands. */
#define ERASE_NVRAM_AT_REBOOT             ZB_FALSE                              /**< Do not erase NVRAM to save the network parameters after device reboot or power-off. */
#define ZB_ON_STATUS                      BSP_BOARD_LED_0                       //LED indicating that device boot was successful
#define ZB_MESSAGE_RECEIVED               BSP_BOARD_LED_3                       //LED indicating that message was receive
#define ZB_NWK_ROLE_LED                   BSP_BOARD_LED_1                       //LED indicating which NWK role device has
#define ZB_FOUND_DEVICE_LED_2             BSP_BOARD_LED_2 

#ifndef ZB_COORDINATOR_ROLE
#error Define ZB_COORDINATROR_ROLE to compile coordinator source code.
#endif 

/*
.....SOME DECALRATIONS AND DEFINTIONS OF VARIABLES AND FUNCTIONS....

*/

static void buttons_routine(bsp_event_t event)
{
  zb_ret_t        error_code;
  zb_uint8_t      transmit_mode_id;

  switch (event)
  {
    case BSP_EVENT_KEY_0:
    {
      current_pressed_button = BSP_EVENT_KEY_0-13;
      NRF_LOG_INFO("BUTTON: %d is pressed", current_pressed_button);
      break;
    }

    case BSP_EVENT_KEY_1:
    {
	current_pressed_button = BSP_EVENT_KEY_1-13;
      	NRF_LOG_INFO("BUTTON: %d is pressed", current_pressed_button);
      	break;
    }

    case BSP_EVENT_KEY_2:
    {
 	current_pressed_button = BSP_EVENT_KEY_2-13;
      	NRF_LOG_INFO("BUTTON: %d is pressed", current_pressed_button);
      	break;
    }

    case BSP_EVENT_KEY_3:
    {
 	current_pressed_button = BSP_EVENT_KEY_3-13;
      	NRF_LOG_INFO("BUTTON: %d is pressed", current_pressed_button);
      	break;

    default: 
    {
      NRF_LOG_INFO("Button without meaning -> no action");
      break;
    }
  }

  ZB_FREE_BUF_BY_REF(event);
};



void zboss_signal_handler(zb_uint8_t param)
{
  zb_zdo_app_signal_type_t  signal = zb_get_app_signal(param,NULL);
  zb_ret_t                  status = ZB_GET_APP_SIGNAL_STATUS(param);
  zb_ret_t                  zb_error_code;
  zb_bool_t                 comm_status;

  g_p_buf    = ZB_BUF_FROM_REF(param); 
  g_p_ind    = ZB_GET_BUF_PARAM(g_p_buf, zb_apsde_data_indication_t);
  // Getting information out of the received Signal.
  switch (signal)
  {
    case ZB_BDB_SIGNAL_DEVICE_FIRST_START:   //Device started and commissioned
    case ZB_BDB_SIGNAL_DEVICE_REBOOT:
    {
      if(status ==RET_OK)
      {
        NRF_LOG_INFO ("Device start: SUCCESSFUL. Network steering started. Signal: %d Status: %d",signal, status);
        comm_status=bdb_start_top_level_commissioning(ZB_BDB_NETWORK_STEERING);
        ZB_COMM_STATUS_CHECK(comm_status);
        //zb_error_code =ZB_SCHEDULE_ALARM(find_member_routine_to,param,ZB_C_SHORT_TIME_DELAY);
        //ZB_ERROR_CHECK(zb_error_code);
      }

      else
      {
        NRF_LOG_ERROR("Network steering failed, retry again. Status %d",status);
        zb_error_code=ZB_SCHEDULE_ALARM(bdb_restart_top_level_commissioning,0,ZB_TIME_ONE_SECOND);

      }
      break;
     }

     case ZB_BDB_SIGNAL_STEERING:
     {
      
      if(status ==RET_OK)
      {
        NRF_LOG_INFO("Steering in progress: %d", signal);
        zb_error_code = ZB_SCHEDULE_ALARM(steering_finished,param,ZB_TIME_ONE_SECOND);
      }
      else
      {
        NRF_LOG_ERROR("Steering failed. retry again in 1s. Status: %d", status);
        zb_error_code = ZB_SCHEDULE_ALARM(bdb_restart_top_level_commissioning,0, ZB_TIME_ONE_SECOND);
        ZB_ERROR_CHECK(zb_error_code);
      }
      break;
     }

     case ZB_ZDO_SIGNAL_PRODUCTION_CONFIG_READY:
     {
      if(status!=RET_OK)
      {
        NRF_LOG_WARNING("Production config is not present!");
      }
      break;
     }

     case ZB_ZDO_SIGNAL_DEVICE_ANNCE:
     {
        NRF_LOG_INFO("\n++++Signal Device Announcement: %d ->Status:%d+++",signal,status);
        UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
        zb_error_code = ZB_GET_OUT_BUF_DELAYED2(get_peer_address,param);
        ZB_ERROR_CHECK(zb_error_code);
      break;
     }

      default:
      NRF_LOG_INFO("UNKNOWN SIGNAL-> %d! Status: %d",signal,status);
      break;
    }
  //Free Buffer
  if(param)
  {
    //ZB_FREE_BUF_BY_REF(param);
  }
 }
/*END*******************************************************************ZBOSS SIGNAL HANDLER******************************************************************************/


int main(void)
 {
    zb_ret_t       zb_err_code;
    zb_ieee_addr_t ieee_addr;


    timers_init();
    log_init();
    leds_init();
    buttons_init();

    ZB_SET_TRACE_LEVEL(ZIGBEE_TRACE_LEVEL);
    ZB_SET_TRACE_MASK(ZIGBEE_TRACE_MASK);
    ZB_SET_TRAF_DUMP_OFF();

    ZB_INIT("zdo_zc");

    zb_osif_get_ieee_eui64(ieee_addr);
    zb_set_long_address(ieee_addr);

    zb_set_network_coordinator_role(IEEE_CHANNEL_MASK);
    zb_set_max_children(MAX_CHILDREN);
    //do not erase NVRAM after Reboot
    zb_set_nvram_erase_at_start(ERASE_NVRAM_AT_REBOOT);

    //ZB_ZCL_REGISTER_DEVICE_CB(zcl_device_cb);

    ZB_AF_REGISTER_DEVICE_CTX(&router_ctx);

    //Registering the zcl_device_cb in order to handle interrupt, when message is received
    ZB_AF_SET_ENDPOINT_HANDLER(COORDINATOR_ENDPOINT, zcl_device_cb);

    /** Start Zigbee Stack. */
    zb_err_code = zboss_start();
    ZB_ERROR_CHECK(zb_err_code);


    bsp_board_led_on(ZB_ON_STATUS);

    while(1)
    {
        bsp_board_led_off(ZB_MESSAGE_RECEIVED);
        zboss_main_loop_iteration();
        UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
    }
}

Parents
  • Hi,

    Have you read this section of the Zigbee SDK documentation?

    Support for Zigbee commissioning

    Best regards,
    Jørgen

  • Hi,

    I'm sorry for the long wait for the answer to this case. I just got this feedback from the developers:

    The trick is to use zboss_start_no_autostart() and then handle commissioning manually in ZB_ZDO_SIGNAL_SKIP_STARTUP. It's somehow described in the docs although I see that DSR didn't update that part of the dev guide. Please see attached diff: 

    diff --git a/sdk/nrf5/examples/zigbee/light_control/light_coordinator/main.c b/sdk/nrf5/examples/zigbee/light_control/light_coordinator/main.c
    index 2d85e098d3..d6b57052e1 100644
    --- a/sdk/nrf5/examples/zigbee/light_control/light_coordinator/main.c
    +++ b/sdk/nrf5/examples/zigbee/light_control/light_coordinator/main.c
    @@ -131,20 +131,16 @@ void zboss_signal_handler(zb_uint8_t param)
     
         switch(sig)
         {
    -        case ZB_BDB_SIGNAL_DEVICE_FIRST_START: // Device started and commissioned first time after NVRAM erase.
    -        case ZB_BDB_SIGNAL_DEVICE_REBOOT:      // BDB initialization completed after device reboot, use NVRAM contents during initialization. Device joined/rejoined and started.
    -            if (status == RET_OK)
    +        case ZB_ZDO_SIGNAL_SKIP_STARTUP:
    +            if (zb_bdb_is_factory_new())
                 {
    -                NRF_LOG_INFO("Device started OK. Start network steering.");
    -                comm_status = bdb_start_top_level_commissioning(ZB_BDB_NETWORK_STEERING);
    +                comm_status = bdb_start_top_level_commissioning(ZB_BDB_NETWORK_STEERING | ZB_BDB_NETWORK_FORMATION);
                     ZB_COMM_STATUS_CHECK(comm_status);
                 }
                 else
                 {
    -                NRF_LOG_ERROR("Device startup failed. Status: %d. Retry network formation after 1 second.", status);
    -                bsp_board_led_off(ZIGBEE_NETWORK_STATE_LED);
    -                zb_err_code = ZB_SCHEDULE_ALARM(bdb_restart_top_level_commissioning, 0, ZB_TIME_ONE_SECOND);
    -                ZB_ERROR_CHECK(zb_err_code);
    +                comm_status = bdb_start_top_level_commissioning(ZB_BDB_INITIALIZATION);
    +                ZB_COMM_STATUS_CHECK(comm_status);
                 }
                 break;
     
    @@ -225,7 +221,7 @@ int main(void)
         zigbee_erase_persistent_storage(ERASE_PERSISTENT_CONFIG);
     
         /** Start Zigbee Stack. */
    -    zb_err_code = zboss_start();
    +    zb_err_code = zboss_start_no_autostart();
         ZB_ERROR_CHECK(zb_err_code);
     
         while(1)
    

    Best regards,
    Jørgen

  • Hi,

    thanks for replying! Yes it works with SKIP_START_UP but this only helps me to control the procedure to found the network.

    But as soon as my End-Device sends a joining request, I get an interrupt in the signal handler with the signal: ZB_NWK_SIGNAL_DEVICE_ASSOCIATED: so the end device already joined the network, before I had a chance to  decide whether the coordinator should give permission or not. 

    Is there a way, to check the incoming joining request, before my Coordinator automatically gives permission?

    If found out that a former ember ZigBee Stack, from 2007 already had this option: http://www.anglia.com/zigbee/pdf/principles.pdf (Turn to slide 5). There's a function that can accept or deny the joining requests. They called it emberTrustCenterJoinHandler(). 
    Is there something similar for the Nordic ZigBee Stack. Kind of a function that enables me, to accept or deny the joining request?

    Thanks
    Greeting Luke

  • Hi,

    Apologies for the long wait for my reply in this case. I just got the feedback from our developer:

    Unfortunately, there is no such functions/API in the current Zigbee stack. There are two approaches that could be used to control which devices join the network:

    1. Use Install Codes. The Install Code of a device which is joining the network must be added to the Trust Center before it can join.
    2. Handle ZB_ZDO_SIGNAL_DEVICE_ANNCE, to detect that a device has joined, and use zdo_mgmt_leave_req() to remove the device from the network. This is not bullet proof since DEVICE_ANNCE is a broadcast message and could be missed by the coordinator.

    Best regards,
    Jørgen

Reply Children
No Data
Related