feat(wifi): retain multiple network credentials
This commit is contained in:
@@ -22,6 +22,10 @@
|
|||||||
#define CONFIG_TQ_BOOT_SOUND_TIMEOUT_MS 3000
|
#define CONFIG_TQ_BOOT_SOUND_TIMEOUT_MS 3000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_TQ_WIFI_CONNECT_CYCLE_TIMEOUT_MS
|
||||||
|
#define CONFIG_TQ_WIFI_CONNECT_CYCLE_TIMEOUT_MS 20000
|
||||||
|
#endif
|
||||||
|
|
||||||
static const char *TAG = "app_comp_boot";
|
static const char *TAG = "app_comp_boot";
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -194,7 +198,7 @@ static esp_err_t app_composition_run_plan_a_boot_sequence(void)
|
|||||||
"control_plane_bootstrap_connectivity");
|
"control_plane_bootstrap_connectivity");
|
||||||
esp_err_t wifi_err = control_plane_bootstrap_connectivity(CONFIG_MULTIMODAL_WIFI_SSID,
|
esp_err_t wifi_err = control_plane_bootstrap_connectivity(CONFIG_MULTIMODAL_WIFI_SSID,
|
||||||
CONFIG_MULTIMODAL_WIFI_PASSWORD,
|
CONFIG_MULTIMODAL_WIFI_PASSWORD,
|
||||||
CONFIG_MULTIMODAL_CONNECT_TIMEOUT_MS);
|
CONFIG_TQ_WIFI_CONNECT_CYCLE_TIMEOUT_MS);
|
||||||
if (wifi_err != ESP_OK) {
|
if (wifi_err != ESP_OK) {
|
||||||
ESP_LOGW(TAG, "Connectivity bootstrap failed: %s", esp_err_to_name(wifi_err));
|
ESP_LOGW(TAG, "Connectivity bootstrap failed: %s", esp_err_to_name(wifi_err));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
#define CONTROL_PLANE_PTT_ACTIVE_POLL_INTERVAL_MS 80
|
#define CONTROL_PLANE_PTT_ACTIVE_POLL_INTERVAL_MS 80
|
||||||
#define CONTROL_PLANE_WIFI_DISCONNECTED_REFRESH_MS 5000
|
#define CONTROL_PLANE_WIFI_DISCONNECTED_REFRESH_MS 5000
|
||||||
#define CONTROL_PLANE_WIFI_DISCONNECT_GRACE_MS 3000
|
#define CONTROL_PLANE_WIFI_DISCONNECT_GRACE_MS 3000
|
||||||
#define CONTROL_PLANE_WIFI_RECONNECT_TIMEOUT_MS 10000
|
#define CONTROL_PLANE_WIFI_REASSOCIATION_TIMEOUT_MS 10000
|
||||||
#define CONTROL_PLANE_WIFI_RECONNECT_BASE_DELAY_MS 5000
|
#define CONTROL_PLANE_WIFI_RECONNECT_BASE_DELAY_MS 5000
|
||||||
#define CONTROL_PLANE_WIFI_RECONNECT_MAX_DELAY_MS 60000
|
#define CONTROL_PLANE_WIFI_RECONNECT_MAX_DELAY_MS 60000
|
||||||
#define CONTROL_PLANE_USER_WEB_RETRY_MS 5000
|
#define CONTROL_PLANE_USER_WEB_RETRY_MS 5000
|
||||||
@@ -128,6 +128,10 @@
|
|||||||
#define CONFIG_TQ_MINI_PROGRAM_PROVISIONING_RECONNECT_FAILURES 2
|
#define CONFIG_TQ_MINI_PROGRAM_PROVISIONING_RECONNECT_FAILURES 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_TQ_WIFI_CONNECT_CYCLE_TIMEOUT_MS
|
||||||
|
#define CONFIG_TQ_WIFI_CONNECT_CYCLE_TIMEOUT_MS 20000
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_TQ_MINI_PROGRAM_PROVISIONING_ENABLE
|
#ifndef CONFIG_TQ_MINI_PROGRAM_PROVISIONING_ENABLE
|
||||||
#define CONFIG_TQ_MINI_PROGRAM_PROVISIONING_ENABLE 0
|
#define CONFIG_TQ_MINI_PROGRAM_PROVISIONING_ENABLE 0
|
||||||
#endif
|
#endif
|
||||||
@@ -1618,7 +1622,8 @@ static esp_err_t control_plane_attempt_wifi_reconnect(void)
|
|||||||
|
|
||||||
ESP_LOGI(TAG, "Attempting Wi-Fi STA reconnect");
|
ESP_LOGI(TAG, "Attempting Wi-Fi STA reconnect");
|
||||||
domain_runtime_behavior_set_keep_awake(true);
|
domain_runtime_behavior_set_keep_awake(true);
|
||||||
esp_err_t err = domain_runtime_wifi_portal_connect_sta(CONTROL_PLANE_WIFI_RECONNECT_TIMEOUT_MS);
|
esp_err_t err = domain_runtime_wifi_portal_connect_sta(
|
||||||
|
CONFIG_TQ_WIFI_CONNECT_CYCLE_TIMEOUT_MS);
|
||||||
domain_runtime_behavior_set_keep_awake(false);
|
domain_runtime_behavior_set_keep_awake(false);
|
||||||
|
|
||||||
if (err == ESP_OK) {
|
if (err == ESP_OK) {
|
||||||
@@ -2195,7 +2200,7 @@ static void control_plane_wifi_state_task(void *arg)
|
|||||||
(unsigned)CONTROL_PLANE_NETWORK_FAILURE_REASSOC_THRESHOLD);
|
(unsigned)CONTROL_PLANE_NETWORK_FAILURE_REASSOC_THRESHOLD);
|
||||||
domain_runtime_behavior_set_keep_awake(true);
|
domain_runtime_behavior_set_keep_awake(true);
|
||||||
esp_err_t reassoc_err = domain_runtime_wifi_portal_reconnect_sta(
|
esp_err_t reassoc_err = domain_runtime_wifi_portal_reconnect_sta(
|
||||||
CONTROL_PLANE_WIFI_RECONNECT_TIMEOUT_MS);
|
CONTROL_PLANE_WIFI_REASSOCIATION_TIMEOUT_MS);
|
||||||
domain_runtime_behavior_set_keep_awake(false);
|
domain_runtime_behavior_set_keep_awake(false);
|
||||||
connected = control_plane_is_sta_connected();
|
connected = control_plane_is_sta_connected();
|
||||||
ESP_LOGW(TAG,
|
ESP_LOGW(TAG,
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ typedef struct {
|
|||||||
/**
|
/**
|
||||||
* @brief Initialize Wi-Fi portal defaults and seed credentials.
|
* @brief Initialize Wi-Fi portal defaults and seed credentials.
|
||||||
*
|
*
|
||||||
* This writes the provided SSID/password into NVS if no credentials exist yet.
|
* This saves the provided SSID/password as the highest-priority entry while
|
||||||
* The underlying Wi-Fi manager is initialized lazily when starting STA or AP.
|
* 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);
|
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.
|
* @brief Trial-connect with credentials without persisting them first.
|
||||||
*
|
*
|
||||||
* On success, the trial credentials atomically replace the saved credential
|
* On success, the trial credentials are saved as the highest-priority entry
|
||||||
* list. On failure, the previous in-memory and NVS credentials remain intact.
|
* 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,
|
esp_err_t wifi_portal_connect_sta_with_credentials(const char *ssid,
|
||||||
const char *password,
|
const char *password,
|
||||||
|
|||||||
@@ -125,6 +125,35 @@ static esp_err_t wifi_portal_lock(void)
|
|||||||
return ESP_OK;
|
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)
|
static wifi_portal_behavior_hooks_t snapshot_behavior_hooks(void)
|
||||||
{
|
{
|
||||||
wifi_portal_behavior_hooks_t hooks = {};
|
wifi_portal_behavior_hooks_t hooks = {};
|
||||||
@@ -153,6 +182,7 @@ static void wifi_manager_event_callback(WifiEvent event, const std::string &data
|
|||||||
break;
|
break;
|
||||||
case WifiEvent::Connected:
|
case WifiEvent::Connected:
|
||||||
ESP_LOGI(TAG, "Connected to \"%s\"", data.c_str());
|
ESP_LOGI(TAG, "Connected to \"%s\"", data.c_str());
|
||||||
|
promote_saved_wifi(data);
|
||||||
(void)apply_sta_stability_policy();
|
(void)apply_sta_stability_policy();
|
||||||
break;
|
break;
|
||||||
case WifiEvent::Disconnected:
|
case WifiEvent::Disconnected:
|
||||||
@@ -209,24 +239,10 @@ static void seed_default_credentials(const char *ssid, const char *password)
|
|||||||
return;
|
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 : "");
|
manager.AddSsid(ssid, password != NULL ? password : "");
|
||||||
|
promote_saved_wifi(ssid);
|
||||||
ESP_LOGI(TAG,
|
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,
|
ssid,
|
||||||
(unsigned)saved_count);
|
(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");
|
ESP_RETURN_ON_ERROR(wifi_portal_lock(), TAG, "Failed to lock Wi-Fi portal");
|
||||||
PortalUnlockGuard guard;
|
PortalUnlockGuard guard;
|
||||||
auto &credentials = SsidManager::GetInstance();
|
auto &credentials = SsidManager::GetInstance();
|
||||||
credentials.Clear();
|
|
||||||
credentials.AddSsid(ssid, password != NULL ? password : "");
|
credentials.AddSsid(ssid, password != NULL ? password : "");
|
||||||
|
promote_saved_wifi(ssid);
|
||||||
ESP_LOGI(TAG,
|
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);
|
ssid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -558,7 +574,8 @@ esp_err_t wifi_portal_save_credentials(const char *ssid, const char *password)
|
|||||||
"Password too long");
|
"Password too long");
|
||||||
|
|
||||||
SsidManager::GetInstance().AddSsid(ssid, password != NULL ? password : "");
|
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;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-2
@@ -1090,10 +1090,19 @@ menu "Example Configuration"
|
|||||||
Password for the seed SSID.
|
Password for the seed SSID.
|
||||||
|
|
||||||
config MULTIMODAL_CONNECT_TIMEOUT_MS
|
config MULTIMODAL_CONNECT_TIMEOUT_MS
|
||||||
int "Wi-Fi connect timeout (ms)"
|
int "Cloud transport connect timeout (ms)"
|
||||||
default 10000
|
default 10000
|
||||||
help
|
help
|
||||||
Timeout for Wi-Fi STA connection attempts in milliseconds.
|
Timeout for multimodal HTTP and WebSocket connection attempts.
|
||||||
|
|
||||||
|
config TQ_WIFI_CONNECT_CYCLE_TIMEOUT_MS
|
||||||
|
int "Wi-Fi candidate connection cycle timeout (ms)"
|
||||||
|
default 20000
|
||||||
|
range 5000 120000
|
||||||
|
help
|
||||||
|
Total time allowed for one scan and connection cycle across
|
||||||
|
visible saved Wi-Fi candidates. Failed cycles continue through
|
||||||
|
the runtime reconnect backoff policy.
|
||||||
|
|
||||||
config VOICE_PROMPT_WIFI_SUCCESS_FILE
|
config VOICE_PROMPT_WIFI_SUCCESS_FILE
|
||||||
string "Wi-Fi success prompt file"
|
string "Wi-Fi success prompt file"
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL=y
|
|||||||
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_ENABLE=y
|
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_ENABLE=y
|
||||||
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_CONNECT_TIMEOUT_MS=30000
|
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_CONNECT_TIMEOUT_MS=30000
|
||||||
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_RECONNECT_FAILURES=2
|
CONFIG_TQ_MINI_PROGRAM_PROVISIONING_RECONNECT_FAILURES=2
|
||||||
|
CONFIG_TQ_WIFI_CONNECT_CYCLE_TIMEOUT_MS=20000
|
||||||
|
|
||||||
# External PSRAM (ESP32-S3 octal mode)
|
# External PSRAM (ESP32-S3 octal mode)
|
||||||
CONFIG_SPIRAM=y
|
CONFIG_SPIRAM=y
|
||||||
|
|||||||
Reference in New Issue
Block a user