diff --git a/subsys/zigbee/lib/zigbee_app_utils/zigbee_app_utils.c b/subsys/zigbee/lib/zigbee_app_utils/zigbee_app_utils.c index d88b3ee99..e8378d1ee 100644 --- a/subsys/zigbee/lib/zigbee_app_utils/zigbee_app_utils.c +++ b/subsys/zigbee/lib/zigbee_app_utils/zigbee_app_utils.c @@ -30,6 +30,10 @@ /* Maximum interval between join/rejoin attempts. */ #define REJOIN_INTERVAL_MAX_S (15 * 60) +/* Rejoin interval, after which the device will perform TC rejoin instead of a secure rejoin. */ +#define TC_REJOIN_INTERVAL_THRESHOLD_S (3) +#define ZB_SECUR_PROVISIONAL_KEY 2 + #define IEEE_ADDR_BUF_SIZE 17 #if defined CONFIG_ZIGBEE_FACTORY_RESET @@ -53,6 +57,7 @@ static volatile bool is_rejoin_start_scheduled; static void rejoin_the_network(zb_uint8_t param); static void start_network_rejoin(void); static void stop_network_rejoin(zb_uint8_t was_scheduled); +void zb_nwk_forget_device(zb_uint8_t addr_ref); #if defined CONFIG_ZIGBEE_FACTORY_RESET @@ -489,6 +494,7 @@ zb_ret_t zigbee_default_signal_handler(zb_bufid_t bufid) zb_zdo_signal_device_update_params_t); char ieee_addr_buf[IEEE_ADDR_BUF_SIZE] = { 0 }; int addr_len; + zb_address_ieee_ref_t addr_ref; addr_len = ieee_addr_to_str(ieee_addr_buf, sizeof(ieee_addr_buf), @@ -500,6 +506,11 @@ zb_ret_t zigbee_default_signal_handler(zb_bufid_t bufid) update_params->short_addr, log_strdup(ieee_addr_buf), update_params->status); + + if ((zb_address_by_ieee(update_params->long_addr, ZB_FALSE, ZB_FALSE, &addr_ref) == RET_OK) + && (zb_secur_get_link_key_by_address(update_params->long_addr, ZB_SECUR_PROVISIONAL_KEY) != NULL)) { + ZB_SCHEDULE_APP_ALARM_CANCEL(zb_nwk_forget_device, addr_ref); + } break; } @@ -623,6 +634,52 @@ zb_ret_t zigbee_default_signal_handler(zb_bufid_t bufid) /* Obsolete signals, used for pre-R21 ZBOSS API. Ignore. */ break; + case ZB_BDB_SIGNAL_TC_REJOIN_DONE: + /* This signal informs that TC rejoin is completed. + * The signal status indicates if the device has successfully + * rejoined the network. + * + * Next step: if the device implement Zigbee router or + * end device, and the TC rejoijn has failed, + * perform restart the generic rejoin procedure. + */ + if (status == RET_OK) { + zb_ext_pan_id_t extended_pan_id; + char ieee_addr_buf[IEEE_ADDR_BUF_SIZE] = { 0 }; + int addr_len; + + zb_get_extended_pan_id(extended_pan_id); + addr_len = ieee_addr_to_str(ieee_addr_buf, + sizeof(ieee_addr_buf), + extended_pan_id); + if (addr_len < 0) { + strcpy(ieee_addr_buf, "unknown"); + } + + LOG_INF("Joined network successfully after TC rejoin (Extended PAN ID: %s, PAN ID: 0x%04hx)", + log_strdup(ieee_addr_buf), + ZB_PIBCACHE_PAN_ID()); + /* Device has joined the network so stop the network + * rejoin procedure. + */ + if (role != ZB_NWK_DEVICE_TYPE_COORDINATOR) { + stop_network_rejoin(ZB_FALSE); + } + } else { + if (role != ZB_NWK_DEVICE_TYPE_COORDINATOR) { + LOG_INF("TC Rejoin was not successful (status: %d)", + status); + start_network_rejoin(); + } else { + LOG_INF("Network steering failed on Zigbee coordinator (status: %d)", + status); + } + } + if (!IS_ENABLED(CONFIG_ZIGBEE_ROLE_END_DEVICE)) { + zb_enable_auto_pan_id_conflict_resolution(ZB_FALSE); + } + break; + default: /* Unimplemented signal. For more information, * see: zb_zdo_app_signal_type_e and zb_ret_e. @@ -697,6 +754,7 @@ static void rejoin_the_network(zb_uint8_t param) } else if (!is_rejoin_in_progress) { /* Calculate new timeout */ zb_time_t timeout_s; + zb_ret_t zb_err_code; if ((1 << rejoin_attempt_cnt) > REJOIN_INTERVAL_MAX_S) { timeout_s = REJOIN_INTERVAL_MAX_S; @@ -705,12 +763,21 @@ static void rejoin_the_network(zb_uint8_t param) rejoin_attempt_cnt++; } - zb_ret_t zb_err_code = ZB_SCHEDULE_APP_ALARM( - start_network_steering, - ZB_FALSE, - ZB_MILLISECONDS_TO_BEACON_INTERVAL(timeout_s * - 1000)); - ZB_ERROR_CHECK(zb_err_code); + if ((timeout_s > TC_REJOIN_INTERVAL_THRESHOLD_S) && (!zb_bdb_is_factory_new())) { + zb_err_code = ZB_SCHEDULE_APP_ALARM( + zb_bdb_initiate_tc_rejoin, + ZB_UNDEFINED_BUFFER, + ZB_MILLISECONDS_TO_BEACON_INTERVAL(timeout_s * + 1000)); + ZB_ERROR_CHECK(zb_err_code); + } else { + zb_err_code = ZB_SCHEDULE_APP_ALARM( + start_network_steering, + ZB_FALSE, + ZB_MILLISECONDS_TO_BEACON_INTERVAL(timeout_s * + 1000)); + ZB_ERROR_CHECK(zb_err_code); + } is_rejoin_in_progress = true; }