Con 50 righe di codice l'ESP32 puo' essere un web server autonomo che risponde a http://esp32.local/ con una pagina di controllo. Nessun cloud, nessuna app, solo un browser.
1. Setup base con WebServer
#include <WiFi.h>
#include <WebServer.h>
#include <ESPmDNS.h>
const char* ssid = "TuaRete";
const char* pass = "PasswordWiFi";
WebServer server(80);
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) { delay(200); Serial.print("."); }
Serial.println(WiFi.localIP());
MDNS.begin("esp32"); // http://esp32.local
pinMode(2, OUTPUT);
server.on("/", handleRoot);
server.on("/on", [](){ digitalWrite(2, HIGH); server.send(200, "text/plain", "ON"); });
server.on("/off", [](){ digitalWrite(2, LOW); server.send(200, "text/plain", "OFF"); });
server.on("/temp", handleTemp);
server.begin();
}
void loop() { server.handleClient(); }
2. Pagina HTML servita dalla flash
const char* HTML_PAGE PROGMEM = R"HTML(
<!DOCTYPE html>
<html><head><meta charset="UTF-8">
<title>ESP32 Dashboard</title>
<style>
body{font-family:sans-serif;max-width:400px;margin:2em auto;padding:1em}
button{width:100%%;padding:1em;font-size:1.2em;margin:.3em 0}
.on{background:#0a0;color:#fff}
.off{background:#a00;color:#fff}
#temp{font-size:3em;text-align:center;color:#08f}
</style></head><body>
<h1>ESP32 Controller</h1>
<button class="on" onclick="fetch('/on')">LED ON</button>
<button class="off" onclick="fetch('/off')">LED OFF</button>
<div id="temp">--- °C</div>
<script>
setInterval(async()=>{
const r = await fetch('/temp');
document.getElementById('temp').textContent = (await r.text()) + ' °C';
}, 1000);
</script></body></html>
)HTML";
void handleRoot() { server.send_P(200, "text/html", HTML_PAGE); }
void handleTemp() {
float t = 20.0 + random(0, 50) / 10.0; // sostituire con sensore vero
server.send(200, "text/plain", String(t, 1));
}
3. Perche' mDNS?
Con MDNS.begin("esp32") puoi raggiungere il device su http://esp32.local senza sapere l'IP. Funziona su macOS/Linux nativamente e su Windows dopo aver installato Bonjour (o iTunes).
4. Response JSON per API
#include <ArduinoJson.h>
server.on("/api/status", [](){
StaticJsonDocument<256> doc;
doc["temp"] = 24.5;
doc["uptime"] = millis() / 1000;
doc["wifi_rssi"] = WiFi.RSSI();
String out; serializeJson(doc, out);
server.send(200, "application/json", out);
});
5. Autenticazione base
if (!server.authenticate("admin", "segreto2026")) {
return server.requestAuthentication();
}
// resto handler
6. WebSocket per aggiornamenti push
Se vuoi aggiornamenti dal server al browser senza polling, usa ArduinoWebsockets o ESPAsyncWebServer: latenze <10ms invece dei ~1000ms del setInterval.
Sicurezza: non esporre mai un ESP32 direttamente su Internet. Nessuna protezione seria contro attacchi. Usa una VPN (WireGuard/Tailscale) o un reverse proxy con autenticazione (nginx + auth basic + Let's Encrypt).