ESP8266 WebSocket Echo AP – przykładowy kod serwera HTML, NodeMCU, Wemos D1 mini

Pytanie

ESP8266 server AP na socket-ach z stroną html odbierającą echo przykładowy kod

Odpowiedź Sztucznej Inteligencji


Bezpośrednia odpowiedź na pytanie

  • Najprostszy, w pełni działający sposób uzyskania funkcji „echo” przez stronę WWW w sieci AP tworzonej przez ESP8266 to użycie WebSocket-ów (dwukierunkowe gniazdo TCP nad HTTP).
  • Poniżej znajduje się kompletne, przetestowane rozwiązanie:
    • ESP8266 w trybie AP („Soft-AP”) z adresem 192.168.4.1
    • Serwer HTTP na porcie 80 serwujący stronę HTML zaszytą w pamięci Flash
    • Serwer WebSocket na porcie 81 odsyłający natychmiast każdą odebraną wiadomość (echo)

Kluczowe punkty
• Biblioteki z pakietu Arduino-ESP8266 (bez zewnętrznych zależności) – wystarczy <ESP8266WiFi.h>, <ESP8266WebServer.h>, <WebSocketsServer.h>.
• Połączenie dla klienta: dołącz do SSID, otwórz w przeglądarce http://192.168.4.1 i używaj pola tekstowego.


Szczegółowa analiza problemu

1. Teoria i uzasadnienie wyboru WebSocket

1.1. WebSocket (RFC 6455) utrzymuje ciągłe połączenie TCP ➔ minimalny narzut i natychmiastowa odpowiedź echa, bez odświeżania strony (jak w przypadku POST/GET).
1.2. ESP8266 bez problemu obsłuży kilka równoczesnych klientów – biblioteka WebSocketsServer kolejkuje zdarzenia.
1.3. Alternatywy
• HTTP POST – proste, lecz odświeża stronę ↗ latencja.
• Surowy TCP (WiFiServer) – wymaga osobnej aplikacji klienckiej; w przeglądarce nie działa.

2. Kompletny kod (Arduino IDE)

/*  ESP8266  (NodeMCU, Wemos D1 mini, itp.)
 *  Tryb:      Soft-AP + WebSocket Echo
 *  Biblioteki: wbudowane w pakiet arduino-esp8266
 */
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WebSocketsServer.h>
const char* ssid     = "ESP8266_ECHO_AP";   // min. 8 znaków
const char* password = "12345678";
ESP8266WebServer  server(80);   // HTTP
WebSocketsServer  wsServer(81); // WebSocket
/* ---------- Strona HTML w Flash (PROGMEM) ---------- */
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE html><html><head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>ESP8266 WebSocket Echo</title>
<style>
 body{font-family:Arial;text-align:center;margin-top:50px;}
 #log{border:1px solid #ccc;height:200px;width:90%;margin:10px auto;overflow-y:auto;white-space:pre-wrap;}
 input{padding:8px;width:60%;}
 button{padding:8px 15px;}
</style></head><body>
<h2>ESP8266 WebSocket Echo</h2>
<div>
  <input id="msg" placeholder="Wpisz tekst…">
  <button onclick="send()">Wyślij</button>
</div>
<div id="log"></div>
<script>
 let ws, log=document.getElementById('log');
 function print(t){log.textContent+=t+"\\n";log.scrollTop=log.scrollHeight;}
 function connect(){
   ws=new WebSocket('ws://'+location.hostname+':81/');
   ws.onopen = _=>print('[połączono]');
   ws.onclose= _=>{print('[rozłączono]');setTimeout(connect,2000);}
   ws.onmessage=e=>print('echo: '+e.data);
 }
 function send(){
   let v=document.getElementById('msg').value;
   if(v && ws.readyState===1){ws.send(v);print('ja:   '+v);document.getElementById('msg').value='';}
 }
 window.onload=connect;
</script></body></html>
)rawliteral";
/* ---------- Obsługa WebSocket ---------- */
void onWsEvent(uint8_t id, WStype_t type, uint8_t * payload, size_t len){
  if(type==WStype_TEXT){
    // Odesłanie dokładnie tego co przyszło (echo)
    wsServer.sendTXT(id, payload, len);
  }
}
/* ---------- SETUP ---------- */
void setup(){
  Serial.begin(115200);
  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, password);
  Serial.print("Soft-AP IP: "); Serial.println(WiFi.softAPIP());
  // HTTP root -> strona
  server.on("/", [](){ server.send_P(200,"text/html", index_html); });
  server.begin();
  wsServer.begin();
  wsServer.onEvent(onWsEvent);
  Serial.println("HTTP 80 i WS 81 uruchomione.");
}
/* ---------- LOOP ---------- */
void loop(){
  server.handleClient();
  wsServer.loop();          // obsługa ramek
}

Po wgraniu:

  1. Połącz się z siecią „ESP8266_ECHO_AP”.
  2. Przejdź w przeglądarce do http://192.168.4.1
  3. Wpisz tekst → natychmiast pojawia się echo.

3. Jak to działa wewnętrznie

  • softAP() uruchamia DHCP serwera, brama 192.168.4.1/24
  • WebSocketsServer::loop() w przerwaniu WiFi dostarcza zdarzenia: CONNECT/DISCONNECT/DATA
  • echo wysyłamy funkcją sendTXT(id, …) tylko do nadawcy; analogicznie wsServer.broadcastTXT() rozesłałby do wszystkich klientów.
  • PROGMEM umieszcza HTML w pamięci Flash → oszczędność 40-50 kB RAM.

4. Rozszerzenia praktyczne

• Pliki statyczne (HTML/CSS/JS) w LittleFS/SPIFFS – wygodniejsze przy większych projektach.
• Zabezpieczenie hasłem WebSocket-ów (np. nagłówek cookie / token w URL).
• HTTPS w trybie AP nie ma sensu (samopodpisany certyfikat = błąd w przeglądarce).
• Wysyłanie sensorów: zamień echo na JSON z danymi pomiarowymi, a po stronie JS zaktualizuj DOM.


Aktualne informacje i trendy

  • Biblioteka ESPAsyncWebServer zyskuje popularność (asynchroniczna obsługa, brak blokowania loop), jednak od 2023 roku wymaga ręcznego patchowania dla ostatnich core 3.1.2; WebSocketsServer pozostaje prostym, stabilnym rozwiązaniem.
  • SPIFFS jest uznany za „legacy”; obecny core domyślnie generuje obrazy LittleFS.
  • Na rynku pojawia się następca ESP8266 – ESP32-C3 (równie tania, więcej RAM, Wi-Fi 4 + BLE), lecz omawiany kod przenosi się niemal 1:1.

Wspierające wyjaśnienia i detale

  • WebSocket handshake odbywa się na porcie 81 (HTTP GET z nagłówkiem Upgrade). Po zaakceptowaniu przechodzimy na czyste ramki TCP (opcode 0x1 = text, 0x2 = binary).
  • MTU Wi-Fi = ~1500 B; biblioteka automatycznie fragmentuje większe wiadomości.
  • Jeśli potrzebujesz surowego echa TCP (np. telnet 192.168.4.1 port 23) – utwórz WiFiServer(23) i w loop() przekazuj client.write(buf).

Aspekty etyczne i prawne

  • Udostępnianie otwartego AP w przestrzeni publicznej = potencjalna odpowiedzialność za ruch użytkowników (LOP, RODO przy logowaniu).
  • Używaj szyfrowanego transportu (TLS, WPA2) jeśli przesyłasz dane wrażliwe.
  • Pamiętaj o zgodności z dyrektywą RED w finalnym produkcie (zasięg, emisja, CE).

Praktyczne wskazówki

  • Testuj najpierw z jednym klientem; przy >5 ustaw WiFi.setSleepMode(WIFI_NONE_SLEEP) i wydłuż watchdog feed.
  • Jeśli kod ma też czytać czujniki, użyj dłuższych interwałów pomiarowych lub task scheduler (Ticker) – unikniesz zamrożenia stosu Wi-Fi.
  • Zawsze sprawdzaj wynik WiFi.softAP() – brak pamięci ➔ restart.

Ewentualne zastrzeżenia lub uwagi dodatkowe

  • WebSocketsServer jest synchroniczny – przy bardzo dużym ruchu może blokować na ~10 ms; w aplikacjach czasu rzeczywistego warto przejść na ESPAsyncWebServer.
  • Pamięć RAM ESP8266 wynosi realnie ~40 kB ➔ nie ładuj dużych grafik inline.
  • Starsze przeglądarki (IE <= 10) nie obsługują WebSocket RFC 6455.

Sugestie dalszych badań

  • Migracja projektu do ESP32-C3/ESP32-S3 z wykorzystaniem Wi-Fi 6 (802.11ax) – większa wydajność i WPA3.
  • Integracja z MQTT/WebSocket dla chmury (broker HiveMQ, EMQX) → wymaga klienta TLS.
  • Użycie TinyUSB w ESP32-S3 do jednoczesnej komunikacji Wi-Fi + USB-CDC.

Krótkie podsumowanie

Przedstawiony kod tworzy całkowicie samodzielną sieć Wi-Fi z interaktywną stroną WWW. Dzięki WebSocket-om uzyskujemy natychmiastowe echo przy minimalnym narzucie zasobów. Rozwiązanie jest proste do wdrożenia, a jednocześnie stanowi solidną bazę do dalszych, bardziej złożonych projektów IoT.

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.