Fix web UI: captive portal DNS + chunked HTML delivery
Phone browsers do a captive portal check (DNS + HTTP) when joining a new WiFi AP. Without a DNS server the DNS query hangs forever and the phone blocks all HTTP traffic to the network — page never loads. Added DNSServer resolving all queries to 192.168.4.1. handleNotFound now 302-redirects to / so captive portal probes get the main page. Replaced single 15 KB send_P() with chunked transfer encoding in 512B pieces with yield() between each chunk, keeping the WiFi stack responsive. Made-with: Cursor
This commit is contained in:
24
src/main.cpp
24
src/main.cpp
@@ -10,6 +10,7 @@
|
|||||||
#include <RadioLib.h>
|
#include <RadioLib.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <WebServer.h>
|
#include <WebServer.h>
|
||||||
|
#include <DNSServer.h>
|
||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
#include <ArduinoOTA.h>
|
#include <ArduinoOTA.h>
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
@@ -35,6 +36,7 @@ CC1101 radio1(&mod1);
|
|||||||
CC1101 radio2(&mod2);
|
CC1101 radio2(&mod2);
|
||||||
|
|
||||||
static WebServer server(WEB_PORT);
|
static WebServer server(WEB_PORT);
|
||||||
|
static DNSServer dnsServer;
|
||||||
static Preferences preferences;
|
static Preferences preferences;
|
||||||
|
|
||||||
// CC1101 valid discrete power levels in dBm (RadioLib only accepts these exact values)
|
// CC1101 valid discrete power levels in dBm (RadioLib only accepts these exact values)
|
||||||
@@ -2240,7 +2242,18 @@ window.addEventListener('resize',capDrawWave);
|
|||||||
)HTML";
|
)HTML";
|
||||||
|
|
||||||
static void handleRoot() {
|
static void handleRoot() {
|
||||||
server.send_P(200, "text/html; charset=utf-8", kHtml, sizeof(kHtml) - 1);
|
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
|
||||||
|
server.send(200, "text/html; charset=utf-8", "");
|
||||||
|
const size_t total = sizeof(kHtml) - 1;
|
||||||
|
size_t off = 0;
|
||||||
|
while (off < total) {
|
||||||
|
size_t n = total - off;
|
||||||
|
if (n > 512) n = 512;
|
||||||
|
server.sendContent_P(kHtml + off, n);
|
||||||
|
off += n;
|
||||||
|
yield();
|
||||||
|
}
|
||||||
|
server.sendContent("");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleLog() {
|
static void handleLog() {
|
||||||
@@ -2531,9 +2544,8 @@ static void handleCaptureWave() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void handleNotFound() {
|
static void handleNotFound() {
|
||||||
const String uri = server.uri();
|
server.sendHeader("Location", "http://192.168.4.1/");
|
||||||
logLine("[HTTP] 404 " + uri);
|
server.send(302, "text/plain", "Redirect");
|
||||||
server.send(404, "text/plain", "404: Not found");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleSelfTest() {
|
static void handleSelfTest() {
|
||||||
@@ -2706,6 +2718,9 @@ void setup() {
|
|||||||
server.onNotFound(handleNotFound);
|
server.onNotFound(handleNotFound);
|
||||||
server.begin();
|
server.begin();
|
||||||
|
|
||||||
|
dnsServer.start(53, "*", WiFi.softAPIP());
|
||||||
|
logLine("[DNS] Captive portal DNS on *:53 → " + WiFi.softAPIP().toString());
|
||||||
|
|
||||||
// OTA firmware updates over WiFi (connect to 'killer' AP, upload via PlatformIO OTA)
|
// OTA firmware updates over WiFi (connect to 'killer' AP, upload via PlatformIO OTA)
|
||||||
ArduinoOTA.setHostname("killer");
|
ArduinoOTA.setHostname("killer");
|
||||||
ArduinoOTA.setPassword("killerpw");
|
ArduinoOTA.setPassword("killerpw");
|
||||||
@@ -2731,6 +2746,7 @@ void setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
dnsServer.processNextRequest();
|
||||||
espNowTick();
|
espNowTick();
|
||||||
ArduinoOTA.handle();
|
ArduinoOTA.handle();
|
||||||
server.handleClient();
|
server.handleClient();
|
||||||
|
|||||||
Reference in New Issue
Block a user