Browse Source

v0.3.2
* fixed/improved: HTTP authentication handling
* added: device hostname (announced via DHCP) can now be configured
* fixed: restart function on web interface
* added: show AP SSID + password on display for some seconds when AP mode is entered

FloKra 4 years ago
parent
commit
563010f58b

+ 6 - 0
CHANGELOG.md

@@ -1,4 +1,10 @@
 # WiFiThermostat - Changelog
+## 0.3.2
+* fixed/improved: HTTP authentication handling
+* added: device hostname (announced via DHCP) can now be configured
+* fixed: restart function on web interface
+* added: show AP SSID + password on display for some seconds when AP mode is entered
+
 ## 0.3.1
 * fixed (issue #1): LCD - outside temp - wrong alignment on 1.1 digit values
 * added: configurable labels for inside and outside temperature ("I" and "O" in EN or "A" in DE)

+ 13 - 0
TODO.txt

@@ -0,0 +1,13 @@
+# WiFi Thermostat - ToDo
+## WiFi Manager
+* update PersWiFiManager to 5.0 or switch to different lib as it seems to be somehow abandoned now
+* only start AP mode after reboot when no WiFi credentials are saved or can´t connect
+* stop AP mode automatically after some minutes
+* do not start AP mode when connection is lost, instead only try to reconnect
+* if reconnect fails for longer time, increase reconnect interval
+* if reconnect fails for really long time (1h?), reboot
+* fix captive portal function (already done partly, wifi.htm must be on "/" when on AP mode)
+
+
+## reset settings via button
+* if MODE button is held during reboot, ask if connection settings should be cleared -> clear if button is pressed again

BIN
bin/WiFiThermostat.ino.d1_mini.20191017_v0.3.2.bin


BIN
libraries/PersWiFiManager-4.0.0.zip


BIN
libraries/PersWiFiManager-5.0.0.zip


+ 209 - 0
libraries/PersWiFiManager-api-reference.md

@@ -0,0 +1,209 @@
+# PersWiFiManager API Reference
+
+## constructor
+[PersWiFiManager::PersWiFiManager](#PersWiFiManager)
+
+## functions
+[PersWiFiManager::attemptConnection](#attemptConnection)
+
+[PersWiFiManager::begin](#begin)
+
+[PersWiFiManager::getApSsid](#getApSsid)
+
+[PersWiFiManager::handleWiFi](#handleWiFi)
+
+[PersWiFiManager::onAp](#onAp)
+
+[PersWiFiManager::onConnect](#onConnect)
+
+[PersWiFiManager::setApCredentials](#setApCredentials)
+
+[PersWiFiManager::setConnectNonBlock](#setConnectNonBlock)
+
+[PersWiFiManager::setupWiFiHandlers](#setupWiFiHandlers)
+
+[PersWiFiManager::startApMode](#startApMode)
+
+---
+
+## PersWiFiManager
+Creates a new PersWiFiManager object
+
+### Signatures
+    PersWiFiManager(ESP8266WebServer& s, DNSServer& d)
+
+### Args
+    ESP8266WebServer& s An existing instance of the ESP8266WebServer class that will be used throughout the program
+    DNSServer& d An existing instance of the DNSServer class that will be used throughout the program
+
+### Notes
+Declare the object globally, or at least in the same scope as your ESP8266WebServer and DNSServer
+
+
+## attemptConnection
+Attempts to auto-connect to last WiFi network used (or other if specified). Falls back to AP mode if unsuccessful.
+
+### Signatures
+    bool attemptConnection()
+    bool attemptConnection(const String& ssid)
+    bool attemptConnection(const String& ssid, const String& pass)
+
+### Args
+    const String& ssid (Optional) SSID to connect to. This overrides the default behavior of connecting to the last network used.
+    const String& pass (Optional) password for the specified SSID. Length must be >= 8 characters
+
+### Returns
+    true if successfully autoconnected, false if switched to AP mode
+
+### Notes
+This function is already called inside begin, or when WiFi settings are changed, but this can be used for manual operation.
+
+
+## begin
+Begins automatic WiFi Configuration
+
+### Signatures
+    bool begin()
+    bool begin(const String& ssid)
+    bool begin(const String& ssid, const String& pass)
+
+### Args
+    const String& ssid (Optional) SSID to connect to. This overrides the default behavior of connecting to the last network used.
+    const String& pass (Optional) password for the specified SSID. Length must be >= 8 characters
+
+### Returns
+    true if successfully autoconnected
+
+### Notes
+
+This sets up the server handlers for WiFi actions, then attempts to autoconnect. If no SSID is specified, it automatically attempts to connect to the last network used.
+
+
+## getApSsid
+API Reference / PersWiFiManager::getApSsid
+Gets the AP mode SSID
+
+### Signatures
+    String getApSsid()
+
+### Returns
+    String containing the AP mode SSID
+
+### Notes
+The AP mode SSID is automatically set by the library, unless overridden by setApCredentials
+
+
+## handleWiFi
+Handles WiFi connecting/disconnecting in non-blocking mode
+
+### Signatures
+    void handleWiFi()
+
+### Notes
+This function does not need to be called in normal mode.
+
+If the PersWiFiManager is set to non-blocking mode with setConnectNonBlock, this must be called in the main loop.
+
+
+## onAp
+Attach a handler function that runs every time AP mode is started
+
+### Signatures
+    void onAp(WiFiChangeHandlerFunction fn)
+
+### Args
+    WiFiChangeHandlerFunction fn A generic function pointer to an AP mode handler function
+
+### Notes
+This will run the handler function every time AP mode is started, when WiFi fails to connect or AP mode is manually triggered.
+
+For successful connection handler, see onConnect
+
+### Example Code
+
+    void setup(){
+	...
+
+	//uses a lambda function as the argument
+	persWM.onAp([]() {
+		//this code runs every time AP mode is started
+		DEBUG_PRINT("AP MODE");
+		DEBUG_PRINT(persWM.getApSsid());
+	});
+
+
+## onConnect
+Attach a handler function that runs every time WiFi connects
+
+### Signatures
+    void onConnect(WiFiChangeHandlerFunction fn)
+
+### Args
+    WiFiChangeHandlerFunction fn A generic function pointer to a wifi connection handler function
+
+### Notes
+This will run the handler function every time the WiFi settings are changed and then a successful connection is made.
+
+For unsuccessful / AP mode connection handler, see onAp
+
+### Example Code
+
+    void setup(){
+	...
+
+	//uses a lambda function as the argument
+	persWM.onConnect([]() {
+		//this code runs every time wifi is connected
+		DEBUG_PRINT("wifi connected");
+		DEBUG_PRINT(WiFi.localIP());
+		EasySSDP::begin(server);
+	});
+
+
+## setApCredentials
+Sets the SSID (and password) to be used for AP mode
+
+### Signatures
+    void setApCredentials(const String& apSsid)
+    void setApCredentials(const String& apSsid, const String& apPass)
+
+### Args
+    const String& apSsid SSID to be used for AP mode.
+    const String& apPass (Optional) Password to be used for AP mode.
+
+### Notes
+Passwords less than 8 characters long will be ignored.
+
+
+## setConnectNonBlock
+Sets the PersWiFiManager connecting actions to non-blocking mode
+
+### Signatures
+    void setConnectNonBlock(bool b)
+
+### Args
+    bool b use true for non-blocking mode, false for regular mode
+
+### Notes
+In non-blocking mode, handleWiFi must be called in the main loop
+
+
+## setupWiFiHandlers
+Attaches WiFi settings and captive DNS handlers to web server and DNS Server
+
+### Signatures
+    void setupWiFiHandlers()
+
+### Notes
+This function is already called inside begin() and doesn’t normally need to be used, but is available for manual operation.
+
+
+## startApMode
+Allows manual starting of AP mode
+
+### Signatures
+    void startApMode()
+
+### Notes
+WiFi settings are controlled by the user via the web-interface, but this allows a manual program-induced switch to AP mode.
+

BIN
libraries/PersWiFiManager-master_20191017.zip


BIN
src/Releases/WiFiThermostat_0.3.2.7z


+ 13 - 2
src/WiFiThermostat/Display.ino

@@ -89,13 +89,24 @@ void displayShowWifiConnectionError() {
   lcd.setCursor(0, 0);
   lcd.print("AP mode active  ");
   lcd.setCursor(0, 1);
-  lcd.print("as              ");
-  lcd.setCursor(3, 1);
+  lcd.print("                ");
+  lcd.setCursor(0, 1);
   lcd.print(persWM.getApSsid());
   lcd.backlight();
   displayActive = true;
   displayLastOnMillis = millis();
   delay(2000);
+  
+  lcd.setCursor(0, 0);
+  lcd.print("Password:       ");
+  lcd.setCursor(0, 1);
+  lcd.print("                ");
+  lcd.setCursor(0, 1);
+  lcd.print(wifiAPModePassword);
+  lcd.backlight();
+  displayActive = true;
+  displayLastOnMillis = millis();
+  delay(2000);
 }
 
 void displayShowMQTTConnected() {

+ 25 - 14
src/WiFiThermostat/WiFiThermostat.ino

@@ -7,16 +7,15 @@
 #define SPIFFS_USE_MAGIC
 
 #define FIRMWARE_NAME "WiFiThermostat"
-#define VERSION "0.3.1"
-
-
+#define VERSION "0.3.2"
 
 // default values, can later be overridden via configuration (conf)
-#define DEVICE_NAME "WiFi-Thermostat-1"
+#define DEVICE_NAME "WiFiThermo-1"
+#define WIFI_APMODE_PASSWORD "LassMiRein"
 #define DEFAULT_HTTP_USER ""
 #define DEFAULT_HTTP_PASS ""
 #define HTTP_SET_TOKEN "grzbrz"
-#define MQTT_SERVER "10.1.1.11"
+#define MQTT_SERVER "mqtt.lan"
 #define MQTT_PORT 1883
 #define MQTT_USER ""
 #define MQTT_PASS ""
@@ -137,9 +136,14 @@ PushButton pirSensor = PushButton(PIN_PIRSENSOR, PRESSED_WHEN_HIGH);
 boolean serialdebug = true;
 boolean mqttdebug = true;
 
+boolean WifiInApMode = false;
+unsigned long WifiApModeStartedAt;
+
 // config variables - do not change here!
 //conf
-char deviceName[31];  // device name - just for web interface
+char deviceName[31];  // device name - for web interface and AP-Mode SSID
+char hostName[31]; // announced hostname on WiFi connection
+char wifiAPModePassword[31];
 char http_user[31];
 char http_pass[31];
 char http_token[31];
@@ -162,7 +166,6 @@ char mqtt_topic_in_setTemp[61];
 char mqtt_topic_in_setMode[61];
 char mqtt_topic_in_setPreset[61];
 
-
 //conf2
 int domoticzIdx_Thermostat = DOMOTICZ_IDX_THERMOSTAT;
 int domoticzIdx_ThermostatMode = DOMOTICZ_IDX_THERMOSTATMODE;
@@ -348,6 +351,7 @@ void setup() {
 
   //set conf default values (bool, int and float variables are set at declaration)
   strlcpy(deviceName, DEVICE_NAME, 31);
+  strlcpy(wifiAPModePassword, WIFI_APMODE_PASSWORD, 31);
   strlcpy(http_user, DEFAULT_HTTP_USER, 31);
   strlcpy(http_pass, DEFAULT_HTTP_PASS, 31);
   strlcpy(http_token, HTTP_SET_TOKEN, 31);
@@ -435,6 +439,7 @@ void setup() {
   }
 
   //if configuration returns empty strings - use the default from source
+  if (strlen(deviceName) < 4) strlcpy(deviceName, DEVICE_NAME, 31);
   if (modename0[0] == '\0') strlcpy(modename0, MODE_NAME_0, 15);
   if (modename1[0] == '\0') strlcpy(modename1, MODE_NAME_1, 15);
   if (psetname0[0] == '\0') strlcpy(psetname0, PRESET_NAME_0, 15);
@@ -442,7 +447,7 @@ void setup() {
   if (psetname2[0] == '\0') strlcpy(psetname2, PRESET_NAME_2, 15);
   if (itemplab[0] == '\0') strlcpy(itemplab, INSIDE_TEMP_LABEL, 2);
   if (otemplab[0] == '\0') strlcpy(otemplab, OUTSIDE_TEMP_LABEL, 2);
-  
+
   setTempSaved = setTemp;
   heatingModeSaved = heatingMode;
   presetSaved = preset;
@@ -453,31 +458,37 @@ void setup() {
   // initialize DHT11/22 temp/hum sensor
   dht.begin();
 
-
+  if (strlen(hostName) >= 4) {  // if no hostname is set WiFi manager will create a unique one automatically based on MAC address
+    WiFi.hostname(hostName);
+  }
 
   mqttPrepareSubscribeTopics();
 
   checkUseDomoticz();
-  delay(500);
-
 
   //optional code handlers to run everytime wifi is connected...
   persWM.onConnect([]() {
     Serial.println("wifi connected");
     Serial.println(WiFi.SSID());
     Serial.println(WiFi.localIP());
+    WifiInApMode = false;
     displayShowWifiConnected();
   });
   //...or AP mode is started
   persWM.onAp([]() {
     Serial.println("AP MODE");
     Serial.println(persWM.getApSsid());
+    WifiInApMode = true;
+    WifiApModeStartedAt = millis();
     displayShowWifiConnectionError();
   });
 
-  //sets network name for AP mode
-  persWM.setApCredentials(DEVICE_NAME);
-  //persWM.setApCredentials(DEVICE_NAME, "password"); optional password
+  // sets network name and password for AP mode
+  if (strlen(wifiAPModePassword) < 8) {
+    strlcpy(wifiAPModePassword, WIFI_APMODE_PASSWORD, 31);
+  }
+  persWM.setApCredentials(deviceName, wifiAPModePassword);
+  //  persWM.setApCredentials(DEVICE_NAME);
 
   //make connecting/disconnecting non-blocking
   persWM.setConnectNonBlock(true);

+ 0 - 11
src/WiFiThermostat/changes_v0.3.txt

@@ -1,11 +0,0 @@
-- split "mode" to "mode" and "preset", changes in nearly all source files
-- add In+Out Temperature display (without humidity) without toggling on LCD line 1
-- add publish topic "presetName" and "presetHA", where presetHA returns "none" for default preset and the name for the rest
-- add configuration for preset names, off-message, option for non toggling temp display (conf2 page)
-- minor fixed in http api and Web-IF
-- fixes/improvements in MQTT handling (subscribe to less topics than before using wildcard)
-- restart: when holding down MODE button for >4s, display shows "Restart?". 
-  Restart is executed if: 
-  - MODE button is keeped holding
-  - MODE button is pressed/held again as long as the "Restarting?" message is displayed
-- return to default operation mode when + or - button is pressed

+ 23 - 1
src/WiFiThermostat/config.ino

@@ -43,7 +43,13 @@ boolean setConfig(char* param, char* value) {
 
   //confdata
   else if ( strcmp(param, "devName") == 0 ) {
-    strlcpy(deviceName, value, 31);
+    if (strlen(value) >= 4) strlcpy(deviceName, value, 31);
+  }
+  else if ( strcmp(param, "hostName") == 0 ) {
+    strlcpy(hostName, value, 31);
+  }
+  else if ( strcmp(param, "wifiappw") == 0 ) {
+    if (strlen(value) >= 8) strlcpy(wifiAPModePassword, value, 31);
   }
   else if ( strcmp(param, "httpUser") == 0 ) {
     strlcpy(http_user, value, 31);
@@ -279,6 +285,14 @@ void getConfig(char* param) {
     sprintf(buf, "devName: '%s'", deviceName);
     sendStatus(buf);
   }
+  else if ( strcmp(param, "hostName") == 0 ) {
+    sprintf(buf, "hostName: '%s'", hostName);
+    sendStatus(buf);
+  }
+  else if ( strcmp(param, "wifiappw") == 0 ) {
+    sprintf(buf, "wifiappw: '%s'", wifiAPModePassword);
+    sendStatus(buf);
+  }
   else if ( strcmp(param, "httpUser") == 0 ) {
     sprintf(buf, "httpUser: '%s'", http_user);
     sendStatus(buf);
@@ -502,6 +516,10 @@ void printConfig() {
   Serial.println("\nconfdata:");
   Serial.print("devName: ");
   Serial.println(deviceName);
+  Serial.print("hostName: ");
+  Serial.println(hostName);
+  Serial.print("wifiappw: ");
+  Serial.println(wifiAPModePassword);
   Serial.print("httpUser: ");
   Serial.println(http_user);
   Serial.print("httpPass: ");
@@ -653,6 +671,8 @@ boolean loadConfig() { // loadConfig 1
       }
 
       strlcpy(deviceName, json["devName"] | "", 31);
+      strlcpy(hostName, json["hostName"] | "", 31);
+      strlcpy(wifiAPModePassword, json["wifiappw"] | "", 31);
       strlcpy(http_user, json["httpUser"] | "", 31);
       strlcpy(http_pass, json["httpPass"] | "", 31);
       strlcpy(http_token, json["httpToken"] | "", 31);
@@ -833,6 +853,8 @@ boolean saveConfig() { // safeConfig
   JsonObject& json = jsonBuffer.createObject();
 
   json["devName"] = deviceName;
+  json["hostName"] = hostName;
+  json["wifiappw"] = wifiAPModePassword;
   json["httpUser"] = http_user;
   json["httpPass"] = http_pass;
   json["httpToken"] = http_token;

+ 127 - 175
src/WiFiThermostat/httpServer.ino

@@ -1,6 +1,6 @@
 //extern ESP8266WebServer httpServer;
 
-static const char httpRoot[] PROGMEM =
+static const char httpMainPage[] PROGMEM =
   R"(<html><body>
   <h1><span id='devname'></span></h1>
   <h3>WiFi Thermostat</h3>
@@ -54,7 +54,11 @@ static const char httpRoot[] PROGMEM =
   <a href='/conf'>Base configuration</a><br>
   <a href='/conf2'>Extended configuration</a><br>
   <a href='/update'>Firmware update</a><br>
-  <a href='/restart'>Restart</a>
+  <br>
+  <form id='restartForm' onsubmit='return res()'>
+  <input type='hidden' name='restart' value='1'>
+  <input type='submit' value='Restart'/>
+  </form>
   <script>
   function g(i) { return document.getElementById(i) };
   var xhttp, updateTime, reqTime, reqFin;
@@ -87,6 +91,14 @@ static const char httpRoot[] PROGMEM =
   var form = document.getElementById('offBtnFrm');
   return transmit(form);
   }
+  function res() {
+  rxhttp = new XMLHttpRequest();
+  rxhttp.timeout = 1000;
+  rxhttp.open('POST', 'restart');
+  rxhttp.send('');
+  rxhttp = null;
+  return false;
+  }
   
   function transmit(f) {
     if (!xhttp) { 
@@ -143,7 +155,9 @@ static const char httpConfPage[] PROGMEM =
 <a href='/'>Home</a><br><br>
 <input type='button' value='reload' onclick='return transmit()'/><br><br>
 <form id='form1' onsubmit='return transmit(this)'>
-Device Name: <input type='text' name='devName' id='devName'/><br><br>
+Device Name: <input type='text' name='devName' id='devName'/> min 4 ch., also used as SSID in WiFi AP Mode<br><br>
+Host Name: <input type='text' name='hostName' id='hostName'/><br><br>
+WiFi AP-Mode Password: <input type='text' name='wifiappw' id='wifiappw'/> min 8 ch<br><br>
 HTTP User *: <input type='text' name='httpUser' id='httpUser'/><br>
 HTTP Password *: <input type='text' name='httpPass' id='httpPass'/><br><br>
 HTTP set token: <input type='text' name='httpToken' id='httpToken'/><br>
@@ -215,7 +229,9 @@ Domoticz Out Topic *: <input type='text' name='domOutTop' id='domOutTop'/><br>
         g('httpUser').value = data.httpUser;
         g('httpPass').value = data.httpPass;
         g('httpToken').value = data.httpToken;
-        g('devName').value = data.devName
+        g('devName').value = data.devName;
+        g('hostName').value = data.hostName;
+        g('wifiappw').value = data.wifiappw;
         g('mqttHost').value = data.mqttHost;
         g('mqttPort').value = data.mqttPort;
         g('mqttUser').value = data.mqttUser;
@@ -413,8 +429,8 @@ toggling I/A-Temp and Hum display*: <input type='checkbox' name='togTHdisp' id='
 </script>
 </body></html>)";
 
-void httpServerHandleRoot() {
-  httpServer.send_P(200, "text/html", httpRoot);
+void httpServerHandleMainPage() {
+  httpServer.send_P(200, "text/html", httpMainPage);
 }
 
 void httpServerHandleConfPage() {
@@ -425,53 +441,49 @@ void httpServerHandleConf2Page() {
   httpServer.send_P(200, "text/html", httpConf2Page);
 }
 
-//void httpServerHandleNotFound() {
-//  String message = "File Not Found\n\n";
-//  message += "URI: ";
-//  message += httpServer.uri();
-//  message += "\nMethod: ";
-//  message += (httpServer.method() == HTTP_GET) ? "GET" : "POST";
-//  message += "\nArguments: ";
-//  message += httpServer.args();
-//  message += "\n";
-//  for (uint8_t i = 0; i < httpServer.args(); i++) {
-//    message += " " + httpServer.argName(i) + ": " + httpServer.arg(i) + "\n";
-//  }
-//  httpServer.send(404, "text / plain", message);
-//}
-
 void httpServerHandleNotFound() {
-  //  if (strlen(http_user) > 0 && strlen(http_pass) > 0) {
-  //    if (!httpServer.authenticate(http_user, http_pass))
-  //      return httpServer.requestAuthentication();
   httpServer.send(404, "text/plain", "");
-  //}
 }
 
-void httpServerInit() {
-  httpServer.on("/delconf", []() {
-    Serial.println("httpServer.on /delconf");
+boolean httpIsAuthenticated() {
+  if (strlen(http_user) > 0 && strlen(http_pass) > 0) {
+    if (!httpServer.authenticate(http_user, http_pass)) return false;
+    else return true;
+  }
+  else return true;
+}
+
+void httpSendUnauthorized() {
+  httpServer.send (401, "text/plain", "UNAUTHORIZED");
+}
+
+void httpSend200OK() {
+  httpServer.send (200, "text/plain", "OK");
+}
+
+boolean httpCheckToken() {
+  if (http_token[0] != '\0') { // dont accept empty token
     if (httpServer.hasArg("token")) {
       char buf[20];
       httpServer.arg("token").toCharArray(buf, 20);
-      if (strcmp(buf, CLEARCONF_TOKEN) == 0) {
-        //        httpServer.send(200, "text / plain", "Token OK - deleting config");
-        deleteConfig();
-      }
-    } //if
-    //    else {
-    //      httpServer.send(200, "text / plain", "not allowed");
-    //    }
+      if (strcmp(buf, http_token) == 0) return true;
+      else return false;
+    }
+  }
+}
+
+void httpServerInit() {
+  httpServer.on("/delconf", []() {
+    if ( httpIsAuthenticated() || (!httpIsAuthenticated() && httpCheckToken()) ) {
+      //Serial.println("httpServer.on /delconf");
+      deleteConfig();
+    }
+    else httpSendUnauthorized();
   });
 
   httpServer.on("/api", []() {
-    boolean isAuthenticated = false;
-    if (strlen(http_user) > 0 && strlen(http_pass) > 0) {
-      if (!httpServer.authenticate(http_user, http_pass)) return httpServer.requestAuthentication();
-      isAuthenticated = true;
-    }
-    else isAuthenticated = true;
-    if (isAuthenticated) {
+    if (!httpIsAuthenticated()) return httpServer.requestAuthentication();
+    else {
       DEBUG_PRINT("httpServer.on /api");
       if (httpServer.hasArg("plusBtn")) {
         setTempStepUp();
@@ -529,102 +541,72 @@ void httpServerInit() {
       json.printTo(jsonchar); //print to char array, takes more memory but sends in one piece
       httpServer.send(200, "application/json", jsonchar);
     }
-    else {
-      httpServer.send (401, "text/plain", "UNAUTHORIZED");
-    }
   }); //httpServer.on /api
 
   httpServer.on("/restart", []() {
-    if (httpServer.hasArg("token")) {
-      Serial.println("web triggered restart");
+    if ( httpIsAuthenticated() || (!httpIsAuthenticated() && httpCheckToken()) ) {
+      //Serial.println("web triggered restart");
       ESP.restart();
     }
-    else {
-      httpServer.send (403, "text/plain", "FORBIDDEN");
-    }
+    else httpSendUnauthorized();
   });
 
   httpServer.on("/mqttReconnect", []() {
-    if (httpServer.hasArg("token")) {
-      Serial.println("web triggered mqttReconnect");
+    if ( httpIsAuthenticated() || (!httpIsAuthenticated() && httpCheckToken()) ) {
+      //Serial.println("web triggered mqttReconnect");
       mqttReconnect();
-      httpServer.sendHeader("Location", String("/"), true);
-      httpServer.send (302, "text/plain", "OK");
-    }
-    else {
-      httpServer.send (403, "text/plain", "FORBIDDEN");
+      httpServer.sendHeader("Location", "/", true);
+      httpServer.send(303);
     }
+    else httpSendUnauthorized();
   });
 
-  httpServer.on("/setPoint", []() {
-    if (httpServer.hasArg("token")) {
-      char buf[20];
-      httpServer.arg("token").toCharArray(buf, 20);
-      if (strcmp(buf, http_token) == 0) {
-        Serial.println("web triggered setPoint");
-        if (httpServer.hasArg("value")) {
-          char bufVal[20];
-          httpServer.arg("value").toCharArray(bufVal, 20);
-          float valueFloat = round(atof(bufVal) * 2.0) / 2.0;
-          setTempTo(valueFloat);
-          httpServer.send (200, "text/plain", "OK");
-        }
+  httpServer.on("/setTemp", []() {
+    if ( httpIsAuthenticated() || (!httpIsAuthenticated() && httpCheckToken()) ) {
+      //Serial.println("web triggered setTemp");
+      if (httpServer.hasArg("value")) {
+        char bufVal[20];
+        httpServer.arg("value").toCharArray(bufVal, 20);
+        float valueFloat = round(atof(bufVal) * 2.0) / 2.0;
+        setTempTo(valueFloat);
+        httpSend200OK();
       }
     } //if
-    else {
-      httpServer.send (403, "text/plain", "FORBIDDEN");
-    }
+    else httpSendUnauthorized();
   });
 
   httpServer.on("/setMode", []() {
-    if (httpServer.hasArg("token")) {
-      char buf[20];
-      httpServer.arg("token").toCharArray(buf, 20);
-      if (strcmp(buf, http_token) == 0) {
-        Serial.println("web triggered setMode");
-        if (httpServer.hasArg("value")) {
-          char bufVal[20];
-          httpServer.arg("value").toCharArray(bufVal, 20);
-          int valueInt = atoi(bufVal);
-          if (valueInt >= 0 && valueInt <= 1) setHeatingmodeTo(valueInt);
-          httpServer.send (200, "text/plain", "OK");
-        }
+    if ( httpIsAuthenticated() || (!httpIsAuthenticated() && httpCheckToken()) ) {
+      //Serial.println("web triggered setMode");
+      if (httpServer.hasArg("value")) {
+        char bufVal[20];
+        httpServer.arg("value").toCharArray(bufVal, 20);
+        int valueInt = atoi(bufVal);
+        if (valueInt >= 0 && valueInt <= 1) setHeatingmodeTo(valueInt);
+        httpSend200OK();
       }
     } //if
-    else {
-      httpServer.send (403, "text/plain", "FORBIDDEN");
-    }
+    else httpSendUnauthorized();
   });
 
   httpServer.on("/setPreset", []() {
-    if (httpServer.hasArg("token")) {
-      char buf[20];
-      httpServer.arg("token").toCharArray(buf, 20);
-      if (strcmp(buf, http_token) == 0) {
-        Serial.println("web triggered setPreset");
-        if (httpServer.hasArg("value")) {
-          char bufVal[20];
-          httpServer.arg("value").toCharArray(bufVal, 20);
-          int valueInt = atoi(bufVal);
-          if (valueInt >= 0 && valueInt <= 2) setPresetTo(valueInt);
-          httpServer.send (200, "text/plain", "OK");
-        }
+    if ( httpIsAuthenticated() || (!httpIsAuthenticated() && httpCheckToken()) ) {
+      //Serial.println("web triggered setPreset");
+      if (httpServer.hasArg("value")) {
+        char bufVal[20];
+        httpServer.arg("value").toCharArray(bufVal, 20);
+        int valueInt = atoi(bufVal);
+        if (valueInt >= 0 && valueInt <= 2) setPresetTo(valueInt);
+        httpSend200OK();
       }
     } //if
-    else {
-      httpServer.send (403, "text/plain", "FORBIDDEN");
-    }
+    else httpSendUnauthorized();
   });
 
   httpServer.on("/confdata", []() {
-    boolean isAuthenticated = false;
-    if (strlen(http_user) > 0 && strlen(http_pass) > 0) {
-      if (!httpServer.authenticate(http_user, http_pass)) return httpServer.requestAuthentication();
-      isAuthenticated = true;
-    }
-    else isAuthenticated = true;
-    if (isAuthenticated) {
-      Serial.println("httpServer.on /confdata");
+    if (!httpIsAuthenticated()) return httpServer.requestAuthentication();
+    else {
+      //Serial.println("httpServer.on /confdata");
 
       for (int i = 0; i < httpServer.args(); i++) {
         char bufName[20];
@@ -633,14 +615,14 @@ void httpServerInit() {
         httpServer.arg(i).toCharArray(bufValue, 101);
 
         if (strlen(bufName) > 0) {
-          Serial.print("web update ");
-          Serial.print(bufName);
-          Serial.print(" = ");
-          Serial.println(bufValue);
+          //Serial.print("web update ");
+          //Serial.print(bufName);
+          //Serial.print(" = ");
+          //Serial.println(bufValue);
           setConfig(bufName, bufValue);
         }
         saveConfigToFlash = true; // will be saved in next loop()
-        Serial.println("web triggered saveConfigToFlash");
+        //Serial.println("web triggered saveConfigToFlash");
       }
       yield();
 
@@ -648,6 +630,8 @@ void httpServerInit() {
       StaticJsonBuffer<1000> jsonBuffer;
       JsonObject &json = jsonBuffer.createObject();
       json["devName"] = deviceName;
+      json["hostName"] = hostName;
+      json["wifiappw"] = wifiAPModePassword;
       json["httpUser"] =  http_user;
       json["httpPass"] =  http_pass;
       json["httpToken"] =  http_token;
@@ -671,20 +655,12 @@ void httpServerInit() {
       json.printTo(jsonchar); //print to char array, takes more memory but sends in one piece
       httpServer.send(200, "application/json", jsonchar);
     }
-    else {
-      httpServer.send (401, "text/plain", "UNAUTHORIZED");
-    }
   }); //httpServer.on /confdata
 
   httpServer.on("/confdata2", []() {
-    boolean isAuthenticated = false;
-    if (strlen(http_user) > 0 && strlen(http_pass) > 0) {
-      if (!httpServer.authenticate(http_user, http_pass)) return httpServer.requestAuthentication();
-      isAuthenticated = true;
-    }
-    else isAuthenticated = true;
-    if (isAuthenticated) {
-      Serial.println("httpServer.on /confdata2");
+    if (!httpIsAuthenticated()) return httpServer.requestAuthentication();
+    else {
+      //Serial.println("httpServer.on /confdata2");
 
       for (int i = 0; i < httpServer.args(); i++) {
         char bufName[20];
@@ -693,14 +669,14 @@ void httpServerInit() {
         httpServer.arg(i).toCharArray(bufValue, 101);
 
         if (strlen(bufName) > 0) {
-          Serial.print("web update ");
-          Serial.print(bufName);
-          Serial.print(" = ");
-          Serial.println(bufValue);
+          //Serial.print("web update ");
+          //Serial.print(bufName);
+          //Serial.print(" = ");
+          //Serial.println(bufValue);
           setConfig(bufName, bufValue);
         }
         saveConfig2ToFlash = true;
-        Serial.println("web triggered saveConfig2ToFlash");
+        //Serial.println("web triggered saveConfig2ToFlash");
       }
       yield();
 
@@ -747,9 +723,6 @@ void httpServerInit() {
       json.printTo(jsonchar); //print to char array, takes more memory but sends in one piece
       httpServer.send(200, "application/json", jsonchar);
     }
-    else {
-      httpServer.send (401, "text/plain", "UNAUTHORIZED");
-    }
   }); //httpServer.on /confdata2
 
 
@@ -757,13 +730,8 @@ void httpServerInit() {
 
   //get heap status, analog input value and all GPIO statuses in one json call
   httpServer.on("/info", HTTP_GET, []() {
-    boolean isAuthenticated = false;
-    if (strlen(http_user) > 0 && strlen(http_pass) > 0) {
-      if (!httpServer.authenticate(http_user, http_pass)) return httpServer.requestAuthentication();
-      isAuthenticated = true;
-    }
-    else isAuthenticated = true;
-    if (isAuthenticated) {
+    if (!httpIsAuthenticated()) return httpServer.requestAuthentication();
+    else {
       String json = " {";
       json += "\"wifissid\":\"" + WiFi.SSID() + "\"";
       json += "\"heap\":" + String(ESP.getFreeHeap());
@@ -771,53 +739,37 @@ void httpServerInit() {
       httpServer.send(200, "text/json", json);
       json = String();
     }
-    else {
-      httpServer.send (401, "text/plain", "UNAUTHORIZED");
-    }
   }); //httpServer.on /info
 
   httpServer.on("/", []() {
-    boolean isAuthenticated = false;
-    if (strlen(http_user) > 0 && strlen(http_pass) > 0) {
-      if (!httpServer.authenticate(http_user, http_pass)) return httpServer.requestAuthentication();
-      isAuthenticated = true;
-    }
-    else isAuthenticated = true;
-    if (isAuthenticated) {
-      httpServerHandleRoot();
+    if ( WifiInApMode ) {
+      httpServer.sendHeader("Location", "/wifi.htm", true);
+      httpServer.send(302);
     }
     else {
-      httpServer.send (401, "text/plain", "UNAUTHORIZED");
+      httpServer.sendHeader("Location", "/main", true);
+      httpServer.send(302);
     }
   });
 
+  httpServer.on("/main", []() {
+      if (!httpIsAuthenticated()) return httpServer.requestAuthentication();
+      else {
+        httpServerHandleMainPage();
+      }
+  });
+
   httpServer.on("/conf", []() {
-    boolean isAuthenticated = false;
-    if (strlen(http_user) > 0 && strlen(http_pass) > 0) {
-      if (!httpServer.authenticate(http_user, http_pass)) return httpServer.requestAuthentication();
-      isAuthenticated = true;
-    }
-    else isAuthenticated = true;
-    if (isAuthenticated) {
-      httpServerHandleConfPage();
-    }
+    if (!httpIsAuthenticated()) return httpServer.requestAuthentication();
     else {
-      httpServer.send (401, "text/plain", "UNAUTHORIZED");
+      httpServerHandleConfPage();
     }
   });
 
   httpServer.on("/conf2", []() {
-    boolean isAuthenticated = false;
-    if (strlen(http_user) > 0 && strlen(http_pass) > 0) {
-      if (!httpServer.authenticate(http_user, http_pass)) return httpServer.requestAuthentication();
-      isAuthenticated = true;
-    }
-    else isAuthenticated = true;
-    if (isAuthenticated) {
-      httpServerHandleConf2Page();
-    }
+    if (!httpIsAuthenticated()) return httpServer.requestAuthentication();
     else {
-      httpServer.send (401, "text/plain", "UNAUTHORIZED");
+      httpServerHandleConf2Page();
     }
   });
 

+ 6 - 2
src/WiFiThermostat/misc.ino

@@ -12,9 +12,7 @@ void every100ms() {
     count100ms = 0;
     everySecond();
   }
-
   checkSaveConfigTriggered();
-
 }
 
 void everySecond() {
@@ -59,6 +57,12 @@ void everyMinute() {
   publishCurrentThermostatValues();
   updateDomoticzDevices();
 
+//  if(WifiInApMode) {
+//    if( (millis() - WifiApModeStartedAt) > WIFI_AP_MODE_TIMEOUT ) {
+//      
+//    }
+//  }
+
   //  Serial.print("WiFi Status: ");
   //  Serial.println(WiFi.status());
 }