MQTT JSON Mitsubishi Heatpump

You are correct. I spent a couple hours right after it came out and couldn’t get it to work.

Ideally we need to be able to send json but iirc neither the old or new binding will do that. My solution with the old was to create the maps to get the job done. With the old binding, you could do separate transforms for in and out so json in and map out. You can only do one transform (or I couldn’t get it to do two) with the new one.

My life is far more busy these days so I finally concluded after a few hours burned that mqtt1 works as of now and I don’t have the time to figure out the new one. I planned to revisit this summer when my HP’s aren’t all powered off at the breaker anyway.

OK, I was afraid this might be the case. Also I am having less time at the moment, so with your result, I will probably postpone my tests, since it works so good with version 1.

Thanks for the heads up!

Running OH2…is it there any tutorial for step by step hacking the Mitsubishi heatpump?

Probably the closest thing I have is this thread and the integration section of the git repo: https://github.com/SwiCago/HeatPump/blob/master/integrations/OpenHAB/README.md

1 Like

Thanks, Moxified.
Do you have any ideea if MSZ-FH2VE heat pump from Mitsubishi is compatible with your work?

Unfortunately I do not know. If it has the CN105 serial header, chances are pretty good.

I see in the thread of known working models the MSZ-FH25VE2 which I wonder if it is similar to yours: https://github.com/SwiCago/HeatPump/issues/13#issuecomment-420850042

1 Like

I have installed the ESP, and the MQTT works fine, to get the Json MQTT into Openhab works fine, but I can not send commands from openhab via MQTT JSON correctly.

I tried to use
Item:

Switch Living_HP_Power "Power"	{ mqtt=">[broker:home/heatpump/set:command:*:JS(ACONOFF.js)],<[broker:home/heatpump:state:JSONPATH($.power)]" }

In transformation folder (with Javascript Transformation installed) with file name :ACONOFF.js

(function(i) {
	if (i=="ON"){
			var ToJson = '{“power:ON"}’;
				}
	if (i=="OFF"){
			var ToJson = '{“power:OFF"}’;
				}							
return ToJson;
})(input)

This resulted in that nothing was sent to MQTT. What is the error? I have never worked with JavaScripts before, so it is probably something trivial.

Yes, that’s correct, as the variable is only defined in the context of if()

afaik the code should be more like:

(function(i) {
    var ToJson = '{"power:OFF"}';
    if (i == "ON") {
        ToJson = '{"power:ON"}';
    }
return ToJson;
})(input)

Thanks, Now it works!!

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 :slight_smile: (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
  }
}
1 Like

Follow up,
the headerfile:

//#define OTA

// wifi settings
const char* ssid     = "yourssid";
const char* password = "yourpassword";

// mqtt server settings
const char* mqtt_server   = "yourserver";
const int mqtt_port       = 1883;
const char* mqtt_username = "";
const char* mqtt_password = "";

// mqtt client settings
// Note PubSubClient.h has a MQTT_MAX_PACKET_SIZE of 128 defined, so either raise it to 256 or use short topics
const char* client_id                   = "heatpump-controller-1"; // Must be unique on the MQTT network
const char* heatpump_topic              = "/house/heating/heatpump";
const char* heatpump_set_topic          = "/house/heating/heatpump/set/#";
const char* heatpump_status_topic       = "/house/heating/heatpump/status";
const char* heatpump_timers_topic       = "/house/heating/heatpump/timers";

const char* heatpump_debug_topic        = "/house/heating/heatpump/debug";
const char* heatpump_debug_set_topic    = "heatpump/debug/set";

// pinouts
const int redLedPin  = 0; // Onboard LED = digital pin 0 (red LED on adafruit ESP8266 huzzah)
const int blueLedPin = 2; // Onboard LED = digital pin 0 (blue LED on adafruit ESP8266 huzzah)

// sketch settings
const unsigned int SEND_ROOM_TEMP_INTERVAL_MS = 60000;

The new things:

// Mitsubishi Heatpump
Thing topic heatpump "Mitsubishi Heatpump" {
Channels:
    Type switch : power         "Power"             [ stateTopic="/house/heating/heatpump/power", commandTopic="/house/heating/heatpump/set/power", on="ON", off="OFF" ]
    Type string : mode          "Mode"              [ stateTopic="/house/heating/heatpump/mode", commandTopic="/house/heating/heatpump/set/mode" ]
    Type number : temperature   "Temperature"       [ stateTopic="/house/heating/heatpump/temperature", commandTopic="/house/heating/heatpump/set/temperature" ]
    Type string : fan           "Fan"               [ stateTopic="/house/heating/heatpump/fan", commandTopic="/house/heating/heatpump/set/fan" ]
    Type string : vane          "Vane"              [ stateTopic="/house/heating/heatpump/vane", commandTopic="/house/heating/heatpump/set/vane" ]
    Type string : status        "Status"            [ stateTopic="/house/heating/heatpump/status/operating" ]
    Type number : room_temp     "Room temperature"  [ stateTopic="/house/heating/heatpump/status/temperature" ]
}

And corresponding items:

Switch Cinema_HP_Power              "Power"                             (GF_Cinema)                                                     {channel="mqtt:topic:mosquitto:heatpump:power"}
String Cinema_HP_Mode               "Mode [%s]"      <text>             (GF_Cinema)                                                     {channel="mqtt:topic:mosquitto:heatpump:mode"}
Number Cinema_HP_Temp               "Inställd Temp: [%d °C]"    <temperature>   (GF_Cinema)                                             {channel="mqtt:topic:mosquitto:heatpump:temperature"}
String Cinema_HP_Fan                "Fläkt: [%s]"     <fan>               (GF_Cinema)                                                   {channel="mqtt:topic:mosquitto:heatpump:fan"}
String Cinema_HP_Vane               "Vane: [%s]"        <flow>          (GF_Cinema)                                                     {channel="mqtt:topic:mosquitto:heatpump:vane"}
String Cinema_HP_Status             "Operating: [%s]"   <text>          (GF_Cinema)                                                     {channel="mqtt:topic:mosquitto:heatpump:status"}
Number Cinema_HP_RoomTemp           "Rumstemperatur (VP): [%d °C]"    <temperature>   (GF_Cinema)                                       {channel="mqtt:topic:mosquitto:heatpump:room_temp"}

Is this still active? I am having trouble getting the nodemcu to read the unit’s settings. Used Swis’s configuration. The debug transmits to mqqt broker, just not reading data from the unit itself.

Maybe this would be also an option - Mitsubishi Heat Pump ? It’s an official espeasy plugin

I am still running my MQTT version of this binding, my heat pump is getting old though, so I hope the next Mitsubishi, when the current one is retired, also has this connector, and works the same. :slight_smile: