Jelajahi Sumber

Merge branch 'feature/prov_mgr_reset_state_v4.3' into 'release/v4.3'

wifi_provisioning: Add API to erase credentials and reset provisioning state (v4.3)

See merge request espressif/esp-idf!14531
Mahavir Jain 4 tahun lalu
induk
melakukan
47b96db12d

+ 12 - 0
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

+ 32 - 0
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;
+}

+ 18 - 0
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

+ 14 - 0
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 */