// MQTT callback void mqttCallback(char* topic, byte* payload, unsigned int length) { // Serial.print("MQTT payload arrived ["); // Serial.print(topic); // Serial.print("] "); // for (int i = 0; i < length; i++) { // Serial.print((char)payload[i]); // } // Serial.println(); if (strcmp(topic, mqtt_topic_in) == 0) { //if topic = mqtt_topic_in Serial.print("received MQTT "); Serial.println(mqtt_topic_in); int len; if (length < 101) len = length; // if input is bigger than dest buffer, cut else len = 100; for (int i = 0; i < len; i++) { cmdPayload[i] = (char)payload[i]; } cmdPayload[len + 1] = '\0'; // Serial.print("cmdPayload:"); // Serial.println(cmdPayload); cmdInQueue = true; // payload is processed in "commands" }//if topic = mqtt_topic_in if (strcmp(topic, outTemp_topic_in) == 0) { //if topic = outTemp_topic_in int len; if (length < 6) len = length; // if input is bigger than dest buffer, cut else len = 5; for (int i = 0; i < len; i++) { outTemp_newValue[i] = (char)payload[i]; } outTemp_newValue[len + 1] = '\0'; outTemp_parseNewValue = true; }//if topic = outTemp_topic_in if (strcmp(topic, outHum_topic_in) == 0) { //if topic = outHum_topic_in int len; if (length < 4) len = length; // if input is bigger than dest buffer, cut else len = 3; for (int i = 0; i < len; i++) { outHum_newValue[i] = (char)payload[i]; } outHum_newValue[len + 1] = '\0'; outHum_parseNewValue = true; }//if topic = outHum_topic_in if (strcmp(topic, domoticz_out_topic) == 0) { //if topic = domoticz_out_topic Serial.print("received MQTT "); Serial.println(domoticz_out_topic); if ( !domoticzOutParserBusy ) { int len; if (length < 450) len = length; // if input is bigger than dest buffer, cut else len = 449; for (int i = 0; i < len; i++) { domoticzOutPayload[i] = (char)payload[i]; } domoticzOutPayload[len + 1] = '\0'; domoticzOutParseData = true; // parse domoticz data in the next loop() } }//if topic = domoticz_out_topic }//mqttCallback void mqttPrepareConnection() { Serial.print("MQTT connection with "); if (strlen(mqtt_user) > 0 && strlen(mqtt_willTopic) == 0) { // user and password, no Last Will Serial.println("user and password, no Last Will"); mqttMode = 2; } else if (strlen(mqtt_user) > 0 && strlen(mqtt_willTopic) > 0) { // user, password and Last Will Serial.println("user, password and Last Will"); mqttMode = 3; } else if (strlen(mqtt_user) == 0 && strlen(mqtt_willTopic) > 0) { // Last Will but no user and password Serial.println("Last Will but no user and password"); mqttMode = 4; } else { // no user, password and no Last Will Serial.println("no user, password and no Last Will"); mqttMode = 1; } } bool mqttReconnect() { mqttclient.disconnect(); delay(10); // Create a random MQTT client ID String mqttClientId = "ESP8266Client-"; mqttClientId += String(random(0xffff), HEX); Serial.print("connecting to MQTT broker with "); bool connRes; switch (mqttMode) { case 1: Serial.print("no user, password and no Last Will"); connRes = mqttclient.connect(mqttClientId.c_str()); break; case 2: Serial.print("user and password, no Last Will"); connRes = mqttclient.connect(mqttClientId.c_str(), mqtt_user, mqtt_pass); break; case 3: Serial.print("user, password and Last Will"); connRes = mqttclient.connect(mqttClientId.c_str(), mqtt_user, mqtt_pass, mqtt_willTopic, mqtt_willQos, mqtt_willRetain, mqtt_willMsg); break; case 4: Serial.println("Last Will, no user and password"); connRes = mqttclient.connect(mqttClientId.c_str(), mqtt_willTopic, mqtt_willQos, mqtt_willRetain, mqtt_willMsg); break; } Serial.print("... attempt: "); Serial.print(mqttReconnectAttempts); Serial.println(); if (connRes) { Serial.print("MQTT connected. Reconnects: "); Serial.println(mqttReconnects); mqttReconnects++; // Once connected, publish an announcement... // char outMsg[30]; // sprintf(outMsg, "connected, %d reconnects", mqttReconnects); // mqttclient.publish(mqtt_topic_out, outMsg, mqtt_outRetain); publishStatus(); //mqttclient.publish(mqtt_topic_out, "connected"); // ... and resubscribe Serial.println("Subscribed to:"); if (strlen(mqtt_topic_in) > 0) { if (mqttclient.subscribe(mqtt_topic_in)) { Serial.println(mqtt_topic_in); mqttInTopicSubscribed = true; } } if (strlen(outTemp_topic_in) > 0) { if (mqttclient.subscribe(outTemp_topic_in)) { Serial.println(outTemp_topic_in); } } if (strlen(outHum_topic_in) > 0) { if (mqttclient.subscribe(outHum_topic_in)) { Serial.println(outHum_topic_in); } } if (useDomoticz && strlen(domoticz_out_topic) > 0) { if (mqttclient.subscribe(domoticz_out_topic)) { Serial.println(domoticz_out_topic); } } } else { Serial.print("MQTT connect FAILED, rc="); Serial.println(mqttclient.state()); } return mqttclient.connected(); } //mqttReconnect void mqttClientInit() { mqttclient.setServer(mqtt_server, mqtt_port); mqttclient.setCallback(mqttCallback); mqttLastReconnectAttempt = 0; mqttReconnectAttempts = 0; } int lastWifiStatus; void mqttHandleConnection() { int currWifiStatus = WiFi.status(); if ( currWifiStatus != lastWifiStatus ) { lastWifiStatus = currWifiStatus; Serial.print("WiFi status changed to: "); Serial.println(currWifiStatus); } if ( currWifiStatus == WL_CONNECTED ) { // MQTT reconnect if not connected (nonblocking) bool doReconnect = false; if (!mqttclient.connected()) doReconnect = true; if (mqttInTopicSubscribed) { // if mqtt_topic_in is subscribed if ( (millis() - mqttLastHeartbeat) > MQTT_HEARTBEAT_MAXAGE) { // also reconnect if no HEARTBEAT was received for some time doReconnect = true; mqttLastHeartbeat = millis(); Serial.println("MQTT HEARTBEAT overdue. Force-Reconnecting MQTT..."); } } if (doReconnect) { unsigned int mqttReconnectAttemptDelay; if (mqttReconnectAttempts < 3) mqttReconnectAttemptDelay = 15000; // if this is the 1-3rd attempt, try again in 15s else mqttReconnectAttemptDelay = 60000; // if more than 3 attempts failed, try again in 1 min if ((millis() - mqttLastReconnectAttempt) > mqttReconnectAttemptDelay) { mqttLastReconnectAttempt = millis(); mqttReconnectAttempts++; if (mqttReconnect()) { // Attempt to reconnect // attempt successful - reset mqttReconnectAttempts mqttReconnectAttempts = 0; } } mqttclient.loop(); } else { mqttclient.loop(); } } } void publishStatus() { char outMsg[60]; long upTime = millis() / 1000; sprintf(outMsg, "connected, reconnects: %d, uptime: %d, free heap: %d", mqttReconnects - 1, upTime, ESP.getFreeHeap()); mqttclient.publish(mqtt_topic_out, outMsg, mqtt_outRetain); yield(); } void sendStatus(char* payload) { char buf[101]; strlcpy(buf, payload, 101); Serial.println(buf); mqttclient.publish(mqtt_topic_out, buf, mqtt_outRetain); yield(); } void publishCurrentThermostatValues() { char tmp_topic_out[50]; float curr_setTemp; if (heatingMode == 1) curr_setTemp = setTemp; else if (heatingMode == 2) curr_setTemp = setTempLow; char setTemp_chararr[6]; char currSetTemp_chararr[6]; dtostrf(setTemp, 1, 1, setTemp_chararr ); dtostrf(curr_setTemp, 1, 1, currSetTemp_chararr ); Serial.print("heatingMode: '"); Serial.print(heatingMode); Serial.println("'"); Serial.print("set temp: '"); Serial.print(setTemp_chararr); Serial.println("'"); Serial.print("current set temp: '"); Serial.print(currSetTemp_chararr); Serial.println("'"); sprintf(tmp_topic_out, "%s/%s", mqtt_topic_out, "setTemp"); mqttclient.publish(tmp_topic_out, setTemp_chararr); yield(); sprintf(tmp_topic_out, "%s/%s", mqtt_topic_out, "currSetTemp"); mqttclient.publish(tmp_topic_out, currSetTemp_chararr); yield(); sprintf(tmp_topic_out, "%s/%s", mqtt_topic_out, "heatingMode"); char heatingMode_chararr[3]; sprintf(heatingMode_chararr, "%d", heatingMode); mqttclient.publish(tmp_topic_out, heatingMode_chararr); yield(); char turnHeatingOn_char[5]; if (turnHeatingOn) strcpy(turnHeatingOn_char, "on"); else strcpy(turnHeatingOn_char, "off"); sprintf(tmp_topic_out, "%s/%s", mqtt_topic_out, "heating"); mqttclient.publish(tmp_topic_out, turnHeatingOn_char); yield(); char buf[101]; sprintf(buf, "%d", heatingOnTime); sprintf(tmp_topic_out, "%s/%s", mqtt_topic_out, "heatingOnTime"); mqttclient.publish(tmp_topic_out, buf); yield(); sprintf(buf, "%d", heatingOffTime); sprintf(tmp_topic_out, "%s/%s", mqtt_topic_out, "heatingOffTime"); mqttclient.publish(tmp_topic_out, buf); yield(); } void publishCurrentSensorValues() { if ( lastTempUpdate != 0 && (millis() - lastTempUpdate) < 120000 ) { char tmp_topic_out[50]; char temp_chararr[6]; char hum_chararr[4]; dtostrf(currTemp, 1, 1, temp_chararr ); sprintf(hum_chararr, "%2i", currHum); Serial.print("temp: '"); Serial.print(temp_chararr); Serial.println("'"); sprintf(tmp_topic_out, "%s/%s", mqtt_topic_out, "temp"); mqttclient.publish(tmp_topic_out, temp_chararr); yield(); Serial.print("hum: '"); Serial.print(currHum); Serial.println("'"); sprintf(tmp_topic_out, "%s/%s", mqtt_topic_out, "hum"); mqttclient.publish(tmp_topic_out, hum_chararr); yield(); dtostrf(currTemp_raw, 1, 1, temp_chararr ); sprintf(hum_chararr, "%2i", currHum_raw); Serial.print("temp_raw: '"); Serial.print(temp_chararr); Serial.println("'"); sprintf(tmp_topic_out, "%s/%s", mqtt_topic_out, "temp_raw"); mqttclient.publish(tmp_topic_out, temp_chararr); yield(); Serial.print("hum_raw: '"); Serial.print(currHum_raw); Serial.println("'"); sprintf(tmp_topic_out, "%s/%s", mqtt_topic_out, "hum_raw"); mqttclient.publish(tmp_topic_out, hum_chararr); yield(); } } void publishCurrentPIRValue() { char tmp_topic_out[50]; char PIRStatus[4]; sprintf(tmp_topic_out, "%s/%s", mqtt_topic_out, "PIR"); if (PIRSensorOn) { strcpy(PIRStatus, "on"); } else { strcpy(PIRStatus, "off"); } mqttclient.publish(tmp_topic_out, PIRStatus); } void mqttPublishHeartbeat() { mqttclient.publish(mqtt_topic_in, "HEARTBEAT"); // publishes to IN-topic. MQTT will force-reconnect if it does not get a HEARTBEAT for 2 min }