ESP8266 Webserverinhalte wie Bilder (PNG und JPEG) aus dem internen Flash-Speicher laden
Der ESP8266 NodeMCU kann als Webserver mit im Code hinterlegten html Webseiten verwendet werden. Es besteht jedoch vielleicht auch der Wunsch Bilder in die Webseite einzufügen. Dies kann mit Hilfe von SPIFFS (SPI Flash File System) erreicht werden. In dieser Anleitung wird diese Möglichkeit beispielhaft gezeigt.
Benötigte Tools für diese Anleitung:
Neben der Arduino IDE und der Installation der ESP8266 Plugins (hier beschrieben) wird das Tool “ESP8266 Sketch Data Upload” benötigt.
- Laden Sie das Tool aus folgendem Git-Repository herunter: https://github.com/esp8266/arduino-esp8266fs-plugin/releases/download/0.1.3/ESP8266FS-0.1.3.zip
- Erstellen Sie in Ihrem Arduino Installations-Verzeichnis das Verzeichnis “tools”, falls es noch nicht existiert.
- Entpacken Sie das .zip Archiv in dieses Verzeichnis (der Pfad sollte dann wie folgt aussehen: <Installations-Verzeichnis>/Arduino/tools/ESP8266FS/)
- Starten Sie die Arduino IDE neu
- Erstellen Sie einen neuen Sketch und speichern Sie diesen
- Navigieren Sie das Abgabeverzeichnis des Sketches (auch über die Arduino IDE möglich durch: Sketch -> Sketch-Ordner Anzeigen)
- Erstellen Sie den Unterordner “data” und legen Sie die Bilddateien und HTML-Dateien hier ab.
- Wenn nun das richtige Board und COM-Port ausgewählt ist, so wie der Serielle Monitor geschlossen ist, können die Dateien über:
Werkzeuge -> ESP8266 Sketch Data Upload an den ESP übertragen werden.
Erstellung der HTML-Webseite mit einem Bild als Beispiel
Erstellen Sie eine neue Text-Datei im bereits angelegten data-Ordner des zu verwendenden Sketches. Die angelegte Datei muss nun in index.html umbenannt und mit dem Texteditor Ihrer Wahl editiert werden. Zu empfehlen ist der Sublime Text-Editor.
Dies ist der Beispiel HTML-Code, welcher in der index.html Datei gespeichert wird:
<!DOCTYPE html> <html> <body> <p>Dies ist eine Beispiel, wie sich eine HTML-Seite und eine Bild aus dem Dateisystem des ESP-Flash laden lässt:</p> <a href="https://goo.gl/eZWtAM"><img src="\image.png" alt="Bild aus dem ESP8266 Flashspeicher" width="350" height="100"></a> </body> </html>
Als Bild wird in diesem Beispiel unser Logo benutzt, welches Sie über einen Rechtsklick und “Bild speicher unter …” ebenfalls im data-Ordner unter dem Namen image.png ablegen.
Der Arduino-Sketch mit dem ESP8266 Webserver
In den bereits angelegten Sketch fügen Sie folgenden Code ein (In der ESP-WLAN-Konfiguration muss der SSID und das dazugehörige Passwort hinterlegt werden):
#include <ESP8266WiFi.h> // Für die WLAN-Funktion des ESP8266 #include <ESP8266WebServer.h> // Für die Web-Server-Funktion des ESP8266 #include <FS.h> // Für die Dateisystemverwaltung des ESP8266 // Die SSID und das dazügehörige Passwort müssen angepasst werden! const char* imagefile = "/image.png"; const char* htmlfile = "/index.html"; //ESP-WLAN Konfiguration const char *ssid = "SSID-von-Ihrem-Lokalen-WLAN"; const char *password = "PW-des-lokalen-WLAN"; //ESP-Web-Server Konfiguration ESP8266WebServer server(80); void handleRoot(){ server.sendHeader("Location", "/index.html",true); //Weiterleitung auf die eigene HTML-Seite server.send(302, "text/plane",""); } void handleWebRequests(){ if(loadFromSpiffs(server.uri())) return; String message = "File Not Detected\n\n"; message += "URI: "; message += server.uri(); message += "\nMethod: "; message += (server.method() == HTTP_GET)?"GET":"POST"; message += "\nArguments: "; message += server.args(); message += "\n"; for (uint8_t i=0; i<server.args(); i++){ message += " NAME:"+server.argName(i) + "\n VALUE:" + server.arg(i) + "\n"; } server.send(404, "text/plain", message); Serial.println(message); } void setup() { delay(1000); Serial.begin(9600); Serial.println(); //Initialisierung des Dateisystems SPIFFS.begin(); Serial.println("Dateisystem initialisiert"); //Initialisierung des WLAN-Clienten Serial.print("Verbunden mit "); Serial.println(ssid); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WLAN verbunden"); Serial.println("IP-Addresse: "); Serial.println(WiFi.localIP()); //Initialisierung Webserver server.on("/",handleRoot); server.onNotFound(handleWebRequests); server.begin(); } void loop() { server.handleClient(); } bool loadFromSpiffs(String path){ String dataType = "text/plain"; if(path.endsWith("/")) path += "index.htm"; if(path.endsWith(".src")) path = path.substring(0, path.lastIndexOf(".")); else if(path.endsWith(".html")) dataType = "text/html"; else if(path.endsWith(".htm")) dataType = "text/html"; else if(path.endsWith(".css")) dataType = "text/css"; else if(path.endsWith(".js")) dataType = "application/javascript"; else if(path.endsWith(".png")) dataType = "image/png"; else if(path.endsWith(".gif")) dataType = "image/gif"; else if(path.endsWith(".jpg")) dataType = "image/jpeg"; else if(path.endsWith(".ico")) dataType = "image/x-icon"; else if(path.endsWith(".xml")) dataType = "text/xml"; else if(path.endsWith(".pdf")) dataType = "application/pdf"; else if(path.endsWith(".zip")) dataType = "application/zip"; File dataFile = SPIFFS.open(path.c_str(), "r"); if (server.hasArg("download")) dataType = "application/octet-stream"; if (server.streamFile(dataFile, dataType) != dataFile.size()) { } dataFile.close(); return true; }
Dieser Sketch wird nun auf den ESP8266 übertragen.
Im Anschluss wird die HTML-Datei und das PNG-Bild über: Werkzeuge -> ESP8266 Sketch Data Upload übertragen.
Die erfolgreiche Übertragung erkennt man an folgender Konsolenausgabe der Aruino IDE:
Das Ergebnis lässt sich nun im Browser betrachten. Um die aufzurufende IP-Adresse herauszufinden wird der Serielle Monitor geöffnet und der ESP8266 neu gestartet.
Nun kann der ESP-Web-Server über den Browser angefragt werden. In diesem Beispiel ist die Adresse: http://192.168.2.61/index.html
Die Beispielseite sieht dann wie folgt aus:
Funktioniert nicht
src\main.cpp: In function ‘void handleWebRequests()’:
src\main.cpp:21:33: error: ‘loadFromSpiffs’ was not declared in this scope
if(loadFromSpiffs(server.uri())) return;
^
*** [.pioenvs\nodemcuv2\src\main.cpp.o] Error 1
Wir haben den Code nochmal erfolgreich getestet. Es wird ein include / eine include-Datei fehlen. Oder es wurde nicht das richtige Board ausgewählt.
noe, ihr habt nur leider nicht mit einer frischen Installation getestet. wir stolpern da ueber einen bug in der spiffs lib. (siehe google!)
Hallo, mir ist es gelungen, laut Ihrer detaillierten Beschreibung das Ganze auf einem WEMOS D1 Board zu installieren. Auch das Flashwerkzeug funktioniert hervorragend nach der Installation in das bei mir noch nicht vorhandene Werkzeug-Verzeichnis ‘tools’. Eigentlich funktioniert alles fast korrekt. Bis auf eine Besonderheit, die aber meines Erachtens nach im HTML code verankert ist. …..
Durch die source Quelle erscheint dass Bild leider nicht direkt nach Aufruf der Webseite im PC Browser oder auf dem AndroidMobilgerät, sondern man muss das Bild noch einmal ‘anklicken’ und dann wird man auf Ihre 42project.net Seite weitergeleitet, was ja auch bei dem HTML Code Sinn macht. Wie muss der korrekte Code lauten, damit das Programm richtig funktioniert ? Danke im voraus.
Funktioniert fast alles, nur der HTML code ist fehlerhaft ….
Das Bild kommt leider nicht aus dem Flashspeicher, sondern man wird auf die Webseite von 42project geleitet. Ist ja nicht verkehrt, weil werbewirksam, aber wie muss der Code tatsächlich lauten, so dass das Bild aus dem Flashspeicher meines ESP kommt?
Hallo, nun habe ich mich angemeldet, und hoffe, dass mein Kommentar auch ankommt. Also folgendes zum ESP8266 Programm mit der Möglichkeit, Daten im FlashSpeicher abzulegen und dann in einer HTML Seite aufzurufen. Mir ist die Programmierung mit einem WEMOS D1 Board gelungen. Alles so, wie Sie beschrieben haben. Nur ein kleiner Mangel ist mir im HTML Code aufgefallen …..
Durch den Verweis auf die Quelle der PNG Datei erhalte ich beim Aufruf der Webseite im PC oder meinem Android Browser bei korrekter Eingabe meiner lokalen IP Adresse
zwar korrekt die ausgegebene HTML Seite meines ESP8266 Servers, aber das Bild muss extra ‘angeklickt’ werden und danach werde ich auf die Webseite von 42project.net geleitet und das Bild erscheint. Allerdings nicht aus meinem Flashspeicher, sondern von ihrer Webseite. Was muss ich am obigen HTML Text verändern, damit das Bild aus meinem Flashspeicher auf der aufgerufenen Seite meines Browers erscheint? Auf eine Antwort hoffend, verbleibt Ihr Leser P.Geisler
Hallo – ich muss Sie um Entschuldigung bitten – denn Sie haben die Sache wirklich korrekt beschrieben ….. Zitat Anfang “Als Bild wird in diesem Beispiel unser Logo benutzt, welches Sie über einen Rechtsklick und “Bild speicher unter …” ebenfalls im data-Ordner unter dem Namen image.png ablegen. ..” Zitat Ende. Wie heisst es doch so kurz und treffend – wer lesen kann ist klar im Vorteil …… nachdem ich das Logo korrekt in image.png im Data Ordner abgelegt hatte, funktioniert nun alles 100%. Vielen Dank für die sehr instruktive Beschreibung dieser Anwendung. Ich glaube, damit habe ich ein solides Fundament für weitere schöne Anwendungen bei Ihnen gefunden.
Vielen Dank für Ihre Kommentare. Gut, dass am Ende alles funktioniert hat.
Hallo,
hat alles bestens geklappt, css geht auch sehr schöne Anleitung.
Ich möchte noch gerne Daten von der Webseite an die Node Mcu übergeben und umgekehrt
das geht bestimmt mit Post, etwas PHP CSS MySQL habe ich schon einmal gemacht aber
wie übergebe ich die Daten im Sketch.
Ich finde nur Beispiele wo der HTML Teil im Sketch mit drin ist da ist das klar
hast du eventuell eine Beispielseite, oder ich finde nicht die richtigen Suchbegriffe.
Freue mich auf Antwort
Gruß Günther
Hallo Günther,
der Beitrag auf dieser Webseite könnte weiterhelfen:
https://techtutorialsx.com/2017/12/17/esp32-arduino-http-server-getting-query-parameters/
Beste Grüße
Armin
Hallo,
danke für die schnelle Antwort.
Das Englisch ist nicht so meins aber ich weiß jetzt wo nach ich suchen muss.
Javascript geht ja auch drauf will ich auch lernen immer Schritt für Schritt
alle haben mal klein angefangen.
Gruß Günther
Moin moin.
Ich würde mich sehr freuen, wenn Ihr mein Problem ausräumt.
Ich versuche eine offline Webseite (mit Bildern u. Text) per AP bereit zu stellen und fand bei der Suche nach einem Beispiel Euren klasse Beitrag.
Der AP wird zwar von anderen Geräten gefunden, man kann sich mit ihm verbinden, ABER
die Startseite aus dem SPIFFS wird nicht aufgerufen / gestartet. ;-((
Egal, ob mit Chrome o. Firefox, es erscheint die Fehlermeldung:
Diese Seite ist nicht erreichbar
http://192.168.4.50/ ist nicht erreichbar
ERR_ADDRESS_UNREACHABLE
Ich weiss nicht, was ich falsch mache ;-(((
Hier mal der Sketch von Euch, den ich für meine Zwecke verändert habe.
“”
#include
#include
#include
#include
const char* htmlfile = “/index.html”;
ESP8266WebServer server(80);
IPAddress IP(192,168,4,50);
IPAddress mask = (255, 255, 255, 0);
void handleRoot(){
server.sendHeader(“Location”, “/index.html”,true);
server.send(302, “text/plane”,””);
}
void handleWebRequests(){
if(loadFromSpiffs(server.uri())) return;
String message = “File Not Detected\n\n”;
message += “URI: “;
message += server.uri();
message += “\nMethod: “;
message += (server.method() == HTTP_GET)?”GET”:”POST”;
message += “\nArguments: “;
message += server.args();
message += “\n”;
for (uint8_t i=0; i<server.args(); i++){
message += " NAME:"+server.argName(i) + "\n VALUE:" + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
Serial.println(message);
}
void setup() {
delay(1000);
// Serial.begin(9600);
Serial.begin(115200);
Serial.println();
WiFi.mode(WIFI_AP);
WiFi.softAP("Test", ""); //"" kein Leerfeld / kein Eintrag = offener AP
WiFi.softAPConfig(IP, IP, mask);
server.begin();
Serial.println();
Serial.println("Test");
Serial.println("Server gestartet.");
Serial.print("IP: "); Serial.println(WiFi.softAPIP());
Serial.print("MAC:"); Serial.println(WiFi.softAPmacAddress());
Serial.println();
SPIFFS.begin();
Serial.println("Dateisystem initialisiert");
Serial.print("Verbunden mit ");
WiFi.mode(WIFI_AP);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WLAN verbunden");
Serial.println("IP-Addresse: ");
Serial.println(WiFi.localIP());
//Initialisierung Webserver
server.on("/",handleRoot);
server.onNotFound(handleWebRequests);
server.begin();
}
void loop() {
server.handleClient();
}
bool loadFromSpiffs(String path){
String dataType = "text/plain";
if(path.endsWith("/")) path += "index.html";
if(path.endsWith(".src")) path = path.substring(0, path.lastIndexOf("."));
else if(path.endsWith(".html")) dataType = "text/html";
else if(path.endsWith(".htm")) dataType = "text/html";
else if(path.endsWith(".css")) dataType = "text/css";
else if(path.endsWith(".js")) dataType = "application/javascript";
else if(path.endsWith(".png")) dataType = "image/png";
else if(path.endsWith(".gif")) dataType = "image/gif";
else if(path.endsWith(".jpg")) dataType = "image/jpeg";
else if(path.endsWith(".ico")) dataType = "image/x-icon";
else if(path.endsWith(".xml")) dataType = "text/xml";
else if(path.endsWith(".pdf")) dataType = "application/pdf";
else if(path.endsWith(".zip")) dataType = "application/zip";
File dataFile = SPIFFS.open(path.c_str(), "r");
if (server.hasArg("download")) dataType = "application/octet-stream";
if (server.streamFile(dataFile, dataType) != dataFile.size()) {
}
dataFile.close();
return true;
}
""
Ich hoffe Ihr könnt mir weiter helfen.
Gruß
Paul
Super Project, gefällt mir richtig gut.
Was muss man denn ändern damit es auch auf einem ESP32 läuft?
LG
Uwe