#include "portal.h" //#define DEBUG #define NONE -1 #define BLINK -2 #define FADEIN -3 #define FADEOUT -4 const IPAddress apIP(192, 168, 1, 1); const char* apSSID; boolean isAPactive; String scanSSIDList; int apiOverrides[4] = {NONE, NONE, NONE, NONE}; boolean requestLedUpdate = false; DNSServer dnsServer; ESP8266WebServer webServer(80); #define ICONPATH "http://openweathermap.org/img/w/" String weatherIcon = ""; void portalSetup(String ssid) { apSSID = ssid.c_str(); WiFi.hostname(ssid); // connect to configured network or fallback to setup AP if (!enterClientMode(NULL, NULL)) { enterAPMode(); // let the user enter the credentials } startWebServer(); } void portalLoop() { if (isAPactive) { dnsServer.processNextRequest(); } webServer.handleClient(); } boolean isConnected() { return !isAPactive; } void startWebServer() { #ifdef DEBUG Serial.print(F("Starting Web Server at ")); Serial.print(WiFi.softAPIP()); Serial.print(" "); Serial.println(WiFi.localIP()); #endif webServer.on("/settings", []() { String s = "

WLAN-Einstellungen

Bitte wähle deinen Accesspoint und gib das Passwort ein.

"; s += "

Passwort:
"; webServer.send(200, "text/html", makePage("WLAN-Einstellungen", s)); }); webServer.on("/setap", []() { String ssid = urlDecode(webServer.arg("ssid")); #ifdef DEBUG Serial.print(F("Connecting to: ")); Serial.println(ssid); #endif String pass = urlDecode(webServer.arg("pass")); String s = "

Einrichtung abgeschlossen.

Das Gerät wird zu \""; s += ssid; s += "\" verbunden."; webServer.send(200, "text/html", makePage("WLAN-Einstellungen", s)); if (!enterClientMode(ssid.c_str(), pass.c_str())) { enterAPMode(); // wrong passphrase } }); webServer.on("/reset", []() { String s = "

Zurückgesetzt

Zum Einstellen bitte mit dem Accesspoint \"Snowman\" verbinden.

"; webServer.send(200, "text/html", makePage("Zurücksetzen", s)); enterAPMode(); }); webServer.on("/api", []() { String response = ""; for (int n = 0; n < webServer.args(); n++) { String sArgName = webServer.argName(n); if (sArgName.startsWith("led")) { String sPinNumber = sArgName.substring(3); if (sPinNumber == "") { String msg = "API: Invalid argument '" + sArgName + "' - pin number invalid\n"; response += msg; #ifdef DEBUG Serial.print(msg); #endif continue; } int pinNumber = sPinNumber.toInt(); if (pinNumber < 0 || pinNumber > 3) { String msg = "API: Invalid argument '" + sArgName + "' - pin number out of range\n"; response += msg; #ifdef DEBUG Serial.print(msg); #endif continue; } String sArg = webServer.arg(n); int val = -1; if (sArg == "fade" || sArg == "fadein") { val = FADEIN; } else if (sArg == "fadeout") { val = FADEOUT; } else if (sArg == "blink") { val = BLINK; } else if (sArg == "clear") { val = NONE; } else { val = sArg.toInt(); } if ((val != FADEIN && val != FADEOUT && val != BLINK && val != NONE && val < 0) || val > PWMRANGE) { String msg = "API: Value out of range for argument '" + sArgName + "': '" + String(val) + "'\n"; response += msg; #ifdef DEBUG Serial.print(msg); #endif continue; } String msg = "API: Overriding pin " + String(pinNumber) + " to " + String(val) + "\n"; response += msg; #ifdef DEBUG Serial.print(msg); #endif apiOverrides[pinNumber] = val; requestLedUpdate = true; } if (webServer.argName(n) == "clear") { if (webServer.arg(n) == "true") { for (int j = 0; j < 4; j++) { apiOverrides[j] = NONE; } } String msg = "API: Cleared pin overrides\n"; response += msg; #ifdef DEBUG Serial.print(msg); #endif requestLedUpdate = true; } } webServer.send(200, "text/html", makePage("API", "
" + response + "
")); }); webServer.on("/", []() { String s = "

Snowman

Einstellungen zurücksetzen

"; s += "

Einstellungen ändern

"; s += "

"; webServer.send(200, "text/html", makePage("Snowman", s)); }); webServer.onNotFound([]() { String redirect = "http://" + ipToStr(apIP) + "/settings"; webServer.send(200, "text/html", makeRedirectPage(redirect, 2)); }); webServer.begin(); } int getAPIOverride(int pin) { return apiOverrides[pin]; } boolean apiNeedLedUpdate() { return requestLedUpdate; } void apiUpdatedLeds() { requestLedUpdate = false; } void setWeatherIcon(String id) { weatherIcon = id; } // must enter AP mode after scanning (SSID & PW get lost) void scanSSIDs() { #ifdef DEBUG Serial.println(F("Scanning networks")); #endif WiFi.disconnect(); WiFi.mode(WIFI_STA); delay(100); int n = WiFi.scanNetworks(); delay(100); scanSSIDList = ""; for (int i = 0; i < n; ++i) { scanSSIDList += ""; } #ifdef DEBUG Serial.println(F("Finished scanning")); #endif } // also read https://github.com/esp8266/Arduino/issues/529 // sets up an AP for the user to enter his/her WiFi credentials void enterAPMode() { #ifdef DEBUG Serial.println(F("Entering AP mode")); #endif scanSSIDs(); // create ad hoc setup-network WiFi.disconnect(); WiFi.mode(WIFI_AP); isAPactive = true; delay(100); WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); WiFi.softAP(apSSID); #ifdef DEBUG Serial.println(F("Started Access Point")); #endif dnsServer.start(apIP); } // returns true if successfully connected to the last AP boolean enterClientMode(const char* ssid, const char *passphrase) { dnsServer.stop(); if (ssid && strlen(ssid) > 0) { // if ssid is not given, try to connect to the memorized AP WiFi.disconnect(); WiFi.begin(ssid, passphrase); // register credentials } WiFi.mode(WIFI_STA); isAPactive = false; delay(100); // SSID and password are memorized until WiFi.begin() // https://github.com/esp8266/Arduino/issues/244 int count = 0; #ifdef DEBUG Serial.print(F("Waiting for Wi-Fi connection to ")); Serial.println(WiFi.SSID()); #endif while (count++ < 30) { // attempt for about 30 * 1/2 = 15 seconds if (WiFi.status() == WL_CONNECTED) { #ifdef DEBUG Serial.println(); Serial.println(F("Connected!")); #endif return true; } delay(500); #ifdef DEBUG Serial.print("."); #endif } #ifdef DEBUG Serial.println(); Serial.println(F("Not connected")); #endif return false; }