ESP8266 Server-Sent Events AP – przykład kodu z ESPAsyncWebServer, dashboard JSON

Pytanie

Server-Sent Events esp8266 AP przykład kodu

Odpowiedź Sztucznej Inteligencji


Bezpośrednia odpowiedź na pytanie

  • Poniżej znajduje się kompletny, gotowy do wgrania przykład Server-Sent Events (SSE) na ESP8266 pracującym w trybie punktu dostępowego (AP), zbudowany w oparciu o najnowszą (2024-06) wersję biblioteki ESPAsyncWebServer.
  • Kod tworzy sieć Wi-Fi, serwuje stronę HTML oraz strumień SSE z danymi JSON aktualizowanymi co 2 s.

Kluczowe punkty
• Tryb AP (WiFi.softAP) z własnym SSID/hasłem.
• Asynchroniczny serwer HTTP + AsyncEventSource.
• Przeglądarka łączy się obiektem EventSource i odbiera push-dane bez odświeżania.


Szczegółowa analiza problemu

1. Dlaczego SSE na ESP8266?

  1. Jednokierunkowy push serwer → klient, wykorzystuje nagłówek text/event-stream.
  2. Prostsze od WebSockets (brak handshake, mniejszy narzut), idealne dla mikrokontrolerów.
  3. Natywne wsparcie we wszystkich współczesnych przeglądarkach (oprócz IE).

2. Architektura rozwiązania

  1. Warstwa łącza – ESP8266 jako AP (domyślny DHCP 192.168.4.1/24).
  2. Warstwa aplikacyjnaESPAsyncWebServer ‎→ obsługuje:
    / – strona HTML (w PROGMEM),
    /events – strumień SSE,
    • statyczne pliki (opcjonalnie przez LittleFS).
  3. Warstwa prezentacji – JavaScript na stronie tworzy EventSource, parsuje JSON i aktualizuje DOM.

3. Kompletny kod (Arduino IDE / PlatformIO)

/*********  ZALEŻNOŚCI  *********/
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>          // me-no-dev/ESPAsyncTCP
#include <ESPAsyncWebServer.h>    // me-no-dev/ESPAsyncWebServer
/*********  KONFIGURACJA AP  *********/
const char* SSID_AP     = "ESP8266-SSE";
const char* PASS_AP     = "esp8266iot";   // ≥ 8 znaków
/*********  SERWER  *********/
AsyncWebServer  server(80);
AsyncEventSource events("/events");
/*********  DANE DEMO  *********/
unsigned long  lastSend   = 0;
const uint32_t SEND_INT   = 2000;    // [ms]
uint32_t       counter    = 0;
/*********  STRONA HTML  *********/
const char INDEX_HTML[] PROGMEM = R"rawlit(
<!DOCTYPE html><html lang="pl"><head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>ESP8266 SSE Dashboard</title>
<style>
body{font-family:sans-serif;text-align:center;background:#eef} #box{margin:2em auto;padding:1em 2em;background:#fff;border-radius:8px;width:280px}
#status{font-size:.9em;color:#666} .val{font-size:2em;color:#0277bd}
</style></head><body>
<h2>ESP8266 SSE Demo</h2><div id="box">
<div>Licznik: <span id="cnt" class="val">--</span></div>
<div>Losowa temp.: <span id="tmp" class="val">--</span> °C</div>
<div id="status">łączenie…</div></div>
<script>
let src = new EventSource('/events');
src.onopen   = _  => status("połączono");
src.onerror  = e  => status("rozłączono ("+ (e.readyState||'') +")");
src.onmessage = e => {
  try{ let d = JSON.parse(e.data);
       cnt.textContent=d.counter;
       tmp.textContent=d.temp.toFixed(1);
  }catch(_){}};
function status(t){document.getElementById('status').textContent=t}
</script></body></html>
)rawlit";
/*********  SETUP  *********/
void setup() {
  Serial.begin(115200);
  WiFi.softAP(SSID_AP, PASS_AP);
  Serial.printf("\n[AP] SSID:%s  IP:%s\n", SSID_AP, WiFi.softAPIP().toString().c_str());
  /* --- ROUTING --- */
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *r){r->send_P(200,"text/html",INDEX_HTML);});
  server.addHandler(&events);          // /events
  events.onConnect([](AsyncEventSourceClient *c){
      Serial.printf("Nowy klient SSE id=%u\n", c->client()->remotePort());
      c->send("{\"hello\":\"world\"}",NULL, millis(), 1000); // pierwszy komunikat
  });
  server.begin();
}
/*********  LOOP  *********/
void loop() {
  /* ESPAsyncWebServer nie wymaga server.handleClient() */
  if (millis()-lastSend > SEND_INT) {
    lastSend = millis();
    counter++;
    float temp = 20.0 + random(-50,51)/10.0;   // symulacja
    String json = "{\"counter\":" + String(counter) +
                  ",\"temp\":"  + String(temp,1) + "}";
    events.send(json.c_str(),     // payload
                "update",         // typ zdarzenia (opcjonalnie)
                millis());        // id – używane do auto-reconnect
  }
}

4. Test krok-po-kroku

  1. Wgraj szkic, otwórz serial monitor (115 200 Bd), odczytaj IP (zwykle 192.168.4.1).
  2. Połącz telefon/PC z siecią „ESP8266-SSE”.
  3. W przeglądarce wpisz http://192.168.4.1/. Licznik i „temp.” powinny aktualizować się co 2 s bez odświeżania strony.
  4. W zakładce „Network ➜ EventStream” (Chrome DevTools) widać surowy strumień SSE.

Aktualne informacje i trendy

• Biblioteka ESPAsyncWebServer została oficjalnie „zamrożona” przez autora (me-no-dev), ale społeczność utrzymuje forki (np. khoih-prog/ESPAsyncWebServer), kompatybilne z core ESP8266 v3.1.2 (2024).
• Dla prostych projektów można użyć blokującej ESP8266WebServer; przy wielu klientach lub dużej dynamice przesyłu lepszy jest model asynchroniczny.
• SSE na ESP8266 zyskuje popularność w dashboardach instalowanych lokalnie (konfiguratory, loggery), ponieważ nie wymaga CORS ani ręcznego „pingowania” AJAX-em.
• Alternatywne trendy: HTTP/2 server-push (na ESP32-S3), WebSockets (dwukierunkowe), MQTT over WebSockets.


Wspierające wyjaśnienia i detale

  • Format ramki SSE:

    id: 123
    event: update
    data: {"key":"val"}
    

    (pusta linia zamyka zdarzenie).

  • AsyncEventSource sam buforuje klientów; w pętli wysyłamy tylko events.send(...).

  • Przeglądarka po utracie Wi-Fi automatycznie wznawia strumień, wysyłając nagłówek Last-Event-ID; dlatego warto przekazywać monotoniczne id.

  • ESP8266 w trybie AP ogranicza liczbę jednoczesnych stacji ≤ 4 (default), można zmienić softAPConfig(max_connection).


Aspekty etyczne i prawne

  • Uprawnienia radiowe: ESP8266 pracuje w paśmie 2,4 GHz; w UE moc ≤ 100 mW EIRP, domyślne ustawienia modułu to spełniają.
  • Bezpieczeństwo: komunikacja AP-klient jest niezaszyfrowana (HTTP). Jeśli urządzenie ma pracować w otwartym środowisku, rozważ WPA2 + token w URL lub przejście na HTTPS (BearSSL – wymaga dodatkowego RAM).
  • Licencje: ESPAsyncWebServer – LGPL-2.1, dołącz do projektu odpowiedni plik LICENSE w repozytorium produktu.

Praktyczne wskazówki

• Unikaj blokujących opóźnień (delay) – zakłócą wysyłkę pakietów TCP.
• Przechowuj duże strony w PROGMEM lub LittleFS.
• Jeżeli wysyłasz binaria (np. Base64), kontroluj wolumen: pamięć TX-FIFO ESP ≈ 2000 B.
• Do OTA update dodaj „AsyncElegantOTA” (kompatybilne z AsyncWebServer).


Ewentualne zastrzeżenia lub uwagi dodatkowe

  • SSE obsługuje tylko strumień w jedną stronę; nie wyślesz komendy z przeglądarki do ESP (od tego jest fetch/XHR lub WebSocket).
  • Przy wielu klientach (>3-4) mogą wystąpić retransmisje i spadki wydajności – kontroluj heap() i loguj LWIP-stats.

Sugestie dalszych badań

• Porównaj SSE z WebSocket w kontekście zużycia RAM (heap) i czasu CPU.
• Przetestuj HTTP/2 server-push na ESP32-S3 (idf-5.x).
• Oceń integrację SSE z Web Components (Lit, Svelte) dla bogatszego UI.
• Zerknij na projekt „esp8266-ws-async” – łączy SSE do push-stanu i WebSocket do sterowania.


Krótkie podsumowanie

Udostępniony przykład pokazuje, jak w kilku liniach uruchomić na ESP8266 własny hotspot z panelem WWW aktualizowanym w czasie rzeczywistym przez Server-Sent Events. Rozwiązanie jest lekkie, nie wymaga ciągłych zapytań AJAX ani skomplikowanego handshake’u WebSocket. W praktyce:

  1. WiFi.softAP → tworzy sieć.
  2. AsyncWebServer → serwuje stronę i stream SSE.
  3. events.send → pushuje JSON.
    Całość działa na aktualnym core ESP8266 3.x, wymaga tylko dwóch bibliotek asynchronicznych. Przy większych projektach zadbaj o bezpieczeństwo (HTTPS lub tunel) i zarządzanie wieloma klientami.

Oceń odpowiedź:

Zadaj dodatkowe pytanie Sztucznej Inteligencji

Czekaj (1min)...
Zastrzeżenie: Odpowiedzi udzielone przez sztuczną inteligencję (model językowy) mogą być niedokładne i wprowadzające w błąd. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi powinny być zweryfikowane przez użytkownika.