fix(wifi): send http response before channel switch and prevent reconnect race
All checks were successful
ESP32 Build & Release / build (push) Successful in 1m11s
All checks were successful
ESP32 Build & Release / build (push) Successful in 1m11s
This commit is contained in:
@@ -239,7 +239,10 @@ static const char SPA_PAGE[] =
|
|||||||
" }else{"
|
" }else{"
|
||||||
" showWf('bad','Failed to connect: '+(j.error||'unknown'));"
|
" showWf('bad','Failed to connect: '+(j.error||'unknown'));"
|
||||||
" }"
|
" }"
|
||||||
" }).catch(function(e){showWf('bad','Network error: '+e);});"
|
" }).catch(function(e){"
|
||||||
|
" showWf('ok','Connection initiated to '+s+'. Device is connecting...');"
|
||||||
|
" setTimeout(function(){refreshWifiStatus();loadSavedWifi();},6000);"
|
||||||
|
" });"
|
||||||
"}"
|
"}"
|
||||||
"function loadSavedWifi(){"
|
"function loadSavedWifi(){"
|
||||||
" fetch('/api/wifi/saved').then(function(r){return r.json();}).then(function(list){"
|
" fetch('/api/wifi/saved').then(function(r){return r.json();}).then(function(list){"
|
||||||
@@ -671,6 +674,24 @@ static esp_err_t handle_wifi_saved(httpd_req_t *req)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char ssid[WIFI_SSID_MAX_LEN + 1];
|
||||||
|
char pass[65];
|
||||||
|
} async_wifi_connect_args_t;
|
||||||
|
|
||||||
|
static void async_wifi_connect_task(void *pvParameters)
|
||||||
|
{
|
||||||
|
async_wifi_connect_args_t *args = (async_wifi_connect_args_t *)pvParameters;
|
||||||
|
if (args) {
|
||||||
|
/* Wait 500ms to allow the HTTP 200 response to be cleanly transmitted and ACKed */
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(500));
|
||||||
|
ESP_LOGI(TAG, "Executing deferred connection to '%s'", args->ssid);
|
||||||
|
wifi_manager_connect_new(args->ssid, args->pass, true);
|
||||||
|
free(args);
|
||||||
|
}
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static esp_err_t handle_wifi_connect(httpd_req_t *req)
|
static esp_err_t handle_wifi_connect(httpd_req_t *req)
|
||||||
{
|
{
|
||||||
if (req->content_len <= 0 || req->content_len >= HTTPD_BODY_MAX) {
|
if (req->content_len <= 0 || req->content_len >= HTTPD_BODY_MAX) {
|
||||||
@@ -710,12 +731,28 @@ static esp_err_t handle_wifi_connect(httpd_req_t *req)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *p = pass ? pass : "";
|
const char *p = pass ? pass : "";
|
||||||
wifi_manager_connect_new(ssid, p, true);
|
|
||||||
|
|
||||||
|
/* Send HTTP 200 OK FIRST before the Wi-Fi stack switches channels or disconnects */
|
||||||
char ok[128];
|
char ok[128];
|
||||||
snprintf(ok, sizeof(ok), "{\"ok\":true,\"ssid\":\"%s\"}\n", ssid);
|
snprintf(ok, sizeof(ok), "{\"ok\":true,\"ssid\":\"%s\"}\n", ssid);
|
||||||
send_json(req, 200, ok);
|
send_json(req, 200, ok);
|
||||||
|
|
||||||
|
/* Defer the actual connection to a background task so the current socket is not interrupted */
|
||||||
|
async_wifi_connect_args_t *args = malloc(sizeof(async_wifi_connect_args_t));
|
||||||
|
if (args) {
|
||||||
|
strncpy(args->ssid, ssid, sizeof(args->ssid) - 1);
|
||||||
|
args->ssid[sizeof(args->ssid) - 1] = '\0';
|
||||||
|
strncpy(args->pass, p, sizeof(args->pass) - 1);
|
||||||
|
args->pass[sizeof(args->pass) - 1] = '\0';
|
||||||
|
if (xTaskCreate(async_wifi_connect_task, "wf_conn_async", 4096, args, 5, NULL) != pdPASS) {
|
||||||
|
ESP_LOGE(TAG, "Failed to create async_wifi_connect_task, connecting synchronously");
|
||||||
|
wifi_manager_connect_new(ssid, p, true);
|
||||||
|
free(args);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wifi_manager_connect_new(ssid, p, true);
|
||||||
|
}
|
||||||
|
|
||||||
free(ssid);
|
free(ssid);
|
||||||
free(pass);
|
free(pass);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ static char s_sta_ip[20] = "No Wi-Fi";
|
|||||||
static char s_active_ssid[WIFI_SSID_MAX_LEN + 1] = {0};
|
static char s_active_ssid[WIFI_SSID_MAX_LEN + 1] = {0};
|
||||||
static SemaphoreHandle_t s_wifi_mux = NULL;
|
static SemaphoreHandle_t s_wifi_mux = NULL;
|
||||||
static SemaphoreHandle_t s_net_lock = NULL;
|
static SemaphoreHandle_t s_net_lock = NULL;
|
||||||
|
static bool s_manual_disconnect = false;
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
@@ -184,7 +185,7 @@ static void wifi_event_handler(void *arg, esp_event_base_t base, int32_t id, voi
|
|||||||
if (s_wifi_group) {
|
if (s_wifi_group) {
|
||||||
xEventGroupClearBits(s_wifi_group, WIFI_CONNECTED_BIT);
|
xEventGroupClearBits(s_wifi_group, WIFI_CONNECTED_BIT);
|
||||||
}
|
}
|
||||||
if (s_active_ssid[0] != '\0' && s_retry_count < WIFI_RETRY_MAX) {
|
if (!s_manual_disconnect && s_active_ssid[0] != '\0' && s_retry_count < WIFI_RETRY_MAX) {
|
||||||
ESP_LOGW(TAG, "disconnected from '%s' (attempt %d), reconnecting...", s_active_ssid, s_retry_count);
|
ESP_LOGW(TAG, "disconnected from '%s' (attempt %d), reconnecting...", s_active_ssid, s_retry_count);
|
||||||
esp_wifi_connect();
|
esp_wifi_connect();
|
||||||
s_retry_count++;
|
s_retry_count++;
|
||||||
@@ -329,10 +330,14 @@ esp_err_t wifi_manager_connect_new(const char *ssid, const char *password, bool
|
|||||||
|
|
||||||
strncpy(s_active_ssid, ssid, sizeof(s_active_ssid) - 1);
|
strncpy(s_active_ssid, ssid, sizeof(s_active_ssid) - 1);
|
||||||
s_active_ssid[sizeof(s_active_ssid) - 1] = '\0';
|
s_active_ssid[sizeof(s_active_ssid) - 1] = '\0';
|
||||||
s_retry_count = 0;
|
s_manual_disconnect = true;
|
||||||
|
|
||||||
esp_wifi_disconnect();
|
esp_wifi_disconnect();
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg));
|
s_manual_disconnect = false;
|
||||||
|
esp_err_t set_err = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg);
|
||||||
|
if (set_err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "esp_wifi_set_config failed: %s", esp_err_to_name(set_err));
|
||||||
|
return set_err;
|
||||||
|
}
|
||||||
esp_err_t ret = esp_wifi_connect();
|
esp_err_t ret = esp_wifi_connect();
|
||||||
|
|
||||||
if (save_to_nvs) {
|
if (save_to_nvs) {
|
||||||
@@ -481,9 +486,9 @@ esp_err_t wifi_manager_start(void)
|
|||||||
|
|
||||||
strncpy(s_active_ssid, target_ssid, sizeof(s_active_ssid) - 1);
|
strncpy(s_active_ssid, target_ssid, sizeof(s_active_ssid) - 1);
|
||||||
s_active_ssid[sizeof(s_active_ssid) - 1] = '\0';
|
s_active_ssid[sizeof(s_active_ssid) - 1] = '\0';
|
||||||
s_retry_count = 0;
|
s_manual_disconnect = true;
|
||||||
|
|
||||||
esp_wifi_disconnect();
|
esp_wifi_disconnect();
|
||||||
|
s_manual_disconnect = false;
|
||||||
esp_err_t err = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg);
|
esp_err_t err = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "esp_wifi_set_config failed: %s", esp_err_to_name(err));
|
ESP_LOGE(TAG, "esp_wifi_set_config failed: %s", esp_err_to_name(err));
|
||||||
|
|||||||
Reference in New Issue
Block a user