diff --git a/components/wifi_provisioning/include/wifi_provisioning/manager.h b/components/wifi_provisioning/include/wifi_provisioning/manager.h index 2edd43fee9..748efcb747 100644 --- a/components/wifi_provisioning/include/wifi_provisioning/manager.h +++ b/components/wifi_provisioning/include/wifi_provisioning/manager.h @@ -553,6 +553,18 @@ esp_err_t wifi_prov_mgr_get_wifi_disconnect_reason(wifi_prov_sta_fail_reason_t * */ esp_err_t wifi_prov_mgr_configure_sta(wifi_config_t *wifi_cfg); +/** + * @brief Reset internal state machine and clear provisioned credentials. + * + * This API can be used to restart provisioning in case invalid credentials are entered. + * + * @return + * - ESP_OK : Reset provisioning state machine successfully + * - ESP_FAIL : Failed to reset provisioning state machine + * - ESP_ERR_INVALID_STATE : Manager not initialized + */ +esp_err_t wifi_prov_mgr_reset_sm_state_on_failure(void); + #ifdef __cplusplus } #endif diff --git a/components/wifi_provisioning/src/manager.c b/components/wifi_provisioning/src/manager.c index e3977cd6e7..b19a5347af 100644 --- a/components/wifi_provisioning/src/manager.c +++ b/components/wifi_provisioning/src/manager.c @@ -869,6 +869,7 @@ static void wifi_prov_mgr_event_handler_internal( case WIFI_REASON_AUTH_FAIL: case WIFI_REASON_ASSOC_EXPIRE: case WIFI_REASON_HANDSHAKE_TIMEOUT: + case WIFI_REASON_MIC_FAILURE: ESP_LOGE(TAG, "STA Auth Error"); prov_ctx->wifi_disconnect_reason = WIFI_PROV_STA_AUTH_ERROR; break; @@ -1553,3 +1554,34 @@ void wifi_prov_mgr_stop_provisioning(void) RELEASE_LOCK(prov_ctx_lock); } + +esp_err_t wifi_prov_mgr_reset_sm_state_on_failure(void) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + ACQUIRE_LOCK(prov_ctx_lock); + + esp_err_t err = ESP_OK; + if (prov_ctx->prov_state != WIFI_PROV_STATE_FAIL) { + ESP_LOGE(TAG, "Trying reset when not in failure state. Current state: %d", prov_ctx->prov_state); + err = ESP_ERR_INVALID_STATE; + goto exit; + } + + wifi_config_t wifi_cfg = {0}; + + err = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to set wifi config, 0x%x", err); + goto exit; + } + + prov_ctx->prov_state = WIFI_PROV_STATE_STARTED; + +exit: + RELEASE_LOCK(prov_ctx_lock); + return err; +} diff --git a/examples/provisioning/wifi_prov_mgr/main/Kconfig.projbuild b/examples/provisioning/wifi_prov_mgr/main/Kconfig.projbuild index 00cbab17f7..3e4922e074 100644 --- a/examples/provisioning/wifi_prov_mgr/main/Kconfig.projbuild +++ b/examples/provisioning/wifi_prov_mgr/main/Kconfig.projbuild @@ -20,6 +20,24 @@ menu "Example Configuration" default 1 if EXAMPLE_PROV_TRANSPORT_BLE default 2 if EXAMPLE_PROV_TRANSPORT_SOFTAP + config EXAMPLE_RESET_PROV_MGR_ON_FAILURE + bool + default y + prompt "Reset provisioned credentials and state machine after session failure" + help + Enable reseting provisioned credentials and state machine after session failure. + This will restart the provisioning service after retries are exhausted. + + config EXAMPLE_PROV_MGR_MAX_RETRY_CNT + int + default 5 + prompt "Max retries before reseting provisioning state machine" + depends on EXAMPLE_RESET_PROV_MGR_ON_FAILURE + help + Set the Maximum retry to avoid reconnecting to an inexistent AP or if credentials + are misconfigured. Provisioned credentials are erased and internal state machine + is reset after this threshold is reached. + config EXAMPLE_PROV_SHOW_QR bool "Show provisioning QR code" default y diff --git a/examples/provisioning/wifi_prov_mgr/main/app_main.c b/examples/provisioning/wifi_prov_mgr/main/app_main.c index 794638a871..733f64fa33 100644 --- a/examples/provisioning/wifi_prov_mgr/main/app_main.c +++ b/examples/provisioning/wifi_prov_mgr/main/app_main.c @@ -45,6 +45,9 @@ static EventGroupHandle_t wifi_event_group; static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { +#ifdef CONFIG_EXAMPLE_RESET_PROV_MGR_ON_FAILURE + static int retries; +#endif if (event_base == WIFI_PROV_EVENT) { switch (event_id) { case WIFI_PROV_START: @@ -64,10 +67,21 @@ static void event_handler(void* arg, esp_event_base_t event_base, "\n\tPlease reset to factory and retry provisioning", (*reason == WIFI_PROV_STA_AUTH_ERROR) ? "Wi-Fi station authentication failed" : "Wi-Fi access-point not found"); +#ifdef CONFIG_EXAMPLE_RESET_PROV_MGR_ON_FAILURE + retries++; + if (retries >= CONFIG_EXAMPLE_PROV_MGR_MAX_RETRY_CNT) { + ESP_LOGI(TAG, "Failed to connect with provisioned AP, reseting provisioned credentials"); + wifi_prov_mgr_reset_sm_state_on_failure(); + retries = 0; + } +#endif break; } case WIFI_PROV_CRED_SUCCESS: ESP_LOGI(TAG, "Provisioning successful"); +#ifdef CONFIG_EXAMPLE_RESET_PROV_MGR_ON_FAILURE + retries = 0; +#endif break; case WIFI_PROV_END: /* De-initialize manager once provisioning is finished */