gysmo38 / mitsubishi2MQTT

Mitsubishi to MQTT with ESP8266 module
GNU Lesser General Public License v2.1
375 stars 134 forks source link

Anyone able to get this working with MQTTThing in Homebridge? #135

Closed ultrathew closed 3 years ago

ultrathew commented 3 years ago

Everything is working perfectly with the web interface and my Mitsubishi MSZ-GE12NA-8, but I can not get it to work with the thermostat device type in the MQTTThing Homebridge plugin. I'm open to using a different HB plugin if anyone's had any success.

produdegr commented 3 years ago

Hi it needs some heavy tweaking (I spend halve a day). It uses explicit message tampering with the apply feature of mqttthing. You need to review each line and adjust the topic to match yours! For example you need to replace all instances of "hvac1" to your value. Also keep in mind that due to the usage of the "apply" feature, all editing must be done manually not with config UI X!

But it works perfectly.

    {
        "type": "heaterCooler",
        "name": "Airconditioner",
        "url": "mqtt://localhost",
        "username": "user",
        "password": "pass",
        "mqttOptions": {
            "keepalive": 30
        },
        "mqttPubOptions": {
            "retain": true
        },
        "logMqtt": true,
        "topics": {
            "setActive": {
                "topic": "mitsubishi2mqtt/hvac1/power/set",
                "apply": "if (message == true) return 'ON'; else return 'OFF';"
            },
            "getActive": {
                "topic": "mitsubishi2mqtt/hvac1/state",
                "apply": "if (JSON.parse(message).mode == 'off') return false; else return true;"
            },
            "getCurrentHeaterCoolerState": {
                "topic": "mitsubishi2mqtt/hvac1/state",
                "apply": "return JSON.parse(message).mode;"
            },
            "setTargetHeaterCoolerState": "mitsubishi2mqtt/hvac1/mode/set",
            "getTargetHeaterCoolerState": {
                "topic": "mitsubishi2mqtt/hvac1/settings",
                "apply": "return JSON.parse(message).mode;"
            },
            "getCurrentTemperature": {
                "topic": "mitsubishi2mqtt/hvac1/state",
                "apply": "return JSON.parse(message).roomTemperature;"
            },
            "setCoolingThresholdTemperature": "mitsubishi2mqtt/hvac1/temp/set",
            "getCoolingThresholdTemperature": {
                "topic": "mitsubishi2mqtt/hvac1/state",
                "apply": "return JSON.parse(message).temperature;"
            },
            "setHeatingThresholdTemperature": "mitsubishi2mqtt/hvac1/temp/set",
            "getHeatingThresholdTemperature": {
                "topic": "mitsubishi2mqtt/hvac1/state",
                "apply": "return JSON.parse(message).temperature;"
            },
            "setRotationSpeed": {
                "topic": "mitsubishi2mqtt/hvac1/fan/set",
                "apply": "return Math.round(message/25);"
            },
            "getRotationSpeed": {
                "topic": "mitsubishi2mqtt/hvac1/state",
                "apply": "if (isNaN(JSON.parse(message).fan)==true) return 50; else return (JSON.parse(message).fan)*25;"
            }
        },
        "currentHeaterCoolerValues": [
            "off",
            "fan_only",
            "heat",
            "cool"
        ],
        "targetHeaterCoolerValues": [
            "heat_cool",
            "heat",
            "cool"
        ],
        "minTemperature": 16,
        "maxTemperature": 31,
        "accessory": "mqttthing"
    },

That should make your day....

Thanks to all collaborators of mitsubishi2MQTT!!!

produdegr commented 3 years ago

Just an updated version: (adjust your topic) { "type": "heaterCooler", "name": "Airconditioner", "url": "mqtt://localhost", "username": "user", "password": "pass", "mqttOptions": { "keepalive": 30 }, "mqttPubOptions": { "retain": false }, "logMqtt": true, "debounceRecvms": 300, "topics": { "setActive": { "topic": "hvac1/basement_aircon/power/set", "apply": "if (message == true) return 'ON'; else return 'OFF';", "state": "if (message == true) return 'ON'; else return 'OFF';" }, "getActive": { "topic": "hvac1/basement_aircon/state", "apply": "if (JSON.parse(message).mode == 'off') return false; else return true;", "state": "if (JSON.parse(message).mode == 'off') return false; else return true;" }, "getCurrentHeaterCoolerState": { "topic": "hvac1/basement_aircon/state", "apply": "return JSON.parse(message).mode;" }, "setTargetHeaterCoolerState": "hvac1/basement_aircon/mode/set", "getTargetHeaterCoolerState": { "topic": "hvac1/basement_aircon/settings", "apply": "return JSON.parse(message).mode;" }, "getCurrentTemperature": { "topic": "hvac1/basement_aircon/state", "apply": "return JSON.parse(message).roomTemperature;" }, "setCoolingThresholdTemperature": "hvac1/basement_aircon/temp/set", "getCoolingThresholdTemperature": { "topic": "hvac1/basement_aircon/state", "apply": "return JSON.parse(message).temperature;" }, "setHeatingThresholdTemperature": "hvac1/basement_aircon/temp/set", "getHeatingThresholdTemperature": { "topic": "hvac1/basement_aircon/state", "apply": "return JSON.parse(message).temperature;" }, "setRotationSpeed": { "topic": "hvac1/basement_aircon/fan/set", "apply": "if (Math.round(message/25)<1) return 1; else return Math.round(message/25);" }, "getRotationSpeed": { "topic": "hvac1/basement_aircon/state", "apply": "if (isNaN(JSON.parse(message).fan)==true) return 50; else return (JSON.parse(message).fan)*25;" } }, "currentHeaterCoolerValues": [ "off", "fan_only", "heat", "cool" ], "targetHeaterCoolerValues": [ "heat_cool", "heat", "cool" ], "minTemperature": 16, "maxTemperature": 31, "accessory": "mqttthing" },

ultrathew commented 3 years ago

This did, indeed make my day. Thank you so much. It's working perfectly. Really appreciate the help.

produdegr commented 3 years ago

Hopefully last update:

{ "type": "heaterCooler", "name": "Airconditioner", "url": "mqtt://localhost", "username": "user", "password": "pass", "mqttOptions": { "keepalive": 30 }, "mqttPubOptions": { "retain": true }, "logMqtt": true, "confirmationPeriodms": 3000, "retryLimit": 3, "debounceRecvms": 500, "validate": true, "topics": { "setActive": { "topic": "hvac2/hallway_aircon/power/set", "apply": "if (message == true) return 'ON'; else return 'OFF';", "state": "if (message == true) return 'ON'; else return 'OFF';" }, "getActive": { "topic": "hvac2/hallway_aircon/state", "apply": "if (JSON.parse(message).mode == 'off') return false; else return true;", "state": "if (JSON.parse(message).mode == 'off') return false; else return true;" }, "getCurrentHeaterCoolerState": { "topic": "hvac2/hallway_aircon/state", "apply": "return JSON.parse(message).mode;" }, "setTargetHeaterCoolerState": "hvac2/hallway_aircon/mode/set", "getTargetHeaterCoolerState": { "topic": "hvac2/hallway_aircon/settings", "apply": "if (JSON.parse(message).mode=='off') return 'cool'; else return JSON.parse(message).mode;" }, "getCurrentTemperature": { "topic": "hvac2/hallway_aircon/state", "apply": "return JSON.parse(message).roomTemperature;" }, "setCoolingThresholdTemperature": "hvac2/hallway_aircon/temp/set", "getCoolingThresholdTemperature": { "topic": "hvac2/hallway_aircon/state", "apply": "return JSON.parse(message).temperature;" }, "setHeatingThresholdTemperature": "hvac2/hallway_aircon/temp/set", "getHeatingThresholdTemperature": { "topic": "hvac2/hallway_aircon/state", "apply": "return JSON.parse(message).temperature;" }, "setRotationSpeed": { "topic": "hvac2/hallway_aircon/fan/set", "apply": "if (Math.round(message/25)<1) return 'AUTO'; else return Math.round(message/25);" }, "getRotationSpeed": { "topic": "hvac2/hallway_aircon/state", "apply": "if (isNaN(JSON.parse(message).fan)==true) return 0; else return (JSON.parse(message).fan)*25;" }, "setSwingMode": { "topic": "hvac2/hallway_aircon/vane/set", "apply": "if (message=='ENABLED') return 'SWING'; else return 'AUTO';" }, "getSwingMode": { "topic": "hvac2/hallway_aircon/state", "apply": "if (JSON.parse(message).vane=='SWING') return 'ENABLED'; else return 'DISABLED';" } }, "currentHeaterCoolerValues": [ "off", "fan_only", "heat", "cool" ], "targetHeaterCoolerValues": [ "heat_cool", "heat", "cool" ], "minTemperature": 16, "maxTemperature": 31, "accessory": "mqttthing" },

produdegr commented 3 years ago

Forgot to mention that because ON value is set to topic .../mode/set and not to /power set, you must activate your aircon by opening it and selecting Cooling/Heating etc. otherwise it may not turn on. I can't see currently a way to send a message to 2 different topics with mqttthings (a bit awgward solution in terms of design).

ultrathew commented 3 years ago

Thank you! This seems to be working properly for me. I'm used to the odd behavior for turning the AC on, as I'd been using various IR blasters to control this unit until now.

produdegr commented 3 years ago

Please note that the "retain": true in the last config is WRONG and must be "retain":false If not ghost turning on of your AC may happen.

@ultrathew if you are happy with the solution please consider closing this issue. Thanks.

ultrathew commented 3 years ago

Thank you for the final bit of help @produdegr - I'm all set.

ultrathew commented 3 years ago

Sorry, I spoke too soon. I just discovered that restarting Homebridge causes the AC to turn on, regardless of the state the AC was in when I restarted Homebridge. Any advice?

produdegr commented 3 years ago

As mentioned above, make sure that the "retain" value in the config is false:

}, "mqttPubOptions": { "retain": false },

RESTART HOMEBRIDGE

Now you need to delete the stuck (because retained) MQTT message in your broker (Mosquitto?). I use the very good MQTT Explorer (http://mqtt-explorer.com/) so run it, connect to broker and delete the topic:

your-topic/mode set = cool (or any message in the topic, just to make sure)

When you click on the message you will see on the right hand side of the MQTT-Explorer a yellow mark called [Retain]. Simply delete this message with MQTT-Explorer and restart mitsubishi2mqtt on your ESP8266 (D1, ESP32 etc.) Now it should be ok. You can double check by clicking on all messages: Retained messages cause the problem when using mqttthings and mitsubishi2mqtt, so no one must show as "retain".

I had this issue and it drove me crazy last 5 days.

ultrathew commented 3 years ago

@produdegr - THANK YOU! That did it. This is my first time dealing with MQTT, and I've been using MQTT Explorer to watch the messages getting passed around. I didn't realize I could send messages with it. Really appreciate all the help. This is working perfectly now.

barakthecat commented 1 year ago

Sorry to drag this back from the dead, but are there updated instructions for this? The ones above aren’t working for me even when I adjust the topic.

produdegr commented 1 year ago

Working as published on my original flashed f/w: Mitsubishi2MQTT 0.7.3. Make sure your MQTT settings on the ESP are correct, then check your MQTT server if they show up. Finally adjust the above config to adopt to your correct topics. If this does not help, the newer f/w may got changed or in homebridge you opened the config with the GUI and saved it. The above config is using in-line commands which sometimes get lost when using Homebridge GUI. Good luck.

barakthecat commented 1 year ago

Thanks so much for publishing this. I figured out my problem - I had mitsubishi2MQTT set to Fahrenheit, and then MQTTThing was interpreting that number as Celsius and then converting it to Fahrenheit, which was triggering an out of range error. Setting mitsubishi2MQTT to Celsius fixed that problem. Now the only remaining issue I have is that I can't turn the unit off from HomeKit. I think this is related to an update in the latest version. When I set the unit to one of the "on" settings (cool/heat/auto), it sends a message to /mode/set. However when I set it to "off" the message goes to /power/set. When using the HomeKit plugin for Home Assistant, both the on and off messages go to /mode/set.

Looking through the issues, # 205 and 206 both relate to the power_command_topic being deprecated and specifies that Mode should be used to change mode and power off. Any idea how to update your code to account for this? Thanks again

produdegr commented 1 year ago

Here is my latest config (sorry have no time to analyze, but it works for me!):

{ "type": "heaterCooler", "name": "MyAirconditionName", "url": "mqtt://localhost", "username": "", "password": "", "mqttOptions": { "keepalive": 30 }, "mqttPubOptions": { "retain": false }, "logMqtt": true, "confirmationPeriodms": 3000, "retryLimit": 3, "debounceRecvms": 500, "validate": true, "topics": { "setActive": { "topic": "hvac2/hallway_aircon/power/set", "apply": "if (message == true) return ''; else return 'OFF';", "state": "if (message == true) return ''; else return 'OFF';" }, "getActive": { "topic": "hvac2/hallway_aircon/state", "apply": "if (JSON.parse(message).mode == 'off') return false; else return true;", "state": "if (JSON.parse(message).mode == 'off') return false; else return true;" }, "getCurrentHeaterCoolerState": { "topic": "hvac2/hallway_aircon/state", "apply": "return JSON.parse(message).mode;" }, "setTargetHeaterCoolerState": "hvac2/hallway_aircon/mode/set", "getTargetHeaterCoolerState": { "topic": "hvac2/hallway_aircon/settings", "apply": "if (JSON.parse(message).mode=='off') return 'cool'; else return JSON.parse(message).mode;" }, "getCurrentTemperature": { "topic": "hvac2/hallway_aircon/state", "apply": "return JSON.parse(message).roomTemperature;" }, "setCoolingThresholdTemperature": "hvac2/hallway_aircon/temp/set", "getCoolingThresholdTemperature": { "topic": "hvac2/hallway_aircon/state", "apply": "return JSON.parse(message).temperature;" }, "setHeatingThresholdTemperature": "hvac2/hallway_aircon/temp/set", "getHeatingThresholdTemperature": { "topic": "hvac2/hallway_aircon/state", "apply": "return JSON.parse(message).temperature;" }, "setRotationSpeed": { "topic": "hvac2/hallway_aircon/fan/set", "apply": "if (Math.round(message/25)<1) return 'AUTO'; else return Math.round(message/25);" }, "getRotationSpeed": { "topic": "hvac2/hallway_aircon/state", "apply": "if (isNaN(JSON.parse(message).fan)==true) return 0; else return (JSON.parse(message).fan)*25;" }, "setSwingMode": { "topic": "hvac2/hallway_aircon/vane/set", "apply": "if (message=='ENABLED') return 'SWING'; else return 'AUTO';" }, "getSwingMode": { "topic": "hvac2/hallway_aircon/state", "apply": "if (JSON.parse(message).vane=='SWING') return 'ENABLED'; else return 'DISABLED';" } }, "currentHeaterCoolerValues": [ "off", "fan_only", "heat", "cool" ], "targetHeaterCoolerValues": [ "heat_cool", "heat", "cool" ], "minTemperature": 16, "maxTemperature": 31, "accessory": "mqttthing" },

Hope this helps.

yargok commented 9 months ago

I know this thread is old, but I wanted to share my experience. Big thanks to produdegr for his code.

When trying it today, I was unable to turn off the mini split from home bridge. I played with MQTT Broker and found that rather than setting "power/set" to off when shutting down power, it worked to set "mode/set" to off. I've modified his code ("SetActive" block) to enable this, and it looks like it is working for me. (Don't forget to set the username, password, and replace all instances of "GuestMiniSplit" with whatever your name is.

    {
        "type": "heaterCooler",
        "name": "GuestMiniSplit",
        "url": "mqtt://localhost",
        "username": "replace",
        "password": "replace",
        "mqttOptions": {
            "keepalive": 30
        },
        "mqttPubOptions": {
            "retain": false
        },
        "logMqtt": false,
        "confirmationPeriodms": 3000,
        "retryLimit": 3,
        "debounceRecvms": 500,
        "validate": true,
        "topics": {
            "setActive": {
                "topic": "mitsubishi2mqtt/GuestMiniSplit/mode/set",
                "apply": "if (message == true) return JSON.parse(message).mode; else return 'OFF';",
                "state": "if (message == true) return JSON.parse(message).mode; else return 'OFF';"
            },
            "getActive": {
                "topic": "mitsubishi2mqtt/GuestMiniSplit/state",
                "apply": "if (JSON.parse(message).mode == 'off') return false; else return true;",
                "state": "if (JSON.parse(message).mode == 'off') return false; else return true;"
            },
            "getCurrentHeaterCoolerState": {
                "topic": "mitsubishi2mqtt/GuestMiniSplit/state",
                "apply": "return JSON.parse(message).mode;"
            },
            "setTargetHeaterCoolerState": "mitsubishi2mqtt/GuestMiniSplit/mode/set",
            "getTargetHeaterCoolerState": {
                "topic": "mitsubishi2mqtt/GuestMiniSplit/settings",
                "apply": "if (JSON.parse(message).mode=='off') return 'cool'; else return JSON.parse(message).mode;"
            },
            "getCurrentTemperature": {
                "topic": "mitsubishi2mqtt/GuestMiniSplit/state",
                "apply": "return JSON.parse(message).roomTemperature;"
            },
            "setCoolingThresholdTemperature": "mitsubishi2mqtt/GuestMiniSplit/temp/set",
            "getCoolingThresholdTemperature": {
                "topic": "mitsubishi2mqtt/GuestMiniSplit/state",
                "apply": "return JSON.parse(message).temperature;"
            },
            "setHeatingThresholdTemperature": "mitsubishi2mqtt/GuestMiniSplit/temp/set",
            "getHeatingThresholdTemperature": {
                "topic": "mitsubishi2mqtt/GuestMiniSplit/state",
                "apply": "return JSON.parse(message).temperature;"
            },
            "setRotationSpeed": {
                "topic": "mitsubishi2mqtt/GuestMiniSplit/fan/set",
                "apply": "if (Math.round(message/25)<1) return 'AUTO'; else return Math.round(message/25);"
            },
            "getRotationSpeed": {
                "topic": "mitsubishi2mqtt/GuestMiniSplit/state",
                "apply": "if (isNaN(JSON.parse(message).fan)==true) return 0; else return (JSON.parse(message).fan)*25;"
            },
            "setSwingMode": {
                "topic": "mitsubishi2mqtt/GuestMiniSplit/vane/set",
                "apply": "if (message=='ENABLED') return 'SWING'; else return 'AUTO';"
            },
            "getSwingMode": {
                "topic": "mitsubishi2mqtt/GuestMiniSplit/state",
                "apply": "if (JSON.parse(message).vane=='SWING') return 'ENABLED'; else return 'DISABLED';"
            }
        },
        "currentHeaterCoolerValues": [
            "off",
            "fan_only",
            "heat",
            "cool"
        ],
        "targetHeaterCoolerValues": [
            "heat_cool",
            "heat",
            "cool"
        ],
        "minTemperature": 16,
        "maxTemperature": 31,
        "accessory": "mqttthing",
        "plugin_map": {
            "plugin_name": "homebridge-mqttthing"
        }
    },