diff --git a/components/wifi_provisioning/include/wifi_provisioning/manager.h b/components/wifi_provisioning/include/wifi_provisioning/manager.h index e1b978162a..0d51bd2739 100644 --- a/components/wifi_provisioning/include/wifi_provisioning/manager.h +++ b/components/wifi_provisioning/include/wifi_provisioning/manager.h @@ -563,6 +563,19 @@ esp_err_t wifi_prov_mgr_configure_sta(wifi_config_t *wifi_cfg); * - ESP_FAIL : Failed to reset provisioning config */ esp_err_t wifi_prov_mgr_reset_provisioning(void); + +/** + * @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 a56b079d24..df08130dd2 100644 --- a/components/wifi_provisioning/src/manager.c +++ b/components/wifi_provisioning/src/manager.c @@ -871,6 +871,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; @@ -1578,3 +1579,34 @@ esp_err_t wifi_prov_mgr_reset_provisioning(void) return ret; } + +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 7dc537f35f..78082bffd3 100644 --- a/examples/provisioning/wifi_prov_mgr/main/Kconfig.projbuild +++ b/examples/provisioning/wifi_prov_mgr/main/Kconfig.projbuild @@ -28,6 +28,24 @@ menu "Example Configuration" This erases the NVS to reset provisioned status of the device on every reboot. Provisioned status is determined by the Wi-Fi STA configuration, saved on the NVS. + 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 06b65d8b06..a5dd06973b 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 */