//#include //#define WIFI_HTM_PROGMEM #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // 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 SPIFFS_DBG #define SPIFFS_USE_MAGIC #define FIRMWARE_NAME "WiFiThermostat" #define FIRMWARE_VERSION "0.6.0" #define FIRMWARE_URL "https://git.flokra.at/flo/WiFiThermostat" #define FIRMWARE_COPYRIGHT "FloKra" #define FIRMWARE_COPYRIGHT_URL "https://www.flokra.at/" // used as prefix in AP mode SSID, computed hostname and MQTT cliend ID #define FIRMWARE_SHORTNAME "WTherm" // 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 #define TIMEZONE "CET-1CEST,M3.5.0/02,M10.5.0/03" #define NTP_TIMEOUT 1500 #define NTP_TIMEZONE 1 #define NTP_MINUTES_TZ 0 #define NTP_SYNC_INTERVAL 7200 #define NTP_SERVER "pool.ntp.org" // conf DevWiFi //#define DEVICE_NAME "WTherm-1" - created from FIRMWARE_SHORTNAME + last 2 // octets of MAC address #define HOST_NAME "" #define WIFI_APMODE_PASSWORD "" #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 false // confMqtt #define MQTT_ENABLE true #define MQTT_SERVER "mqtt.lan" #define MQTT_PORT 1883 #define MQTT_USER "" #define MQTT_PASS "" #define MQTT_TOPIC_IN "Test/Thermostat" #define MQTT_TOPIC_OUT "Test/Thermostat/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/Thermostat/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.2 // hysteresis, normally 0.1 - 0.5 #define DEFAULT_HEATING_MIN_OFFTIME 120 // minimal time the heating keeps turned off 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 "none" #define PRESET_NAME_1 "reduction1" #define PRESET_NAME_2 "reduction2" // 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" // other (not configurable via WebIF) #define DEFAULT_SETTEMP_HEATOFF 5.0 // set temperature in OFF mode (freezing guard > 0) // 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 18.0 // set temperature in night/low mode // default values that can only be configured at compile time / hardware // configuration #define BUTTON_DEBOUNCE_TIME 120 #define BUTTON_HOLD_TIME 750 #define SETTEMP_LOW_MIN 14.0 // minimal configurable temperature for reduction mode #define SETTEMP_LOW_MAX 21.5 // maximal configurable temperature for reduction mode // 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 #define LCDLINES 2 // default logic levels #define RELAISONSTATE HIGH #define BUTTONONSTATE LOW // 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 #define DEFAULT_LOGLEVEL_SERIAL LOGLEVEL_DEBUG #define DEFAULT_LOGLEVEL_WEB LOGLEVEL_DEBUG #define DEFAULT_LOGLEVEL_MQTT LOGLEVEL_DEBUG #define DEFAULT_LOGLEVEL_SYSLOG LOGLEVEL_DEBUG // END PRE-COMPILE CONFIGURATION PROGMEM const char PGMStr_changedTo[] = "changed to"; PROGMEM const char PGMStr_preset[] = "preset"; PROGMEM const char PGMStr_heatingMode[] = "heatingMode"; PROGMEM const char PGMStr_setTemp[] = "setTemp"; PROGMEM const char PGMStr_currentSetTemp[] = "currSetTemp"; PROGMEM const char PGMStr_setTempLow[] = "setTempLow"; 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_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_connectedFailed[] = "connect FAILED"; const char PGMStr_MQTTStateM4[] PROGMEM = "CONNECTION_TIMEOUT"; const char PGMStr_MQTTStateM3[] PROGMEM = "CONNECTION_LOST"; const char PGMStr_MQTTStateM2[] PROGMEM = "CONNECT_FAILED"; const char PGMStr_MQTTStateM1[] PROGMEM = "DISCONNECTED"; const char PGMStr_MQTTState0[] PROGMEM = "CONNECTED"; const char PGMStr_MQTTState1[] PROGMEM = "CONNECT_BAD_PROTOCOL"; const char PGMStr_MQTTState2[] PROGMEM = "CONNECT_BAD_CLIENT_ID"; const char PGMStr_MQTTState3[] PROGMEM = "CONNECT_UNAVAILABLE"; const char PGMStr_MQTTState4[] PROGMEM = "CONNECT_BAD_CREDENTIALS"; const char PGMStr_MQTTState5[] PROGMEM = "CONNECT_UNAUTHORIZED"; char mqttCurrentStateName[25]; const char *const PGMStr_MQTTStates[] PROGMEM = { PGMStr_MQTTStateM4, PGMStr_MQTTStateM3, PGMStr_MQTTStateM2, PGMStr_MQTTStateM1, PGMStr_MQTTState0, PGMStr_MQTTState1, PGMStr_MQTTState2, PGMStr_MQTTState3, PGMStr_MQTTState4, PGMStr_MQTTState5, }; //--------------------------------------------------------------------------------------------------------------------------------------------- PushButton buttonPlus = PushButton(PIN_BUTTON_PLUS, ENABLE_INTERNAL_PULLUP); PushButton buttonMinus = PushButton(PIN_BUTTON_MINUS, ENABLE_INTERNAL_PULLUP); PushButton buttonMode = PushButton(PIN_BUTTON_MODE, ENABLE_INTERNAL_PULLUP); PushButton pirSensor = PushButton(PIN_PIRSENSOR, PRESSED_WHEN_HIGH); bool serialdebug = DEBUG_SERIAL; bool mqttdebug = DEBUG_MQTT; bool WifiInApMode = false; unsigned long WifiApModeStartedAt; // time struct tm lt; // http://www.cplusplus.com/reference/ctime/tm/ const char *const PROGMEM dayNames[] = {"Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"}; const char *const PROGMEM dayShortNames[] = {"So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"}; const char *const PROGMEM monthNames[] = {"Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"}; const char *const PROGMEM monthShortNames[] = {"Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"}; // config variables - do not change here! // confDevWiFi struct confDataDevWiFi { char deviceName[33]; // device name - for web interface and AP-Mode SSID char hostName[33]; // announced hostname on WiFi connection char WiFiSSID1[33]; char WiFiPW1[64]; char WiFiSSID2[33]; char WiFiPW2[64]; char WiFiAPModeSSID[33]; // generated, not set via config char WiFiAPModePassword[64]; uint16_t WiFiAPModeTimeout; uint16_t WiFiRetryInterval; uint16_t WiFiConnCheckInterval; uint16_t WiFiRebootOnNoConnect; } confDevWiFi; // confWeb struct confDataWeb { char http_token[31]; char http_user[31]; char http_pass[31]; bool http_user_auth; char http_user1[31]; char http_pass1[31]; char http_user2[31]; char http_pass2[31]; bool enableConsole; } confWeb; // confMqtt struct confDataMqtt { bool mqtt_enable; char mqtt_server[41]; uint16_t mqtt_port; char mqtt_user[31]; char mqtt_pass[31]; char mqtt_topic_in[51]; // MQTT in topic for commands char mqtt_topic_out[51]; // MQTT out base topic, will be extended by various value names char mqtt_willTopic[51]; // MQTT Last Will topic uint8_t mqtt_willQos; // MQTT Last Will topic QOS bool mqtt_willRetain; // MQTT Last Will retain char mqtt_willMsg[31]; // MQTT Last Will payload char mqtt_connMsg[31]; bool mqtt_outRetain; // send MQTT out with retain flag bool mqtt_outRetain_sensors; // send MQTT out with retain flag uint8_t mqtt_outPubInterval; uint8_t mqtt_outPubInterval_sensors; bool mqtt_enable_heartbeat; unsigned long mqtt_heartbeat_maxage_reconnect; unsigned long mqtt_heartbeat_maxage_reboot; } confMqtt; // confBas struct confDataBas { float setTempMin; // minimal temperature that can be set float setTempMax; // maximal temperature that can be set bool autoSaveSetTemp; bool autoSaveHeatingMode; bool saveToMqttRetained; uint16_t measureInterval; // interval for temp/hum measurement uint16_t displayInterval; // interval for display updates (if out-temp is // active, display will toggle in this interval) uint16_t displayTimeout; // display timeout after keypress (illumination) bool PIR_enablesDisplay; // PIR sensor enables display illumination bool PIR_enablesDisplay_preset0only; bool togglingTempHumAIDisplay; } confBas; // confAdv struct confDataAdv { float hysteresis; // hysteresis, normally 0.1 - 0.5 uint16_t heatingMinOffTime; // minimal time the heating keeps turned off in // s float tempCorrVal; // correction value for // temperature sensor reading int humCorrVal; // correction value for humidity sensor reading float setTempDecreaseVal; // decreases the set temp to overcome further // temperature rise when the heating is already // switched off char offMessage[15]; char iTempLabel[2]; char oTempLabel[2]; char modeName0[15]; char modeName1[15]; char psetName0[15]; char psetName1[15]; char psetName2[15]; } confAdv; // confAdd struct confDataAdd { char mqtt_topic_pir[51]; char mqtt_payload_pir_on[10]; char mqtt_payload_pir_off[10]; char outTemp_topic_in[51]; char outHum_topic_in[51]; } confAdd; // confTime struct confDataTime { bool ntpEnable; char timeZoneStr[50]; char ntpServer1[31]; char ntpServer2[31]; unsigned long ntpSyncInterval; } confTime; // confLog struct confDataLog { uint8_t logLevelSerial; uint8_t logLevelWeb; uint8_t logLevelMqtt; uint8_t logLevelSyslog; } confLog; bool mqtt_tempDisabled_credentialError = false; char mqtt_topic_in_cmd[61]; char mqtt_topic_in_setTemp[61]; char mqtt_topic_in_setMode[61]; char mqtt_topic_in_setPreset[61]; // set values float setTemp = DEFAULT_SETTEMP; float setTempLow = DEFAULT_SETTEMP_LOW; // set temperature in night/low mode float setTempLow2 = DEFAULT_SETTEMP_LOW2; // set temperature in night/low mode float currSetTemp = DEFAULT_SETTEMP; uint8_t heatingMode = DEFAULT_HEATINGMODE; // 0 = off, 1 = heat uint8_t preset = DEFAULT_PRESET; // 0 = normal/day, 1 = night/reduction 1, 2 = // reduction 2 (long term leave) // saved set values (same as above, held in memory additionally to prevent // saving unchanged values) float setTempSaved; float setTempLowSaved; float setTempLow2Saved; uint8_t heatingModeSaved; uint8_t presetSaved; // global pre set conf variables - not changeable via configuration float setTempLowMin = SETTEMP_LOW_MIN; float setTempLowMax = SETTEMP_LOW_MAX; uint16_t debounceTime = BUTTON_DEBOUNCE_TIME; uint16_t buttonHoldTime = BUTTON_HOLD_TIME; unsigned long maxMeasurementAge = MAX_MEASUREMENT_AGE; unsigned long maxMeasurementAgeOut = MAX_MEASUREMENT_AGE_OUT; // global variables for program flow float currTemp; // last reading from DHT sensor with smoothing float currTemp_raw; // last reading from DHT sensor (raw) uint16_t currHum; // last reading from DHT sensor with smoothing uint16_t currHum_raw; // last reading from DHT sensor (raw) bool turnHeatingOn = false; // true if heating is active (relais switched on) unsigned long heatingLastOnMillis; // last time heating was switched on unsigned long heatingLastOffMillis; // last time heating was switched off float outTemp; // outside temp (via MQTT if enabled and in-topic configured) uint16_t outHum; // outside temp (via MQTT if enabled and in-topic configured) unsigned long outTempHumLastUpdate; // last reading from out temp/hum source char outTemp_newValue[6]; bool outTemp_parseNewValue; char outHum_newValue[4]; bool outHum_parseNewValue; char currentModeName[15]; char currentPresetName[15]; uint16_t displayInterval; uint8_t whichTempToDisplay; // 1=temp inside (from DHT sensor), 2= temp outside // (via MQTT) - if out temp/hum available this value // and the displayed value pair toggles with every // displayInterval unsigned long lastMeasure = 0; // millis of last temp/hum measurement unsigned long lastDisplayUpdate = 0; // millis of last display update unsigned long lastDisplayToggle = 0; // millis of last display toggle unsigned long lastTempUpdate = 0; // last update time of DHT reading char msg[50]; // buffer MQTT in payload char topic[50]; // buffer MQTT in topic bool displayActive = false; // gets true when button is pressed. display light // gets switched on until timeout. button actions // are only performed while display is active bool PIRSensorOn = false; unsigned long heatingOnTime, heatingOffTime; bool config_was_changed = 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 unsigned long lastUpdate_setTempLow2 = 0; // set to millis() every time setTemp value is changed unsigned long lastUpdate_heatingMode = 0; // set to millis() every time heatingMode value is changed unsigned long lastUpdate_preset = 0; // set to millis() every time preset value is changed char cmdPayload[101]; // buffer for commands bool cmdInQueue = false; // command is queued and will be processed next loop() run bool saveConfigToFlash = false; // conf is saved in next loop() run bool saveConfig2ToFlash = false; // conf2 is saved in next loop() run 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 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 bool heatingModeAlreadySaved = true; // only save if not yet done bool presetAlreadySaved = true; // only save if not yet done unsigned long lastRun = 0; uint16_t count100ms = 0; uint16_t countSeconds = 0; uint16_t countMeasureInterval = 0; uint16_t countDisplayInterval = 0; uint16_t displayOverlayMsgTimeout = 2; unsigned long mqttLastReconnectAttempt = 0; uint16_t mqttReconnectAttempts = 0; uint16_t mqttReconnects = 0; bool mqttConnected = false; unsigned long mqttLastHeartbeat; bool mqttInTopicSubscribed = false; bool pendingRestart = false; bool doRestart = false; unsigned long pendingRestart_lastMillis = 0; bool displayShowFullscreenMsg = false; // unsigned long displayShowFullscreenMsg_lastMillis = 0; bool pendingPresetToggle = false; bool updateDisplayImmediately = false; uint8_t pendingPreset; char pendingPresetName[15]; // unsigned long pendingPreset_millis = 0; // int pendingPreset_timeout = 2000; bool displayShowLine2OverlayMsg = false; // build Uptime String (unnecessary, i know ;) ) uint16_t sysUptime_days = 0; uint16_t sysUptime_hours = 0; uint16_t sysUptime_mins = 0; char uptimeStr[15]; DHT dht(PIN_DHTSENSOR, DHTTYPE); LiquidCrystal_I2C lcd(LCDADDR, LCDCOLS, LCDLINES); WiFiClient espClient; void mqttCallback(char *topic, byte *payload, uint16_t length); PubSubClient mqttclient(espClient); ESP8266WebServer httpServer(80); WebSocketsServer webSocket(81); DNSServer dnsServer; PersWiFiManager persWM(httpServer, dnsServer); ESP8266HTTPUpdateServer httpUpdater; // WebSocketsServer unsigned long int wsValidSessionId = 0; void updateTime(); bool setupTime(); void updateTimeFromNTP(); void sendLog(const char *msg, uint8_t loglevel = 1); void sendLog(const __FlashStringHelper *msg, uint8_t loglevel = 1); void setup() { Serial.begin(115200); delay(50); Serial.println(); Serial.print(FIRMWARE_NAME); Serial.print(" v"); Serial.print(FIRMWARE_VERSION); Serial.println(" starting..."); pinMode(PIN_RELAIS, OUTPUT); digitalWrite(PIN_RELAIS, !RELAISONSTATE); setupInputsButtons(); // set conf default values // set initial deviceName createDeviceName(); loadConf_defaults(); //if (serialdebug) // Serial.println("default config values loaded.."); sendLog(F("DEV: default config values loaded."), LOGLEVEL_INFO); initDisplay(); sendLog(F("Mounting SPIFFS..."), LOGLEVEL_INFO); if (!SPIFFS.begin()) { sendLog(F("Failed to mount SPIFFS"), LOGLEVEL_ERROR); return; } #ifdef FORCE_SPIFFS_FORMAT SPIFFS_format(); #endif SPIFFS_formatIfIsnt(); SPIFFS_listFiles(); loadConf_all(); loadSavedValues(); // if configuration returned empty strings - use the defaults where a values // is necessary if (strlen(deviceName) < 4) strlcpy(deviceName, DEVICE_NAME, // 31); loadConf_restoreDefaultWhenMissing(); updateCurrentHeatingModeName(); updateCurrentPresetName(); // initialize DHT11/22 temp/hum sensor dht.begin(); if (strlen(confDevWiFi.hostName) >= 4) { // if no hostname is set WiFi manager will create a unique one automatically // based on MAC address WiFi.hostname(confDevWiFi.hostName); } // optional code handlers to run everytime wifi is connected... persWM.onConnect([]() { //Serial.print(F("WiFi: connected to '")); //Serial.print(WiFi.SSID()); //Serial.print(F("' with IP: ")); //Serial.println(WiFi.localIP()); char buf[60]; sprintf(buf, "%s: %s '%s' %s: '%s'", PGMStr_WiFi, PGMStr_connectedTo, WiFi.SSID().c_str(), PGMStr_withIP, WiFi.localIP().toString().c_str()); sendLog(buf, LOGLEVEL_INFO); WifiInApMode = false; if (confTime.ntpEnable) setupTime(); displayShowWifiConnected(); }); //...or AP mode is started persWM.onAp([]() { //Serial.print(F("WiFi: AP mode, SSID: '")); //Serial.print(persWM.getApSsid()); //if (strlen(confDevWiFi.WiFiAPModePassword) >= 4) //{ // Serial.print("', PW: '"); // Serial.print(confDevWiFi.WiFiAPModePassword); //} //Serial.println("'"); char buf[60]; sprintf(buf, "%s: AP-MODE started, SSID '%s', PW: '%s'", PGMStr_WiFi, persWM.getApSsid().c_str(), confDevWiFi.WiFiAPModePassword); sendLog(buf, LOGLEVEL_INFO); WifiInApMode = true; WifiApModeStartedAt = millis(); displayShowWifiConnectionError(); }); persWM.onApOff([]() { //Serial.println(F("WiFi: AP mode stopped")); sendLog(F("WiFi: AP-MODE stopped"), LOGLEVEL_INFO); }); // sets network name and password for AP mode // sprintf(WiFiAPModeSSID, "%s-%s", FIRMWARE_SHORTNAME, deviceName); if (strlen(confDevWiFi.deviceName) >= 8) strlcpy(confDevWiFi.WiFiAPModeSSID, confDevWiFi.deviceName, sizeof(confDevWiFi.WiFiAPModeSSID)); else { byte mac[6]; WiFi.macAddress(mac); sprintf(confDevWiFi.WiFiAPModeSSID, "%s-%02X%02X", FIRMWARE_SHORTNAME, (uint8_t)mac[4], (uint8_t)mac[5]); } //Serial.print(F("WiFi: AP-SSID name: ")); //Serial.println(confDevWiFi.WiFiAPModeSSID); if (strlen(confDevWiFi.WiFiAPModePassword) < 5) persWM.setApCredentials(confDevWiFi.WiFiAPModeSSID); else persWM.setApCredentials(confDevWiFi.WiFiAPModeSSID, confDevWiFi.WiFiAPModePassword); //Serial.print(F("WiFi: SSID 1: ")); Serial.println(confDevWiFi.WiFiSSID1); //Serial.print("', PW: '"); Serial.print(confDevWiFi.WiFiPW1); Serial.println("'"); //Serial.print(F("WiFi: SSID 2: ")); Serial.println(confDevWiFi.WiFiSSID2); //Serial.print("', PW: '"); Serial.print(confDevWiFi.WiFiPW2); Serial.println("'"); persWM.setWifi1Credentials(confDevWiFi.WiFiSSID1, confDevWiFi.WiFiPW1); persWM.setWifi2Credentials(confDevWiFi.WiFiSSID2, confDevWiFi.WiFiPW2); persWM.setHttpCredentials(confWeb.http_user, confWeb.http_pass); persWM.setApTimeout(confDevWiFi.WiFiAPModeTimeout); persWM.setConnCheckInterval(confDevWiFi.WiFiConnCheckInterval); persWM.setForceRetryWifi1Interval(confDevWiFi.WiFiRetryInterval); persWM.setRebootOnNoConnect(confDevWiFi.WiFiRebootOnNoConnect); // make connecting/disconnecting non-blocking persWM.setConnectNonBlock(true); // in non-blocking mode, program will continue past this point without waiting persWM.begin(); delay(500); httpServerInit(); if (confWeb.enableConsole) startWebSocketServer(); if (confMqtt.mqtt_enable) { mqttPrepareSubscribeTopics(); mqttClientInit(); } buildUptimeString(); sendLog(F("DEV: setup complete."), LOGLEVEL_INFO); } // void setup void loop() { checkMillis(); persWM.handleWiFi(); // in non-blocking mode, handleWiFi must be called in the // main loop yield(); mqttHandleConnection(); yield(); outTempHum_updateOnNewValue(); yield(); dnsServer.processNextRequest(); httpServer.handleClient(); buttonPlus.update(); buttonMinus.update(); buttonMode.update(); pirSensor.update(); yield(); evalCmd(); yield(); if (Serial.available()) { serialEvent(); yield(); } if (updateDisplayImmediately) { updateDisplayImmediately = false; updateDisplay(); } if (confWeb.enableConsole) { if (WiFi.status() == WL_CONNECTED) { webSocket.loop(); } else { webSocket.disconnect(); } } } // void loop