mqtt.ino 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. /*#include <Arduino.h>*/
  2. #define MQTT_RECONNECT_INTERVAL_3_TRIES 15000
  3. #define MQTT_RECONNECT_INTERVAL_10_TRIES 60000
  4. #define MQTT_RECONNECT_INTERVAL_LONG 300000
  5. bool mqttHeartbeatReceived = false;
  6. // MQTT callback
  7. void mqttCallback(char *topic, unsigned char *payload, uint16_t length)
  8. {
  9. // Serial.print("MQTT payload arrived [");
  10. // Serial.print(topic);
  11. // Serial.print("] ");
  12. // for (int i = 0; i < length; i++) {
  13. // Serial.print((char)payload[i]);
  14. // }
  15. // Serial.println();
  16. //char tmp_topic_pub[51];
  17. //char tmp_payload_pub[51];
  18. if (strcmp(topic, mqtt_topic_in_cmd) == 0)
  19. { //if topic = mqtt_topic_in_cmd
  20. int len;
  21. if (length < sizeof(cmdPayload))
  22. len = length; // if input is bigger than dest buffer, cut
  23. else
  24. len = sizeof(cmdPayload) - 1;
  25. for (int i = 0; i < len; i++)
  26. {
  27. cmdPayload[i] = (char)payload[i];
  28. }
  29. cmdPayload[len] = '\0';
  30. // Serial.print("cmdPayload:");
  31. // Serial.println(cmdPayload);
  32. //if (serialdebug)
  33. //{
  34. // Serial.print("MQTT: received '");
  35. // Serial.print(mqtt_topic_in_cmd);
  36. // Serial.print("' - '");
  37. // Serial.print(cmdPayload);
  38. // Serial.println("'");
  39. //}
  40. //if (mqttdebug)
  41. //{
  42. // sprintf(tmp_topic_pub, "%s/%s", confMqtt.mqtt_topic_out, "mqtt_received");
  43. // sprintf(tmp_payload_pub, "%s: %s", mqtt_topic_in_cmd, cmdPayload);
  44. // mqttclient.publish(tmp_topic_pub, tmp_payload_pub);
  45. //}
  46. if (strncmp(cmdPayload, "HEARTBEAT", 9) == 0)
  47. {
  48. mqttLastHeartbeat = millis();
  49. mqttHeartbeatReceived = true;
  50. mqttConnected = true;
  51. }
  52. else
  53. {
  54. cmdInQueue = true; // payload is processed in "commands"
  55. }
  56. } //if topic = mqtt_topic_in_cmd
  57. if (strcmp(topic, mqtt_topic_in_setTemp) == 0)
  58. { //if topic = mqtt_topic_in_setTemp
  59. int len;
  60. if (length < sizeof(cmdPayload))
  61. len = length; // if input is bigger than dest buffer, cut
  62. else
  63. len = sizeof(cmdPayload) - 1;
  64. for (int i = 0; i < len; i++)
  65. {
  66. cmdPayload[i] = (char)payload[i];
  67. }
  68. //cmdPayload[len + 1] = '\0';
  69. cmdPayload[len] = '\0';
  70. // Serial.print("cmdPayload:");
  71. // Serial.println(cmdPayload);
  72. char tmpPayload[11];
  73. strlcpy(tmpPayload, cmdPayload, 10);
  74. float valueFloat;
  75. valueFloat = round(atof(tmpPayload) * 2.0) / 2.0;
  76. setTempTo(valueFloat);
  77. //if (serialdebug)
  78. //{
  79. // Serial.print("MQTT: received '");
  80. // Serial.print(mqtt_topic_in_setTemp);
  81. // Serial.print("' - '");
  82. // Serial.print(cmdPayload);
  83. // Serial.println("'");
  84. //}
  85. //if (mqttdebug)
  86. //{
  87. // sprintf(tmp_topic_pub, "%s/%s", confMqtt.mqtt_topic_out, "mqtt_received");
  88. // sprintf(tmp_payload_pub, "%s: %s", mqtt_topic_in_setTemp, cmdPayload);
  89. // mqttclient.publish(tmp_topic_pub, tmp_payload_pub);
  90. //}
  91. char buf[50];
  92. sprintf(buf, "MQTT IN: setTemp to %2.1f", valueFloat);
  93. sendLog(buf, LOGLEVEL_INFO);
  94. cmdInQueue = false; // payload is processed in "commands"
  95. } //if topic = mqtt_topic_in_setTemp
  96. if (strcmp(topic, mqtt_topic_in_setMode) == 0)
  97. { //if topic = mqtt_topic_in_setMode
  98. uint8_t len;
  99. if (length < sizeof(cmdPayload))
  100. len = length; // if input is bigger than dest buffer, cut
  101. else
  102. len = sizeof(cmdPayload) - 1;
  103. for (int i = 0; i < len; i++)
  104. {
  105. cmdPayload[i] = (char)payload[i];
  106. }
  107. //cmdPayload[len + 1] = '\0';
  108. cmdPayload[len] = '\0';
  109. // Serial.print("cmdPayload:");
  110. // Serial.println(cmdPayload);
  111. char tmpPayload[21];
  112. strlcpy(tmpPayload, cmdPayload, sizeof(tmpPayload));
  113. strlwr(tmpPayload);
  114. unsigned char tmpHeatMode = 100;
  115. char tmpModename0[15];
  116. char tmpModename1[15];
  117. strlcpy(tmpModename0, confAdv.modeName0, sizeof(tmpModename0));
  118. strlcpy(tmpModename1, confAdv.modeName1, sizeof(tmpModename1));
  119. strlwr(tmpModename0);
  120. strlwr(tmpModename1);
  121. if (strcmp(tmpPayload, tmpModename0) == 0)
  122. tmpHeatMode = 0;
  123. else if (strcmp(tmpPayload, tmpModename1) == 0)
  124. tmpHeatMode = 1;
  125. else if (strcmp(tmpPayload, "off") == 0)
  126. tmpHeatMode = 0;
  127. else if (strcmp(tmpPayload, "aus") == 0)
  128. tmpHeatMode = 0;
  129. else if (strcmp(tmpPayload, "on") == 0)
  130. tmpHeatMode = 1;
  131. else if (strcmp(tmpPayload, "ein") == 0)
  132. tmpHeatMode = 1;
  133. else if (strcmp(tmpPayload, "heat") == 0)
  134. tmpHeatMode = 1;
  135. else if (atoi(tmpPayload) == 0)
  136. tmpHeatMode = 0;
  137. else if (atoi(tmpPayload) == 1)
  138. tmpHeatMode = 1;
  139. if (tmpHeatMode == 0 || tmpHeatMode == 1)
  140. {
  141. setHeatingmodeTo(tmpHeatMode);
  142. //if (serialdebug)
  143. //{
  144. // Serial.print(F("set heatmode to: "));
  145. // Serial.println(tmpHeatMode);
  146. //}
  147. //if (serialdebug)
  148. //{
  149. // Serial.print("MQTT: received '");
  150. // Serial.print(mqtt_topic_in_setMode);
  151. // Serial.print("' - '");
  152. // Serial.print(cmdPayload);
  153. // Serial.println("'");
  154. //}
  155. //if (mqttdebug)
  156. //{
  157. // sprintf(tmp_topic_pub, "%s/%s", confMqtt.mqtt_topic_out, "mqtt_received");
  158. // sprintf(tmp_payload_pub, "%s: %s", mqtt_topic_in_setMode, cmdPayload);
  159. // mqttclient.publish(tmp_topic_pub, tmp_payload_pub);
  160. //}
  161. char buf[50];
  162. sprintf(buf, "MQTT IN: setMode to %u", tmpHeatMode);
  163. sendLog(buf, LOGLEVEL_INFO);
  164. }
  165. cmdInQueue = false; // payload is processed in "commands"
  166. } //if topic = mqtt_topic_in_setMode
  167. if (strcmp(topic, mqtt_topic_in_setPause) == 0)
  168. { //if topic = mqtt_topic_in_setMode
  169. uint8_t len;
  170. uint8_t _setTo = 255;
  171. if (length < sizeof(cmdPayload))
  172. len = length; // if input is bigger than dest buffer, cut
  173. else
  174. len = sizeof(cmdPayload) - 1;
  175. for (int i = 0; i < len; i++)
  176. {
  177. cmdPayload[i] = (char)payload[i];
  178. }
  179. //cmdPayload[len + 1] = '\0';
  180. cmdPayload[len] = '\0';
  181. // Serial.print("cmdPayload:");
  182. // Serial.println(cmdPayload);
  183. char tmpPayload[21];
  184. strlcpy(tmpPayload, cmdPayload, sizeof(tmpPayload));
  185. strlwr(tmpPayload);
  186. if (strcmp(tmpPayload, "1") == 0) _setTo = 1;
  187. else if (strcmp(tmpPayload, "0") == 0) _setTo = 0;
  188. if(_setTo == 1 || _setTo == 0) {
  189. setHeatingPause(_setTo);
  190. char buf[50];
  191. sprintf(buf, "MQTT IN: setPause to %u", _setTo);
  192. sendLog(buf, LOGLEVEL_INFO);
  193. }
  194. cmdInQueue = false; // payload is processed in "commands"
  195. } //if topic = mqtt_topic_in_setPause
  196. if (strcmp(topic, mqtt_topic_in_setPreset) == 0)
  197. { //if topic = mqtt_topic_in_setPreset
  198. char tmpPayload[21];
  199. char tmpPresetName0[15];
  200. char tmpPresetName1[15];
  201. char tmpPresetName2[15];
  202. uint16_t len;
  203. unsigned char tmpPreset = 100;
  204. if (length < sizeof(cmdPayload))
  205. len = length; // if input is bigger than dest buffer, cut
  206. else
  207. len = sizeof(cmdPayload) - 1;
  208. for (unsigned char i = 0; i < len; i++)
  209. {
  210. cmdPayload[i] = (char)payload[i];
  211. }
  212. //cmdPayload[len + 1] = '\0';
  213. cmdPayload[len] = '\0';
  214. // Serial.print("cmdPayload:");
  215. // Serial.println(cmdPayload);
  216. strlcpy(tmpPayload, cmdPayload, sizeof(tmpPayload));
  217. strlwr(tmpPayload);
  218. strlcpy(tmpPresetName0, confAdv.psetName0, sizeof(tmpPresetName0));
  219. strlcpy(tmpPresetName1, confAdv.psetName1, sizeof(tmpPresetName1));
  220. strlcpy(tmpPresetName2, confAdv.psetName2, sizeof(tmpPresetName2));
  221. strlwr(tmpPresetName0);
  222. strlwr(tmpPresetName1);
  223. strlwr(tmpPresetName2);
  224. if (strcmp(tmpPayload, tmpPresetName0) == 0)
  225. tmpPreset = 0;
  226. else if (strcmp(tmpPayload, tmpPresetName1) == 0)
  227. tmpPreset = 1;
  228. else if (strcmp(tmpPayload, tmpPresetName2) == 0)
  229. tmpPreset = 2;
  230. else if (strcmp(tmpPayload, "none") == 0)
  231. tmpPreset = 0;
  232. else if (strcmp(tmpPayload, "norm") == 0)
  233. tmpPreset = 0;
  234. else if (strcmp(tmpPayload, "red1") == 0)
  235. tmpPreset = 1;
  236. else if (strcmp(tmpPayload, "red2") == 0)
  237. tmpPreset = 2;
  238. else if (atoi(tmpPayload) == 0)
  239. tmpPreset = 0;
  240. else if (atoi(tmpPayload) == 1)
  241. tmpPreset = 1;
  242. else if (atoi(tmpPayload) == 2)
  243. tmpPreset = 2;
  244. if (tmpPreset <= 2)
  245. {
  246. setPresetTo(tmpPreset);
  247. //if (serialdebug)
  248. //{
  249. // Serial.print(F("set preset to: "));
  250. // Serial.println(tmpPreset);
  251. //}
  252. //if (serialdebug)
  253. //{
  254. // Serial.print(F("MQTT: received '"));
  255. // Serial.print(mqtt_topic_in_setPreset);
  256. // Serial.print("' - '");
  257. // Serial.print(cmdPayload);
  258. // Serial.println("'");
  259. //}
  260. //if (mqttdebug)
  261. //{
  262. // sprintf(tmp_topic_pub, "%s/%s", confMqtt.mqtt_topic_out, "mqtt_received");
  263. // sprintf(tmp_payload_pub, "%s: %s", mqtt_topic_in_setPreset, cmdPayload);
  264. // mqttclient.publish(tmp_topic_pub, tmp_payload_pub);
  265. //}
  266. char buf[50];
  267. sprintf(buf, "MQTT IN: setPreset to %s", cmdPayload);
  268. sendLog(buf, LOGLEVEL_INFO);
  269. }
  270. cmdInQueue = false; // payload is processed in "commands"
  271. } //if topic = mqtt_topic_in_setPreset
  272. if (strcmp(topic, confAdd.outTemp_topic_in) == 0)
  273. { //if topic = outTemp_topic_in
  274. int len;
  275. if (length < 6)
  276. len = length; // if input is bigger than dest buffer, cut
  277. else
  278. len = 5;
  279. for (int i = 0; i < len; i++)
  280. {
  281. outTemp_newValue[i] = (char)payload[i];
  282. }
  283. //outTemp_newValue[len + 1] = '\0';
  284. outTemp_newValue[len] = '\0';
  285. outTemp_parseNewValue = true;
  286. } //if topic = outTemp_topic_in
  287. if (strcmp(topic, confAdd.outHum_topic_in) == 0)
  288. { //if topic = outHum_topic_in
  289. int len;
  290. if (length < 4)
  291. len = length; // if input is bigger than dest buffer, cut
  292. else
  293. len = 3;
  294. for (int i = 0; i < len; i++)
  295. {
  296. outHum_newValue[i] = (char)payload[i];
  297. }
  298. //outHum_newValue[len + 1] = '\0';
  299. outHum_newValue[len] = '\0';
  300. outHum_parseNewValue = true;
  301. } //if topic = outHum_topic_in
  302. } //mqttCallback
  303. void mqttPrepareSubscribeTopics()
  304. {
  305. //char tmp_topic_out[50];
  306. sprintf(mqtt_topic_in_cmd, "%s/%s", confMqtt.mqtt_topic_in, "cmd");
  307. sprintf(mqtt_topic_in_setTemp, "%s/%s", mqtt_topic_in_cmd, "setTemp");
  308. sprintf(mqtt_topic_in_setMode, "%s/%s", mqtt_topic_in_cmd, "setMode");
  309. sprintf(mqtt_topic_in_setPreset, "%s/%s", mqtt_topic_in_cmd, "setPreset");
  310. sprintf(mqtt_topic_in_setPause, "%s/%s", mqtt_topic_in_cmd, "setPause");
  311. }
  312. bool mqttReconnect(void)
  313. {
  314. mqttclient.disconnect();
  315. delay(10);
  316. // Create MQTT client ID from device name
  317. //String mqttClientId = "ESP8266Client-";
  318. String mqttClientId = FIRMWARE_SHORTNAME;
  319. mqttClientId += "-";
  320. //mqttClientId += String(random(0xffff), HEX); //or random
  321. mqttClientId += String(confDevWiFi.deviceName);
  322. //if (serialdebug)
  323. // Serial.print(F("MQTT: connecting to broker '"));
  324. // Serial.print(confMqtt.mqtt_server);
  325. // Serial.print(F("' with "));
  326. boolean connRes;
  327. mqttReconnectAttempts++;
  328. char connectMode[20];
  329. if (strlen(confMqtt.mqtt_user) > 0 && strlen(confMqtt.mqtt_willTopic) == 0)
  330. {
  331. // user and password, no Last Will
  332. //if (serialdebug)
  333. // Serial.print(F("Auth, no LWT"));
  334. strlcpy(connectMode, "Auth, no LWT", sizeof(connectMode));
  335. connRes = mqttclient.connect(mqttClientId.c_str(), confMqtt.mqtt_user, confMqtt.mqtt_pass);
  336. }
  337. else if (strlen(confMqtt.mqtt_user) > 0 && strlen(confMqtt.mqtt_willTopic) > 0)
  338. {
  339. // user, password and Last Will
  340. //if (serialdebug)
  341. // Serial.print(F("Auth and LWT"));
  342. strlcpy(connectMode, "Auth and LWT", sizeof(connectMode));
  343. connRes = mqttclient.connect(mqttClientId.c_str(), confMqtt.mqtt_user, confMqtt.mqtt_pass, confMqtt.mqtt_willTopic, confMqtt.mqtt_willQos, confMqtt.mqtt_willRetain, confMqtt.mqtt_willMsg);
  344. }
  345. else if (strlen(confMqtt.mqtt_user) == 0 && strlen(confMqtt.mqtt_willTopic) > 0)
  346. {
  347. // Last Will but no user and password
  348. //if (serialdebug)
  349. // Serial.print(F("LWT, no Auth"));
  350. strlcpy(connectMode, "LWT, no Auth", sizeof(connectMode));
  351. connRes = mqttclient.connect(mqttClientId.c_str(), confMqtt.mqtt_willTopic, confMqtt.mqtt_willQos, confMqtt.mqtt_willRetain, confMqtt.mqtt_willMsg);
  352. }
  353. else
  354. {
  355. // no user, password and no Last Will
  356. //if (serialdebug)
  357. // Serial.print(F("no Auth, no LWT"));
  358. strlcpy(connectMode, "no Auth, no LWT", sizeof(connectMode));
  359. connRes = mqttclient.connect(mqttClientId.c_str());
  360. }
  361. //if (serialdebug)
  362. //{
  363. // Serial.print(F(", attempt: "));
  364. // Serial.print(mqttReconnectAttempts);
  365. // Serial.println();
  366. //}
  367. char logBuf[70];
  368. sprintf(logBuf, "MQTT: connecting to %s:%u w/ %s, attempt: %u", confMqtt.mqtt_server, confMqtt.mqtt_port, connectMode, mqttReconnectAttempts);
  369. sendLog(logBuf, LOGLEVEL_INFO);
  370. if (connRes)
  371. { // if connection was successful
  372. // if (serialdebug)
  373. // {
  374. // Serial.print(F("MQTT: connected. Reconnects: "));
  375. // Serial.println(mqttReconnects);
  376. // }
  377. //char logBuf2[50];
  378. //sprintf(logBuf2, "MQTT: connected to %s:%u, Reconnects: %u", confMqtt.mqtt_server, confMqtt.mqtt_port, mqttReconnects);
  379. //sendLog(logBuf2, LOGLEVEL_INFO);
  380. //sendLog(F("MQTT: connected. Reconnects: "), LOGLEVEL_INFO);
  381. mqttConnected = true;
  382. mqttReconnects++;
  383. mqttOnConnect();
  384. //if (serialdebug)
  385. //Serial.println("MQTT: subscribed topics:");
  386. sendLog("MQTT: subscribed topics:", LOGLEVEL_INFO);
  387. if (strlen(mqtt_topic_in_cmd) > 0)
  388. {
  389. char mqtt_topic_in_subscribe[52];
  390. sprintf(mqtt_topic_in_subscribe, "%s/%s", mqtt_topic_in_cmd, "#");
  391. if (mqttclient.subscribe(mqtt_topic_in_subscribe))
  392. {
  393. //if (serialdebug) {
  394. // Serial.print(" ");
  395. // Serial.println(mqtt_topic_in_subscribe);
  396. //}
  397. char buf[60];
  398. sprintf(buf, " %s", mqtt_topic_in_subscribe);
  399. sendLog(buf, LOGLEVEL_INFO);
  400. mqttInTopicSubscribed = true;
  401. }
  402. }
  403. if (strlen(confAdd.outTemp_topic_in) > 0)
  404. {
  405. if (mqttclient.subscribe(confAdd.outTemp_topic_in))
  406. {
  407. //if (serialdebug) {
  408. // Serial.print(" ");
  409. // Serial.println(confAdd.outTemp_topic_in);
  410. //}
  411. char buf[60];
  412. sprintf(buf, " %s", confAdd.outTemp_topic_in);
  413. sendLog(buf, LOGLEVEL_INFO);
  414. }
  415. }
  416. if (strlen(confAdd.outHum_topic_in) > 0)
  417. {
  418. if (mqttclient.subscribe(confAdd.outHum_topic_in))
  419. {
  420. //if (serialdebug) {
  421. // Serial.print(" ");
  422. // Serial.println(confAdd.outHum_topic_in);
  423. //}
  424. char buf[60];
  425. sprintf(buf, " %s", confAdd.outHum_topic_in);
  426. sendLog(buf, LOGLEVEL_INFO);
  427. }
  428. }
  429. mqttReconnectAttempts = 0;
  430. return mqttclient.connected();
  431. }
  432. else
  433. {
  434. int mqttConnRes = mqttclient.state();
  435. char logBuf[70];
  436. mqtt_updateCurrentStateName();
  437. sprintf_P(logBuf, "%s: %s, rc=%d (%s)", PGMStr_MQTT, PGMStr_connectedFailed, mqttConnRes, mqttCurrentStateName);
  438. sendLog(logBuf, LOGLEVEL_INFO);
  439. if (mqttReconnectAttempts >= 3 && (mqttConnRes == 4 || mqttConnRes == 5))
  440. {
  441. // MQTT credentials are invalid/rejected from the server - stop trying to reconnect until reboot
  442. mqtt_tempDisabled_credentialError = true;
  443. if (confLog.logLevelSerial >= LOGLEVEL_VERBOSE)
  444. {
  445. //Serial.println(F("MQTT disabled until reboot due to credential error"));
  446. sendLog(F("MQTT disabled until reboot due to credential error"), LOGLEVEL_ERROR);
  447. }
  448. }
  449. mqttConnected = false;
  450. mqttOnDisconnect();
  451. return mqttclient.connected();
  452. }
  453. } //mqttReconnect
  454. void mqttClientInit()
  455. {
  456. if (confMqtt.mqtt_enable)
  457. {
  458. mqttclient.setServer(confMqtt.mqtt_server, confMqtt.mqtt_port);
  459. mqttclient.setCallback(mqttCallback);
  460. mqttLastReconnectAttempt = 0;
  461. mqttReconnectAttempts = 0;
  462. mqtt_tempDisabled_credentialError = false;
  463. }
  464. }
  465. int lastWifiStatus;
  466. void mqttHandleConnection()
  467. {
  468. if (mqttHeartbeatReceived)
  469. {
  470. mqttHeartbeatReceived = false;
  471. sendLog(F("MQTT: received HEARTBEAT - resetting timer..."), LOGLEVEL_VERBOSE);
  472. }
  473. int currWifiStatus = WiFi.status();
  474. if (currWifiStatus != lastWifiStatus)
  475. {
  476. lastWifiStatus = currWifiStatus;
  477. //Serial.print("WiFi status changed to: ");
  478. //Serial.println(currWifiStatus);
  479. }
  480. if (confMqtt.mqtt_enable && !mqtt_tempDisabled_credentialError && currWifiStatus == WL_CONNECTED)
  481. {
  482. // MQTT reconnect if not connected (nonblocking)
  483. boolean doReconnect = false;
  484. if (!mqttclient.connected())
  485. doReconnect = true;
  486. if (mqttInTopicSubscribed && confMqtt.mqtt_heartbeat_maxage_reconnect > 0)
  487. { // if mqtt_topic_in is subscribed
  488. if (confMqtt.mqtt_enable_heartbeat && confMqtt.mqtt_heartbeat_maxage_reconnect > 0 && ((millis() - mqttLastHeartbeat) > confMqtt.mqtt_heartbeat_maxage_reconnect))
  489. { // also reconnect if no HEARTBEAT was received for some time
  490. doReconnect = true;
  491. mqttConnected = false;
  492. mqttLastHeartbeat = millis();
  493. //Serial.println(F("MQTT: HEARTBEAT overdue. Force-Reconnecting MQTT..."));
  494. sendLog(F("MQTT: HEARTBEAT overdue. Force-Reconnecting MQTT..."), LOGLEVEL_WARN);
  495. }
  496. }
  497. if (doReconnect)
  498. {
  499. unsigned long mqttReconnectAttemptDelay;
  500. if (mqttReconnectAttempts < 3)
  501. mqttReconnectAttemptDelay = MQTT_RECONNECT_INTERVAL_3_TRIES; // if this is the 1-3rd attempt, try again in 15s
  502. else if (mqttReconnectAttempts < 10)
  503. mqttReconnectAttemptDelay = MQTT_RECONNECT_INTERVAL_10_TRIES; // if more than 3 attempts failed, try again every min
  504. else
  505. mqttReconnectAttemptDelay = MQTT_RECONNECT_INTERVAL_LONG; // if more than 10 attempts failed, try again every 5 min
  506. if (confMqtt.mqtt_enable_heartbeat && confMqtt.mqtt_heartbeat_maxage_reboot > 0 && ((millis() - mqttLastHeartbeat) > confMqtt.mqtt_heartbeat_maxage_reboot))
  507. {
  508. // if no heartbeat was received for set time, reboot the ESP
  509. //Serial.println(F("MQTT: HEARTBEAT_MAXAGE_REBOOT overdue. Restarting..."));
  510. sendLog(F("MQTT: HEARTBEAT_MAXAGE_REBOOT overdue. Restarting..."), LOGLEVEL_WARN);
  511. restart();
  512. }
  513. if ((millis() - mqttLastReconnectAttempt) > mqttReconnectAttemptDelay)
  514. {
  515. mqttLastReconnectAttempt = millis();
  516. //#ifdef USE_MQTT_TLS
  517. // verifytls();
  518. //#endif
  519. mqttReconnect();
  520. }
  521. mqttclient.loop();
  522. }
  523. else
  524. {
  525. mqttclient.loop();
  526. }
  527. }
  528. }
  529. void mqttPublishStatus()
  530. {
  531. if (confMqtt.mqtt_enable && mqttclient.state() == 0)
  532. {
  533. char outMsg[60];
  534. sprintf_P(outMsg, "%s: %s: %s:%u, %s: %d", PGMStr_MQTT, PGMStr_connectedTo, confMqtt.mqtt_server, confMqtt.mqtt_port, PGMStr_reconnects, mqttReconnects - 1);
  535. //mqttclient.publish(confMqtt.mqtt_topic_out, outMsg, confMqtt.mqtt_outRetain);
  536. sendLog(outMsg, LOGLEVEL_INFO);
  537. }
  538. }
  539. void mqttOnConnect()
  540. {
  541. mqttPublishConnectMsg();
  542. mqttPublishStatus();
  543. displayShowMQTTConnected();
  544. }
  545. void mqttOnDisconnect()
  546. {
  547. displayShowMQTTConnectionError();
  548. }
  549. void mqttPublishConnectMsg()
  550. {
  551. if (strlen(confMqtt.mqtt_willTopic) > 4)
  552. {
  553. if (confMqtt.mqtt_enable && mqttclient.state() == 0)
  554. {
  555. mqttclient.publish(confMqtt.mqtt_willTopic, confMqtt.mqtt_connMsg, confMqtt.mqtt_willRetain);
  556. //sendLog(F("MQTT: connected"), LOGLEVEL_INFO);
  557. }
  558. }
  559. }
  560. void mqttPublishHeartbeat()
  561. {
  562. if (confMqtt.mqtt_enable && confMqtt.mqtt_enable_heartbeat && mqttclient.state() == 0)
  563. {
  564. mqttclient.publish(mqtt_topic_in_cmd, "HEARTBEAT", false); // publishes to IN-topic. MQTT will force-reconnect if it does not get a HEARTBEAT for 2 min
  565. }
  566. }
  567. void mqtt_updateCurrentStateName()
  568. {
  569. if (confMqtt.mqtt_enable)
  570. {
  571. sprintf_P(mqttCurrentStateName, "%s", PGMStr_MQTTStates[mqttclient.state() + 4]);
  572. }
  573. else
  574. sprintf_P(mqttCurrentStateName, "%s", PGMStr_MQTTState_DIS);
  575. }
  576. void mqttResetConnection()
  577. {
  578. sendLog(F("MQTT: resetting connection..."));
  579. if (!confMqtt.mqtt_enable)
  580. mqttclient.disconnect();
  581. else
  582. {
  583. mqttclient.disconnect();
  584. mqttPrepareSubscribeTopics();
  585. mqttClientInit();
  586. }
  587. configChangedMqttConnResetRequired = false;
  588. }