mqtt.ino 20 KB

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