feat(wifi): retain multiple network credentials

This commit is contained in:
chenjintao
2026-08-24 16:16:16 +08:00
parent 23f4969404
commit ae27d5bbaa
6 changed files with 67 additions and 29 deletions
+6 -4
View File
@@ -15,8 +15,9 @@ typedef struct {
/**
* @brief Initialize Wi-Fi portal defaults and seed credentials.
*
* This writes the provided SSID/password into NVS if no credentials exist yet.
* The underlying Wi-Fi manager is initialized lazily when starting STA or AP.
* This saves the provided SSID/password as the highest-priority entry while
* retaining existing credentials. The underlying Wi-Fi manager is initialized
* lazily when starting STA or AP.
*/
esp_err_t wifi_portal_init_defaults(const char *seed_ssid, const char *seed_password);
@@ -50,8 +51,9 @@ esp_err_t wifi_portal_connect_sta(int timeout_ms);
/**
* @brief Trial-connect with credentials without persisting them first.
*
* On success, the trial credentials atomically replace the saved credential
* list. On failure, the previous in-memory and NVS credentials remain intact.
* On success, the trial credentials are saved as the highest-priority entry
* while older credentials are retained. On failure, the previous in-memory
* and NVS credentials remain intact.
*/
esp_err_t wifi_portal_connect_sta_with_credentials(const char *ssid,
const char *password,
+36 -19
View File
@@ -125,6 +125,35 @@ static esp_err_t wifi_portal_lock(void)
return ESP_OK;
}
static void promote_saved_wifi(const std::string &ssid)
{
if (ssid.empty()) {
return;
}
if (wifi_portal_lock() != ESP_OK) {
ESP_LOGW(TAG, "Could not promote connected Wi-Fi \"%s\": portal lock timed out",
ssid.c_str());
return;
}
PortalUnlockGuard guard;
install_wifi_storage_hooks();
auto &credentials = SsidManager::GetInstance();
const auto &ssid_list = credentials.GetSsidList();
for (size_t i = 0; i < ssid_list.size(); ++i) {
if (ssid_list[i].ssid != ssid) {
continue;
}
if (i > 0U) {
credentials.SetDefaultSsid((int)i);
ESP_LOGI(TAG, "Promoted connected Wi-Fi \"%s\" to highest priority",
ssid.c_str());
}
return;
}
}
static wifi_portal_behavior_hooks_t snapshot_behavior_hooks(void)
{
wifi_portal_behavior_hooks_t hooks = {};
@@ -153,6 +182,7 @@ static void wifi_manager_event_callback(WifiEvent event, const std::string &data
break;
case WifiEvent::Connected:
ESP_LOGI(TAG, "Connected to \"%s\"", data.c_str());
promote_saved_wifi(data);
(void)apply_sta_stability_policy();
break;
case WifiEvent::Disconnected:
@@ -209,24 +239,10 @@ static void seed_default_credentials(const char *ssid, const char *password)
return;
}
bool configured_ssid_saved = false;
for (const auto &item : manager.GetSsidList()) {
if (item.ssid == ssid) {
configured_ssid_saved = true;
break;
}
}
if (saved_count > 0U && !configured_ssid_saved) {
ESP_LOGI(TAG,
"Configured seed SSID changed to \"%s\"; replacing %u stale credential candidate(s)",
ssid,
(unsigned)saved_count);
manager.Clear();
}
manager.AddSsid(ssid, password != NULL ? password : "");
promote_saved_wifi(ssid);
ESP_LOGI(TAG,
"Ensured configured Wi-Fi credentials for SSID \"%s\" with %u previous candidate(s)",
"Ensured configured Wi-Fi credentials for SSID \"%s\" while preserving %u previous candidate(s)",
ssid,
(unsigned)saved_count);
}
@@ -456,10 +472,10 @@ esp_err_t wifi_portal_connect_sta_with_credentials(const char *ssid,
ESP_RETURN_ON_ERROR(wifi_portal_lock(), TAG, "Failed to lock Wi-Fi portal");
PortalUnlockGuard guard;
auto &credentials = SsidManager::GetInstance();
credentials.Clear();
credentials.AddSsid(ssid, password != NULL ? password : "");
promote_saved_wifi(ssid);
ESP_LOGI(TAG,
"Credential trial succeeded and replaced saved Wi-Fi for SSID \"%s\"",
"Credential trial succeeded and saved Wi-Fi \"%s\" as highest priority",
ssid);
}
@@ -558,7 +574,8 @@ esp_err_t wifi_portal_save_credentials(const char *ssid, const char *password)
"Password too long");
SsidManager::GetInstance().AddSsid(ssid, password != NULL ? password : "");
ESP_LOGI(TAG, "Saved Wi-Fi credentials for SSID \"%s\"", ssid);
promote_saved_wifi(ssid);
ESP_LOGI(TAG, "Saved Wi-Fi credentials for SSID \"%s\" as highest priority", ssid);
return ESP_OK;
}