MQTT JSON Mitsubishi Heatpump

I’m trying to interface OH with my Mitsubishi heatpumps using this ESP8266 library. The MQTT example code works great and I can control the HP from CLI but my only OH MQTT interaction has been simple switch, contact and temperature.

I haven’t found any good examples on here of successfully configuring items to parse out a json string and send in json.

Would it be easier/better to reconfigure the ESP code to send on separate topics for each item instead of a json string?

Anybody want to write a binding :slight_smile:

A Huzzah, plug and some pins and you have yourself full control of modern Mitsubishi heatpump wall units via MQTT for under $15.

Example json for status and control:

status topic:

 {"power":"OFF","mode":"COOL","temperature":24.00,"fan":"AUTO","vane":"AUTO","wideVane":"|","iSee":false}
command to turn on: {"power": "ON"}

Some available commands:

"power",  /* ON/OFF */
"mode", /* HEAT/COOL/FAN/DRY/AUTO */
"temperature",    /* Between 16 and 31 */
"fan",   /* Fan speed: 1-4, AUTO, or QUIET */
"vane",   /* Air direction (vertical): 1-5, SWING, or AUTO */
"wideVane",    /* Air direction (horizontal): <<, <, |, >, >>, <>, or SWING */
1 Like

Parsing values out of JSON is pretty easy with the JSONPATH transform.

For example:

JSONPATH($.temperature) will pull 24 out of the JSON example you supply above.

Generating JSON from a Rule is a little more challenging but not much more. To send power ON:

Heatpump.sendCommand("{\"power\": \"ON\"}")

There are probably some more clever things you could do if you think about it but the above should be sufficient.

Hi Rich,

What a mess. I sucessfully setup some items that use jsonpath to transform as you suggest but OH complains about it in the logs endlessly. It doesn’t like the NULL. It also seems to have a hard time putting it into mapdb or mysql persistence and throws errors about that and on startup doesn’t restore.

If that wasn’t bad enough, you can’t map a command because json has a “:” in it and you can’t put that in the item’s MQTT statement. I found that I could replace the mqtt transform with a map and was going to create custom map files to have the full on={“power”:“ON”} This even worked in my mqtt pub/sub tests.

Next I tried to setup my sitemap to have a switch item with mappings for cool, heat, dry. Well, if the mode string had null still in it, basicUI would just break and show a 500 with a bunch of junk. If you published data to the topic with anything other than null it would be fine.

So, I have spent 5 hours fighting with this and am about ready to loose my mind. Some of the various errors and warnings I get:

2017-06-02 19:57:51.461 [ItemStateChangedEvent ] - MBACMode changed from NULL to null
2017-06-02 19:57:51.476 [ItemStateChangedEvent ] - MBACFan changed from NULL to null
2017-06-02 19:57:51.562 [ItemStateChangedEvent ] - MBACVane changed from NULL to null

2017-06-02 19:59:57.532 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'default.items’
2017-06-02 19:59:57.833 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn’t post update for 'MBACPower’
2017-06-02 19:59:57.835 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn’t post update for 'MBACTemp’
2017-06-02 19:59:57.874 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn’t post update for 'MBACPower’
2017-06-02 19:59:57.876 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn’t post update for 'MBACTemp’
2017-06-02 19:59:57.886 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn’t post update for 'MBACPower’
2017-06-02 19:59:57.887 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn’t post update for 'MBACTemp’
2017-06-02 19:59:57.926 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn’t post update for 'MBACPower’
2017-06-02 19:59:57.928 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn’t post update for 'MBACTemp’
2017-06-02 19:59:57.971 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn’t post update for 'MBACPower’
2017-06-02 19:59:57.974 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn’t post update for ‘MBACTemp’

2017-06-02 19:56:55.673 [ERROR] [.eclipse.smarthome.model.persistence] - [org.eclipse.smarthome.model.persistence.manager(106)] The unsetModelRepository method has thrown an exception
java.lang.NullPointerException
at org.eclipse.smarthome.model.persistence.internal.PersistenceModelManager.unsetModelRepository(PersistenceModelManager.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[:1.8.0_131]

2017-06-02 19:43:27.329 [WARN ] [pse.smarthome.core.items.GenericItem] - failed notifying listener ‘[org.eclipse.smarthome.core.persistence.internal.PersistenceManagerImpl@50867ec8, MBACFan, null]’ about state update of item java.lang.NullPointerException: {}

First of all, have you installed the JSONPATH transform?

What are the specific errors reported in the logs?

It should work if you escape the : using a \

ON: {"power"\:"ON"}

What type is the Item itself? If you have mappings, the Item needs to be a Number or a String.

I think the nulls are coming from the transform. Again, is the transform installed?

You can try to run the transform from a Rule so you can print things out.

transform("JSONPATH", "<path string>", MyItem.state.toString)

Make sure your MQTT Item is of type String and you do not apply a transform to it.

If I had to guess, the JSONPATH is not matching the string, resulting in a null, and OH cannot parse a null into the Item’s state.

I checked via karif and it shows as started? Do I need that esh-transform-jsonpath?

> openhab> feature:list | grep json
> esh-transform-jsonpath                    | 0.9.0.b4         |          | Started     | addons-2.0.0                | JSONPath Transformation
> openhab-transformation-jsonpath           | 2.0.0            | x        | Started     | addons-2.0.0                | JSONPath Transformation
> esh-storage-json                          | 0.9.0.b4         |          | Started     | distro-2.0.0                |
> openhab> 



String MBACMode					"Modeq: [%s]"									{ mqtt=">[broker:heatpump/set:command:*:MAP(ACMode.map)],<[broker:heatpump/status:state:JSONPATH($.mode)]" }
Switch item=MBACMode mappings=[COOL="Cool", HEAT="Heat", DRY="Dry"]

My item is a string. You can see my map statement. I tried using the : but I get errors in OH saying the item is improperly formed you need 5 sections separated by “:” blah blah. I tried everything including unicode to no avail. Somebody else mentioned the same issue in a different post.

The weird part is it “works”. If I publish to the topic, OH will see and parse the json out into the items. I could even change the mode via switch item in basicUI and it would publish my mapped statements. Just had all of the other fallout of null’s at startup or if you edited .items file which broke basicUI. Just seemed like an unreliable setup.

restoreOnStartup should deal with the nulls. Not sure what is going on.

You and me both. I just can’t figure it out.

I just checked my mysql db and there are values for my items. They start with null, move to something else and most go back to null as the last entry.

snippet from my mysql.persist:

MBACMode : strategy = everyUpdate, restoreOnStartup
MBACFan : strategy = everyUpdate, restoreOnStartup
MBACPower : strategy = everyUpdate, restoreOnStartup
MBACTemp : strategy = everyUpdate, restoreOnStartup
MBACVane  : strategy = everyUpdate, restoreOnStartup

At this point I’m going to guess that your items are receiving one it more messages that are not the same JSON message as you are expecting. If the transform can’t match it returns null.

That’s possible. Here is the exact json message that the hp sends:

{"power":"OFF","mode":"COOL","temperature":24.00,"fan":"AUTO","vane":"AUTO","wideVane":"|","iSee":false}

My items. You can see MBACPower and MBACMode have an outgoing and a map statement. I had MBACPower working it seemed and moved on to mode. That’s when I ran into all sorts of trouble:

String hvactest					"[%s]"											{ mqtt="<[broker:heatpump/status:state:default" }
Switch MBACPower																{ mqtt=">[broker:heatpump/set:command:*:MAP(ACPower.map)],<[broker:heatpump/status:state:JSONPATH($.power)]" }
Number MBACTemp					"Temp: [%d]"									{ mqtt="<[broker:heatpump/status:state:JSONPATH($.temperature)]" }
String MBACMode					"Mode: [%s]"									{ mqtt=">[broker:heatpump/set:command:*:MAP(ACMode.map)],<[broker:heatpump/status:state:JSONPATH($.mode)]" }
String MBACFan					"Fan: [%s]"										{ mqtt="<[broker:heatpump/status:state:JSONPATH($.fan)]" }
String MBACVane					"Vane: [%s]"									{ mqtt="<[broker:heatpump/status:state:JSONPATH($.vane)]" }

Another enigma is that I see item state changes from “NULL” to “null”. I know jsonpath states that it will return null if it cannot find anything in the string. It seems like maybe jsonpath’s null is different from OH’s NULL and OH doesn’t like jsonpath’s null. Make sense?

At OH restart:

2017-06-02 19:57:51.461 [ItemStateChangedEvent ] - MBACMode changed from NULL to null

Thanks for your responses!

NULL and null are indeed not the same thing and OH will be unable to use null to set the state of an item. Are you certain that JSON steering is the only message being sent?

The errors really look like you have a second message being published and your JSONPATH can’t handle this seconds message.

I’m certain, the HP is off, I am sending the command using mosquitto_pub in a different ssh session for testing.

Change an item and save, OH refreshes default.items, you see that it goes from say “COOL” to NULL to null. I then do a pub of that string I posted, it will change from null to COOL again and will stay that way until you either restart OH or mess with a config file. But you can always publish the MQTT message and it will fix.

Ok so I spent the morning trying to start over. Couple things I found. 1, mapdb doesn’t work right. It does fine storing numbers and switch states but although debug shows it commits the string value, it doesn’t restore it on startup. I changed everything to mysql and now everything restores on startup… separate issue I’ll dig into later. This is a testOH install anyway.

I blew away all of my items and deleted all mysql tables so there was nothing left over. I created new items with new names pointing to heatpump2 topic instead of heatpump.

It all worked. I could send, receive, transform with my map and it all restored on startup. It was great.

THEN, I changed the heatpump2 topic back to heatpump. It immediately changed mode to null and the sitemap broke again.

I tried restarting my mosquitto service but that didn’t do anything. I’m subscribed to heatpump/# and nothing is coming through, what is it about that topic that breaks everything?

My bigger concern is, how long until heatpump2 or whatever other topics I use break the same way?

Any thoughts on this?

Actually, just did a google and found you can purge “retained” messages from mosquitto: mosquitto_pub -t heatpump/status -r -n

I did this and now topic heatpump works as well. I’ll have to do some additional testing later to see if it breaks again. Perhaps when the heatpump was sending mqtt it sent junk that was stuck in the retained messages. I need to learn more about retained messages. I need to do some yard work first.

OK! I figured it out and frankly, I think this is a bug that should be fixed if it hasn’t been in a newer release (I’m on stable).

The HP sends two different status updates to the heatpump/status topic:

{"power":"ON","mode":"COOL","temperature":24.00,"fan":"AUTO","vane":"AUTO","wideVane":"|","iSee":false}
{"roomTemperature":21.00,"operating":false}

I had the HP sending these updates to the mqtt server a few days ago and then disconnected it. For my OH testing, I figured it would be satisfactory to just use mosquitto_pub/sub clients to get OH items and things right instead of turning my ac on and off every 30 seconds.

Somehow, mosquitto kept the less complete message in retained even though I had been sending the complete one manually all day. When OH restarted or items changed it would get the shorter message even though the most recent item published was the longer more complete message.

OK, so why I think this is a bug. While it is fully permissible for OH/jsonpath to return NULL for an item that isn’t found in a message, I don’t feel it is acceptable for it to return “null” which causes OH to blow up. The jsonpath transform needs to be updated to return the usable NULL so that items and rules don’t tilt.

In the short term, I’ll see what can be done on my esp code to ensure all needed roots are sent at the same time. But, I plan on powering off the HP system in the winter to save electricity (bout 100w standby draw for my 5 zone system). I’m afraid json will start returning null once the HP is no longer updating status.

MQTT clients specify when they connect whether to retain messages. In my experience you do not want to configure oh in this way.

That sounds like what was happening in your case with the messages.

As for your “bug”, it may not be so simple to fix. File an issue and see where it goes.

I’m not certain the current behavior is wrong myself. If I have a transform that should be able to work with a message fail, I want an error, not to have my Item reset to undefined (i.e. NULL). The transform and/or the regex to match which messages to catch should let one handle the case where there is more than one tire of message on the same topic.

If no messages are being sent the JSON transform will not be running. If different messages are being sent, you need to account for those messages in your MQTT using the regex message matching field so these other messages are ignored and no parsed by JSONPATH at all.

Yup, checked the code and they put: mqtt_client.publish(heatpump_status_topic, bufferInfo, true)

The last true is retained. I saw that and wondered as I had never had a third argument in my subpubclient code… now I know. I’ll clean those out.

Can you do a regex and jsonmap inside an mqtt definition? My goal, as always, is reliability which is why I don’t like the system breaking if it gets a bad message.

I hear you on the idea of an error instead of NULL. I would rather see a WARN log entry or something. Passing a value that breaks basicUI and throws all sorts of weird persistence errors about not being able to map null… is although obvious, not overly clear. I saw those errors early on but when I saw an error about not being able to map a null, I had no clue that null != NULL.

Is that a recent addition? There used to be a setting in mqtt.cfg to set it as retaining.

Look at the mqtt readme documents it. You can put the regex after the transform and it will only try to process messages that match the regex.

That .publish is code on the ESP8266, not OH. I haven’t set OH’s mqtt to do any retaining. The example code that comes with the ESP8266 Heatpump library defaults to retain on several of the topics.

An embarrassing realization came to light just recently. The HP was actually using two different topics and I had crossed them in my testing.

The short status topic was heatpump/status
The long settings state topic was heatpump

I had set my items to get their status from heatpump/status. It should have come from heatpump ONLY. I fixed the mistake and all works as it should. I was actually in the process of trying to tweak the code to separate the two topics when I realized they already were.

I’m sorry for the ride. Thanks so much for your help. Hopefully I will be able to help somebody else get this running in the future.

I find I learn more from wild rides like these than almost everything. And we have all experienced similar problems where we take days trying to solve a problem only to discover some typo or head smacking obvious problem.

#Moxified I’m trying to do the same as you are.

I have serial communications with my HP, and successful retrieve the status from the HP via MQTT

{“power”:“ON”,“mode”:“COOL”,“temperature”:19,“fan”:“4”,“vane”:“3”,“wideVane”:"<<"}

Do you have any idea why I get this when I try publish from a standard MQTT client

Topic: heatpump/set

Payload: “mode”:“HEAT”

!root.success(): invalid JSON on heatpump_set_topic…

Thanks :slight_smile: