dlarrick / hass-kumo

Home Assistant module interfacing with Mitsubishi mini-split units
MIT License
98 stars 21 forks source link

Get and Set 'Advanced Installer Settings' / Function Code Values via Integration? #139

Open joergbattermann opened 6 months ago

joergbattermann commented 6 months ago

Application Note 3050 for M- & P- Series Units defines the Function Settings (see page 10 onwards in the corresponding .pdf file) for the indoor units and while most of those settings are rather static, some I do actually change throughout of the year and one in particular (room temperature sensing location) I'd ideally change more frequently / once a day or so.. and hence I was wondering if the integration already has or could support getting and setting these Function Settings by number and (numeric) value?

It appears these are already in the kumo_cache.json file in the "reportedInitialSettings": {}, albeit I am not a 100% how that section logically works. There's a sub-section which contains "assigned_settings": { }, there' also a "leftovers_settings": {} sub-sections and then a bunch of named key/value entries also.

"assigned_settings": { } and "leftovers_settings": {} contain keys by their Setting / Mode No (as per the Application Note: 3050 .pdf / setting in app and also MHK2) and the corresponding value per the same (.pdf) table.

I am not entirely sure what goes into "assigned_settings": { } and "leftovers_settings": {} (I assume some are/where the ones set during the initial installer setup and the other ones the one I set thereafter)... simply because -I- have modified the values of mode no "25" and "02" in the app (or on the MHK2 and then refreshed the settings in the Kumo Cloud app.).. you can see they're different to the default values as per that .pdf's table:

image

Inside the Kumo App you can see and set those under Settings > System Setup > Installer Settings > Home > Zone Name > Advanced > Settings by Number , in the MHK2 unit you can set them in the semi-secret Settings Menu (see the same .pdf linked above on page 4).

Is there any way to get/set these function codes & their values today already or is there any chance this could be added in the future?

Thanks!

dlarrick commented 6 months ago

TL;DR: this may be possible, but someone would have to figure out how to do it locally.

The Kumo HA integration (and pykumo Python library) uses the undocumented API running on your local indoor units, via your local network. The only piece that communicates with the KumoCloud service is at setup, to get info about the devices that are associated with the user's account there. The kumo_cache.json file is the verbatim info retrieved from the KumoCloud servers, so that it can be reused at next HA startup (if prefer_cache is on).

The information and control that we do have was reverse-engineered, mostly by observing the traffic between the Android/iOS app and the indoor units. This traffic goes over http, so it's easy enough to snoop. The traffic to the KumoCloud servers is https, and harder to get at -- especially since what we're most interested in is the traffic between those servers and the indoor unit.

I don't think anyone has tried capturing traffic on a phone while in the Installer Settings section of the app. If this does direct communication with the unit, then yes, it would likely be easy enough to add support. If it goes through the KumoCloud servers, though, it's probably beyond the scope of pykumo.

If you do manage to capture traffic, it's local, and you want to try out reading/sending those sections, see the notes over at pykumo for interactive use.

joergbattermann commented 6 months ago

Thanks @dlarrick! Started capturing some traffic and gonna try the pykumo in interactive mode (i.e. saw that the app's 'Refresh Settings' command sends* a PUT request to the unit locally with that json body: {"c":{"adapter":{"status":{"runState":"reboot"}}}}) (which literally just seems to tell the Kumo Cloud interface to reboot and probably pull the unit's values along the way) but is there any way in the HA integration to send those raw queries / commands? As in, is there a 'HA Wrapper' (if there is such a thing?) around the Query or Command an Indoor Unit Directly part of pykumo available?

Besides that however, these installer settings seem to go through the cloud (only*), more precisely via a POST to https://geo-c.kumocloud.com/relayDeviceCommands/v2 sending a json with

[
    "<SOME LONG ID>",
    {
        "<SOME OTHER SHORTER ID>": {
            "indoorUnit": {
                "initialSettings": {
                    "25": 3
                }
            }
        }
    }
]

sends* / only*: The reason I put an asterisk up there twice is because the local command to refresh the settings aka reboot, is sent to was sent to http://undefined/api?m=<SOME VERY VERY LONG ID> and the request literally was to http://undefined/api ... and I have not replaced 'undefined' with my Kumo Cloud adapter's ip / potential hostname, so I am not sure if the app / Kumo Cloud doesn't have/know the actual local ip of the adapter or if they use requests internally/in the app as a sort of hard-coded "identifier" but I saw -0- http requests go to the actual ip of the kumo cloud adapter

Any way, refresh settings seems to cause the adapter to reboot and therefore (I assume) pull the new values off the indoor unit and send them to the kumo cloud shortly thereafter with a POST to https://geo-c.kumocloud.com/saveUserData/v2.

Is that call to an undefined host normal / is there any function in the app that is known to call the adapter's local api? Just tried changing temperature and that one also goes through the cloud, so not sure if there's something misconfigured with my particular system at the moment.

Thanks!

dlarrick commented 6 months ago

I think Mitsubishi has made a recent change where most everything goes thru the cloud. Which is... not great. There may be a way to force it to go local. Such as disconnecting your router from the Internet :-) or blocking the KumoCloud servers via firewall.

The "reboot" command is definitely news! Thanks for that! This may possibly be a way out of the error-response issues we've been seeing in the past year or so -- which seemed to be a memory leak in the unit's adapter. I'll definitely add that command to pykumo and try to figure out when it makes sense to use it.

{"c":{"indoorUnit":{"initialSettings":{}}}} is definitely one of the commands that the local indoor units understand. They reply with what seems to be the current set of settings. Like the following for one of my units:

{"r":{"indoorUnit":{"initialSettings":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0}}}}

(background: you send a 'c' ('command') dictionary, and the indoor unit responds with an 'r' ('response') with things filled in. Sub-dictionaries you leave blank are queries. Values you set within those sub-dictionaries are commands to change that value. The 'r' response to a non-empty command is at least sometimes what the value used to be.

So if you include values in that c POST to your indoor unit with the appropriate change you want to make, it may well work. (Lawyer mode: if this breaks your indoor unit or WiFi adapter, you get to keep both pieces and I'm not responsible, etc.)

We just need to map those numeric settings to things that it's reasonable and safe to control, which the docs you quoted should help us figure out.

But overall I think this is quite promising!

joergbattermann commented 5 months ago

This took a little while but here's the request info sent when making changes to these advanced installer settings in the iOS Kumo Cloud app... in this case below I changed the value of setting no 25 ("Fan speed setting after set point has been met in Heat Mode" as per .pdf ("Application Note 3050 How to configure the Function Settings on a Deluxe MA")) to value '3' and the app sent the following request:

POST /relayDeviceCommands/v2 HTTP/1.1
host: geo-c.kumocloud.com
accept: application/json, text/plain, */*
sec-fetch-site: cross-site
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
sec-fetch-mode: cors
content-type: application/json;charset=utf-8
origin: file://
user-agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
connection: keep-alive
content-length: 101
sec-fetch-dest: empty

[
  "<SOME VERY LONG ID?>",
  {
    "<SOME SHORTER ID?>": {
      "indoorUnit": {
        "initialSettings": {
          "25": 3
        }
      }
    }
  }
]

.. and the response was:

HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
date: Sat, 20 Apr 2024 21:40:37 GMT
content-length: 32
connection: keep-alive

[
  true,
  null,
  [
    "<SOME SHORTER ID?>"
  ]
]

The app also makes one change, so one key / setting and its -value at a time. The moment you select a value in the app, the app sends that POST request with the singular changed/selected value for that one key/setting of 25 in the example above.. there's quasi no bulk changing multiple values and then committing/saving them in the app in on go.

dlarrick commented 3 months ago

FYI the latest version of PyKumo (v0.3.9) which is pulled in by hass-kumo v0.3.12 implements the ability to reboot the WiFi adapter when it sees certain API errors. I think this will help stability for folks, so thanks for finding that!

joergbattermann commented 3 months ago

FYI the latest version of PyKumo (v0.3.9) which is pulled in by hass-kumo v0.3.12 implements the ability to reboot the WiFi adapter when it sees certain API errors. I think this will help stability for folks, so thanks for finding that!

Nice, thank you!