Browse Source

0.6.2 2020-01-23

* CONF
    * config is only saved if values have changed
    * config restart note on web interface only shown if a value that requires restart was changed
    * many settings can be changed without restart now
    * MQTT conf change resets connection (without restart)
    * string params can now be set empty by command "set PARAM 0"
    * notes on serial/mqtt/web-console when a value was changed but not saved, a config change requires restart or a config change requires MQTT connection reset
* COMMANDS: added command for MQTT connection reset and info: mqttreset, mqttinfo
* moved some pre compile settings and version info to header files fwsettings.h, fwversion.h
* preparations for MQTT-TLS, but does not yet work
* WebSockets console can now be disabled at compile time to save Flash and RAM, non-WS console with buffer works well, so no real need for WS version
FloKra 4 years ago
parent
commit
fda2eb22e9

+ 14 - 0
CHANGELOG.md

@@ -1,5 +1,19 @@
 # WiFiThermostat - Changelog
 
+## 0.6.2 2020-01-23
+
+* CONF
+    * config is only saved if values have changed
+    * config restart note on web interface only shown if a value that requires restart was changed
+    * many settings can be changed without restart now
+    * MQTT conf change resets connection (without restart)
+    * string params can now be set empty by command "set PARAM 0"
+    * notes on serial/mqtt/web-console when a value was changed but not saved, a config change requires restart or a config change requires MQTT connection reset
+* COMMANDS: added command for MQTT connection reset and info: mqttreset, mqttinfo
+* moved some pre compile settings and version info to header files fwsettings.h, fwversion.h
+* preparations for MQTT-TLS, but does not yet work
+* WebSockets console can now be disabled at compile time to save Flash and RAM, non-WS console with buffer works well, so no real need for WS version
+
 ## 0.6.1 2020-01-16
 
 * improved uptime evaluation/output

+ 2 - 0
COMMANDS.md

@@ -20,6 +20,8 @@ All commands can be used via Serial, MQTT (/cmd topic) and Web Console.
 | savevalues          | save set values
 | clearcreds          | delete all passwords  ***
 | clearwifi           | delete WiFi configurations    ****
+| mqttinfo            | show MQTT connection info
+| mqttreset           | reset MQTT connection and reconnect
 | encrypt             | switch on encrypted stored passwords
 | decrypt             | switch off encrypted stored passwords  <br> WARNING: deletes all currently saved credentials ****
 | ls                  | list files on SPIFFS

BIN
build/elf/WiFiThermostat.ino.d1_mini.20200123_v0.6.2.elf.zip


BIN
releases/bin/WiFiThermostat.ino.d1_mini.20200123_v0.6.2.bin


BIN
releases/src/WiFiThermostat_0.6.2.zip


+ 63 - 196
src/WiFiThermostat.ino

@@ -1,11 +1,19 @@
 //#include <Arduino.h>
 
+#include "fwversion.h"
+#include "fwsettings.h"
+
 // ESP8266 core libs
 #include <ESP8266HTTPUpdateServer.h>
 #include <ESP8266WebServer.h>
 #include <ESP8266WiFi.h>
 #include <ESP8266mDNS.h>
-//#include <WiFiClient.h>
+
+#ifdef USE_MQTT_TLS
+#include <WiFiClientSecure.h>
+#else
+#include <WiFiClient.h>
+#endif
 
 // WiFiManager
 #include <PersWiFiManagerExt.h>
@@ -36,193 +44,6 @@
 #include <ButtonEventCallback.h>
 #include <PushButton.h>
 
-// PRE-COMPILE CONFIGURATION
-
-//#define FORCE_SPIFFS_FORMAT
-
-//#define DEBUG_VERBOSE
-//#define DEBUGMODE // WARNING - DEBUGMODE reveals saved passwords on serial connection and shows note in web interface
-
-//#define DEBUG_SERIAL true
-#define DEBUG_MQTT true
-
-// ENABLE FEATURES
-#define ENABLE_FEATURE_NTP_TIME
-#define ENABLE_FEATURE_WEB_CONSOLE_WEBSOCKETS
-#define ENABLE_FEATURE_WEB_CONSOLE_BUFFERED
-#define ENABLE_FEATURE_PW_ENCRYPTION
-#define ENABLE_FEATURE_HTTP_UPDATER
-
-#ifdef ENABLE_FEATURE_NTP_TIME
-#include <time.h>
-#endif
-
-//#ifdef ENABLE_FEATURE_WEB_CONSOLE_WEBSOCKETS
-#include <WebSocketsServer.h>
-//#endif
-
-// DEFINE NAMES
-#define FIRMWARE_NAME "WiFiThermostat"
-#define FIRMWARE_VERSION "0.6.1"
-#define FIRMWARE_URL "https://git.flokra.at/flo/WiFiThermostat"
-#define FIRMWARE_COPYRIGHT "FloKra"
-#define FIRMWARE_COPYRIGHT_URL "https://www.flokra.at/"
-#define FIRMWARE_SHORTNAME "WTherm"
-
-// ENCRYPTION KEY used for passwords - up to 100 chars
-#define PW_ENCRYPTION_KEY "PLhg2i7fPoYSoipq1hTF1KOqyzp3OPWtUzufCDWmD9KgxbaKYOG5WbxoO4QoLDj3F6Iif4R55UbHX1nRo7GKNqT6QXQCTsdFvFem"
-
-// default values, can later be overridden via configuration
-#define MAX_MEASUREMENT_AGE 30000      // in ms, for measured inside Temp/Hum
-#define MAX_MEASUREMENT_AGE_OUT 300000 // in ms, for received outside Temp/Hum
-
-// NTP defaults
-#ifdef ENABLE_FEATURE_NTP_TIME
-#define DEFAULT_NTP_ENABLED true
-#define DEFAULT_NTP_SERVER "pool.ntp.org"
-#define DEFAULT_NTP_SYNC_INTERVAL 7200
-#define DEFAULT_TIMEZONE "CET-1CEST,M3.5.0/02,M10.5.0/03"
-#endif
-
-// confDevWiFi
-//#define DEVICE_NAME "WTherm-1" // now created from FIRMWARE_SHORTNAME + last 2 octets of MAC address
-//#define DEFAULT_HOST_NAME "" // now created from FIRMWARE_SHORTNAME + last 2 octets of MAC address
-#define DEFAULT_WIFI_APMODE_PASSWORD "nichtsicher" // min 8 chars!
-#define DEFAULT_WIFI_APMODE_TIMEOUT 5      //min
-#define DEFAULT_WIFI_RETRY_INTERVAL 5      //min
-#define DEFAULT_WIFI_CONNCHECK_INTERVAL 20 //s
-#define DEFAULT_WIFI_REBOOT_ONNOCONNECT 60 //min
-
-// confWeb
-#define HTTP_SET_TOKEN ""
-#define DEFAULT_HTTP_USER ""
-#define DEFAULT_HTTP_PASS ""
-#define DEFAULT_HTTP_USER_AUTH false
-#define DEFAULT_ENABLE_WEBCONSOLE true
-
-// confMqtt
-#define MQTT_ENABLE false
-#define MQTT_SERVER ""
-#define MQTT_PORT 1883
-#define MQTT_USER ""
-#define MQTT_PASS ""
-#define MQTT_TOPIC_IN "Test/WTherm"
-#define MQTT_TOPIC_OUT "Test/WTherm/stat"
-#define MQTT_OUT_RETAIN false
-#define MQTT_OUT_RETAIN_SENSORS false
-#define MQTT_OUT_PUBLISH_INTERVAL 0         // min, 0=only on change
-#define MQTT_OUT_PUBLISH_INTERVAL_SENSORS 5 // min, 0=only on change
-#define MQTT_WILLTOPIC "Test/WTherm/availability"
-#define MQTT_WILLQOS 2
-#define MQTT_WILLRETAIN false
-#define MQTT_WILLMSG "offline"
-#define MQTT_CONNMSG "online"
-#define MQTT_ENABLE_HEARTBEAT true
-
-// max interval for MQTT heartbeat message. only applicable if MQTT
-// IN-topic is defined. after this timeout MQTT reconnect is forced
-#define MQTT_HEARTBEAT_MAXAGE 180000
-
-// max interval for MQTT heartbeat message. only applicable if MQTT
-// IN-topic is defined. after this timeout the ESP will reboot
-#define MQTT_HEARTBEAT_MAXAGE_REBOOT 1800000
-
-// confBas
-#define DEFAULT_SETTEMP_MIN 16.0 // minimal temperature that can be set
-#define DEFAULT_SETTEMP_MAX 26.0 // maximal temperature that can be set
-#define AUTOSAVE_SETTEMP true
-#define AUTOSAVE_SETMODE false
-#define SAVE_TO_MQTT_RETAINED false
-#define DEFAULT_MEASURE_INTERVAL 15 // interval for temp/hum measurement
-
-// interval for display updates (if out-temp is active, display will toggle
-// in this interval)
-#define DEFAULT_DISPLAY_INTERVAL 5
-#define DEFAULT_DISPLAY_TIMEOUT 30 // display timeout after keypress (illumination)
-#define DEFAULT_PIR_ENABLES_DISPLAY false
-#define DEFAULT_PIR_ENABLES_DISPLAY_PRESET0_ONLY true
-#define DEFAULT_TOGGLING_I_O_TEMPHUM false
-
-// confAdv
-#define DEFAULT_HYSTERESIS 0.15         // hysteresis, normally 0.1 - 0.3
-#define DEFAULT_HEATING_MIN_OFFTIME 300 // minimal time the heating must keep turned off until it can start again, in s
-
-// correction value for temperature sensor reading
-#define TEMPSENSOR_CORRECTION_VALUE 0.0
-#define HUMSENSOR_CORRECTION_VALUE 0 // correction value for humidity sensor reading
-
-// decreases the set temp to overcome further temperature rise when the
-// heating is already switched off
-#define SETTEMP_DECREASE_VALUE 0.0
-#define OFF_MESSAGE "HEATING OFF"
-#define INSIDE_TEMP_LABEL "I"
-#define OUTSIDE_TEMP_LABEL "O"
-#define MODE_NAME_0 "off"
-#define MODE_NAME_1 "heat"
-#define PRESET_NAME_0 "Normal"
-#define PRESET_NAME_1 "Reduction 1"
-#define PRESET_NAME_2 "Reduction 2"
-
-// confAdd
-#define OUTTEMP_TOPIC_IN ""
-#define OUTHUM_TOPIC_IN ""
-#define MQTT_TOPIC_PIR "" // extra publish topic for PIR sensor
-#define MQTT_TOPIC_PIR_ON "ON"
-#define MQTT_TOPIC_PIR_OFF "OFF"
-
-// confLog
-#define DEFAULT_LOGLEVEL_SERIAL LOGLEVEL_DEBUG
-#define DEFAULT_LOGLEVEL_WEB LOGLEVEL_INFO
-#define DEFAULT_LOGLEVEL_MQTT LOGLEVEL_INFO
-#define DEFAULT_LOGLEVEL_SYSLOG LOGLEVEL_DEBUG // SYSLOG not implemented yet
-#define LOG_WEB_REQUESTS false
-
-// other (not configurable via commands/WebIF)
-#define DEFAULT_SETTEMP_HEATOFF 5.0 // heating target temperature in OFF mode (freezing guard, therefore > 0)
-#define SETTEMP_LOW_MIN 14.0        // minimal configurable temperature for reduction mode
-#define SETTEMP_LOW_MAX 21.5        // maximal configurable temperature for reduction mode
-
-// default initial values
-#define DEFAULT_SETTEMP 21.5
-#define DEFAULT_HEATINGMODE 1
-#define DEFAULT_PRESET 1
-#define DEFAULT_SETTEMP_LOW 20.0  // set temperature in night/low mode
-#define DEFAULT_SETTEMP_LOW2 17.0 // set temperature in night/low mode
-
-// COMPILE TIME SETTINGS
-// default values that can only be configured at compile time / hardware configuration
-#define BUTTON_DEBOUNCE_TIME 120
-#define BUTTON_HOLD_TIME 750
-
-// pin assignments and I2C addresses
-#define PIN_DHTSENSOR 13
-#define PIN_RELAIS 15 // 16
-#define PIN_BUTTON_PLUS 2
-#define PIN_BUTTON_MINUS 0
-#define PIN_BUTTON_MODE 14
-#define PIN_PIRSENSOR 12
-#define DHTTYPE DHT22 // DHT sensor type
-#define LCDADDR 0x27  // I2C address LCD
-#define LCDCOLS 16    // LCD cols
-#define LCDLINES 2    // LCD lines
-
-// default logic levels
-#define RELAISONSTATE HIGH
-#define BUTTONONSTATE LOW
-
-// SPIFFS settings
-#define SPIFFS_DBG
-#define SPIFFS_USE_MAGIC
-
-// LOG LEVELS
-#define LOGLEVEL_OFF 0
-#define LOGLEVEL_ERROR 1
-#define LOGLEVEL_WARN 2
-#define LOGLEVEL_INFO 3
-#define LOGLEVEL_DEBUG 4
-#define LOGLEVEL_VERBOSE 5
-
-// END PRE-COMPILE CONFIGURATION
 
 PROGMEM const char PGMStr_FIRMWARE_NAME[] = FIRMWARE_NAME;
 PROGMEM const char PGMStr_FIRMWARE_VERSION[] = FIRMWARE_VERSION;
@@ -241,12 +62,13 @@ PROGMEM const char PGMStr_setTempLow2[] = "setTempLow2";
 PROGMEM const char PGMStr_switchHeating[] = "switch heating";
 PROGMEM const char PGMStr_mqttRetainedSave[] = "MQTT retained save";
 PROGMEM const char PGMStr_heating[] = "heating";
-PROGMEM const char PGMStr_thermostat[] = "TSTAT";
+PROGMEM const char PGMStr_thermostat[] = "THST";
 PROGMEM const char PGMStr_WiFi[] = "WiFi";
 //PROGMEM const char PGMStr_connectedTo[] = "connected to";
 //PROGMEM const char PGMStr_withIP[] = "with IP";
 PROGMEM const char PGMStr_MQTT[] = "MQTT";
-PROGMEM const char PGMStr_connectedReconnects[] = "connected, reconnects";
+PROGMEM const char PGMStr_connectedTo[] = "connected to";
+PROGMEM const char PGMStr_reconnects[] = "reconnects";
 PROGMEM const char PGMStr_connectedFailed[] = "connect FAILED";
 
 PROGMEM const char compile_date[] = __DATE__ " " __TIME__;
@@ -327,6 +149,7 @@ struct confDataDevWiFi
   uint16_t WiFiRetryInterval;
   uint16_t WiFiConnCheckInterval;
   uint16_t WiFiRebootOnNoConnect;
+  bool wasChanged;
 } confDevWiFi;
 
 // confWeb
@@ -342,6 +165,7 @@ struct confDataWeb
   char http_pass2[31];
   bool wConsole;
   bool wsConsole;
+  bool wasChanged;
 } confWeb;
 
 // confMqtt
@@ -366,6 +190,7 @@ struct confDataMqtt
   bool mqtt_enable_heartbeat;
   unsigned long mqtt_heartbeat_maxage_reconnect;
   unsigned long mqtt_heartbeat_maxage_reboot;
+  bool wasChanged;
 } confMqtt;
 
 // confBas
@@ -383,6 +208,7 @@ struct confDataBas
   bool PIR_enablesDisplay;  // PIR sensor enables display illumination
   bool PIR_enablesDisplay_preset0only;
   bool togglingTempHumAIDisplay;
+  bool wasChanged;
 } confBas;
 
 // confAdv
@@ -405,6 +231,7 @@ struct confDataAdv
   char psetName0[15];
   char psetName1[15];
   char psetName2[15];
+  bool wasChanged;
 } confAdv;
 
 // confAdd
@@ -415,6 +242,7 @@ struct confDataAdd
   char mqtt_payload_pir_off[10];
   char outTemp_topic_in[51];
   char outHum_topic_in[51];
+  bool wasChanged;
 } confAdd;
 
 // confTime
@@ -425,6 +253,7 @@ struct confDataTime
   char ntpServer1[31];
   char ntpServer2[31];
   unsigned long ntpSyncInterval;
+  bool wasChanged;
 } confTime;
 
 // confLog
@@ -435,6 +264,7 @@ struct confDataLog
   uint8_t logLevelMqtt;
   uint8_t logLevelSyslog;
   bool logWebRequests;
+  bool wasChanged;
 } confLog;
 
 // Uptime
@@ -514,7 +344,9 @@ bool displayActive = false; // gets true when button is pressed. display light
                             // are only performed while display is active
 bool PIRSensorOn = false;
 unsigned long heatingOnTime, heatingOffTime;
-bool config_was_changed = false;
+//bool config_was_changed = false;
+bool configChangedRestartRequired = false;
+bool configChangedMqttConnResetRequired = false;
 
 unsigned long lastUpdate_setTemp = 0;     // set to millis() every time setTemp value is changed
 unsigned long lastUpdate_setTempLow = 0;  // set to millis() every time setTemp value is changed
@@ -534,6 +366,8 @@ uint16_t saveValuesTimeout = 5000;
 unsigned long lastValueChange;       // is set to millis() whenever setTemp value
                                      // and/or heatingMode value is changed. used for
                                      // autoSave function with hardcoded 5s timeout
+unsigned long lastConfigChange;
+bool lastConfigChangeNoteAlreadyDone = false;
 bool setTempAlreadySaved = true;     // only save if not yet done
 bool setTempLowAlreadySaved = true;  // only save if not yet done
 bool setTempLow2AlreadySaved = true; // only save if not yet done
@@ -571,8 +405,8 @@ bool displayShowLine2OverlayMsg = false;
 // if command "debugmode 1" is called...
 bool sysInfoEverySecond = false;
 
-#ifdef ENABLE_FEATURE_WEB_CONSOLE_BUFFERED
-char webLogBuffer[4096];
+#ifdef ENABLE_FEATURE_WEB_CONSOLE
+char webLogBuffer[WEB_CONSOLE_BUFFER_SIZE];
 unsigned int webLogBuffer_index = 0;
 #endif
 
@@ -581,9 +415,14 @@ unsigned int webLogBuffer_index = 0;
 DHT dht(PIN_DHTSENSOR, DHTTYPE);
 LiquidCrystal_I2C lcd(LCDADDR, LCDCOLS, LCDLINES);
 
-WiFiClient espClient;
+#ifdef USE_MQTT_TLS
+//WiFiClientSecure wifiClient;
+BearSSL::WiFiClientSecure wifiClient;
+#else
+WiFiClient wifiClient;
+#endif
 
-PubSubClient mqttclient(espClient);
+PubSubClient mqttclient(wifiClient);
 
 ESP8266WebServer httpServer(80);
 
@@ -763,6 +602,15 @@ void setup()
 
   // in non-blocking mode, program will continue past this point without waiting
   persWM.begin();
+
+#ifdef USE_MQTT_TLS
+  //randomSeed(micros());
+  //wifiClient.setFingerprint(MQTT_TLS_fingerprint);
+  wifiClient.setInsecure();
+  wifiClient.allowSelfSignedCerts();
+  wifiClient.setCiphersLessSecure();
+#endif
+
   delay(500);
 
   httpServerInit();
@@ -777,7 +625,8 @@ void setup()
     mqttPrepareSubscribeTopics();
     mqttClientInit();
   }
-  sendLog(F("DEV: setup complete."), LOGLEVEL_INFO);
+
+  sendLog(F("DEV:  setup complete."), LOGLEVEL_INFO);
 } // void setup
 
 void loop()
@@ -835,3 +684,21 @@ void loop()
 #endif
 
 } // void loop
+
+//#ifdef USE_MQTT_TLS
+//void verifytls() {
+//  // Use WiFiClientSecure class to create TLS connection
+//  Serial.print(F("MQTT: trying TLS connection to "));
+//  Serial.println(confMqtt.mqtt_server);
+//  if (!wifiClient.connect(confMqtt.mqtt_server, confMqtt.mqtt_port)) {
+//    Serial.println("connection failed");
+//    return;
+//  }
+//
+//  if (wifiClient.verify(MQTT_TLS_fingerprint, confMqtt.mqtt_server)) {
+//    Serial.println("certificate matches");
+//  } else {
+//    Serial.println("certificate doesn't match");
+//  }
+//}
+//#endif

+ 115 - 60
src/commands.ino

@@ -3,11 +3,13 @@
 char serBuffer[SER_INPUT_SIZE + 1];
 int serBufferCount;
 
-void serialEvent() {
+void serialEvent()
+{
   char ch = Serial.read();
   serBuffer[serBufferCount] = ch;
   serBufferCount++;
-  if (ch == 13 || ch == 10) { // ASCII code 13 = "CR",  10 = "LF"
+  if (ch == 13 || ch == 10)
+  { // ASCII code 13 = "CR",  10 = "LF"
     serBuffer[serBufferCount - 1] = '\0';
 #ifdef DEBUG_VERBOSE
     Serial.print("serial cmd: '");
@@ -21,8 +23,10 @@ void serialEvent() {
   }
 }
 
-void evalCmd() {
-  if (cmdInQueue) {
+void evalCmd()
+{
+  if (cmdInQueue)
+  {
     //Serial.print("cmdPayload: ");
     //Serial.println(cmdPayload);
 
@@ -30,21 +34,27 @@ void evalCmd() {
     strlcpy(cmdPayload_lower, cmdPayload, sizeof(cmdPayload_lower));
     strlwr(cmdPayload_lower);
 
-    if (strncmp(cmdPayload_lower, "loadconf", 8) == 0) {
+    if (strncmp(cmdPayload_lower, "loadconf", 8) == 0)
+    {
       sendLog(F("loading config..."));
       loadConf_all();
     }
 
-    else if (strncmp(cmdPayload_lower, "set ", 4) == 0) {
+    else if (strncmp(cmdPayload_lower, "set ", 4) == 0)
+    {
       char buf[81];
       char setconfCmd[16];
 
       uint8_t len = strlen(cmdPayload) - 4;
-      for (unsigned char i = 0; i < len; i++) {
-        if (i < (sizeof(buf)-1)) buf[i] = cmdPayload[i + 4];
+      for (unsigned char i = 0; i < len; i++)
+      {
+        if (i < (sizeof(buf) - 1))
+          buf[i] = cmdPayload[i + 4];
       }
-      if (len <= (sizeof(buf)-1)) buf[len] = '\0';
-      else buf[(sizeof(buf)-1)] = '\0';
+      if (len <= (sizeof(buf) - 1))
+        buf[len] = '\0';
+      else
+        buf[(sizeof(buf) - 1)] = '\0';
 
 #ifdef DEBUG_VERBOSE
       Serial.print("Buf: ");
@@ -53,10 +63,13 @@ void evalCmd() {
 
       bool cmdNoPayload = false;
       uint8_t setconfCmdLen = 0;
-      for (unsigned char i = 0; i < len; i++) {
+      for (unsigned char i = 0; i < len; i++)
+      {
         //if (buf[i] == 32 || buf[i] == '\0') break; // if SPACE command name is finished, if \0 command parameter is missing
-        if (buf[i] == 32 || buf[i] == 61 || buf[i] == 58) break; // if SPACE(32) or =(61) or :(58) command name is finished
-        else if (buf[i] == 0 || buf[i] == 10 || buf[i] == 13) { // if \0, LF (10) or CR (13) command parameter is missing
+        if (buf[i] == 32 || buf[i] == 61 || buf[i] == 58)
+          break; // if SPACE(32) or =(61) or :(58) command name is finished
+        else if (buf[i] == 0 || buf[i] == 10 || buf[i] == 13)
+        { // if \0, LF (10) or CR (13) command parameter is missing
           cmdNoPayload = true;
           break;
         }
@@ -66,7 +79,8 @@ void evalCmd() {
       setconfCmd[setconfCmdLen] = '\0';
       yield();
 
-      if (setconfCmdLen == len) cmdNoPayload = true;
+      if (setconfCmdLen == len)
+        cmdNoPayload = true;
 
 #ifdef DEBUG_VERBOSE
       Serial.print("setconfCmd: '");
@@ -74,23 +88,26 @@ void evalCmd() {
       Serial.print("'");
 #endif
 
-      if ( cmdNoPayload ) {
+      if (cmdNoPayload)
+      {
 #ifdef DEBUG_VERBOSE
         Serial.println(", no payload, displaying current value");
 #endif
         //getConfig(setconfCmd);
         cmdPrintHelp();
-        
       }
-      else {
+      else
+      {
         char setconfPayload[62];
 #ifdef DEBUG_VERBOSE
         Serial.println();
 #endif
         int setconfPayloadLen = 0;
-        for (int i = 0; i < len; i++) {
+        for (int i = 0; i < len; i++)
+        {
           char c = buf[i + setconfCmdLen + 1];
-          if (c == 0 || c == 10 || c == 13) break; // if \0, LF (10) or CR (13) command parameter is finished
+          if (c == 0 || c == 10 || c == 13)
+            break; // if \0, LF (10) or CR (13) command parameter is finished
           setconfPayload[i] = c;
           setconfPayloadLen++;
         }
@@ -101,36 +118,44 @@ void evalCmd() {
         Serial.print(setconfPayload);
         Serial.println("'");
 #endif
+
         char bufg[100];
         sprintf(bufg, "set '%s'->'%s'", setconfCmd, setconfPayload);
-        sendLog(bufg);
+        sendLog(bufg, LOGLEVEL_VERBOSE);
+
         setConfig(setconfCmd, setconfPayload);
       }
     }
 
-
-
-    else if (strncmp(cmdPayload_lower, "get ", 4) == 0) {
+    else if (strncmp(cmdPayload_lower, "get ", 4) == 0)
+    {
       char buf[81];
       char setconfCmd[16];
 
       uint8_t len = strlen(cmdPayload) - 4;
-      for (int i = 0; i < len; i++) {
-        if (i < 81) buf[i] = cmdPayload[i + 4];
+      for (int i = 0; i < len; i++)
+      {
+        if (i < 81)
+          buf[i] = cmdPayload[i + 4];
       }
-      if (len <= (sizeof(buf)-1)) buf[len] = '\0';
-      else buf[(sizeof(buf)-1)] = '\0';
+      if (len <= (sizeof(buf) - 1))
+        buf[len] = '\0';
+      else
+        buf[(sizeof(buf) - 1)] = '\0';
 
 #ifdef DEBUG_VERBOSE
       Serial.print("Buf: ");
       Serial.println(buf);
 #endif
-      
+
       uint8_t setconfCmdLen = 0;
-      for (int i = 0; i < len; i++) {
+      for (int i = 0; i < len; i++)
+      {
         //if (buf[i] == 32 || buf[i] == '\0') break; // if SPACE command name is finished, if \0 command parameter is missing
-        if (buf[i] == 32 || buf[i] == 61 || buf[i] == 58) break; // if SPACE(32) or =(61) or :(58) command name is finished
-        else if (buf[i] == 0 || buf[i] == 10 || buf[i] == 13) { // if \0, LF (10) or CR (13) command parameter is missing
+        if (buf[i] == 32 || buf[i] == 61 || buf[i] == 58)
+          break; // if SPACE(32) or =(61) or :(58) command name is finished
+        else if (buf[i] == 0 || buf[i] == 10 || buf[i] == 13)
+        { // if \0, LF (10) or CR (13) command parameter is missing
           break;
         }
         setconfCmd[i] = buf[i];
@@ -191,95 +216,123 @@ void evalCmd() {
       //getConfig(setconfCmd);
     }*/
 
-    else if (strncmp(cmdPayload_lower, "restart", 7) == 0) {
+    else if (strncmp(cmdPayload_lower, "restart", 7) == 0)
+    {
       sendLog(F("restarting..."));
       restart();
     }
 
-    else if (strncmp(cmdPayload_lower, "sysinfo", 7) == 0) {
+    else if (strncmp(cmdPayload_lower, "sysinfo", 7) == 0)
+    {
       logSysdata();
     }
 
-    else if (strncmp(cmdPayload_lower, "debugmode 1", 11) == 0) {
+    else if (strncmp(cmdPayload_lower, "debugmode 1", 11) == 0)
+    {
       sendLog(F("debugmode on"));
       sysInfoEverySecond = true;
     }
 
-    else if (strncmp(cmdPayload_lower, "debugmode 0", 11) == 0) {
+    else if (strncmp(cmdPayload_lower, "debugmode 0", 11) == 0)
+    {
       sendLog(F("debugmode off"));
       sysInfoEverySecond = false;
     }
 
 #ifdef ENABLE_FEATURE_NTP_TIME
-    else if (strncmp(cmdPayload_lower, "date", 7) == 0) {
+    else if (strncmp(cmdPayload_lower, "date", 7) == 0)
+    {
       printDate();
     }
 #endif
 
 #ifdef ENABLE_FEATURE_NTP_TIME
-    else if (strncmp(cmdPayload_lower, "syncclock", 7) == 0) {
+    else if (strncmp(cmdPayload_lower, "syncclock", 7) == 0)
+    {
       syncClock(true);
     }
 #endif
 
-    else if (strncmp(cmdPayload_lower, "clearcreds", 10) == 0) {
+    else if (strncmp(cmdPayload_lower, "clearcreds", 10) == 0)
+    {
       confClearCredentials();
     }
 
-    else if (strncmp(cmdPayload_lower, "clearwifi", 10) == 0) {
+    else if (strncmp(cmdPayload_lower, "clearwifi", 10) == 0)
+    {
       confClearWiFiCredentials();
     }
 
-    else if (strncmp(cmdPayload_lower, "saveconf", 8) == 0) {
+    else if (strncmp(cmdPayload_lower, "saveconf", 8) == 0)
+    {
       saveConfig_all();
     }
-    
-    else if (strncmp(cmdPayload_lower, "savevalues", 10) == 0) {
+
+    else if (strncmp(cmdPayload_lower, "savevalues", 10) == 0)
+    {
       saveValues();
     }
 
-    else if (strncmp(cmdPayload_lower, "encrypt", 10) == 0) {
+    else if (strncmp(cmdPayload_lower, "encrypt", 10) == 0)
+    {
       confEncrypt();
     }
 
-    else if (strncmp(cmdPayload_lower, "decrypt", 10) == 0) {
+    else if (strncmp(cmdPayload_lower, "decrypt", 10) == 0)
+    {
       confDecrypt();
     }
 
-    else if (strncmp(cmdPayload_lower, "ls", 2) == 0) {
+    else if (strncmp(cmdPayload_lower, "ls", 2) == 0)
+    {
       SPIFFS_listFiles();
     }
 
-    else if (strncmp(cmdPayload_lower, "ipcfg", 5) == 0) {
+    else if (strncmp(cmdPayload_lower, "ipcfg", 5) == 0)
+    {
       printIpcfg();
     }
-    
 
-    else if (strncmp(cmdPayload_lower, "help", 4) == 0) {
+    else if (strncmp(cmdPayload_lower, "help", 4) == 0)
+    {
       cmdPrintHelp();
     }
-    else if (strncmp(cmdPayload_lower, "getconf", 7) == 0) {
+
+    else if (strncmp(cmdPayload_lower, "mqttreset", 9) == 0)
+    {
+      mqttResetConnection();
+    }
+
+    else if (strncmp(cmdPayload_lower, "mqttinfo", 8) == 0)
+    {
+      mqttPublishStatus();
+    }
+
+    else if (strncmp(cmdPayload_lower, "getconf", 7) == 0)
+    {
       sendLog(F("CONF: listing all conf parameters:"));
-      getConfig((char*)"confDevWiFi");
-      getConfig((char*)"confWeb");
-      getConfig((char*)"confMqtt");
-      getConfig((char*)"confBas");
-      getConfig((char*)"confAdv");
-      getConfig((char*)"confAdd");
-      getConfig((char*)"confTime");
-      getConfig((char*)"confLog");
+      getConfig((char *)"confDevWiFi");
+      getConfig((char *)"confWeb");
+      getConfig((char *)"confMqtt");
+      getConfig((char *)"confBas");
+      getConfig((char *)"confAdv");
+      getConfig((char *)"confAdd");
+      getConfig((char *)"confTime");
+      getConfig((char *)"confLog");
       sendLog(F("------"));
     }
-    else if (strncmp(cmdPayload_lower, "delconf", 7) == 0) {
+    else if (strncmp(cmdPayload_lower, "delconf", 7) == 0)
+    {
       sendLog(F("deleting configuration..."));
       deleteConfig();
     }
-    
+
     cmdInQueue = false;
   }
 }
 
-void cmdPrintHelp() {
+void cmdPrintHelp()
+{
   sendLog(F("valid commands:"));
   sendLog(F("   sysinfo       show uptime, heap usage..."));
   sendLog(F("   date          show current date/time"));
@@ -294,6 +347,8 @@ void cmdPrintHelp() {
   sendLog(F("   savevalues    save set values"));
   sendLog(F("   clearcreds    delete all passwords"));
   sendLog(F("   clearwifi     delete WiFi configurations"));
+  sendLog(F("   mqttinfo      MQTT connection status"));
+  sendLog(F("   mqttreset     reset MQTT connection"));
   sendLog(F("   encrypt       switch on encrypted stored passwords"));
   sendLog(F("   decrypt       switch off encrypted stored passwords"));
   sendLog(F("                 WARNING: deletes all currently saved credentials"));

File diff suppressed because it is too large
+ 876 - 132
src/config.ino


+ 191 - 0
src/fwsettings.h

@@ -0,0 +1,191 @@
+// PRE-COMPILE CONFIGURATION
+
+//#define FORCE_SPIFFS_FORMAT
+
+//#define DEBUG_VERBOSE
+//#define DEBUGMODE // WARNING - DEBUGMODE reveals saved passwords on serial connection and shows note in web interface
+
+//#define DEBUG_SERIAL true
+#define DEBUG_MQTT true
+
+//#define USE_MQTT_TLS
+// currently does not work
+
+// ENABLE FEATURES
+#define ENABLE_FEATURE_NTP_TIME
+#define ENABLE_FEATURE_WEB_CONSOLE
+//#define ENABLE_FEATURE_WEB_CONSOLE_WEBSOCKETS
+#define ENABLE_FEATURE_PW_ENCRYPTION
+#define ENABLE_FEATURE_HTTP_UPDATER
+
+
+#define WEB_CONSOLE_BUFFER_SIZE 4000
+
+#ifdef ENABLE_FEATURE_NTP_TIME
+#include <time.h>
+#endif
+
+//#ifdef ENABLE_FEATURE_WEB_CONSOLE_WEBSOCKETS
+#include <WebSocketsServer.h>
+//#endif
+
+// ENCRYPTION KEY used for passwords - up to 100 chars
+#define PW_ENCRYPTION_KEY "PLhg2i7fPoYSoipq1hTF1KOqyzp3OPWtUzufCDWmD9KgxbaKYOG5WbxoO4QoLDj3F6Iif4R55UbHX1nRo7GKNqT6QXQCTsdFvFem"
+
+// default values, can later be overridden via configuration
+#define MAX_MEASUREMENT_AGE 30000      // in ms, for measured inside Temp/Hum
+#define MAX_MEASUREMENT_AGE_OUT 300000 // in ms, for received outside Temp/Hum
+
+// NTP defaults
+#ifdef ENABLE_FEATURE_NTP_TIME
+#define DEFAULT_NTP_ENABLED true
+#define DEFAULT_NTP_SERVER "pool.ntp.org"
+#define DEFAULT_NTP_SYNC_INTERVAL 7200
+#define DEFAULT_TIMEZONE "CET-1CEST,M3.5.0/02,M10.5.0/03"
+#endif
+
+// confDevWiFi
+//#define DEVICE_NAME "WTherm-1" // now created from FIRMWARE_SHORTNAME + last 2 octets of MAC address
+//#define DEFAULT_HOST_NAME "" // now created from FIRMWARE_SHORTNAME + last 2 octets of MAC address
+#define DEFAULT_WIFI_APMODE_PASSWORD "nichtsicher" // min 8 chars!
+#define DEFAULT_WIFI_APMODE_TIMEOUT 5      //min
+#define DEFAULT_WIFI_RETRY_INTERVAL 5      //min
+#define DEFAULT_WIFI_CONNCHECK_INTERVAL 20 //s
+#define DEFAULT_WIFI_REBOOT_ONNOCONNECT 60 //min
+
+// confWeb
+#define HTTP_SET_TOKEN ""
+#define DEFAULT_HTTP_USER ""
+#define DEFAULT_HTTP_PASS ""
+#define DEFAULT_HTTP_USER_AUTH false
+#define DEFAULT_ENABLE_WEBCONSOLE true
+
+// confMqtt
+#define MQTT_ENABLE false
+#define MQTT_SERVER ""
+#define MQTT_PORT 1883
+#define MQTT_USER ""
+#define MQTT_PASS ""
+#define MQTT_TOPIC_IN "Test/WTherm"
+#define MQTT_TOPIC_OUT "Test/WTherm/stat"
+#define MQTT_OUT_RETAIN false
+#define MQTT_OUT_RETAIN_SENSORS false
+#define MQTT_OUT_PUBLISH_INTERVAL 0         // min, 0=only on change
+#define MQTT_OUT_PUBLISH_INTERVAL_SENSORS 5 // min, 0=only on change
+#define MQTT_WILLTOPIC "Test/WTherm/availability"
+#define MQTT_WILLQOS 2
+#define MQTT_WILLRETAIN false
+#define MQTT_WILLMSG "offline"
+#define MQTT_CONNMSG "online"
+#define MQTT_ENABLE_HEARTBEAT true
+
+// max interval for MQTT heartbeat message. only applicable if MQTT
+// IN-topic is defined. after this timeout MQTT reconnect is forced
+#define MQTT_HEARTBEAT_MAXAGE 180000
+
+// max interval for MQTT heartbeat message. only applicable if MQTT
+// IN-topic is defined. after this timeout the ESP will reboot
+#define MQTT_HEARTBEAT_MAXAGE_REBOOT 1800000
+
+// confBas
+#define DEFAULT_SETTEMP_MIN 16.0 // minimal temperature that can be set
+#define DEFAULT_SETTEMP_MAX 26.0 // maximal temperature that can be set
+#define AUTOSAVE_SETTEMP true
+#define AUTOSAVE_SETMODE false
+#define SAVE_TO_MQTT_RETAINED false
+#define DEFAULT_MEASURE_INTERVAL 15 // interval for temp/hum measurement
+
+// interval for display updates (if out-temp is active, display will toggle
+// in this interval)
+#define DEFAULT_DISPLAY_INTERVAL 5
+#define DEFAULT_DISPLAY_TIMEOUT 30 // display timeout after keypress (illumination)
+#define DEFAULT_PIR_ENABLES_DISPLAY false
+#define DEFAULT_PIR_ENABLES_DISPLAY_PRESET0_ONLY true
+#define DEFAULT_TOGGLING_I_O_TEMPHUM false
+
+// confAdv
+#define DEFAULT_HYSTERESIS 0.15         // hysteresis, normally 0.1 - 0.3
+#define DEFAULT_HEATING_MIN_OFFTIME 300 // minimal time the heating must keep turned off until it can start again, in s
+
+// correction value for temperature sensor reading
+#define TEMPSENSOR_CORRECTION_VALUE 0.0
+#define HUMSENSOR_CORRECTION_VALUE 0 // correction value for humidity sensor reading
+
+// decreases the set temp to overcome further temperature rise when the
+// heating is already switched off
+#define SETTEMP_DECREASE_VALUE 0.0
+#define OFF_MESSAGE "HEATING OFF"
+#define INSIDE_TEMP_LABEL "I"
+#define OUTSIDE_TEMP_LABEL "O"
+#define MODE_NAME_0 "off"
+#define MODE_NAME_1 "heat"
+#define PRESET_NAME_0 "Normal"
+#define PRESET_NAME_1 "Reduction 1"
+#define PRESET_NAME_2 "Reduction 2"
+
+// confAdd
+#define OUTTEMP_TOPIC_IN ""
+#define OUTHUM_TOPIC_IN ""
+#define MQTT_TOPIC_PIR "" // extra publish topic for PIR sensor
+#define MQTT_TOPIC_PIR_ON "ON"
+#define MQTT_TOPIC_PIR_OFF "OFF"
+
+// confLog
+#define DEFAULT_LOGLEVEL_SERIAL LOGLEVEL_DEBUG
+#define DEFAULT_LOGLEVEL_WEB LOGLEVEL_INFO
+#define DEFAULT_LOGLEVEL_MQTT LOGLEVEL_INFO
+#define DEFAULT_LOGLEVEL_SYSLOG LOGLEVEL_DEBUG // SYSLOG not implemented yet
+#define LOG_WEB_REQUESTS false
+
+// other (not configurable via commands/WebIF)
+#define DEFAULT_SETTEMP_HEATOFF 5.0 // heating target temperature in OFF mode (freezing guard, therefore > 0)
+#define SETTEMP_LOW_MIN 14.0        // minimal configurable temperature for reduction mode
+#define SETTEMP_LOW_MAX 21.5        // maximal configurable temperature for reduction mode
+
+// default initial values
+#define DEFAULT_SETTEMP 21.5
+#define DEFAULT_HEATINGMODE 1
+#define DEFAULT_PRESET 1
+#define DEFAULT_SETTEMP_LOW 20.0  // set temperature in night/low mode
+#define DEFAULT_SETTEMP_LOW2 17.0 // set temperature in night/low mode
+
+// COMPILE TIME SETTINGS
+// default values that can only be configured at compile time / hardware configuration
+#define BUTTON_DEBOUNCE_TIME 120
+#define BUTTON_HOLD_TIME 750
+
+// pin assignments and I2C addresses
+#define PIN_DHTSENSOR 13
+#define PIN_RELAIS 15 // 16
+#define PIN_BUTTON_PLUS 2
+#define PIN_BUTTON_MINUS 0
+#define PIN_BUTTON_MODE 14
+#define PIN_PIRSENSOR 12
+#define DHTTYPE DHT22 // DHT sensor type
+#define LCDADDR 0x27  // I2C address LCD
+#define LCDCOLS 16    // LCD cols
+#define LCDLINES 2    // LCD lines
+
+// default logic levels
+#define RELAISONSTATE HIGH
+#define BUTTONONSTATE LOW
+
+// SPIFFS settings
+#define SPIFFS_DBG
+#define SPIFFS_USE_MAGIC
+
+// LOG LEVELS
+#define LOGLEVEL_OFF 0
+#define LOGLEVEL_ERROR 1
+#define LOGLEVEL_WARN 2
+#define LOGLEVEL_INFO 3
+#define LOGLEVEL_DEBUG 4
+#define LOGLEVEL_VERBOSE 5
+
+// END PRE-COMPILE CONFIGURATION
+
+
+#ifdef USE_MQTT_TLS
+static const char *MQTT_TLS_fingerprint PROGMEM = "EC 0E 4B 32 77 6B 6A 03 C6 60 37 A4 DD 0C 4C 47 BC 2D 11 23";
+//static const char *MQTT_TLS_fingerprint PROGMEM = "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00";
+#endif

+ 7 - 0
src/fwversion.h

@@ -0,0 +1,7 @@
+// DEFINE NAMES
+#define FIRMWARE_NAME "WiFiThermostat"
+#define FIRMWARE_VERSION "0.6.2"
+#define FIRMWARE_URL "https://git.flokra.at/flo/WiFiThermostat"
+#define FIRMWARE_COPYRIGHT "FloKra"
+#define FIRMWARE_COPYRIGHT_URL "https://www.flokra.at/"
+#define FIRMWARE_SHORTNAME "WTherm"

+ 2 - 2
src/html_confMqtt.h

@@ -126,8 +126,8 @@ static const char html_confmqtt_body[] PROGMEM = R"=====(
 otherwise in intervals additionally. <br>
 Intervals can also be switched off without retain. <br>
 Just set them to 0 to disable.</p>
-<p><b>Interval States **</b><br><input type='number' name='outPubInt' id='outPubInt'></p>
-<p><b>Interval Sensors **</b><br><input type='number' name='outPubIntSens' id='outPubIntSens'></p>
+<p><b>Interval States [min]**</b><br><input type='number' name='outPubInt' id='outPubInt'></p>
+<p><b>Interval Sensors [min]**</b><br><input type='number' name='outPubIntSens' id='outPubIntSens'></p>
 <p class='n'>** 0 to disable</p>
 </fieldset>
 <br>

+ 1 - 1
src/html_console.h

@@ -1,6 +1,6 @@
 /* clang-format off */
 
-#ifdef ENABLE_FEATURE_WEB_CONSOLE_WEBSOCKETS
+#ifdef ENABLE_FEATURE_WEB_CONSOLE
 
 static const char js_csapp[] PROGMEM = R"=====(function g(i) { return document.getElementById(i) };
 var xhttp, updateTime, reqTime, reqFin;

+ 6 - 15
src/httpServer.ino

@@ -17,7 +17,7 @@
 #include "html_console_ws.h"
 #endif
 
-#ifdef ENABLE_FEATURE_WEB_CONSOLE_BUFFERED
+#ifdef ENABLE_FEATURE_WEB_CONSOLE
 #include "html_console.h"
 #endif
 
@@ -32,7 +32,7 @@ void httpServerHandleMainPage()
   if (httpIsAuthenticatedAdmin())
   {
     httpServer.sendContent_P(html_main_body_adminonly);
-#ifdef ENABLE_FEATURE_WEB_CONSOLE_BUFFERED
+#ifdef ENABLE_FEATURE_WEB_CONSOLE
     if (confWeb.wConsole)
       httpServer.sendContent_P(html_main_body_adminonly_console);
 #endif
@@ -63,7 +63,7 @@ void httpServerHandleConfPage()
   httpServer.sendContent_P(html_bodytag);
   httpServerSendHtmlBodyPageheadChunked();
   httpServer.sendContent_P(html_conf_body);
-#ifdef ENABLE_FEATURE_WEB_CONSOLE_BUFFERED
+#ifdef ENABLE_FEATURE_WEB_CONSOLE
     if (confWeb.wConsole)
       httpServer.sendContent_P(html_conf_body_console);
 #endif
@@ -209,7 +209,7 @@ void httpServerHandleRestartPage()
   httpServerSendHtmlHeadChunked();
   httpServer.sendContent_P(html_head_end);
   httpServer.sendContent_P(html_bodytag);
-  config_was_changed = false;
+  configChangedRestartRequired = false;
   httpServerSendHtmlBodyPageheadChunked();
   httpServer.sendContent_P(html_restarting_body);
   httpServerSendHtmlFooterChunked();
@@ -253,7 +253,7 @@ void httpServerSendHtmlBodyPageheadChunked()
   httpServer.sendContent(" - ");
   httpServer.sendContent(confDevWiFi.deviceName);
   httpServer.sendContent_P(html_body_pagehead_part2);
-  if (config_was_changed)
+  if (configChangedRestartRequired)
     httpServer.sendContent_P(html_body_pagehead_confchangednote);
 }
 
@@ -759,7 +759,6 @@ void httpServerInit()
       loadConfigWeb();
 
       httpServerHandleConfSavedPage();
-      config_was_changed = true;
       // yield();
       // ESP.restart();
     }
@@ -814,7 +813,6 @@ void httpServerInit()
 
       //httpServerHandleConfSavedRestartPage();
       httpServerHandleConfSavedPage();
-      config_was_changed = true;
       //restart();
     }
   }); //httpServer.on /setConfMqtt
@@ -945,8 +943,6 @@ void httpServerInit()
 
       //httpServerHandleConfSavedRestartPage();
       httpServerHandleConfSavedPage();
-
-      config_was_changed = true;
       //restart();
     }
   }); //httpServer.on /setConfDev
@@ -984,7 +980,6 @@ void httpServerInit()
       loadConfigBas();
 
       httpServerHandleConfSavedPage();
-      config_was_changed = true;
     }
   }); //httpServer.on /setConfBas
 
@@ -1021,7 +1016,6 @@ void httpServerInit()
       loadConfigAdv();
 
       httpServerHandleConfSavedPage();
-      config_was_changed = true;
     }
   }); //httpServer.on /setConfAdv
 
@@ -1058,7 +1052,6 @@ void httpServerInit()
       loadConfigAdd();
 
       httpServerHandleConfSavedPage();
-      config_was_changed = true;
     }
   }); //httpServer.on /setConfAdd
 
@@ -1096,7 +1089,6 @@ void httpServerInit()
       loadConfigTime();
 
       httpServerHandleConfSavedPage();
-      config_was_changed = true;
     }
   }); //httpServer.on /setConfTime
 #endif
@@ -1134,7 +1126,6 @@ void httpServerInit()
       loadConfigLog();
 
       httpServerHandleConfSavedPage();
-      config_was_changed = true;
     }
   }); //httpServer.on /setConfLog
 
@@ -1855,7 +1846,7 @@ void httpServerInit()
     httpServerHandleNotFound();
   }); //httpServer.onNotFound
 
-#ifdef ENABLE_FEATURE_WEB_CONSOLE_BUFFERED
+#ifdef ENABLE_FEATURE_WEB_CONSOLE
   if (confWeb.wConsole)
   {
     httpServer.on("/console", []() {

+ 1 - 1
src/logging.ino

@@ -54,7 +54,7 @@ void sendLog(const char *msg, uint8_t loglevel)
     }
 #endif
 
-#ifdef ENABLE_FEATURE_WEB_CONSOLE_BUFFERED
+#ifdef ENABLE_FEATURE_WEB_CONSOLE
     if (confWeb.wConsole && loglevel <= confLog.logLevelWeb)
     {
         char buf3[250];

+ 1 - 1
src/miscFunctions.ino

@@ -74,7 +74,7 @@ void restart()
 void logSysdata()
 {
   char logBuf[101];
-  sprintf_P(logBuf, "SYS: uptime=%s, freeHeap=%u, heapFragm=%u%%", getUptimeStr(true), ESP.getFreeHeap(), ESP.getHeapFragmentation());
+  sprintf_P(logBuf, "SYS:  uptime=%s, heapFree=%u, heapFragm=%u%%, heapMaxBlock=%u", getUptimeStr(true), ESP.getFreeHeap(), ESP.getHeapFragmentation(), ESP.getMaxFreeBlockSize());
   //sprintf_P(logBuf, "SYS: uptime=%lu, freeHeap=%u, heapFragm=%u%%", millis(), ESP.getFreeHeap(), ESP.getHeapFragmentation());
   sendLog(logBuf, LOGLEVEL_INFO);
 }

+ 35 - 14
src/mqtt.ino

@@ -26,7 +26,7 @@ void mqttCallback(char *topic, unsigned char *payload, uint16_t length)
     if (length < sizeof(cmdPayload))
       len = length; // if input is bigger than dest buffer, cut
     else
-      len = sizeof(cmdPayload)-1;
+      len = sizeof(cmdPayload) - 1;
 
     for (int i = 0; i < len; i++)
     {
@@ -69,7 +69,7 @@ void mqttCallback(char *topic, unsigned char *payload, uint16_t length)
     if (length < sizeof(cmdPayload))
       len = length; // if input is bigger than dest buffer, cut
     else
-      len = sizeof(cmdPayload)-1;
+      len = sizeof(cmdPayload) - 1;
 
     for (int i = 0; i < len; i++)
     {
@@ -116,7 +116,7 @@ void mqttCallback(char *topic, unsigned char *payload, uint16_t length)
     if (length < sizeof(cmdPayload))
       len = length; // if input is bigger than dest buffer, cut
     else
-      len = sizeof(cmdPayload)-1;
+      len = sizeof(cmdPayload) - 1;
 
     for (int i = 0; i < len; i++)
     {
@@ -199,7 +199,7 @@ void mqttCallback(char *topic, unsigned char *payload, uint16_t length)
     if (length < sizeof(cmdPayload))
       len = length; // if input is bigger than dest buffer, cut
     else
-      len = sizeof(cmdPayload)-1;
+      len = sizeof(cmdPayload) - 1;
 
     for (unsigned char i = 0; i < len; i++)
     {
@@ -372,7 +372,7 @@ bool mqttReconnect(void)
   //}
 
   char logBuf[70];
-  sprintf(logBuf, "MQTT: connecting to broker with %s, attempt: %u", connectMode, mqttReconnectAttempts);
+  sprintf(logBuf, "MQTT: connecting to %s:%u w/ %s, attempt: %u", confMqtt.mqtt_server, confMqtt.mqtt_port, connectMode, mqttReconnectAttempts);
   sendLog(logBuf, LOGLEVEL_INFO);
 
   if (connRes)
@@ -382,9 +382,9 @@ bool mqttReconnect(void)
     //   Serial.print(F("MQTT: connected. Reconnects: "));
     //   Serial.println(mqttReconnects);
     // }
-    char logBuf2[50];
-    sprintf(logBuf2, "MQTT: connected. Reconnects: %u", mqttReconnects);
-    sendLog(logBuf2, LOGLEVEL_INFO);
+    //char logBuf2[50];
+    //sprintf(logBuf2, "MQTT: connected to %s:%u, Reconnects: %u", confMqtt.mqtt_server, confMqtt.mqtt_port, mqttReconnects);
+    //sendLog(logBuf2, LOGLEVEL_INFO);
     //sendLog(F("MQTT: connected. Reconnects: "), LOGLEVEL_INFO);
 
     mqttConnected = true;
@@ -480,7 +480,8 @@ int lastWifiStatus;
 
 void mqttHandleConnection()
 {
-  if(mqttHeartbeatReceived) {
+  if (mqttHeartbeatReceived)
+  {
     mqttHeartbeatReceived = false;
     sendLog(F("MQTT: received HEARTBEAT - resetting timer..."), LOGLEVEL_VERBOSE);
   }
@@ -533,6 +534,9 @@ void mqttHandleConnection()
       if ((millis() - mqttLastReconnectAttempt) > mqttReconnectAttemptDelay)
       {
         mqttLastReconnectAttempt = millis();
+        //#ifdef USE_MQTT_TLS
+        //        verifytls();
+        //#endif
         mqttReconnect();
       }
       mqttclient.loop();
@@ -549,7 +553,7 @@ void mqttPublishStatus()
   if (confMqtt.mqtt_enable && mqttclient.state() == 0)
   {
     char outMsg[60];
-    sprintf_P(outMsg, "%s: %s: %d", PGMStr_MQTT, PGMStr_connectedReconnects, mqttReconnects - 1);
+    sprintf_P(outMsg, "%s: %s: %s:%u, %s: %d", PGMStr_MQTT, PGMStr_connectedTo, confMqtt.mqtt_server, confMqtt.mqtt_port, PGMStr_reconnects, mqttReconnects - 1);
     //mqttclient.publish(confMqtt.mqtt_topic_out, outMsg, confMqtt.mqtt_outRetain);
     sendLog(outMsg, LOGLEVEL_INFO);
   }
@@ -587,9 +591,26 @@ void mqttPublishHeartbeat()
   }
 }
 
-void mqtt_updateCurrentStateName() {
-  if(confMqtt.mqtt_enable) {
-    sprintf_P(mqttCurrentStateName, "%s", PGMStr_MQTTStates[mqttclient.state()+4]);
+void mqtt_updateCurrentStateName()
+{
+  if (confMqtt.mqtt_enable)
+  {
+    sprintf_P(mqttCurrentStateName, "%s", PGMStr_MQTTStates[mqttclient.state() + 4]);
+  }
+  else
+    sprintf_P(mqttCurrentStateName, "%s", PGMStr_MQTTState_DIS);
+}
+
+void mqttResetConnection()
+{
+  sendLog(F("MQTT: resetting connection..."));
+  if (!confMqtt.mqtt_enable)
+    mqttclient.disconnect();
+  else
+  {
+    mqttclient.disconnect();
+    mqttPrepareSubscribeTopics();
+    mqttClientInit();
   }
-  else sprintf_P(mqttCurrentStateName, "%s", PGMStr_MQTTState_DIS);
+  configChangedMqttConnResetRequired = false;
 }

+ 62 - 28
src/scheduler.ino

@@ -1,27 +1,37 @@
 
-void checkMillis() {
-  if ( (millis() - lastRun) >= 100 ) {
+void checkMillis()
+{
+  if ((millis() - lastRun) >= 100)
+  {
     lastRun = millis();
     every100ms();
   }
 }
 
-void every100ms() {
-  if (count100ms < 10) count100ms++;
-  else {
+void every100ms()
+{
+  if (count100ms < 10)
+    count100ms++;
+  else
+  {
     count100ms = 0;
     everySecond();
   }
   //checkSaveConfigTriggered();
 }
 
-void everySecond() {
-  if (countSeconds < 60) countSeconds++;
-  else {
+void everySecond()
+{
+  if (countSeconds < 60)
+    countSeconds++;
+  else
+  {
     countSeconds = 0;
     everyMinute();
   }
-  
+
+  confChangedLogNote(false); // only outputs once if false and only if config is not saved
+
   //webSocket.sendTXT(num, "Test\n");
   // if(confWeb.enableConsole && webSocket.connectedClients() > 0) {
   //   char buf[40];
@@ -31,28 +41,41 @@ void everySecond() {
 
   handleDisplayTimeout();
   checkValuesChanged();
-  if(sysInfoEverySecond) logSysdata();
+  if (sysInfoEverySecond)
+    logSysdata();
 
 #ifdef ENABLE_FEATURE_WEB_CONSOLE_WEBSOCKETS
   clearValidSessionId();
 #endif
 
-  if (countMeasureInterval < confBas.measureInterval) countMeasureInterval++;
-  else {
+  if (countMeasureInterval < confBas.measureInterval)
+    countMeasureInterval++;
+  else
+  {
     countMeasureInterval = 0;
     measureTempHum();
     thermostat();
   }
 
-  if (countDisplayInterval < confBas.displayInterval) countDisplayInterval++;
-  else {
+  if (countDisplayInterval < confBas.displayInterval)
+    countDisplayInterval++;
+  else
+  {
     countDisplayInterval = 0;
     updateDisplay();
   }
 
-  if (doRestart) restart();
+  if (doRestart)
+    restart();
+
+  if (configChangedMqttConnResetRequired && !confCheckUnsaved())
+  {
+    configChangedMqttConnResetRequired = false;
+    mqttResetConnection();
+  }
 
-  if ( (millis() - pendingRestart_lastMillis) > 3000 ) pendingRestart = false;
+  if ((millis() - pendingRestart_lastMillis) > 3000)
+    pendingRestart = false;
 
   //  if ( preset != pendingPreset) {
   //    if ( (millis() - pendingPreset_millis) > pendingPreset_timeout ) {
@@ -64,37 +87,48 @@ void everySecond() {
 unsigned int outPubInterval_states_count = 0;
 unsigned int outPubInterval_sensors_count = 0;
 
-void everyMinute() {
+void everyMinute()
+{
 #ifdef ENABLE_FEATURE_NTP_TIME
-  if(confTime.ntpEnable) {
+  if (confTime.ntpEnable)
+  {
     syncClock();
   }
 #endif
 
   logSysdata();
 
-  if(confMqtt.mqtt_enable) {
-    
-    if(!confMqtt.mqtt_willRetain) mqttPublishConnectMsg();
-    
+  confChangedLogNote(true);
+  
+  if (confMqtt.mqtt_enable)
+  {
+
+    if (!confMqtt.mqtt_willRetain)
+      mqttPublishConnectMsg();
+
     mqttPublishStatus();
 
-    if(confMqtt.mqtt_enable_heartbeat) mqttPublishHeartbeat();
- 
-    if(confMqtt.mqtt_outPubInterval > 0 && outPubInterval_states_count >= confMqtt.mqtt_outPubInterval) {
+    if (confMqtt.mqtt_enable_heartbeat)
+      mqttPublishHeartbeat();
+
+    if (confMqtt.mqtt_outPubInterval > 0 && outPubInterval_states_count >= confMqtt.mqtt_outPubInterval)
+    {
       outPubInterval_states_count = 0;
       publishCurrentThermostatValues(true); // true forces publishing
     }
-    else {
+    else
+    {
       outPubInterval_states_count++;
       publishCurrentThermostatValues(false); // false publishes only changed values
     }
 
-    if(confMqtt.mqtt_outPubInterval_sensors > 0 && outPubInterval_sensors_count >= confMqtt.mqtt_outPubInterval_sensors) {
+    if (confMqtt.mqtt_outPubInterval_sensors > 0 && outPubInterval_sensors_count >= confMqtt.mqtt_outPubInterval_sensors)
+    {
       outPubInterval_sensors_count = 0;
       publishCurrentSensorValues(true); // true forces publishing
     }
-    else {
+    else
+    {
       outPubInterval_sensors_count++;
       publishCurrentSensorValues(false); // false publishes only changed values
     }

+ 2 - 2
src/time.ino

@@ -12,7 +12,7 @@ bool setupTime()
     }
     else return false;
     setenv("TZ", confTime.timeZoneStr, 1); // Zeitzone einstellen https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
-    sendLog(F("NTP: updating time..."), LOGLEVEL_INFO);
+    sendLog(F("NTP:  updating time..."), LOGLEVEL_INFO);
     return true;
 }
 
@@ -25,7 +25,7 @@ void syncClock(bool force)
         lastsek = lt.tm_sec;
         if (force || !(time(&now) % confTime.ntpSyncInterval))
         {
-            //sendLog(F("NTP: updating time"), LOGLEVEL_INFO);
+            //sendLog(F("NTP:  updating time"), LOGLEVEL_INFO);
             setupTime();
         }
     }

+ 4 - 4
src/websockets.ino

@@ -43,7 +43,7 @@ void startWebSocketServer() { // Start a WebSocket server
   webSocket.begin();                          // start the websocket server
   webSocket.onEvent(webSocketEvent);          // if there's an incomming websocket message, go to function 'webSocketEvent'
   //Serial.println("WebSocket server started.");
-  sendLog("WS: WebSocket server started on Port 81", LOGLEVEL_INFO);
+  sendLog("WS:   WebSocket server started on Port 81", LOGLEVEL_INFO);
 }
 
 void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
@@ -57,7 +57,7 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length
                 {
                     IPAddress ip = webSocket.remoteIP(num);
                     //Serial.printf("WS: Connected Client-[%u], %d.%d.%d.%d, URL: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);
-                    sprintf(logBuf, "WS: Client[%u] connected, %d.%d.%d.%d, URL: %s", num, ip[0], ip[1], ip[2], ip[3], payload);
+                    sprintf(logBuf, "WS:   Client[%u] connected, %d.%d.%d.%d, URL: %s", num, ip[0], ip[1], ip[2], ip[3], payload);
                     sendLog(logBuf, LOGLEVEL_INFO);
     
 	    			// send message to client
@@ -65,8 +65,8 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length
                 }
                 break;
             case WStype_TEXT:
-                //Serial.printf("WS: received from Client-[%u]: %s\n", num, payload);
-                sprintf(logBuf, "WS: received from Client[%u]: %s", num, payload);
+                //Serial.printf("WS:   received from Client-[%u]: %s\n", num, payload);
+                sprintf(logBuf, "WS:   received from Client[%u]: %s", num, payload);
                 sendLog(logBuf, LOGLEVEL_INFO);
 
                 char buf[31];

Some files were not shown because too many files changed in this diff