Hi everyone,
A month ago, I decided I needed to update to new MQTT binding, and while it, I also decided to change the code in the ESP8266, to get rid of JSON, since I thought it was an unncessery step, (and I’m useless with json (primary driver) )
I have been running it for some weeks now without issues. I do have a heat pump without some features, so I have only tested the items that follows.
Posting it here, if anyone are interested in an alternative to the original (which works great).
The ino:
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include <PubSubClient.h>
#include <HeatPump.h>
#include "mitsubishi_heatpump_mqtt_esp8266.h"
#ifdef OTA
#include <ESP8266mDNS.h>
#include <ArduinoOTA.h>
#endif
// wifi, mqtt and heatpump client instances
WiFiClient espClient;
PubSubClient mqtt_client(espClient);
HeatPump hp;
unsigned long lastTempSend;
unsigned long lastRemoteTemp; //holds last time a remote temp value has been received from OpenHAB
unsigned long wifiMillis; //holds millis for counting up to hard reset for wifi reconnect
// debug mode, when true, will send all packets received from the heatpump to topic heatpump_debug_topic
// this can also be set by sending "on" to heatpump_debug_set_topic
bool _debugMode = false;
bool retain = true; //change to false to disable mqtt retain
void setup() {
pinMode(redLedPin, OUTPUT);
digitalWrite(redLedPin, HIGH);
pinMode(blueLedPin, OUTPUT);
digitalWrite(blueLedPin, HIGH);
WIFIConnect(); //connect to wifi
// configure mqtt connection
mqtt_client.setServer(mqtt_server, mqtt_port);
mqtt_client.setCallback(mqttCallback);
//mqttConnect(); //this is now called during loop
// connect to the heatpump. Callbacks first so that the hpPacketDebug callback is available for connect()
hp.setSettingsChangedCallback(hpSettingsChanged);
hp.setStatusChangedCallback(hpStatusChanged);
hp.setPacketCallback(hpPacketDebug);
#ifdef OTA
ArduinoOTA.begin();
#endif
hp.connect(&Serial);
lastTempSend = millis();
lastRemoteTemp = millis();
}
void hpSettingsChanged() {
char topic[128];
char payload[128];
heatpumpSettings currentSettings = hp.getSettings();
sprintf( topic, "%s/power", heatpump_topic);
mqtt_client.publish(topic, currentSettings.power.c_str(), retain);
sprintf( topic, "%s/mode", heatpump_topic);
mqtt_client.publish(topic, currentSettings.mode.c_str(), retain);
sprintf( payload, "%f", currentSettings.temperature );
sprintf( topic, "%s/temperature", heatpump_topic);
mqtt_client.publish(topic, payload, retain);
sprintf( topic, "%s/fan", heatpump_topic);
mqtt_client.publish(topic, currentSettings.fan.c_str(), retain);
sprintf( topic, "%s/vane", heatpump_topic);
mqtt_client.publish(topic, currentSettings.vane.c_str(), retain);
sprintf( topic, "%s/wideVane", heatpump_topic);
mqtt_client.publish(topic, currentSettings.wideVane.c_str(), retain);
sprintf( topic, "%s/iSee", heatpump_topic);
mqtt_client.publish(topic, currentSettings.iSee?"true":"false", retain);
}
void hpStatusChanged(heatpumpStatus currentStatus) {
char topic[128];
char payload[128];
sprintf( topic, "%s/operating", heatpump_status_topic);
mqtt_client.publish(topic, currentStatus.operating?"true":"false", retain);
sprintf( payload, "%f", currentStatus.roomTemperature );
sprintf( topic, "%s/temperature", heatpump_status_topic);
mqtt_client.publish(topic, payload, retain);
}
void hpPacketDebug(byte* packet, unsigned int length, char* packetDirection) {
if (_debugMode) {
String message;
for (int idx = 0; idx < length; idx++) {
if (packet[idx] < 16) {
message += "0"; // pad single hex digits with a 0
}
message += String(packet[idx], HEX) + " ";
}
const size_t bufferSize = JSON_OBJECT_SIZE(1);
DynamicJsonBuffer jsonBuffer(bufferSize);
JsonObject& root = jsonBuffer.createObject();
root[packetDirection] = message;
char buffer[512];
root.printTo(buffer, sizeof(buffer));
if(!mqtt_client.publish(heatpump_debug_topic, buffer)) {
mqtt_client.publish(heatpump_debug_topic, "failed to publish to heatpump/debug topic");
}
}
}
void mqttCallback(char* topic, byte* payload_b, unsigned int length) {
bool understood = true;
char payload[length + 1];
for (int i = 0; i < length; i++) // Copy payload into message buffer with null termination
payload[i] = (char)payload_b[i];
payload[length] = '\0';
// mqtt_client.publish( heatpump_debug_topic, topic, false );
// mqtt_client.publish( heatpump_debug_topic, payload, false );
if ( strstr( topic, "power" ))
hp.setPowerSetting( (String) payload );
else if ( strstr( topic, "mode" ))
hp.setModeSetting( payload );
else if ( strstr( topic, "temperature" ))
{
float temp = strtof( payload, NULL );
hp.setTemperature( temp );
}
else if ( strstr( topic, "fan" ))
hp.setFanSpeed( payload );
else if ( strstr( topic, "vane" ))
hp.setVaneSetting( payload );
else if ( strstr( topic, "wideVane" ))
hp.setWideVaneSetting( payload );
else understood = false;
if ( understood )
if ( !hp.update() )
mqtt_client.publish(heatpump_debug_topic, "heatpump: update() failed");
}
void mqttConnect() {
// Loop until we're reconnected
while (!mqtt_client.connected()) {
// Attempt to connect
if (mqtt_client.connect(client_id, mqtt_username, mqtt_password)) {
mqtt_client.subscribe(heatpump_set_topic);
mqtt_client.subscribe(heatpump_debug_set_topic);
} else {
// Wait 5 seconds before retrying
delay(5000);
if (WiFi.status() !=WL_CONNECTED) //reconnect wifi
{
WIFIConnect();
}
}
}
}
void WIFIConnect() { //wifi reconnect
WiFi.disconnect();
WiFi.mode(WIFI_STA); //set to not broadcast ssid
WiFi.begin(ssid, password);
wifiMillis = millis(); //start "timer"
while (WiFi.status() != WL_CONNECTED) { //sit here indefinitely trying to connect
// wait 500ms, flashing the blue LED to indicate WiFi connecting...
digitalWrite(blueLedPin, LOW);
delay(250);
digitalWrite(blueLedPin, HIGH);
delay(250);
if ((unsigned long)(millis() - wifiMillis) >= 20000) break;
//if (millis() > wifiMillis + 20000) break; //call reset
}
}
void loop() {
if (WiFi.status() !=WL_CONNECTED) //reconnect wifi
{
WIFIConnect();
} else {
if (!mqtt_client.connected()) {
mqttConnect();
}
hp.sync();
//if (millis() > (lastTempSend + SEND_ROOM_TEMP_INTERVAL_MS)) { // only send the temperature every 60s
if ((unsigned long)(millis() - lastTempSend) >= SEND_ROOM_TEMP_INTERVAL_MS) { //only send the temperature every 60s (default)
hpStatusChanged(hp.getStatus());
lastTempSend = millis();
}
//if (millis() > (lastRemoteTemp + 300000)) { //reset to local temp sensor after 5 minutes of no remote temp
if ((unsigned long)(millis() - lastRemoteTemp) >= 300000) { //reset to local temp sensor after 5 minutes of no remote temp udpates
hp.setRemoteTemperature(0);
lastRemoteTemp = millis();
}
mqtt_client.loop();
#ifdef OTA
ArduinoOTA.handle();
#endif
}
}