Fix captive portal redirect: visible countdown, keep AP up until it finishes
Previously the softAP was torn down (esp_restart) only 1s after sending the success page, while the page's own redirect timer waited 7s -- so the AP (and the phone's captive-portal session with it) was gone long before the redirect could fire. Now the page shows a live 10s countdown before redirecting, and the device holds the AP up for 11s so the countdown always completes. Also added a "Redirect now" button for a phone that's already reconnected to normal WiFi.
This commit is contained in:
@@ -448,11 +448,17 @@ static esp_err_t save_config_post_handler(httpd_req_t *req)
|
|||||||
|
|
||||||
/* The success page hands the browser off to the server's claim page,
|
/* The success page hands the browser off to the server's claim page,
|
||||||
* carrying this device's id -- how a frame gets linked to a user
|
* carrying this device's id -- how a frame gets linked to a user
|
||||||
* account. The ~7s delay covers the phone dropping this softAP (the
|
* account. This page is entirely self-contained (no external
|
||||||
* device reboots right after this response) and rejoining its normal
|
* resources) so it renders fully from what we send now, before the
|
||||||
* WiFi before the redirect fires; the visible link is the fallback
|
* softAP goes away -- a phone mid-load of a remote asset would just
|
||||||
* if the phone loses that race. Scheme handling matches
|
* time out once the AP drops. The visible countdown ticks down for
|
||||||
* frame_client.c's build_url(): a bare host gets http://. */
|
* PROVISIONING_COUNTDOWN_S seconds and then redirects; the AP is kept
|
||||||
|
* alive for one second longer than that (see the vTaskDelay below) so
|
||||||
|
* the countdown always finishes, and the phone has that whole window
|
||||||
|
* to rejoin its normal WiFi and let the redirect land on the real
|
||||||
|
* server. "Redirect now" covers a phone that's already reconnected.
|
||||||
|
* Scheme handling matches frame_client.c's build_url(): a bare host
|
||||||
|
* gets http://. */
|
||||||
char device_id[FRAME_DEVICE_ID_LEN + 1];
|
char device_id[FRAME_DEVICE_ID_LEN + 1];
|
||||||
frame_device_id_get(device_id, sizeof(device_id));
|
frame_device_id_get(device_id, sizeof(device_id));
|
||||||
|
|
||||||
@@ -463,25 +469,40 @@ static esp_err_t save_config_post_handler(httpd_req_t *req)
|
|||||||
}
|
}
|
||||||
snprintf(claim_url, sizeof(claim_url), "%s%s/claim?device_id=%s", scheme, cfg.toolsserver, device_id);
|
snprintf(claim_url, sizeof(claim_url), "%s%s/claim?device_id=%s", scheme, cfg.toolsserver, device_id);
|
||||||
|
|
||||||
char resp[1024];
|
#define PROVISIONING_COUNTDOWN_S 10
|
||||||
|
|
||||||
|
char resp[1536];
|
||||||
snprintf(resp, sizeof(resp),
|
snprintf(resp, sizeof(resp),
|
||||||
"<!doctype html><html><head>"
|
"<!doctype html><html><head>"
|
||||||
"<meta http-equiv=\"refresh\" content=\"7;url=%s\">"
|
"<meta http-equiv=\"refresh\" content=\"%d;url=%s\">"
|
||||||
"<style>body{font-family:sans-serif;text-align:center;padding:2em}</style></head>"
|
"<style>body{font-family:sans-serif;text-align:center;padding:2em}"
|
||||||
|
"#now{display:inline-block;margin-top:1em;padding:.6em 1.2em;"
|
||||||
|
"background:#2563eb;color:#fff;text-decoration:none;border-radius:8px}</style></head>"
|
||||||
"<body><h3>Saved — the frame is restarting</h3>"
|
"<body><h3>Saved — the frame is restarting</h3>"
|
||||||
"<p>Reconnect to your normal WiFi. You'll be taken to the claim page "
|
"<p>Reconnect to your normal WiFi if it doesn't happen automatically.</p>"
|
||||||
"in a few seconds…</p>"
|
"<p>Redirecting you in <span id=\"n\">%d</span> seconds…</p>"
|
||||||
"<p><a href=\"%s\">Continue to claim your frame</a></p>"
|
"<p><a id=\"now\" href=\"%s\">Redirect now</a></p>"
|
||||||
"<script>setTimeout(function(){location.href=%c%s%c},7000)</script>"
|
"<script>"
|
||||||
|
"var n=%d,e=document.getElementById('n');"
|
||||||
|
"var t=setInterval(function(){"
|
||||||
|
"n--;if(e)e.textContent=n;"
|
||||||
|
"if(n<=0){clearInterval(t);location.href='%s';}"
|
||||||
|
"},1000);"
|
||||||
|
"</script>"
|
||||||
"</body></html>",
|
"</body></html>",
|
||||||
claim_url, claim_url, '"', claim_url, '"');
|
PROVISIONING_COUNTDOWN_S, claim_url, PROVISIONING_COUNTDOWN_S, claim_url,
|
||||||
|
PROVISIONING_COUNTDOWN_S, claim_url);
|
||||||
httpd_resp_set_type(req, "text/html");
|
httpd_resp_set_type(req, "text/html");
|
||||||
httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN);
|
httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN);
|
||||||
|
|
||||||
/* Let the response flush to the client before rebooting into STA mode. */
|
/* Keep the softAP up for the full visible countdown (plus a 1s margin
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
* for the response to flush and the JS timer to fire) before tearing
|
||||||
|
* it down -- see the comment above for why. */
|
||||||
|
vTaskDelay(pdMS_TO_TICKS((PROVISIONING_COUNTDOWN_S + 1) * 1000));
|
||||||
esp_restart();
|
esp_restart();
|
||||||
|
|
||||||
|
#undef PROVISIONING_COUNTDOWN_S
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user