WiFiThermostat.ino 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704
  1. //#include <Arduino.h>
  2. #include "fwversion.h"
  3. #include "fwsettings.h"
  4. // ESP8266 core libs
  5. #include <ESP8266HTTPUpdateServer.h>
  6. #include <ESP8266WebServer.h>
  7. #include <ESP8266WiFi.h>
  8. #include <ESP8266mDNS.h>
  9. #ifdef USE_MQTT_TLS
  10. #include <WiFiClientSecure.h>
  11. #else
  12. #include <WiFiClient.h>
  13. #endif
  14. // WiFiManager
  15. #include <PersWiFiManagerExt.h>
  16. // DNS server used for captive portal in WiFiManager
  17. #include <DNSServer.h>
  18. // MQTT client
  19. #include <PubSubClient.h>
  20. // SPIFFS FS support - used for config storage
  21. #include <FS.h>
  22. // Json lib - used for config storage and web api
  23. #include <ArduinoJson.h>
  24. //#include <string.h>
  25. // I2C and LCD display
  26. #include <Wire.h>
  27. #include <LiquidCrystal_I2C.h>
  28. // DHT22 sensor lib
  29. #include <DHT.h>
  30. // Button handling
  31. #include <Bounce2.h>
  32. #include <Button.h>
  33. #include <ButtonEventCallback.h>
  34. #include <PushButton.h>
  35. PROGMEM const char PGMStr_FIRMWARE_NAME[] = FIRMWARE_NAME;
  36. PROGMEM const char PGMStr_FIRMWARE_VERSION[] = FIRMWARE_VERSION;
  37. PROGMEM const char PGMStr_FIRMWARE_URL[] = FIRMWARE_URL;
  38. PROGMEM const char PGMStr_FIRMWARE_COPYRIGHT[] = FIRMWARE_COPYRIGHT;
  39. PROGMEM const char PGMStr_FIRMWARE_COPYRIGHT_URL[] = FIRMWARE_COPYRIGHT_URL;
  40. PROGMEM const char PGMStr_FIRMWARE_SHORTNAME[] = FIRMWARE_SHORTNAME;
  41. PROGMEM const char PGMStr_changedTo[] = "changed to";
  42. PROGMEM const char PGMStr_preset[] = "preset";
  43. PROGMEM const char PGMStr_heatingMode[] = "heatingMode";
  44. PROGMEM const char PGMStr_setTemp[] = "setTemp";
  45. PROGMEM const char PGMStr_currentSetTemp[] = "currSetTemp";
  46. PROGMEM const char PGMStr_setTempLow[] = "setTempLow";
  47. PROGMEM const char PGMStr_setTempLow2[] = "setTempLow2";
  48. PROGMEM const char PGMStr_switchHeating[] = "switch heating";
  49. PROGMEM const char PGMStr_mqttRetainedSave[] = "MQTT retained save";
  50. PROGMEM const char PGMStr_heating[] = "heating";
  51. PROGMEM const char PGMStr_thermostat[] = "THST";
  52. PROGMEM const char PGMStr_WiFi[] = "WiFi";
  53. //PROGMEM const char PGMStr_connectedTo[] = "connected to";
  54. //PROGMEM const char PGMStr_withIP[] = "with IP";
  55. PROGMEM const char PGMStr_MQTT[] = "MQTT";
  56. PROGMEM const char PGMStr_connectedTo[] = "connected to";
  57. PROGMEM const char PGMStr_reconnects[] = "reconnects";
  58. PROGMEM const char PGMStr_connectedFailed[] = "connect FAILED";
  59. PROGMEM const char compile_date[] = __DATE__ " " __TIME__;
  60. const char PGMStr_confDevWiFi[] PROGMEM = "confDevWiFi";
  61. const char PGMStr_confWeb[] PROGMEM = "confWeb";
  62. const char PGMStr_confMqtt[] PROGMEM = "confMqtt";
  63. const char PGMStr_confBas[] PROGMEM = "confBas";
  64. const char PGMStr_confAdv[] PROGMEM = "confAdv";
  65. const char PGMStr_confAdd[] PROGMEM = "confAdd";
  66. const char PGMStr_confTime[] PROGMEM = "confTime";
  67. const char PGMStr_confLog[] PROGMEM = "confLog";
  68. //const char PGMStr_delimiter[] PROGMEM = "--------";
  69. const char PGMStr_MQTTState_DIS[] PROGMEM = "DISABLED";
  70. const char PGMStr_MQTTState_M4[] PROGMEM = "CONNECTION_TIMEOUT";
  71. const char PGMStr_MQTTState_M3[] PROGMEM = "CONNECTION_LOST";
  72. const char PGMStr_MQTTState_M2[] PROGMEM = "CONNECT_FAILED";
  73. const char PGMStr_MQTTState_M1[] PROGMEM = "DISCONNECTED";
  74. const char PGMStr_MQTTState_0[] PROGMEM = "CONNECTED";
  75. const char PGMStr_MQTTState_1[] PROGMEM = "CONNECT_BAD_PROTOCOL";
  76. const char PGMStr_MQTTState_2[] PROGMEM = "CONNECT_BAD_CLIENT_ID";
  77. const char PGMStr_MQTTState_3[] PROGMEM = "CONNECT_UNAVAILABLE";
  78. const char PGMStr_MQTTState_4[] PROGMEM = "CONNECT_BAD_CREDENTIALS";
  79. const char PGMStr_MQTTState_5[] PROGMEM = "CONNECT_UNAUTHORIZED";
  80. const char *const PGMStr_MQTTStates[] PROGMEM =
  81. {
  82. PGMStr_MQTTState_M4,
  83. PGMStr_MQTTState_M3,
  84. PGMStr_MQTTState_M2,
  85. PGMStr_MQTTState_M1,
  86. PGMStr_MQTTState_0,
  87. PGMStr_MQTTState_1,
  88. PGMStr_MQTTState_2,
  89. PGMStr_MQTTState_3,
  90. PGMStr_MQTTState_4,
  91. PGMStr_MQTTState_5,
  92. };
  93. char mqttCurrentStateName[25];
  94. //---------------------------------------------------------------------------------------------------------------------------------------------
  95. PushButton buttonPlus = PushButton(PIN_BUTTON_PLUS, ENABLE_INTERNAL_PULLUP);
  96. PushButton buttonMinus = PushButton(PIN_BUTTON_MINUS, ENABLE_INTERNAL_PULLUP);
  97. PushButton buttonMode = PushButton(PIN_BUTTON_MODE, ENABLE_INTERNAL_PULLUP);
  98. PushButton pirSensor = PushButton(PIN_PIRSENSOR, PRESSED_WHEN_HIGH);
  99. bool WifiInApMode = false;
  100. unsigned long WifiApModeStartedAt;
  101. #ifdef ENABLE_FEATURE_PW_ENCRYPTION
  102. char encKey[] = PW_ENCRYPTION_KEY;
  103. #endif
  104. bool confEncryptionEnabled = false;
  105. #ifdef ENABLE_FEATURE_NTP_TIME
  106. struct tm lt; // http://www.cplusplus.com/reference/ctime/tm/
  107. //const char *const PROGMEM dayNames[] = {"Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"};
  108. //const char *const PROGMEM dayShortNames[] = {"So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"};
  109. //const char *const PROGMEM monthNames[] = {"Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"};
  110. //const char *const PROGMEM monthShortNames[] = {"Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"};
  111. #endif
  112. // config variables - do not change here!
  113. // confDevWiFi
  114. struct confDataDevWiFi
  115. {
  116. char deviceName[33]; // device name - for web interface and AP-Mode SSID
  117. char hostName[33]; // announced hostname on WiFi connection
  118. char WiFiSSID1[33];
  119. char WiFiPW1[64];
  120. char WiFiSSID2[33];
  121. char WiFiPW2[64];
  122. char WiFiAPModeSSID[33]; // generated, not set via config
  123. char WiFiAPModePassword[64];
  124. uint16_t WiFiAPModeTimeout;
  125. uint16_t WiFiRetryInterval;
  126. uint16_t WiFiConnCheckInterval;
  127. uint16_t WiFiRebootOnNoConnect;
  128. bool wasChanged;
  129. } confDevWiFi;
  130. // confWeb
  131. struct confDataWeb
  132. {
  133. char http_token[31];
  134. char http_user[31];
  135. char http_pass[31];
  136. bool http_user_auth;
  137. char http_user1[31];
  138. char http_pass1[31];
  139. char http_user2[31];
  140. char http_pass2[31];
  141. bool wConsole;
  142. bool wsConsole;
  143. bool wasChanged;
  144. } confWeb;
  145. // confMqtt
  146. struct confDataMqtt
  147. {
  148. bool mqtt_enable;
  149. char mqtt_server[41];
  150. uint16_t mqtt_port;
  151. char mqtt_user[31];
  152. char mqtt_pass[31];
  153. char mqtt_topic_in[51]; // MQTT in topic for commands
  154. char mqtt_topic_out[51]; // MQTT out base topic, will be extended by various value names
  155. char mqtt_willTopic[51]; // MQTT Last Will topic
  156. uint8_t mqtt_willQos; // MQTT Last Will topic QOS
  157. bool mqtt_willRetain; // MQTT Last Will retain
  158. char mqtt_willMsg[31]; // MQTT Last Will payload
  159. char mqtt_connMsg[31];
  160. bool mqtt_outRetain; // send MQTT out with retain flag
  161. bool mqtt_outRetain_sensors; // send MQTT out with retain flag
  162. uint8_t mqtt_outPubInterval;
  163. uint8_t mqtt_outPubInterval_sensors;
  164. bool mqtt_enable_heartbeat;
  165. unsigned long mqtt_heartbeat_maxage_reconnect;
  166. unsigned long mqtt_heartbeat_maxage_reboot;
  167. bool wasChanged;
  168. } confMqtt;
  169. // confBas
  170. struct confDataBas
  171. {
  172. float setTempMin; // minimal temperature that can be set
  173. float setTempMax; // maximal temperature that can be set
  174. bool autoSaveSetTemp;
  175. bool autoSaveHeatingMode;
  176. bool saveToMqttRetained;
  177. uint16_t measureInterval; // interval for temp/hum measurement
  178. uint16_t displayInterval; // interval for display updates (if out-temp is
  179. // active, display will toggle in this interval)
  180. uint16_t displayTimeout; // display timeout after keypress (illumination)
  181. bool PIR_enablesDisplay; // PIR sensor enables display illumination
  182. bool PIR_enablesDisplay_preset0only;
  183. bool togglingTempHumAIDisplay;
  184. bool wasChanged;
  185. } confBas;
  186. // confAdv
  187. struct confDataAdv
  188. {
  189. float hysteresis; // hysteresis, normally 0.1 - 0.5
  190. uint16_t heatingMinOffTime; // minimal time the heating keeps turned off in
  191. // s
  192. float tempCorrVal; // correction value for
  193. // temperature sensor reading
  194. int humCorrVal; // correction value for humidity sensor reading
  195. float setTempDecreaseVal; // decreases the set temp to overcome further
  196. // temperature rise when the heating is already
  197. // switched off
  198. char offMessage[15];
  199. char iTempLabel[2];
  200. char oTempLabel[2];
  201. char modeName0[15];
  202. char modeName1[15];
  203. char psetName0[15];
  204. char psetName1[15];
  205. char psetName2[15];
  206. bool wasChanged;
  207. } confAdv;
  208. // confAdd
  209. struct confDataAdd
  210. {
  211. char mqtt_topic_pir[51];
  212. char mqtt_payload_pir_on[10];
  213. char mqtt_payload_pir_off[10];
  214. char outTemp_topic_in[51];
  215. char outHum_topic_in[51];
  216. bool wasChanged;
  217. } confAdd;
  218. // confTime
  219. struct confDataTime
  220. {
  221. bool ntpEnable;
  222. char timeZoneStr[50];
  223. char ntpServer1[31];
  224. char ntpServer2[31];
  225. unsigned long ntpSyncInterval;
  226. bool wasChanged;
  227. } confTime;
  228. // confLog
  229. struct confDataLog
  230. {
  231. uint8_t logLevelSerial;
  232. uint8_t logLevelWeb;
  233. uint8_t logLevelMqtt;
  234. uint8_t logLevelSyslog;
  235. bool logWebRequests;
  236. bool wasChanged;
  237. } confLog;
  238. // Uptime
  239. struct sysUptimeStruct
  240. {
  241. unsigned int day = 0;
  242. unsigned int hour = 0;
  243. unsigned int min = 0;
  244. unsigned int sec = 0;
  245. unsigned int highMillis = 0;
  246. unsigned int rollover = 0;
  247. char uptimeStr[16];
  248. } sysUptime;
  249. bool mqtt_tempDisabled_credentialError = false;
  250. char mqtt_topic_in_cmd[61];
  251. char mqtt_topic_in_setTemp[61];
  252. char mqtt_topic_in_setMode[61];
  253. char mqtt_topic_in_setPreset[61];
  254. // set values
  255. float setTemp = DEFAULT_SETTEMP;
  256. float setTempLow = DEFAULT_SETTEMP_LOW; // set temperature in night/low mode
  257. float setTempLow2 = DEFAULT_SETTEMP_LOW2; // set temperature in night/low mode
  258. float currSetTemp = DEFAULT_SETTEMP;
  259. uint8_t heatingMode = DEFAULT_HEATINGMODE; // 0 = off, 1 = heat
  260. uint8_t preset = DEFAULT_PRESET; // 0 = normal/day, 1 = night/reduction 1, 2 =
  261. // reduction 2 (long term leave)
  262. // saved set values (same as above, held in memory additionally to prevent
  263. // saving unchanged values)
  264. float setTempSaved;
  265. float setTempLowSaved;
  266. float setTempLow2Saved;
  267. uint8_t heatingModeSaved;
  268. uint8_t presetSaved;
  269. // global pre set conf variables - not changeable via configuration
  270. float setTempLowMin = SETTEMP_LOW_MIN;
  271. float setTempLowMax = SETTEMP_LOW_MAX;
  272. uint16_t debounceTime = BUTTON_DEBOUNCE_TIME;
  273. uint16_t buttonHoldTime = BUTTON_HOLD_TIME;
  274. unsigned long maxMeasurementAge = MAX_MEASUREMENT_AGE;
  275. unsigned long maxMeasurementAgeOut = MAX_MEASUREMENT_AGE_OUT;
  276. // global variables for program flow
  277. float currTemp; // last reading from DHT sensor with smoothing
  278. float currTemp_raw; // last reading from DHT sensor (raw)
  279. uint16_t currHum; // last reading from DHT sensor with smoothing
  280. uint16_t currHum_raw; // last reading from DHT sensor (raw)
  281. bool turnHeatingOn = false; // true if heating is active (relais switched on)
  282. unsigned long heatingLastOnMillis; // last time heating was switched on
  283. unsigned long heatingLastOffMillis; // last time heating was switched off
  284. float outTemp; // outside temp (via MQTT if enabled and in-topic configured)
  285. uint16_t outHum; // outside temp (via MQTT if enabled and in-topic configured)
  286. unsigned long outTempHumLastUpdate; // last reading from out temp/hum source
  287. char outTemp_newValue[6];
  288. bool outTemp_parseNewValue;
  289. char outHum_newValue[4];
  290. bool outHum_parseNewValue;
  291. char currentModeName[15];
  292. char currentPresetName[15];
  293. uint16_t displayInterval;
  294. uint8_t whichTempToDisplay; // 1=temp inside (from DHT sensor), 2= temp outside
  295. // (via MQTT) - if out temp/hum available this value
  296. // and the displayed value pair toggles with every
  297. // displayInterval
  298. unsigned long lastMeasure = 0; // millis of last temp/hum measurement
  299. unsigned long lastDisplayUpdate = 0; // millis of last display update
  300. unsigned long lastDisplayToggle = 0; // millis of last display toggle
  301. unsigned long lastTempUpdate = 0; // last update time of DHT reading
  302. //char msg[101]; // buffer MQTT in payload
  303. //char topic[70]; // buffer MQTT in topic
  304. bool displayActive = false; // gets true when button is pressed. display light
  305. // gets switched on until timeout. button actions
  306. // are only performed while display is active
  307. bool PIRSensorOn = false;
  308. unsigned long heatingOnTime, heatingOffTime;
  309. //bool config_was_changed = false;
  310. bool configChangedRestartRequired = false;
  311. bool configChangedMqttConnResetRequired = false;
  312. unsigned long lastUpdate_setTemp = 0; // set to millis() every time setTemp value is changed
  313. unsigned long lastUpdate_setTempLow = 0; // set to millis() every time setTemp value is changed
  314. unsigned long lastUpdate_setTempLow2 = 0; // set to millis() every time setTemp value is changed
  315. unsigned long lastUpdate_heatingMode = 0; // set to millis() every time heatingMode value is changed
  316. unsigned long lastUpdate_preset = 0; // set to millis() every time preset value is changed
  317. char cmdPayload[101]; // buffer for commands
  318. bool cmdInQueue = false; // command is queued and will be processed next loop() run
  319. // not used any more, now triggered directly
  320. //bool saveConfigToFlash = false; // conf is saved in next loop() run
  321. //bool saveConfig2ToFlash = false; // conf2 is saved in next loop() run
  322. // ----
  323. uint16_t saveValuesTimeout = 5000;
  324. unsigned long lastValueChange; // is set to millis() whenever setTemp value
  325. // and/or heatingMode value is changed. used for
  326. // autoSave function with hardcoded 5s timeout
  327. unsigned long lastConfigChange;
  328. bool lastConfigChangeNoteAlreadyDone = false;
  329. bool setTempAlreadySaved = true; // only save if not yet done
  330. bool setTempLowAlreadySaved = true; // only save if not yet done
  331. bool setTempLow2AlreadySaved = true; // only save if not yet done
  332. bool heatingModeAlreadySaved = true; // only save if not yet done
  333. bool presetAlreadySaved = true; // only save if not yet done
  334. unsigned long lastRun = 0;
  335. uint16_t count100ms = 0;
  336. uint16_t countSeconds = 0;
  337. uint16_t countMeasureInterval = 0;
  338. uint16_t countDisplayInterval = 0;
  339. uint16_t displayOverlayMsgTimeout = 2;
  340. unsigned long mqttLastReconnectAttempt = 0;
  341. uint16_t mqttReconnectAttempts = 0;
  342. uint16_t mqttReconnects = 0;
  343. bool mqttConnected = false;
  344. unsigned long mqttLastHeartbeat;
  345. bool mqttInTopicSubscribed = false;
  346. bool pendingRestart = false;
  347. bool doRestart = false;
  348. unsigned long pendingRestart_lastMillis = 0;
  349. bool displayShowFullscreenMsg = false;
  350. // unsigned long displayShowFullscreenMsg_lastMillis = 0;
  351. bool pendingPresetToggle = false;
  352. bool updateDisplayImmediately = false;
  353. uint8_t pendingPreset;
  354. char pendingPresetName[15];
  355. bool displayShowLine2OverlayMsg = false;
  356. // if command "debugmode 1" is called...
  357. bool sysInfoEverySecond = false;
  358. #ifdef ENABLE_FEATURE_WEB_CONSOLE
  359. char webLogBuffer[WEB_CONSOLE_BUFFER_SIZE];
  360. unsigned int webLogBuffer_index = 0;
  361. #endif
  362. // END global variables
  363. DHT dht(PIN_DHTSENSOR, DHTTYPE);
  364. LiquidCrystal_I2C lcd(LCDADDR, LCDCOLS, LCDLINES);
  365. #ifdef USE_MQTT_TLS
  366. //WiFiClientSecure wifiClient;
  367. BearSSL::WiFiClientSecure wifiClient;
  368. #else
  369. WiFiClient wifiClient;
  370. #endif
  371. PubSubClient mqttclient(wifiClient);
  372. ESP8266WebServer httpServer(80);
  373. // WebSocketsServer
  374. #ifdef ENABLE_FEATURE_WEB_CONSOLE_WEBSOCKETS
  375. WebSocketsServer webSocket(81);
  376. unsigned long int wsValidSessionId = 0;
  377. #endif
  378. DNSServer dnsServer;
  379. PersWiFiManager persWM(httpServer, dnsServer);
  380. #ifdef ENABLE_FEATURE_HTTP_UPDATER
  381. ESP8266HTTPUpdateServer httpUpdater;
  382. #endif
  383. // FUNCTION PROTOTYPES
  384. #ifdef ENABLE_FEATURE_NTP_TIME
  385. void updateTime();
  386. bool setupTime();
  387. void syncClock(bool force = false);
  388. #endif
  389. char *getUptimeStr(bool includeSeconds = false);
  390. void sendLog(const char *msg, uint8_t loglevel = 1);
  391. void sendLog(const __FlashStringHelper *msg, uint8_t loglevel = 1);
  392. void mqttCallback(char *topic, byte *payload, uint16_t length);
  393. char *getTimeStringFromSeconds(unsigned int inSeconds);
  394. // END - FUNCTION PROTOTYPES
  395. // MAIN FUNCTIONS
  396. void setup()
  397. {
  398. Serial.begin(115200);
  399. delay(50);
  400. Serial.println();
  401. Serial.print(PGMStr_FIRMWARE_NAME);
  402. Serial.print(F(" v"));
  403. Serial.print(PGMStr_FIRMWARE_VERSION);
  404. Serial.println(F(" starting..."));
  405. pinMode(PIN_RELAIS, OUTPUT);
  406. digitalWrite(PIN_RELAIS, !RELAISONSTATE);
  407. setupInputsButtons();
  408. // set conf default values
  409. loadConf_defaults();
  410. //if (serialdebug)
  411. // Serial.println("default config values loaded..");
  412. sendLog(F("CONF: default config loaded."), LOGLEVEL_INFO);
  413. initDisplay();
  414. sendLog(F("Mounting SPIFFS..."), LOGLEVEL_INFO);
  415. if (!SPIFFS.begin())
  416. {
  417. sendLog(F("Failed to mount SPIFFS"), LOGLEVEL_ERROR);
  418. return;
  419. }
  420. #ifdef FORCE_SPIFFS_FORMAT
  421. SPIFFS_format();
  422. #endif
  423. SPIFFS_formatIfIsnt();
  424. //SPIFFS_listFiles();
  425. #ifdef ENABLE_FEATURE_PW_ENCRYPTION
  426. confCheckEncrypted();
  427. #endif
  428. loadConf_all();
  429. loadSavedValues();
  430. // if configuration returned empty strings - use the defaults where a values
  431. // is necessary if (strlen(deviceName) < 4) strlcpy(deviceName, DEVICE_NAME,
  432. // 31);
  433. loadConf_restoreDefaultWhenMissing();
  434. updateCurrentHeatingModeName();
  435. updateCurrentPresetName();
  436. // initialize DHT11/22 temp/hum sensor
  437. dht.begin();
  438. if (strlen(confDevWiFi.hostName) >= 4)
  439. { // if no hostname is set WiFi manager will create a unique one automatically
  440. // based on MAC address
  441. WiFi.hostname(confDevWiFi.hostName);
  442. }
  443. // optional code handlers to run everytime wifi is connected...
  444. persWM.onConnect([]() {
  445. //Serial.print(F("WiFi: connected to '"));
  446. //Serial.print(WiFi.SSID());
  447. //Serial.print(F("' with IP: "));
  448. //Serial.println(WiFi.localIP());
  449. //char buf[60];
  450. //sprintf(buf, "%s: %s '%s' %s: '%s'", PGMStr_WiFi, PGMStr_connectedTo, WiFi.SSID().c_str(), PGMStr_withIP, WiFi.localIP().toString().c_str());
  451. //sendLog(buf, LOGLEVEL_INFO);
  452. printIpcfg();
  453. WifiInApMode = false;
  454. #ifdef ENABLE_FEATURE_NTP_TIME
  455. if (confTime.ntpEnable)
  456. setupTime();
  457. #endif
  458. displayShowWifiConnected();
  459. });
  460. //...or AP mode is started
  461. persWM.onAp([]() {
  462. //Serial.print(F("WiFi: AP mode, SSID: '"));
  463. //Serial.print(persWM.getApSsid());
  464. //if (strlen(confDevWiFi.WiFiAPModePassword) >= 4)
  465. //{
  466. // Serial.print("', PW: '");
  467. // Serial.print(confDevWiFi.WiFiAPModePassword);
  468. //}
  469. //Serial.println("'");
  470. char buf[60];
  471. sprintf(buf, "%s: AP-MODE started, SSID '%s', PW: '%s'", PGMStr_WiFi, persWM.getApSsid().c_str(), confDevWiFi.WiFiAPModePassword);
  472. sendLog(buf, LOGLEVEL_INFO);
  473. WifiInApMode = true;
  474. WifiApModeStartedAt = millis();
  475. displayShowWifiConnectionError();
  476. });
  477. persWM.onApOff([]() {
  478. //Serial.println(F("WiFi: AP mode stopped"));
  479. sendLog(F("WiFi: AP-MODE stopped"), LOGLEVEL_INFO);
  480. });
  481. // sets network name and password for AP mode
  482. // sprintf(WiFiAPModeSSID, "%s-%s", FIRMWARE_SHORTNAME, deviceName);
  483. if (strlen(confDevWiFi.deviceName) >= 8)
  484. strlcpy(confDevWiFi.WiFiAPModeSSID, confDevWiFi.deviceName, sizeof(confDevWiFi.WiFiAPModeSSID));
  485. else
  486. {
  487. byte mac[6];
  488. WiFi.macAddress(mac);
  489. sprintf(confDevWiFi.WiFiAPModeSSID, "%s-%02X%02X", FIRMWARE_SHORTNAME, (uint8_t)mac[4], (uint8_t)mac[5]);
  490. }
  491. //Serial.print(F("WiFi: AP-SSID name: "));
  492. //Serial.println(confDevWiFi.WiFiAPModeSSID);
  493. if (strlen(confDevWiFi.WiFiAPModePassword) < 5)
  494. {
  495. persWM.setApCredentials(confDevWiFi.WiFiAPModeSSID);
  496. //sendLog("WIFI-AP: open network");
  497. }
  498. else
  499. {
  500. persWM.setApCredentials(confDevWiFi.WiFiAPModeSSID, confDevWiFi.WiFiAPModePassword);
  501. //sendLog("WIFI-AP: with password");
  502. }
  503. //Serial.print(F("WiFi: SSID 1: ")); Serial.println(confDevWiFi.WiFiSSID1); //Serial.print("', PW: '"); Serial.print(confDevWiFi.WiFiPW1); Serial.println("'");
  504. //Serial.print(F("WiFi: SSID 2: ")); Serial.println(confDevWiFi.WiFiSSID2); //Serial.print("', PW: '"); Serial.print(confDevWiFi.WiFiPW2); Serial.println("'");
  505. persWM.setWifi1Credentials(confDevWiFi.WiFiSSID1, confDevWiFi.WiFiPW1);
  506. persWM.setWifi2Credentials(confDevWiFi.WiFiSSID2, confDevWiFi.WiFiPW2);
  507. persWM.setHttpCredentials(confWeb.http_user, confWeb.http_pass);
  508. persWM.setApTimeout(confDevWiFi.WiFiAPModeTimeout);
  509. persWM.setConnCheckInterval(confDevWiFi.WiFiConnCheckInterval);
  510. persWM.setForceRetryWifi1Interval(confDevWiFi.WiFiRetryInterval);
  511. persWM.setRebootOnNoConnect(confDevWiFi.WiFiRebootOnNoConnect);
  512. // make connecting/disconnecting non-blocking
  513. persWM.setConnectNonBlock(true);
  514. // in non-blocking mode, program will continue past this point without waiting
  515. persWM.begin();
  516. #ifdef USE_MQTT_TLS
  517. //randomSeed(micros());
  518. //wifiClient.setFingerprint(MQTT_TLS_fingerprint);
  519. wifiClient.setInsecure();
  520. wifiClient.allowSelfSignedCerts();
  521. wifiClient.setCiphersLessSecure();
  522. #endif
  523. delay(500);
  524. httpServerInit();
  525. #ifdef ENABLE_FEATURE_WEB_CONSOLE_WEBSOCKETS
  526. if (confWeb.wsConsole)
  527. startWebSocketServer();
  528. #endif
  529. if (confMqtt.mqtt_enable)
  530. {
  531. mqttPrepareSubscribeTopics();
  532. mqttClientInit();
  533. }
  534. sendLog(F("DEV: setup complete."), LOGLEVEL_INFO);
  535. } // void setup
  536. void loop()
  537. {
  538. checkMillis();
  539. persWM.handleWiFi(); // in non-blocking mode, handleWiFi must be called in the
  540. // main loop
  541. yield();
  542. mqttHandleConnection();
  543. yield();
  544. outTempHum_updateOnNewValue();
  545. yield();
  546. dnsServer.processNextRequest();
  547. httpServer.handleClient();
  548. buttonPlus.update();
  549. buttonMinus.update();
  550. buttonMode.update();
  551. pirSensor.update();
  552. yield();
  553. evalCmd();
  554. yield();
  555. if (Serial.available())
  556. {
  557. serialEvent();
  558. yield();
  559. }
  560. if (updateDisplayImmediately)
  561. {
  562. updateDisplayImmediately = false;
  563. updateDisplay();
  564. }
  565. #ifdef ENABLE_FEATURE_WEB_CONSOLE_WEBSOCKETS
  566. if (confWeb.wsConsole)
  567. {
  568. if (WiFi.status() == WL_CONNECTED)
  569. {
  570. webSocket.loop();
  571. }
  572. else
  573. {
  574. webSocket.disconnect();
  575. }
  576. }
  577. #endif
  578. } // void loop
  579. //#ifdef USE_MQTT_TLS
  580. //void verifytls() {
  581. // // Use WiFiClientSecure class to create TLS connection
  582. // Serial.print(F("MQTT: trying TLS connection to "));
  583. // Serial.println(confMqtt.mqtt_server);
  584. // if (!wifiClient.connect(confMqtt.mqtt_server, confMqtt.mqtt_port)) {
  585. // Serial.println("connection failed");
  586. // return;
  587. // }
  588. //
  589. // if (wifiClient.verify(MQTT_TLS_fingerprint, confMqtt.mqtt_server)) {
  590. // Serial.println("certificate matches");
  591. // } else {
  592. // Serial.println("certificate doesn't match");
  593. // }
  594. //}
  595. //#endif