Beispiel 5: Web-Server mit Außensteuerung

Dieses Beispiel ergänzt das Beispiel 4. Es kommt eine vorgefertigte Web-Site hinzu, mit der eine einfache Außensteuerung realisiert werden kann. Per Web-Site können die Zugangsdaten zum WLAN und die Authentifizierungsdaten gepflegt werden. Wenn die Authentifizierungsdaten geändert werden, soll die Änderung sofort wirksam werden. Eine Änderung der WLAN-Zugangsdaten wird erst nach einem Reset wirksam.

Es sind zwei weitere Dateien im SPIFFS notwendig: "config.html", die HTML-Datei zur Pflege der Außensteuerungsparameter, und "config.txt", die Datei mit den Parameter-Werten:

Dateien

Die Außensteuerung beinhaltet in diesem Beispiel die Zugangsdaten für das WLAN und die Authentifizierungsdaten:

Außensteuerungsparameter

Achtung: Die Zugangsdaten zum WLAN sollten angepasst werden, bevor die Dateien ins SPIFFS hochgeladen werden. Wichtig ist dies in der Datei (config.txt), sicherheitshalber aber auch im Quellcode. Die zusätzlichen Dateien können auch mit dem SPIFFS-Editor hochgeladen werden. 

Details zur internen Darstellung dieser Parameter siehe ESP8266 UrsSettings: Alles nur eine Einstellungssache!

Außensteuerung

Für die Verwaltung der Außensteuerungsparameter ist die Klasse MySettings zuständig.

class MySettingsClass : public UrsSettingsBaseClass {
 public:
   // ID-Daten für WiFi Station
   StringSetting(SSID,     "...");
   StringSetting(Password, "...");
   StringSetting(Hostname, "UrsAsync5");

   // Administrator
   StringSetting(AdminUser,     "admin");
   StringSetting(AdminPassword, "geheim");
};

Erweiterung von MyWebServerClass

Die Klasse erhält drei zusätzliche Elemente.

class MyWebServerClass : public UrsAsyncWebServerBaseClass {
protected:
  // Überschreibt die Methode 'notFoundHandler' von 'UrsAsyncWebServer'
  virtual void notFoundHandler(AsyncWebServerRequest *request) override;

  UrsAsyncConfigEditorClass configEditor;

  void configChangedHandler(UrsSettingsBaseClass * settings);

// ...

public:
  // Startet den Web.Server
  void begin(MySettingsClass& settings); 
};

Als erstes wird die Methode notFoundHandler überschrieben. Ziel ist es der "404"-Fehlermeldung eine bessere Optik zu geben.

UrsAsyncConfigEditorClass configEditor; sorgt für die Einbindung der Weg-Site, wie vorher schon beim SPIFFS-Editor geschehen. Die UrsAsyncConfigEditorClass-Klasse unterstützt mehrere Ereignisse. U.a. gibt es eine Rückmeldung, wenn neue Konfigurationsdaten gespeichert wurden. Die Methode configChangedHandler behandelt diesen Fall und passt die hinterlegten Authentifizierungsdaten an (s.u.).

UrsAsyncConfigEditorClass benötigt bei der Methode begin als zusätzlichen Parameter ein Objekt der UrsSettingsBaseClass-Klasse. Die erweiterte Methode begin von MyWebServerClass erhält den Parameter settings vom Typ MySettingsClass. MySettingsClass ist von UrsSettingsBaseClass abgeleitet und kann für diesen Zweck verwandt werden.

Implementierung

Die Methode begin muss ergänzt und configChangedHandler implementiert werden. Der Optik wegen wurde auch der notFoundHandler überschrieben.

begin

Die Instanz  configEditorWebSite der UrsAsyncConfigEditorClass-Klasse muss beim Server registriert und konfiguriert werden:

registerWebSite(configEditorWebSite);
configEditorWebSite.setRealm(protectedArea);
configEditorWebSite.setSettings(&settings);
configEditorWebSite.onConfigChanged([this](UrsSettingsBaseClass * settings) {configChangedHandler(settings); });

configChangedHandler

Der Handler erhält als Parameter den vorher (s. begin) hinterlegten Pointer auf das neu erstellte UrsSettingsBaseClass-Objekt. Dies ist vom Typ MySettingsClass, kann also entsprechend gecastet werden:

void MyWebServerClass::configChangedHandler(UrsSettingsBaseClass * settings) {
  MySettingsClass *ms = (MySettingsClass *)settings;
  protectedArea.username = ms->AdminUser;
  protectedArea.password = ms->AdminPassword;
  Serial.println("Konfiguration geändert");
}

Geänderte Zugangskennungen werden an die für diesen Web-Server zuständigen Instanz protectedArea vom Typ UrsAsyncRealm weiter gereicht.

Auf Änderungen bei den WLAN-Zugangsdaten kann über einen Reset des Systems reagiert werden. In einem realen Praxisprojekt, sollte man (ggf. nur bedarfsweise) einen (zusätzlichen) Access-Point einrichten, damit man über diesen bei ungültigen WLAN-Zugangsdaten Zugriff auf die Außensteuerungsdaten zur Anpassung der Zugangsdaten erhält.

notFoundHandler

Bei der neuen notFoundHandler-Methode wird ein zusätzliches Logo ausgegeben:

404-Meldung

static const char logo[] PROGMEM =
"  _    _  _____    _____   _  _     ___   _  _\n"
" | |  | ||  __ \\  / ____| | || |   / _ \\ | || |\n"
" | |  | || |__) || (___   | || |_ | | | || || |_ \n"
" | |  | ||  _  /  \\___ \\  |__   _|| | | ||__   _|\n"
" | |__| || | \\ \\  ____) |    | |  | |_| |   | |\n"
"  \\____/ |_|  \\_\\|_____/     |_|   \\___/    |_|\n\n";

void MyWebServerClass::notFoundHandler(AsyncWebServerRequest * request) {
  request->send(404, String(), String(logo) + String(F("Ressource '")) + request->url() + F("' nicht vorhanden"));
  Serial.printf("File not found: %s\n", request->url().c_str());
}

Die Verschiebung der Zeichen innerhalb des Logos resultieren aus der notwendigen Verdopplung des Backslash "\".

Anpassungen im Hauptprogramm

Die Anpassungen betreffen nur die Methode setup. Die Außensteuerungsparameter werden aus der SPIFFS-Datei "config.txt" geladen. Der Aufruf von MyWebServer.begin benötigt ein zusätzliches Argument eine Referenz auf das Objekt mit den Außensteuerungsdaten.

void setup() {

// ...

  // Dateisystem mounten und Einstellungen laden
  // -------------------------------------------------------------------------
  if (!SPIFFS.begin()) {
    Serial.println(F("\nSPIFFS nicht initialisiert!\nDefault-Konfiguration wird genutzt.\n"));
  }
  else {
    mySettings.loadFromFile("/config.txt");
    Serial.println(F("\nSPIFFS ok: Konfigurationsdaten aus 'config.txt' geladen.\n"));
  }

// ...

  // Web-Server starten
  MyWebServer.begin(mySettings);
}

Download

Das Beispiel ist als "UrsAsyncWebServerExample4" in der Bibliotheks-ZIP-Datei enthalten.