MQTT JSON Mitsubishi Heatpump

Yeah. I have a rule that does this. I’ll try to post more details tomorrow. Today is busy.

Below is a stripped down version of my Remote Temp rule.

Basically, you need to send a temperature every 5 minutes to the HP or it will revert to using its internal temp sensor. In the rule, I have a 5 minute cron. Even if nothing changes, it will send the temp again which will tell the HP to continue using the temp.

Additionally, it is set to monitor the current temp of said thermostats as well as power state of the HP’s. If you turn a HP on, you want the rule to trigger immediately so that it will get the current room temp instead of waiting up to 5 minutes. Secondly, every time the thermostat changes, you want an instant update to the HP of the new temp.

I don’t bother to differentiate which thermostat or HP changes. I simply check if the HP is on… if so, send the current temp to it from its applicable source.

The last little bit that I recommend but you can see I don’t do on my theater HP… have a built in heartbeat for the thermostat. If your remote temp source somehow fails and you don’t check for it, you would continue sending the last known temperature to the HP indefinitely. That could cause the HP to over cool or over heat drastically.

Lastly, I left 2 of my 5 HP examples here. The first one uses a zwave thermostat, the second one uses an arduino with dht22 over MQTT. I rarely use that HP and I’m always in the room so I never built in a heartbeat… I should though.

Hopefully this helps.

rule "HP RemoteTemp" //allows HP's to use wall mounted thermostats if available as room temp
    when
        Item FirstFloorThermostatCurrentTemperature changed or
        Item Num_C_Theater_RMT changed or
        Item Living_HP_Power changed from OFF to ON or
        Item Theater_HP_Power changed from OFF to ON or
        Time cron "0 */5 * * * ?" //every 5 minutes
    then
        logInfo("HP RemoteTemp", "Rule Triggered")
        if (FirstFloorThermostatComm.state != ON) { //Is Livingroom Thermostat responsive
			if (Living_HP_Power.state == ON) {
                logInfo("HP RemoteTemp", "updating LR HP remote temp")
				Living_HP_RemoteTemp.sendCommand(FirstFloorThermostatCurrentTemperature.state.toString)
			}
		} else logInfo("HP RemoteTemp", "LR Thermostat Comm error, defaulting to internal")
        if (Theater_HP_Power.state == ON) { //Theater HP
            logInfo("HP RemoteTemp", "updating Theater HP remote temp")
			Theater_HP_RemoteTemp.sendCommand(Num_C_Theater_RMT.state.toString)
		}
end

I finally bought the ready made cable with pigtales for connecting and installed the ESP8266 in the heatpump.
Used a ESP-01 and it works like a charm with the modifications done by Moxified on the code.

Thanks for all hard work @Moxified and good questions from @Nanna_Agesen.

My heatpump: MSZ-SF35VE

Thanks
Vegard

For temp value there are another way.
In place of using MAP use a Jscript and place it in Transformation Folder like this one :
(Don’t forget to install Javascript Transformation First)

(function(i) {
var ToJson = '{“remoteTemp”: ’ + String(i) + ‘}’;
return ToJson;
})(input)

And call it with this :

{ mqtt=">[broker:home/livingroom/heatpump/set:command:*:JS(ACRemoteTemp.js)]" }

You must create a JS For Each Transformation, but it’s more easy with this solution.

(If you must repeat an action more of two make a script :wink: )

Olivier

This really only “applies” when you’ll have to repeat a process yourself multiple times. The time it would take a non-developer like me to find something like var ToJson and understand how it works would take 100 times longer than the 3 minutes in excel it took to create my maps which work fine. Sure your solution might be faster for the computer too but not enough to make a difference for me :slight_smile:

That being said, thanks for adding the solution. Far more elegant than mine!

I could be wrong but I think you could have issues with that for remote temp. I found inconsistency (I think it was mobile app vs basicui iirc) in decimal places. Either way, the heat pump only wanted a 2 digit integer. Your code would pass the decimal places on assuming ‘i’ wasn’t forced to an integer someplace else. This could be fixed in the arduino code I suppose but just a thought. Certainly correct me if I’m incorrect here.

Moxified,

I’m also new on OpenHab and I’ve searched for my personnal use, and yes that take a few time more than write it with hand :wink:. But reusable at volontee.

It’s also a solution for a lot of people wanted to send JSON to a MQTT brokker.

For your case you can also set the step by degree in place of 0.1 in sitemap or adjust also the script.

(function(i) {
var ToJson = '{“remoteTemp”: ’ + String(Math.trunc(i)) + ‘}’;
return ToJson;
})(input)

So 55.1 = 55 or 55.9 = 55

Olivier

So, I was thinking about testing the MQTT v2 binding some day, and I suspect the biggest hurdle for me will be the Mitsubishi MQTT set-up workig. So, I figured I should ask here, if anyone has done the job already, and in this would be willing to share their things/items?

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