Popularny post AlcoMatt Napisano Marzec 3, 2021 Popularny post Udostępnij Napisano Marzec 3, 2021 (edytowany) Ten artykuł jest częścią serii "Tworzenie interfejsu sieciowego z wykorzystaniem ESP" #1 - część 1 (właśnie to czytasz) #2 - część 2 ESP32 czy też ESP8266 na dobre już zagościło w wielu warsztatach domowych majsterkowiczów. Większość obecnych projektów z wykorzystaniem ESP skupia się wokół dorzucenia do niego garści czujników, podłączenia do baterii i wybudzania go od czasu do czasu, aby wysłać dane o wykonanych pomiarach do naszego serwera. Czasem zdarza się, że nasze urządzenie pobiera pewne dane z zewnątrz i je wykorzystuje, np. budzik czas z serwera NTP, czy stacja pogodowa, informacje o pogodzie z wybranego serwisu. Co w sytuacji kiedy chcemy kontrolować nasze urządzenie lub obserwować jego stan z poziomu przeglądarki, a nie posiadamy Raspberry Pi, czy innej opcji, na której moglibyśmy mieć własny serwer? Co jeżeli zastosowanie dodatkowego serwera jest po prostu nieadekwatne do naszego celu? W tym artykule postaram się: omówić najpopularniejsze rozwiązania pokazać jak uruchomić serwer www ESP32 stworzyć prostą stronę www do naszych zadań wykonać interakcje strona-ESP w postaci: kontroli portu GPIO wyświetlanie wyniku pomiaru z ADC pobieranie pliku z pamięci ESP/karty SD Ten artykuł bierze udział w naszym konkursie! Na zwycięzców czekają karty podarunkowe Allegro, m.in.: 2000 zł, 1000 zł i 500 zł. Potrafisz napisać podobny poradnik? Opublikuj go na forum i zgłoś się do konkursu! Czekamy na ciekawe teksty związane z elektroniką i programowaniem. Sprawdź szczegóły » Wszystkie powyższe rzeczy postaram się zobrazować w jak najprostszy i przejrzysty sposób. Poruszany temat jest niewątpliwie bardzo złożony i niestety nie jest możliwe aby wszystkie informacje zawrzeć w jednym artykule. Temat wymaga zarówno znajomość obsługi samego ESP, HTML, JavaScriptu czy też CSS, zaś znajomość protokołów sieciowych również byłaby mile widziana. Tutaj będą jedynie ukazane podstawy jak to wszystko ze sobą połączyć. Pokazane metody z pewnością nie będą należeć do najbardziej optymalnych rozwiązań, mają jedynie na celu ukazanie koncepcji i zachęcenia do dalszej analizy tego zagadnienia. Wszystkie kody będą skomentowane. W treści będę również odsyłał do dodatkowych materiałów, które dokładniej opisują poszczególne zagadnienia oraz tam gdzie można zdobyć więcej wartościowych informacji. Ale w jakim celu? Część z osób może zadać pytanie po co uruchamiać serwer na ESP, wiąże się to z dużym poborem energii, pomiary najlepiej z wielu czujników wysyłać w jedno miejsce, to dużo pracy itd. Inni zaś, od razu stwierdzą, że to jest to czego oni potrzebują. Jako że nie widzę większego sensu pisania długich wywodów na temat dlaczego warto, dlaczego nie, kiedy tak, kiedy nie. Przedstawię poniżej dwa praktyczne przykłady i możliwości takich realizacji które pozwolą samemu ocenić te aspekty. Pierwszym przykładem jest zdalny interfejs drukarki 3D. Dzięki niemu możemy zdalnie uruchomić drukarkę, wysyłać do niej pliki, uruchamiać druk, obserwować parametry druku, dostosowywać je, konfigurować drukarkę i wiele innych. Zostało to zrealizowane na ESP8266 i projekt jest dostępny pod tymi linkami Duet WiFi Server oraz Duet Web Control Drugi przykład jest to interfejs do sterowania lampką/oświetleniem LED. Z poziomu przeglądarki możemy ustawiać różne efekty świetlne, barwę, jasność, konfigurować urządzenie. Więcej o tym projekcie można dowiedzieć się tutaj Aircookie WLED Co będzie nam potrzebne? Podstawowa znajomość platformy ESP oraz programowania w Arduino w tym obsługa SPIFFS lub kart SD Płytka z ESP32 (wszystko powinno być kompatybilne z ESP8266) Zainstalowana biblioteka Async Web Server Dodatkowo: Znajomość języka angielskiego – dodatkowe odnośniki Płytka stykowa, potencjometr, fotorezystor czy cokolwiek sobie wymyślicie aby urozmaicić sobie temat Zrozumienie tematu również ułatwi znajomość podstaw HTML oraz JavaScriptu. Jako że wymagane są już podstawowe umiejętności odnośnie obsługi ESP oraz Arduino, pominę kwestie instalacji biblioteki, omówienia zagadnień struktury programu czy też obsługi peryferiów. Z czym to się je? Podstawowa koncepcja naszego projektu opiera się na tym, iż na ESP uruchamiamy serwer, który na zapytanie klienta (klient czyli nas - naszej przeglądarki) zwraca odpowiednie pliki lub wykonuje pewne operacje. W ten sposób możemy poprosić ESP aby zwrócił nam plik HTML zawierający naszą stronę, przeglądarka ją odbierze, a my będziemy się mogli cieszyć widokiem naszej witryny. W ten sposób możemy wyróżnić pierwszy ze sposobów interakcji z naszym ESP, czyli z wykorzystaniem metod HTTP. W uproszczeniu, metody są to pewnego rodzaju „komunikaty” czego oczekujemy od naszego serwera. Przykładowo, wysyłamy zapytanie „GET” – oznacza że chcemy coś od serwera i ma on nam to dać, zapytanie „POST” – oznacza że chcemy coś dać od siebie. Każde nasze zapytanie będzie skutkować odpowiedzią (lub jej brakiem ). Odpowiedzi posiadają swoje kody, które mają różne znaczenie – to daje nam dodatkowe możliwości interakcji. Wiedząc co oznacza dany kod możemy przykładowo stwierdzać czy dostaliśmy odpowiedź, czy wyświetlić jakiś błąd, lub stwierdzić że coś nie istnieje (każdemu znane 404). Najprostszym użyciem tych zapytań jest po prostu wykorzystanie odpowiednich struktur w HTML z stosownymi atrybutami. Metodę „POST” możemy wykorzystać przy tworzeniu formularza. Wadą tego rozwiązania jest fakt tego iż będzie to skutkować przeładowaniem strony przy każdej tego typu akcji. Inną opcją jest wykorzystanie pomocy Java Scriptu który będzie służył jako nasza „trzecia ręka” wykonująca te operacje w tle. Rozwiązanie to nazywa się AJAX (z angielskiego Asynchronus JavaScript and XML) i na nim się głównie skupimy w tym artykule. Drugą powszechną opcją jest skorzystanie z WebSocket. Jest to sposób ciągłej komunikacji między klientem a serwerem. Polega ona na nawiązaniu „kontaktu” z serwerem i zapytaniem go czy jest chętny na „pogawędkę”. Metoda ta idealnie się nadaje do wymiany ciągów informacji na żywo. Przykładowo potrzebujemy ciągłego odczytu z przetwornika ADC – można stwierdzić „wirtualny port szeregowy”. Oczywiście moglibyśmy zrealizować to samo zadanie z wykorzystaniem wcześniej wspomnianych metod, ale wykorzystanie metody HTTP wiąże się z całym procesem, wysłania zapytania, otrzymania odpowiedzi, co w skali procesora trwa wieki (np. jedno zapytanie kilkadziesiąt – set ms). Tutaj nie mamy tego problemu, gdyż nasze połączenie ciągle trwa i sobie rozmawiamy. W przypadku gdy nie zależy nam na ciągłym podglądzie (np. odświeżanie informacji raz na pół minuty) możemy spokojnie zadowolić się wykorzystaniem AJAX i metod HTTP. Ponadto warto nadmienić iż korzystanie z WebSocketów jest zarówno korzystne dla serwera jak i klienta ze względu na minimalną ilość przesyłanych danych (ograniczenie tego co jest nam w rzeczywistości zbędne). No to zaczynamy! Na wstępie warto nadmienić że pracujemy wewnątrz sieci lokalnej. Jeżeli połączymy się z naszym WiFi, inne urządzenia z tej samej sieci będą miały dostęp do naszego serwera. Bez stosownej konfiguracji sieci (jak i czasem ograniczeń narzuconych przez naszego dostawcę internetowego) nie będziemy mieć dostępu do naszego urządzenia z dowolnego miejsca na świecie. Na początek zacznijmy od tego czym jest nasza biblioteka i dlaczego ona. Otóż umożliwia ona komunikację asynchroniczną, co pozwala nam na posiadanie więcej niż jednego połączenia w danej chwili i działa poza pętlą loop(). Aby się nie rozpisywać na temat innych zalet i możliwości zainteresowanych dogłębną analizą odeślę tutaj. Uwaga dla użytkowników ESP8266! Biblioteka od obsługi WiFi definiuje się jako: #include <ESP8266WiFi.h> Zaś obsługa SPIFFS: #include <FS.h> Ponadto w poniższej pętli while() potrzebne jest opóźnienie, aby zapobiec uruchamianiu się watchdoga while (WiFi.status() != WL_CONNECTED){ delay(1000); } Powyższe uwagi będą zawarte w komentarzach kodów. Uruchamiamy serwer! #include <Arduino.h> #include <WiFi.h> //ESP8266 //#include <ESP8266WiFi.h> #include <SPIFFS.h> //ESP8266 //#include <FS.h> #include <ESPAsyncWebServer.h> #define SSID "nazwa sieci" #define PASS "hasło sieci" AsyncWebServer serwer(80); //utwórzmy obiekt serwera na porcie 80 void setup() { Serial.begin(115200); //zainicjujmy port szeregowy WiFi.begin(SSID, PASS); //połącz z naszą siecią wifi while (WiFi.status() != WL_CONNECTED){ //poczekajmy aż ESP połączy się z naszą seicią //delay(1000); //dla ESP8266 } Serial.printf("\nAdres IP:"); Serial.println(WiFi.localIP()); //wypisz adres IP naszego ESP przez port szeregowy //tutaj odbywa sie obsługa zapytań serwer.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/" typu GET, request->send_P(200, "text/plain", "Witaj! :)"); //odpowiedz mu kodem 200, danymi tekstowymi, o treści "Witaj! :)" }); serwer.begin(); //zainicjujmy nasz serwer } void loop() { } W powyższym kodzie widzimy następujące etapy, łączymy się z naszą siecią WiFi, ESP zwraca nam przez port szeregowy swój adres IP w naszej sieci. Będzie on nam potrzebny do wpisania w pasku przeglądarki w celu połączenia się z serwerem. Następnie tworzymy funkcję która obsługuje konkretne zapytania, w naszym przypadku po otrzymaniu zapytania GET pod adresem „/” – można to określić jako „folder główny” serwera, tak samo jak w komputerze mamy dysk np. „D:\” – odeśle klientowi odpowiedź o kodzie 200 (oznacza to „ok” – więcej o kodach tutaj) i zawartości typu tekstowej (są to typy MIME, mówią one przeglądarce co jej chcemy przekazać – więcej o typach MIME tutaj). Rezultatem, po wpisaniu w pasek przeglądarki adresu IP naszego ESP, jest strona. Tworzymy prostą stronę Jako że celem tutaj nie jest nauka HTML czy też CSS, ograniczyłem stronę do absolutnego minimum, potrzebnego do naszych zabaw. Tutaj też, odeślę do wartościowego źródła gdzie można znaleźć wiele wartościowych informacji odnośnie HTML, JavaScript, CSS oraz innych. Nasza strona będzie się składać z pola tekstowego gdzie wyświetlimy wartość odczytaną z ADC, dwóch przycisków do włączania i wyłączania diody oraz przycisku pobierania pliku z naszego ESP. <!DOCTYPE html> <html> <head> <title>Strona</title> <meta charset="UTF-8"/> </head> <body> <p id="pomiar">Wartość:</p> <button id="on">Włącz</button> <button id="off">Wyłącz</button><br> <button id="download">Pobierz obrazek</button> <script> </script> </body> </html> Kluczowe podczas tworzenia takiej strony jest nadawanie unikalnego ID każdemu elementowi, ułatwi to współpracę z JavaScriptem. Gdy już mamy przygotowaną stronę musimy ją wgrać do SPIFFS. Stąd będziemy wysyłać plik HTML jako odpowiedź dla klienta. Analogicznie można te pliki wgrać na kartę pamięci i z delikatną modyfikacją kodu serwować z niej pliki. #include <Arduino.h> #include <WiFi.h> //ESP8266 //#include <ESP8266WiFi.h> #include <SPIFFS.h> //ESP8266 //#include <FS.h> #include <SPIFFS.h> #include <ESPAsyncWebServer.h> #define SSID "nazwa sieci" #define PASS "hasło sieci" AsyncWebServer serwer(80); //utwórzmy obiekt serwera na porcie 80 void setup() { Serial.begin(115200); //zainicjujmy port szeregowy SPIFFS.begin(); //zainicjujmy system plików WiFi.begin(SSID, PASS); //połącz z naszą siecią wifi while (WiFi.status() != WL_CONNECTED){ //poczekajmy aż ESP połączy się z naszą seicią //delay(1000); //dla ESP8266 } Serial.printf("\nAdres IP:"); Serial.println(WiFi.localIP()); //wypisz adres IP naszego ESP przez port szeregowy //tutaj odbywa sie obsługa zapytań serwer.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytania pod adresem "/" typu GET, request->send(SPIFFS, "/index.html", "text/html"); //odpowiedz plikiem index.html z SPIFFS (można to zmienić na kartę SD) //zawierającym naszą stronę będącą plikem tekstowym HTML }); serwer.begin(); //zainicjujmy nasz serwer } void loop() { } Teraz po wpisaniu adresu IP naszej strony w pasek przeglądarki ukaże się nam prosta strona. Pora na działanie! Na pierwszy ogień weźmiemy obsługę LED. W tym celu konieczne będzie dorzucenie trochę JavaScriptu do naszej strony document.getElementById("on").onclick = function () { //po nacisinięciu elementu o ID "on" const zapytanie = new XMLHttpRequest(); //wyślijmy zapytanie GET, pod adresem /on zapytanie.open("GET", "/on"); zapytanie.send(); }; document.getElementById("off").onclick = function () { //po nacisinięciu elementu o ID "off" const zapytanie = new XMLHttpRequest(); //wyślijmy zapytanie GET, pod adresem /off zapytanie.open("GET", "/off"); zapytanie.send(); }; Kod ten sprawdza czy któryś z przycisków został naciśnięty, a jeżeli został wysyła stosowne zapytanie do naszego serwera. Finalnie kod strony przedstawia się jak poniżej. <!DOCTYPE html> <html> <head> <title>Strona</title> <meta charset="UTF-8"/> </head> <body> <p id="pomiar">Wartość:</p> <button id="on">Włącz</button> <button id="off">Wyłącz</button><br> <button id="download">Pobierz obrazek</button> <script> document.getElementById("on").onclick = function () { //po nacisinięciu elementu o ID "on" const zapytanie = new XMLHttpRequest(); //wyślijmy zapytanie GET, pod adresem /on zapytanie.open("GET", "/on"); zapytanie.send(); }; document.getElementById("off").onclick = function () { //po nacisinięciu elementu o ID "off" const zapytanie = new XMLHttpRequest(); //wyślijmy zapytanie GET, pod adresem /off zapytanie.open("GET", "/off"); zapytanie.send(); }; </script> </body> </html> Ponadto w sekcji setup() naszego kodu ESP musimy dodać obsługę nowo powstałych zapytań. serwer.on("/on", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/on" typu GET, digitalWrite(LED, LOW); //zapal diodę request->send(200); //odeślij odpowiedź z kodem 200 OK }); serwer.on("/off", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/off" typu GET, digitalWrite(LED, HIGH); //zgaś diodę request->send(200); //odeślij odpowiedź z kodem 200 OK }); Co daje nam w rezultacie kod jak poniżej. Ważne aby wszystkie zapytania były przed funkcją serwer.begin() #include <Arduino.h> #include <WiFi.h> //ESP8266 //#include <ESP8266WiFi.h> #include <SPIFFS.h> //ESP8266 //#include <FS.h> #include <SPIFFS.h> #include <ESPAsyncWebServer.h> #define SSID "nazwa sieci" //nazwa sieci #define PASS "haslo sieci" //hasło sieci #define LED 22 //numer pinu gdzie mamy podłączoną diodę AsyncWebServer serwer(80); //utwórzmy obiekt serwera na porcie 80 void setup() { Serial.begin(115200); //zainicjujmy port szeregowy SPIFFS.begin(); //zainicjujmy system plików pinMode(LED, OUTPUT); //ustawmy naszeg pin jako wyjście WiFi.begin(SSID, PASS); //połącz z naszą siecią wifi while (WiFi.status() != WL_CONNECTED){ //poczekajmy aż ESP połączy się z naszą seicią //delay(1000); //dla ESP8266 } Serial.printf("\nAdres IP:"); Serial.println(WiFi.localIP()); //wypisz adres IP naszego ESP przez port szeregowy //tutaj odbywa sie obsługa zapytań serwer.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytania pod adresem "/" typu GET, request->send(SPIFFS, "/index.html", "text/html"); //odpowiedz plikiem index.html z SPIFFS (można to zmienić na kartę SD) //zawierającym naszą stronę będącą plikem tekstowym HTML }); serwer.on("/on", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/on" typu GET, digitalWrite(LED, LOW); //zapal diodę request->send(200); //odeślij odpowiedź z kodem 200 OK }); serwer.on("/off", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/off" typu GET, digitalWrite(LED, HIGH); //zgaś diodę request->send(200); //odeślij odpowiedź z kodem 200 OK }); serwer.begin(); //zainicjujmy nasz serwer } void loop() { } Teraz możemy zaobserwować działanie naszego kodu. Odczyt ADC Teraz pora na odczyt wartości z przetwornika analogowo-cyfrowego. Tym razem nasz skrypt będzie automatycznie, z pewnym interwałem czasowym (500ms), wysyłał zapytanie do serwera. setInterval(function () { const zapytanie = new XMLHttpRequest(); zapytanie.open("GET", "/adc"); zapytanie.send(); zapytanie.onreadystatechange = function () { if (this.readyState == 4 && this.status == 200) { document.getElementById("pomiar").innerHTML = "Pomiar:" + this.responseText; } }; }, 500); Powyższy fragment powinien znaleźć się w pliku .html w sekcji <script>, tak jak poprzednio. Serwer w odpowiedzi będzie zwracał wartość z ADC w postaci tekstu, zaś JavaScript, w tle będzie nam podmieniał wartości na stronie uzyskane w odpowiedzi od serwera, bez konieczności przeładowania. W kodzie ESP wystarczy że dodamy taki fragment kodu do sekcji setup() przed funkcją serwer.begin(). serwer.on("/adc", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/off" typu GET, String wartosc = String(analogRead(ADC)); //wykonaj pomiar ADC i zapisz do Stringa request->send(200, "text/plain", wartosc); //odeślij odpowiedź z kodem 200 OK i odczytem z wartością }); Na powyższej animacji widać jak zmieniają się wartości. W konsoli przeglądarki (przycisk F12 powinien nam ją uruchomić w większości przeglądarek) można obserwować wszystkie zapytania wymieniane między klientem a serwerem. Jest to bardzo przydatne narzędzie do „debugowania” kiedy coś nie chce do końca z nami współpracować. Powyższe zadania możemy zrealizować również w inny sposób, poprzez wywołanie naszej funkcji z poziomu funkcji obsługi zapytań. Przykład obsługi ADC przedstawiałby się w następujący sposób. #include <Arduino.h> #include <WiFi.h> //ESP8266 //#include <ESP8266WiFi.h> #include <SPIFFS.h> //ESP8266 //#include <FS.h> #include <SPIFFS.h> #include <ESPAsyncWebServer.h> #define SSID "nazwa sieci" //nazwa sieci #define PASS "hasło sieci" //hasło sieci #define ADC 34 //numer pinu potencjometru AsyncWebServer serwer(80); //utwórzmy obiekt serwera na porcie 80 String odczyt_ADC() { return String(analogRead(ADC)); } void setup() { Serial.begin(115200); //zainicjujmy port szeregowy SPIFFS.begin(); //zainicjujmy system plików pinMode(LED, OUTPUT); //ustawmy naszeg pin jako wyjście WiFi.begin(SSID, PASS); //połącz z naszą siecią wifi while (WiFi.status() != WL_CONNECTED){ //poczekajmy aż ESP połączy się z naszą seicią //delay(1000); //dla ESP8266 } Serial.printf("\nAdres IP:"); Serial.println(WiFi.localIP()); //wypisz adres IP naszego ESP przez port szeregowy //tutaj odbywa sie obsługa zapytań serwer.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytania pod adresem "/" typu GET, request->send(SPIFFS, "/index.html", "text/html"); //odpowiedz plikiem index.html z SPIFFS (można to zmienić na kartę SD) //zawierającym naszą stronę będącą plikem tekstowym HTML }); serwer.on("/adc", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/off" typu GET, request->send(200, "text/plain", odczyt_ADC()); //odeślij odpowiedź z kodem 200 OK i odczytem z wartością }); serwer.begin(); //zainicjujmy nasz serwer } void loop() { } Pobieranie pliku Na koniec zajmiemy się pobieraniem pliku z naszego serwera. W celu pokazania jak korzystać z typów MIME przedstawię jak pobrać obrazek z naszego prostego serwera. Do naszej ESP pamięci wgramy poniższy obrazek. W tym celu musimy dodać fragment skryptu do naszej strony. document.getElementById("download").onclick = function () { //po nacisinięciu elementu o ID "download" location.href = "/download"; //przekieruj pod /download }; Podobnie jak uprzednio dodajemy go do naszej sekcji <script></script>. Działa on podobnie jak poprzednie włączanie i wyłączanie diody, lecz w normalnej sytuacji, takie działanie spowodowałoby przekierowanie pod ten adres /download. Ponieważ w kodzie programu ustawimy atrybut pobierania. Będzie to skutkowało wyskoczeniem okna pobierania. serwer.on("/download", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/off" typu GET, request->send(SPIFFS, "/Lenna.png", "image/png", true); //odeślij odpowiedź w postaci pliku png o nazwie obrazek.png z SPIFFS i umożliwij pobranie (true) }); Jak widzimy musimy wskazać skąd nasz plik ma zostać pobrany (SPIFFS, może to być również karta SD), następnie wskazujemy dokładną lokalizację naszego pliku, jego rodzaj (MIME) oraz ustawiamy atrybut pobierania jako true. W efekcie uzyskujemy pobieranie naszego pliku. Zachęcam do sprawdzenia rezultatu po zmienieniu atrybutu pobierania na false. Poniżej zamieszam finalne wersje programu Arduino oraz kodu strony HTML. #include <Arduino.h> #include <WiFi.h> //ESP8266 //#include <ESP8266WiFi.h> #include <SPIFFS.h> //ESP8266 //#include <FS.h> #include <SPIFFS.h> #include <ESPAsyncWebServer.h> #define SSID "nazwa sieci" //nazwa sieci #define PASS "hasło sieci" //hasło sieci #define LED 22 //numer pinu gdzie mamy podłączoną diodę #define ADC 34 //numer pinu potencjometru AsyncWebServer serwer(80); //utwórzmy obiekt serwera na porcie 80 void setup() { Serial.begin(115200); //zainicjujmy port szeregowy SPIFFS.begin(); //zainicjujmy system plików pinMode(LED, OUTPUT); //ustawmy naszeg pin jako wyjście WiFi.begin(SSID, PASS); //połącz z naszą siecią wifi while (WiFi.status() != WL_CONNECTED){ //poczekajmy aż ESP połączy się z naszą seicią //delay(1000); //dla ESP8266 } Serial.printf("\nAdres IP:"); Serial.println(WiFi.localIP()); //wypisz adres IP naszego ESP przez port szeregowy //tutaj odbywa sie obsługa zapytań serwer.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytania pod adresem "/" typu GET, request->send(SPIFFS, "/index.html", "text/html"); //odpowiedz plikiem index.html z SPIFFS (można to zmienić na kartę SD) //zawierającym naszą stronę będącą plikem tekstowym HTML }); serwer.on("/on", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/on" typu GET, digitalWrite(LED, LOW); //zapal diodę request->send(200); //odeślij odpowiedź z kodem 200 OK }); serwer.on("/off", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/off" typu GET, digitalWrite(LED, HIGH); //zgaś diodę request->send(200); //odeślij odpowiedź z kodem 200 OK }); serwer.on("/adc", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/off" typu GET, String wartosc = String(analogRead(ADC)); //wykonaj pomiar ADC i zapisz do Stringa request->send(200, "text/plain", wartosc); //odeślij odpowiedź z kodem 200 OK i odczytem z wartością }); serwer.on("/download", HTTP_GET, [](AsyncWebServerRequest *request){ //na otrzymane od klienta zapytanie pod adresem "/off" typu GET, request->send(SPIFFS, "/Lenna.png", "image/png", false); //odeślij odpowiedź w postaci pliku png o nazwie obrazek.png z SPIFFS i umożliwij pobranie (true) }); serwer.begin(); //zainicjujmy nasz serwer } void loop() { } <!DOCTYPE html> <html> <head> <title>Strona</title> <meta charset="UTF-8" /> </head> <body> <p id="pomiar">Wartość:</p> <button id="on">Włącz</button> <button id="off">Wyłącz</button><br> <button id="download">Pobierz obrazek</button> <script> document.getElementById("on").onclick = function () { //po nacisinięciu elementu o ID "on" const zapytanie = new XMLHttpRequest(); //wyślijmy zapytanie GET, pod adresem /on zapytanie.open("GET", "/on"); zapytanie.send(); }; document.getElementById("off").onclick = function () { //po nacisinięciu elementu o ID "on" const zapytanie = new XMLHttpRequest(); //wyślijmy zapytanie GET, pod adresem /off zapytanie.open("GET", "/off"); zapytanie.send(); }; setInterval(function () { const zapytanie = new XMLHttpRequest(); //wyślijmy zapytanie jak poprzednio zapytanie.open("GET", "/adc"); zapytanie.send(); zapytanie.onreadystatechange = function () { if (this.readyState == 4 && this.status == 200) { document.getElementById("pomiar").innerHTML = "Wartość:" + this.responseText; } }; }, 500); document.getElementById("download").onclick = function () { //po nacisinięciu elementu o ID "download" location.href = "/download"; }; </script> </body> </html> Podsumowanie Bardzo się cieszę że dotrwałeś do tego momentu! Jak wspomniałem na początku, przedstawione rozwiązania są najprostszymi, niekoniecznie zgodnymi ze sztuką rozwiązaniami. Starałem się w kodach programów ograniczyć wszystkie zbędne fragmenty i uprościć do absolutnego minimum – czego często brakuje w poradnikach z internetu, co skutkuje utrudnioną analizą działania programu. Pokazane sposoby mają na celu jedynie wprowadzenie do koncepcji tematu, zachęcenia do pracy oraz poznawania możliwości rozwiązań sieciowych, o których można by było pisać całe książki. Zarówno komunikacja z wykorzystaniem Websocketów czy tworzenie samej strony którą widzi klient – czyli strony internetowej – mogłaby zająć czas na oddzielne artykuły. W drugiej części artykułu omówię w teoretyczny sposób (bez gotowych rozwiązań programowych) jak z wykorzystaniem ESP oraz dostępnych technologii i bibliotek rozwiać takie problemy jak: konfigurowanie urządzenia z poziomu przeglądarki przeglądanie i zarządzanie plikami w pamięci ESP provisioning i co to oraz po co to właściwie jest M. S. Edytowano Kwiecień 14, 2021 przez Gieneq Dodanie uwag 9 2
Treker (Damian Szymański) Marzec 3, 2021 Udostępnij Marzec 3, 2021 @AlcoMatt witam na forum i dziękuję za ciekawy artykuł. Wpis został zaakceptowany, więc jest już widoczny publicznie 1
Popularny post Elvis Marzec 3, 2021 Popularny post Udostępnij Marzec 3, 2021 A tak jako ciekawostka - kto wie skąd pochodzi ten przykładowy obrazek? Bardzo często jest używany więc, może warto wiedzieć 3
AlcoMatt Marzec 3, 2021 Autor tematu Udostępnij Marzec 3, 2021 @Treker Cieszę się bardzo! @Elvis Nie bez powodu go wybrałem. Taki mały smaczek
SOYER Marzec 3, 2021 Udostępnij Marzec 3, 2021 Obiektyw google którym wyszukałem to zdjęcie, pewnie wiele zawdzięcza temu zdjęciu. To ci Lena, nie wiedziałem... 1
czeslaw Marzec 8, 2021 Udostępnij Marzec 8, 2021 (edytowany) Chciałbym nieśmialo zapytać czy tu mozna zadawać niefachowe czy wrecz głupie pytania? Widzę tu jak dotychczas mądre wpisy. A ja probuję wystartować, bezskutecznie. Zaznaczam że dotychczas w odniesieniu do ESP8266 używałem Lua, ESPlorer i Flasher pod Windowsem 10, 32-bit i jakoś to szło. Zdaję sobie sprawy z ograniczeń platformy Lua więc chcialem sprobować czegoś lepszego czyli Arduino. A tutaj gubię się w tych bibliotekach i nie wiem jak zainstalować tę wspomnianą biliotekę albo jak uruchomić stosowne aplikacje do programowania ESP? Gdzie i w jakiej kolejnosci poklikać? Edytowano Marzec 8, 2021 przez czeslaw
AlcoMatt Marzec 8, 2021 Autor tematu Udostępnij Marzec 8, 2021 @czeslaw Zawsze wychodzę z założenia że nie ma głupich pytań. Na początku warto zacząć od tego czy chcesz programować w Arduino IDE czy w innym. Arduino IDE jest to środowisko dostarczane od producenta płytek Arduino jak i samego, określę to, frameworka Arduino. Durgą popularną opcją jest PlatformIO IDE. Osobiście preferuję drugą opcję i polecam. Tutaj jest pokazany proces instalacji samego środowiska, jak i dodawania bibliotek, czy tworzenia samego projektu. 1
czeslaw Marzec 11, 2021 Udostępnij Marzec 11, 2021 W fazie tworzenia projektu napotykam dylemat, który framework wybrać i dlaczego? A jesli już to zrobilem to co dalej? Próbowałem uruchomić RUN Without Debuging. Ale wtedy pojawia sie komunikat o błędzie. Czyli platformIO nie wspiera debugowania Node Mcu 0.9 ESP12... Chyba się poddam...
opp34 Marzec 11, 2021 Udostępnij Marzec 11, 2021 (edytowany) Opisz proszę precyzyjnie, jaki jest problem. W przypadku instalowania biblioteki, przy założeniu, że programujesz w Arduino IDE, są dwie opcje. Pierwsza to zastosowanie narzędzia wbudowanego w IDE. W tym celu otwierasz IDE, przechodzisz do zakładki Tools, a potem Manage Libraries. Otwiera się okno, w którym w prawym górnym rogu możesz wpisać nazwę biblioteki, a potem ją zainstalować (znajdujesz odpowiednią na liście i przyciskasz przycisk Install). Niektóre biblioteki nie znajdziesz na liście, tak jest z biblioteką wymienioną w tym artykule. Wówczas trzeba ją zainstalować ręcznie. Aby to zrobić, pobierz ją ze GitHuba za pomocą zielonego przycisku Code, Download ZIP. Po pobraniu rozpakuj paczkę, powinieneś mieć folder o nazwie ESPAsyncWebServer-master, zawierający w sobie folder src i pozostałe pliki. Następnie folder ESPAsyncWebServer-master trzeba skopiować do folderu, w którym Arduino IDE przechowuje biblioteki. Znajduje się on zazwyczaj pod adresem C:\Users\NazwaUżytkownika\Documents\Arduino\libraries. Możesz też otworzyć ten folder poprzez otwarcie Arduino IDE, utworzenie i zapisanie szkicu, kliknięciu wewnątrz szkicu i użyciu skrótu CTRL + K. Powoduje on otwarcie folderu, w którym znajduje się szkic. Wówczas wystarczy cofnąć się o jeden poziom i tam znajdziesz folder libraries. Jeśli chodzi o wybór płytki, którą programujesz, w Arduino IDE przechodzisz do Tools, Boards, następnie ESP8266 Boards i wybierasz płytkę, np. NodeMCU 1.0 (ESP12-E Module). Jeśli nie posiadasz w ogóle opcji płytek ESP, wówczas trzeba najpierw je zainstalować. Tutaj znajdziesz opis, jak to zrobić. Edytowano Marzec 11, 2021 przez opp34
czeslaw Marzec 12, 2021 Udostępnij Marzec 12, 2021 (edytowany) #include <Arduino.h> #include <ESPAsyncWebServer.h> #include <WiFi.h> #include <SPIFFS.h> ESPAsyncWebSerwer udało mi sie pobrać (chyba?) Aktualnie kompilator "wywala" mi sie z komunikatem " błąd WiFi.h : nie ma takiego pliku lub katalogu". Co jak się domyślam, oznacza to że należy pobrać i dołączyć biblioteki WiFi a takze SPIFFS. Na razie nie wiem jak, nie udaje mi się. Edytowano Marzec 12, 2021 przez czeslaw
opp34 Marzec 12, 2021 Udostępnij Marzec 12, 2021 Trudno jest odpowiedzieć jednoznacznie, ponieważ podanie prostej dyrektywy include z nazwą pliku nagłówkowego nie precyzuje, jaka biblioteka jest potrzebna. Bywa, że nazwy plików w poszczególnych bibliotekach pokrywają się (zazwyczaj są to biblioteki do tych samych zadań, stąd też nie załączasz ich jednocześnie i nie stanowi to problemu). W przypadku tego artykułu zrobiłbym założenie, że chodzi o standardowe biblioteki ESP32 od producenta płytek, firmy Espressif. Pobierz je sobie stąd. Jest to paczka bibliotek, w której znajdziesz SPIFFS (biblioteka do obsługi SPI Flash File System, tj. system plików, które są przechowywane w pamięci Flash ESP) oraz WiFi. Procedura ręcznego dodawania biblioteki jest praktycznie taka sama, jak pisałem poprzednio (przenosisz to, co wewnątrz folderu libraries do folderu, w którym przetrzymywane są wszystkie biblioteki Arduino IDE). Na dołączonej stronie jest też opis, jak dodać te biblioteki automatycznie. Uproszczając, otwierasz Arduino IDE, przechodzisz do File, potem Preferences oraz wklejasz https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json w pole Additional Board Manager URLs. Tyle jestem w stanie podpowiedzieć, nie wchodząc w szczegóły tego artykułu.
czeslaw Marzec 12, 2021 Udostępnij Marzec 12, 2021 (edytowany) Mam plytkę node mcu ESP8266. A nie ESP32. Czy to jest obojętne? Tak czy inaczej, pobralem rozpakowalem i skopiowalem do katalogu lib wskazany przez Ciebie pakiet. Nic to nie dało Edytowano Marzec 12, 2021 przez czeslaw
czeslaw Marzec 12, 2021 Udostępnij Marzec 12, 2021 (edytowany) Dodałem jeszcze ten SPIFFS ale nadal kuśtyka mi ta kompilacja. Widać nie ten pakiet podstawiłem. Edytowano Marzec 12, 2021 przez czeslaw
AlcoMatt Marzec 13, 2021 Autor tematu Udostępnij Marzec 13, 2021 (edytowany) @czeslaw Sprawdziłem, z tego co wyczytałem to w przypadku ESP8266 biblioteka WiFi to ESP8266WiFi.h SPIFFS zaś wymaga biblioteki FS.h zamiast SPIFFS.h Jeżeli biblioteka Async Web Server została poprawnie zainstalowana, reszta kodu powinna działać bez zmian (jedynie po zmianie powyższych bibliotek w kodzie). Rzeczywiście jest to niedopatrzenie z mojej strony. Jeżeli jesteś w stanie to zweryfikować, to daj znać, wtedy uwzględnię to w treści. Z tego powodu też nadmieniłem że mile widziane są podstawy. Edytowano Marzec 13, 2021 przez AlcoMatt
czeslaw Marzec 13, 2021 Udostępnij Marzec 13, 2021 Jak sprawdzić? Żebym dobrze zrozumiał? 1. Czyli mam zmienić w pliku projektu linie 3 i 4 odpowiednio na "ESP8266WiFi.h" oraz "FS.h" 2. Następnie wyszukać na GITHUBIE i wgrać do katalogu "lib" pakiety o powyższych nazwach?
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »