In einem anderen Tutorial habe ich bereits gezeigt, wie man einen einfachen Webserver auf einem ESP8266 realisieren kann. Dieser Webserver eignet sich gut für den Einstieg und bietet auch ein paar Funktionen die in der Praxis genügen. Beispielsweise für eine eigene API. Möchte man hingegen auch was optisch ansprechendes haben kommt man mit diesem Webserver schnell an seine Grenzen. Zwar könnte man auch einfache HTML-Teile direkt in den Code integrieren - was man häufig in Tutorials sieht - jedoch ist dies weder praktikabel, noch übersichtlich.
In diesem Tutorial werden wir diese - ich nenne sie mal - Workarounds aus der Welt schaffen und einen besseren Webserver mit richtigen Dateien programmieren. Neben echten HTML-Dateien kann der Webserver natürlich jegliche andere Art von Datei ausliefern. Egal ob CSS-, Javascript, oder Bilddateien. Möglich ist das mit dem ESPAsyncWebserver.
Produktempfehlungen und -suche in Verbindung mit dem Amazon Partnerprogramm:
¹ Angaben ohne Gewähr. Bei einem Kauf über den Link erhalten wir eine Provision.
Zum Kapitel springen Bibliotheken installieren
Für den Betrieb des ESPAsyncWebservers werden zwei Bibliotheken benötigt. Einmal der eigentliche ESPAsyncWebserver und dazu eine Abhängigkeit, die ESPAsyncTCP Bibliothek. Normalerweise würden wir an dieser Stelle den Bibliotheksverwalter der Arduino IDE aufrufen. In diesem Fall geht das leider nicht. Keine der beiden Bibliotheken ist über den Bibliotheksverwalter verfügbar. Wir müssen diese beiden Pakete manuell installieren, dies ist glücklicherweise fast genauso leicht.
Ich habe euch im folgenden die beiden Master als Direktdownload verlinkt. Die Quellen sind jeweils die Git-Repositories der beiden Bibliotheken. Beim Klick auf den Link startet der Download direkt.
Direkter Download via Github-Master:
- Download ESPAsyncWebserver-master.zip
- Download ESPAsyncTCP-master.zip
Die beiden heruntergeladenen zip-Archive müssen entpackt werden. Danach kann das -master
aus beiden Ordnernamen entfernt werden. Die beiden Ordner bzw. Bibliotheken müssen dann manuell zu den Arduino IDE Bibliotheken hinzugefügt werden. Der Ordner der Arduino-Bibliotheken befindet sich in der Regel im Ordner der Arduino IDE, welcher sich wiederum in eurem persönlichen Benutzerordner unter Dokumente
befindet.
Bei mir lautet der Pfad:
/Users/cooper.bin/Documents/Arduino/libraries
In dem Ordner sind all eure installierten Bibliotheken gespeichert. Bei mir ist der Ordner aktuell leer, da ich schlichtweg keine weiteren Bibliotheken installiert habe. Aus diesem Grund befinden sich in meinem Ordner auch nur die beiden Dateien des Downloads.
Spätestens jetzt sollte die Arduino IDE einmal neugestartet werden. Nach dem Neustart befinden sich in den Beispielen Einträge der beiden Bibliotheken.
Arduino IDE
└───Datei
└───Beispiele
└───ESP Async WebServer
└───ESP Async TCP
Zum entgültigen Validieren der erfolgreichen Installation kann das Beispiel simple_server
auf den ESP8266 hochgeladen werden. Dies ist sozusagen eine grundlegende Form des ESPAsyncWebservers ohne viel Overhead. Hier müssen einmal die WLAN-Daten angepasst werden. Danach kann das Programm Plug & Play auf den ESP hochgeladen werden. Wenn auf der Webseite des ESPs dann Hello world!
angezeigt wird kann es weitergehen, den Webserver mit echten HTML Dateien in Betrieb zu nehmen.
Zum Kapitel springen HTML-Template
Es gibt keinen ESP8266 Webserver mit HTML Dateien, ohne HTML-Dateien. Dafür habe ich ein kleines Template vorbereitet. Das Template beinhaltet ein paar Dateien die den Einsatz des Webserves zwar veranschaulichen, die Sache aber nicht unnötig komliziert macht. Die Dateistruktur des Templates sieht wie folgt aus:
./data
├── assets/
│ ├── css/
│ │ └── style.css
│ ├── images/
│ │ └── favicon-96.png
│ └── js/
│ └── script.js
└── index.html
Download: esp8266-webserver-html-template.zip
Im Ordner data
ist das komplette Frontend der Webseite verankert. Damit der Webserver dieses Frontend auch ordnungsgemäß ausliefern kann, muss dieses zunächst auf den ESP8266 hochgeladen werden. Und zwar direkt in dessen Dateisystem.
Eine genaue Anleitung wie das funktioniert, könnt ihr in meinem Tutorial Dateien auf dem ESP8266 speichern und lesen: Das LittleFS Dateisystem nachlesen. Besser gesagt braucht ihr für den Upload von Dateien in das Dateisystem des ESPs nur das Kapitel Dateiupload vom PC auf den ESP8266.
Zum Kapitel springen Programmcode
Der folgene Programmcode ist auf das nötigste reduziert, sodass er wirklich nur die Teile beinhaltet, die man für den Betrieb eines dateibasierten Webservers benötigt. Ich habe viele Kommentare eingefügt, die einzelene Code-Bestandteile erklären. Wer mein anderes Tutorial zum Thema einfacher Webserver auf dem ESP8266 vielleicht kennt, wird mit vielen Teilen des Codes vertraut sein. Die einzig große Änderung ist, dass wir jetzt eben richtge Dateien aus dem Dateisystem ausliefern.
Zu jedem Pfad auf dem Webserver wird die passende Datei ausgeliefert. Das gilt zum einen natürlich erstmal für normale Webseiten - so wie etwa die Startseite.
// Datei `index.html` wird ausgeliefert
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/index.html");
});
Zum anderen sind Dateien letzten Endes auch nichts anderes als Pfade auf dem Webserver, die ebenfalls Dateien ausliefern. Je nach Dateityp bietet es sich dann auch an, den passenden Content-Type festzulegen. Auf die gleiche Art und Weise kann man jegliche Dateien vom ESP8266 an den Client senden.
Produktempfehlungen und -suche in Verbindung mit dem Amazon Partnerprogramm:
¹ Angaben ohne Gewähr. Bei einem Kauf über den Link erhalten wir eine Provision.
// Gleiches mit einer Javascript-Datei
server.on("/assets/js/script.js", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/assets/js/script.js", "application/javascript");
});
// Gleiches mit einem PNG-Bild
server.on("/assets/images/favicon-96.png", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/assets/images/favicon-96.png", "image/png");
});
Wenn man die einzelnen Bestandteile zusammensetzt, erhält man einen vollumfänglichen Webserver auf dem ESP8266, welcher in der Lage ist, HTML und andere Dateien auszuliefern.
//
// Einfacher Webserver der Dateien aus dem LittleFS (Filesystem) ausliefert
// cooper.bin @ makesmart.net
// mehr Infos unter: https://makesmart.net/blog/read/esp8266-webserver-mit-echten-html-dateien
//
void setupServerRoutes();
void setupFilePaths();
// WLAN
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
// Webserver
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
// Filesystem
#include <LittleFS.h>
// Standard HTTP-Port 80
AsyncWebServer server(80);
// WLAN-Zugangsdaten
const char* ssid = "ssid";
const char* password = "password";
// Hostname des ESPs -> http://makesmartesp.local/
const char* espHostname = "makesmartesp";
// Was passiert, wenn eine Seite nicht gefunden werden kann
// Es wird die Datei `404.html` ausgeliefert
void notFound(AsyncWebServerRequest *request) {
AsyncWebServerResponse* response =
request -> beginResponse(LittleFS, "/404.html", "text/html");
response -> setCode(404);
request -> send(response);
}
void setup() {
delay(500);
Serial.begin(115200);
Serial.println();
delay(500);
// Dateisystem initialisieren
if(LittleFS.begin()){
Serial.println("Dateisystem: Initialisiert");
}else{
Serial.println("Dateisystem: Fehler beim Initialisieren");
}
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("WLAN Verbindung fehlgeschlagen");
return;
}
Serial.print("Verbunden! IP-Adresse: "); Serial.println(WiFi.localIP());
// Starten des mDNS-Servers
if ( !MDNS.begin(espHostname) ) {
Serial.println("Fehler beim Staren des mDNS-Servers!");
}
// Server Routen werden in einer eigenen Funktion definiert
setupServerRoutes();
// Datei Routen werden in einer eigenen Funktion definiert
setupFilePaths();
server.begin();
}
void loop() {
MDNS.update();
}
void setupServerRoutes(){
// Als Document-Root gilt der Ordner `data`;
// siehe: https://makesmart.net/blog/read/dateien-auf-dem-esp8266-speichern-und-lesen-das-spiffs-dateisystem
// Alle Pfade zu Dateien müssen relativ vom Ordner "data" definiert werden
// Datei `index.html` wird ausgeliefert
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/index.html");
});
server.onNotFound(notFound);
}
void setupFilePaths(){
// In `server.on` wird die Webserver-Route definiert
// in der Logik wird dann die CSS Datei aus dem LittleFS ausgeliefert: `assets/css/style.css`
server.on("/assets/css/style.css", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/assets/css/style.css", "text/css");
});
// Gleiches mit einer Javascript-Datei
server.on("/assets/js/script.js", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/assets/js/script.js", "application/javascript");
});
// Gleiches mit einem PNG-Bild
server.on("/assets/images/favicon-96.png", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/assets/images/favicon-96.png", "image/png");
});
}