|
@@ -1,72 +1,71 @@
|
|
|
|
|
|
// MQTT callback
|
|
|
void mqttCallback(char* topic, byte* payload, unsigned int length) {
|
|
|
-// Serial.print("Message arrived [");
|
|
|
-// Serial.print(topic);
|
|
|
-// Serial.print("] ");
|
|
|
-// for (int i = 0; i < length; i++) {
|
|
|
-// Serial.print((char)payload[i]);
|
|
|
-// }
|
|
|
-// Serial.println();
|
|
|
+ // 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);
|
|
|
|
|
|
- for (int i = 0; i < length; i++) {
|
|
|
+ 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[length + 1] = '\0';
|
|
|
-
|
|
|
- Serial.print("cmdPayload:");
|
|
|
- Serial.println(cmdPayload);
|
|
|
-
|
|
|
- cmdInQueue = true;
|
|
|
-
|
|
|
+ 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
|
|
|
- char inValue[length + 1];
|
|
|
- for (int i = 0; i < length; i++) {
|
|
|
- inValue[i] = (char)payload[i];
|
|
|
+ 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];
|
|
|
}
|
|
|
- inValue[sizeof(inValue) - 1] = '\0';
|
|
|
- //Serial.print(inValue);
|
|
|
- //Serial.println();
|
|
|
- float invalueFloat = atof(inValue);
|
|
|
- outTemp = invalueFloat;
|
|
|
- outTempHumLastUpdate = millis();
|
|
|
- Serial.print("atemp=");
|
|
|
- Serial.println(invalueFloat);
|
|
|
+ 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
|
|
|
- char inValue[length + 1];
|
|
|
- for (int i = 0; i < length; i++) {
|
|
|
- inValue[i] = (char)payload[i];
|
|
|
+ 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];
|
|
|
}
|
|
|
- inValue[sizeof(inValue) - 1] = '\0';
|
|
|
- //Serial.print(inValue);
|
|
|
- //Serial.println();
|
|
|
- outHum = atoi(inValue);
|
|
|
- outTempHumLastUpdate = millis();
|
|
|
- Serial.print("ahum=");
|
|
|
- Serial.println(inValue);
|
|
|
+ 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 ) {
|
|
|
- for (int i = 0; i < length; i++) {
|
|
|
+ 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[length + 1] = '\0';
|
|
|
+ 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) {
|
|
@@ -91,26 +90,28 @@ void mqttPrepareConnection() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-boolean mqttReconnect() {
|
|
|
+bool mqttReconnect() {
|
|
|
+ mqttclient.disconnect();
|
|
|
+ delay(10);
|
|
|
// Create a random MQTT client ID
|
|
|
String mqttClientId = "ESP8266Client-";
|
|
|
mqttClientId += String(random(0xffff), HEX);
|
|
|
|
|
|
- Serial.print("MQTT - connecting with ");
|
|
|
+ Serial.print("connecting to MQTT broker with ");
|
|
|
|
|
|
- boolean connRes;
|
|
|
+ bool connRes;
|
|
|
|
|
|
switch (mqttMode) {
|
|
|
case 1:
|
|
|
- Serial.println("no user, password and no Last Will");
|
|
|
+ Serial.print("no user, password and no Last Will");
|
|
|
connRes = mqttclient.connect(mqttClientId.c_str());
|
|
|
break;
|
|
|
case 2:
|
|
|
- Serial.println("user and password, no Last Will");
|
|
|
+ Serial.print("user and password, no Last Will");
|
|
|
connRes = mqttclient.connect(mqttClientId.c_str(), mqtt_user, mqtt_pass);
|
|
|
break;
|
|
|
case 3:
|
|
|
- Serial.println("user, password and Last Will");
|
|
|
+ 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:
|
|
@@ -119,6 +120,10 @@ boolean mqttReconnect() {
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
+ Serial.print("... attempt: ");
|
|
|
+ Serial.print(mqttReconnectAttempts);
|
|
|
+ Serial.println();
|
|
|
+
|
|
|
if (connRes) {
|
|
|
Serial.print("MQTT connected. Reconnects: ");
|
|
|
Serial.println(mqttReconnects);
|
|
@@ -135,6 +140,7 @@ boolean mqttReconnect() {
|
|
|
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) {
|
|
@@ -153,6 +159,10 @@ boolean mqttReconnect() {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ else {
|
|
|
+ Serial.print("MQTT connect FAILED, rc=");
|
|
|
+ Serial.println(mqttclient.state());
|
|
|
+ }
|
|
|
return mqttclient.connected();
|
|
|
} //mqttReconnect
|
|
|
|
|
@@ -162,29 +172,50 @@ void mqttClientInit() {
|
|
|
mqttclient.setServer(mqtt_server, mqtt_port);
|
|
|
mqttclient.setCallback(mqttCallback);
|
|
|
mqttLastReconnectAttempt = 0;
|
|
|
+ mqttReconnectAttempts = 0;
|
|
|
}
|
|
|
|
|
|
+int lastWifiStatus;
|
|
|
+
|
|
|
void mqttHandleConnection() {
|
|
|
- if ( WiFi.status() == WL_CONNECTED ) {
|
|
|
+ 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)
|
|
|
- if (!mqttclient.connected()) {
|
|
|
- long now = millis();
|
|
|
+ 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...");
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- int mqttReconnectAttemptDelay;
|
|
|
- if(mqttReconnectAttempts <= 3) mqttReconnectAttemptDelay = 15000; // if this is the 1-3rd attempt, try again in 15s
|
|
|
- else mqttReconnectAttemptDelay = 300000; // if more than 3 attempts failed, try again every 5 min
|
|
|
+ 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 (now - mqttLastReconnectAttempt > mqttReconnectAttemptDelay) {
|
|
|
- mqttLastReconnectAttempt = now;
|
|
|
+ if ((millis() - mqttLastReconnectAttempt) > mqttReconnectAttemptDelay) {
|
|
|
+ mqttLastReconnectAttempt = millis();
|
|
|
mqttReconnectAttempts++;
|
|
|
if (mqttReconnect()) { // Attempt to reconnect
|
|
|
// attempt successful - reset mqttReconnectAttempts
|
|
|
- mqttReconnectAttempts=0;
|
|
|
+ mqttReconnectAttempts = 0;
|
|
|
}
|
|
|
}
|
|
|
- } else { // Client connected
|
|
|
mqttclient.loop();
|
|
|
- }//else
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ mqttclient.loop();
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -193,13 +224,15 @@ void publishStatus() {
|
|
|
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);
|
|
|
- if (mqttclient.connected()) mqttclient.publish(mqtt_topic_out, buf, mqtt_outRetain);
|
|
|
+ mqttclient.publish(mqtt_topic_out, buf, mqtt_outRetain);
|
|
|
+ yield();
|
|
|
}
|
|
|
|
|
|
void publishCurrentThermostatValues() {
|
|
@@ -227,29 +260,35 @@ void publishCurrentThermostatValues() {
|
|
|
|
|
|
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() {
|
|
@@ -266,12 +305,14 @@ void publishCurrentSensorValues() {
|
|
|
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);
|
|
@@ -281,22 +322,24 @@ void publishCurrentSensorValues() {
|
|
|
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) {
|
|
|
+ if (PIRSensorOn) {
|
|
|
strcpy(PIRStatus, "on");
|
|
|
}
|
|
|
else {
|
|
@@ -304,4 +347,9 @@ void publishCurrentPIRValue() {
|
|
|
}
|
|
|
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
|
|
|
+}
|
|
|
+
|
|
|
|