krahabb / meross_lan

Home Assistant integration for Meross devices
MIT License
387 stars 46 forks source link

Issue on Managing MTS960 due to API change #449

Closed bernardpe closed 1 week ago

bernardpe commented 4 weeks ago

Version of the custom_component

Configuration


Add your logs here.

Describe the bug

A clear and concise description of what the bug is.

MTS960 : firmware version : 4.2.6 hardware version : 4.0.0

it seems that API on MTS960 has been change, using modeB : I found that for MTS960 :

inferring the mts960 mode is now :

MTS960_MODE_HEAT_COOL = 1 MTS960_MODE_SCHEDULE = 2 MTS960_MODE_TIMER = 3

State to know if switch is ON/OFF

mapping the "state" key value to the socket/plug action

MTS960_STATE_UNKNOWN = 0 MTS960_STATE_ON = 1 MTS960_STATE_OFF = 2 # this appears when the plug is off (why not 0?)

To now of MTS960 is on HEAT or COOL mode we need to check/set working attribut

MTS960_WORKING_HEAT = 1 MTS960_WORKING_COOL = 2

To switch OFF : we can use onof with following value

mapping the "ONOFF" key value to the socket/plug action

MTS960_ONOFF_UNKNOWN = 0 MTS960_ONOFF_ON = 1 MTS960_ONOFF_OFF = 2 # this appears when the plug is off (why not 0?)

Debug log

By Activating the trace : 2024/06/05 - 10:56:53 RX http GETACK Appliance.Control.Thermostat.ModeB {"modeB":[{"channel":0,"mode":1,"targetTemp":2500,"working":2,"currentTemp":2435,"state":2,"onoff":1,"sensorStatus":1}]}


Add your logs here.

the Fix base on dev has been done on my github

bernardpe commented 4 weeks ago

the Fix base has been done on a fork on my dev branch

krahabb commented 3 weeks ago

Hello @bernardpe, Your fix looks awesome and by looking at your repo branches I trust you've grasped the logic in my implementation so I would happily merge it into main dev. Since I've found 2 different related branches I don't know how to proceed... It would be better if you could raise a PR into my dev branch so that I could easily merge it from my repo

bernardpe commented 3 weeks ago

hi,

thanks for the feedback !

the right branch is dev_fix_mts960 the other has been created just for the report !

Do you want me to make a create a pull request ?

I'd like as well to add on the near futur :

Happy to contribute on this integration !

Bernard

bernardpe commented 3 weeks ago

PR created : Fix Issue MTS960 API change #455

bernardpe commented 3 weeks ago

Hi, I see that the pull has been done, thanks !

For Next : I do not found the way to get the preset temperature from mts960 using API, did you have any idea about this, any API documentation reference guide ?

Bernard

krahabb commented 3 weeks ago

Thank you @bernardpe !

I'd like as well to add on the near futur :

  • setup on homeassistant the Temperature range collected from API GET Appliance.Control.Thermostat.CtlRange {"ctlRange":[{"channel":0}]} 2024/06/05 - 10:56:53 RX http GETACK Appliance.Control.Thermostat.CtlRange {"ctlRange":[{"channel":0,"max":11000,"min":-3000,"ctlMax":3600,"ctlMin":300}]}
  • Adding a homeassistant entity for : -- simple entity to get temperature -- entity to get power switch status (On/Off)
  • management of 2 types of count down
  • Adding preset values getting recorded on MTS960 --> today the preset values is empty because I do not found the way to get the preset temperature from mts960 using API, did you have any idea about this, any API documentation reference guide ?

As for adding the entity for temperature (current?) I'm going to implement that since I've found it would be better to 'generalize' those sensors for other thermostats too (mts200/mts100) and mts100 already has it so I have to refactor a bit of code there... For the power switch do you mean a binary sensor reporting the current state of the output relay?

In general I don't have any idea about the real api and its meanings for this device...my work was totally 'guess-based' off a trace uploaded by another user (#356) and inferred knowledge from mts200/mts100.

This device though is anyway different from the semantics of the HA climate entity when it operates in timer/counter mode (for example we should 'disable' the target temp since it's no meaning then) but we could leverage the 'Auto'/'Presets' features of the standard climate entities to expose these 'non-standard' behaviors. There's a lot going on under the hood....

Having the device in place and still controlled by the app should be enough to infer what the different namespaces/payloads do (like you did for implementing the current fix/feature)

I guess you've already did that but you can use the tracing feature to automatically 'snapshot' the current state of all of the namespaces and then look for clues about the different settings (done through the app and hopefully recorded) in the trace.

The Download diagnostics might be even better (easier to get) if you just have to snapshot the namespaces since it does all the namespace queries in a single pass (provided the device is reachable over HTTP).

The 'tracing' instead might be helpful to also catch messages over a period of time and this could be valuable if the device has also an associated Meross cloud profile in meross_lan since this way you would also get the (eventual) pushes incoming through MQTT

If you would like to upload a 'diagnostic' or a 'trace' I could look at it and provide my thoughts: I guess the traces I have are now a bit too old since they came from a device which was pretty new at the moment and your mts960 might have more abilities than before.

bernardpe commented 3 weeks ago

hi,

thanks for your comments and sorry for the late anwser !

About the temperature, yes the idea is to have a entity with current temperature !

I thinking about having a entity to get the mode that has been selected (Cooling/Heating) because today we just know when the output power in on/off on cooling/heating !

About the timer, I already implemented on the current commit Auto mode to switch to schedule, but no way today to make distinction about schedule mode and count down !

I think that all of this is specific MTS960 and to not need any generalization !

Let me know. Bernard

bernardpe commented 3 weeks ago

Just BTW, I saw that there is a issue created on MTS960 always reported as heating mode, this is fixed on my commit as well !

Talking about issue https://github.com/krahabb/meross_lan/issues/417

Bernard

krahabb commented 2 weeks ago

Hello @bernardpe, I'm following up on this in order to try move the development to a 'stable' point and then publish a somewhat consistent set of features in the incoming Moonlight.3

As for correctly mapping the modes I'm trying to understand how this works with the 'working modes' mentioned in the official manual. I see the official Meross manual says there are 7 modes:

In my initial implementation I thought these were directly mapped '1 - 1' with the "mode" field but this is not true and you've already implemented a better mapping by using the "working" field.

Now, from the description you wrote I could infere this table:

'Meross docs' mode "mode" "working"
HEAT 1 1
COOL 1 2
CYCLE TIMER 3* unknown
COUNTDOWN ON 3* unknown
COUNTDOWN OFF 3* unknown
HEAT SCHEDULE 2* 1
COOL SCHEDULE 2* 2

*) this is my guess, I'm not sure if you intended to give these modes some logic in your patch or if they're just 'HVAC Mode -> Auto' and that's it

For the 'unknown' mappings I could guess this:

'Meross docs' mode "mode" "working"
CYCLE TIMER 3 unknown
COUNTDOWN ON 3 1
COUNTDOWN OFF 3 2

If these could be reasonable we could think of mapping these timer modes to the fan_only HVACMode so that we could have this map:

HA HVACMode "mode" "working" comment
heat 1 1 actual implementation
cool 1 2 actual implementation
auto 2 1 or 2 Use auto to set the mts960 heat/cool schedule mode (and the reverse)
fan_only 3 1 or 2 Use fan_only to set any of the timer/counter modes (and the reverse)

We could then also map the MTS960 internal state to these HVACAction:

"mode" "working" "state" HVACAction comment
1 1 1 heating manual heating mode actively heating (plug on)
1 1 2 idle manual heating mode idle(plug off)
1 2 1 cooling manual cooling mode actively cooling (plug on)
1 2 2 idle manual cooling mode idle(plug off)
2 1 1 heating schedule heating mode actively heating (plug on)
2 1 2 idle schedule heating mode idle(plug off)
2 2 1 cooling schedule cooling mode actively cooling (plug on)
2 2 2 idle schedule cooling mode idle(plug off)

Now, I want to be sure about the difference between the "state" and the "onoff" fields:

If this is correct (the general idea and the mappings of the payload fields) we could start focusing on cleaning up the management for the manual/scheduled heating/cooling modes and then, once done, proceed to find a nice implementation for the counter/timer modes.

As for the counter/timer modes we should better investigate if all of these map to "mode" == 3 or if there's another dedicated mode. In case they're all mapping to "mode" == 3, I guess the "working" field would carry the actual real mode of operation i.e. it should discriminate between countdown on countdown off cycle timer

Regarding one of your previos questions, I guess the heating/cooling schedule is carried in the Appliance.Control.Thermostat.ScheduleB message and this is actually handled in meross_lan by setting up a calendar entity (this is how's been implemented for mts100/150/200 and so ported to the mts960 too). The implementation is a bit fragile because HA calendar has a more general behavior than allowed in the mts family of schedules parameters but it is the 'closest match' entity actually available to manage the device. Also, since the different mts have slightly different rules for this message, it might be it is not working very well since the meross_lan calendar implementation was built over mts100 and then copied/adapted to mts200

Another question was about how to configure the 'preset' and the temperature control range.

There's a lot to be defined but, as I've said, we could start focusing on finishing up (somehow) the heating/cooling schedule mode.

krahabb commented 2 weeks ago

I've also created a dedicated branch for this job so we can focus on modifications about the mts960.

bernardpe commented 2 weeks ago

Hi

Thanks for the comments but the fact is not as easy as you mention

Yes mode on doc is not mode on api ! Yes there is only 3 mode on api : Count down on / count down off / cycle is managed as a timer on the api (and btw on ui app) Onoff is on when the device manage one of the 3 mode onOff is off when all mode are disable and output power are off

I still trying to found using api how to get preset temperature (there is 3 and we can add some using app !), I verified that the data is really recorded to device because preset temperature is showing up on a other app.

Yes today auto = scheduled on my implementation using fan only for timer (count down on / off and cycled mode) make sense I will make the change

The issue when the calendar today implementation is that do not reflect setting on device, I will check how to do better

Regards Bernard

bernardpe commented 2 weeks ago

Just adding that scheduled mode works on me previous comments

Just count down on/off and cycled are reported as auto

That why I d like to add an entity to report the "user" mode (the 7 is the doc)

bernardpe commented 2 weeks ago

Adding a other comment

Mode 1 is not a manual mode this is a auto mode depending the temperature (output power managed by device) On heating working : current temperature lower then temperature selected : output on instead off On cooling working : current temperature greater then temperature selected : output on instead off

Note : not as simple : starting Output power depend delta temperature current vs temperature selected

krahabb commented 2 weeks ago

Yep 'manual' I mean you manually set the target temperature ("mode" == 1): this is in contrast with 'scheduled/auto' ("mode"==3). I guess we're just using different names but we agree on the meaning ;)

I'm refactoring a bit the code (nothing big tbh) implementing also a basic 'ctlRange' parsing (not sure I got the correct values there: I think the 'max/min' are the general thermostat target temp limits, the 'ctlMax/ctlMin' dunno really).

P.S. if you could post a 'Download diagnostics' of your mts960 I could inspect that for clues since the trace I have might be a bit old and lacks a lot of namespaces/data

bernardpe commented 2 weeks ago

Hi, I just commited fan_only for Timer (count_down and cycle) and I made a change on CtlRange for MTS960 because we need to use KEY_CTLMAX and KEY_CTLMIN instead of KEY_MAX and KEY_MIN

Because is we use KEY_MAX/KEY_MIN and when we setup a target temp outside range of KEY_CTLMIN/KEY_CTLMAX this will be not take in account !

I will now add an entities for :

and next will be to implement properly alarm (high, low).

About Preset Temperature I just validate using wireshark that this preset is only recorded on the MQTT Broker and not on the device !

Bernard

bernardpe commented 2 weeks ago

hi,

I just commited a bush of modifications : 1/ display precision for current generic temperature is now 1 instead of 2 commit : Set the suggested_display_precision to 2 for the current temperature /// Sorry about comment now clear ! 2/ Add a Generic output power entity By adding on the init a parameter True for has_sensor_output_power and _update_output_power(True/False) to set the value of the entity 3/ issue on configuration parameter of the device (like Lock etc...) was not working on MTS960 ==> We need to send a array of payload ! manager._push_payload_data_as_array = True to configure this 4/ Multiple issue on calendar a/ management of number of schedule per days using section from json, on my case this is 12 ! got issue when trying to add more section (parameter manage_key_section) b/ issue when updating scheduler when a day of week got multiple entry and the days after got 1 only the entry was copied to from previous days, to fix this we need to add as many as entry there are on the section value entry with [0, temp of the first] this is activated when parameter manage_key_section is activated c/ bad Temperature scaling using 10 instead of climate.device_scale when updated temperature from hass scheduler d/ unable to update first event of a day, update is delete + insert for deletion of the first is not allowed ! how we catch the deletion and perform the update e/ Management of FREQ=week and BYDAY is selected much more easy to insert multiple scheduler ! f/ Issue when received MQTT message : the hass is not updated because there is no deepcopy of native_scheduler !

The calendar is now working add/update/delete and update from device

Working now on Mode Status report as entity

bernardpe commented 1 week ago

hi,

the Mode Status entity has been commited just now.

Report Cooling/Heating/Schedule Cool/Scheduling Heat/Countdown On/Countdown Off/Cycle/Off there is a extra attribut to inform the Type of Timer.

I added the NameSpace NS_APPLIANCE_CONTROL_THERMOSTAT_TIMER on the pooling, in case of no MQTT. attention get for this name space is not working (return empty information) we need to send a METHOD PUSH with timer empty to get the current timer value !

Question: Frost Warning is not only Frost is Device Warning, I think is make sense to change the wording ?

on the device MTS960 there multiple alarm : High Temperature Warning Low Temperature Warning Sensor Warning

I think it make sense develop on the config form for MTS960 the setting of this 3 alarm type ?

I wanted to be able to setup a Timer (downdown On/Off, Cycle) do you have a idea how we can integrate a custom form to be able to make this ? Or another idea for this ?

Bernard

bernardpe commented 1 week ago

Commited right now better management of Frost Config. 1/ change Label from Frost_switch to Frost Alarm 2/ Hide Frost Temperature when Frost Alarm is off

krahabb commented 1 week ago

Hello @bernardpe , sorry for not being able to follow up on the job you're doing. I'll take the time to get back to it anyway.

I see there are not (yet) PRs for the merge so I cannot easily check this. Since the dev branch is diverging a bit I've created a more dedicated branch for you to merge (dev_mts960_bernardpe) so that any merge of your work should be succesful without any collision due to my attitutde to keep refactoring the whole codebase (in the dev branch)

I'll let you know my thoughts... Just a quick feedback: Some namespaces appear to not respond to GET and the NS_APPLIANCE_CONTROL_THERMOSTAT_TIMER is likely falling in this category. I don't know why it works like this but that's it. Some other users had then discovered that an empty PUSH instead works and is replied with the current info from the device so you've found the correct way for this NS to be queried..good job ;) In meross_lan there are some use-cases for this, for example the FAN_FILTERMAINTENANCE namespace works exactly like this.

bernardpe commented 1 week ago

Hi

Thanks for the answer

I will do a PR for tomorrow !

There is some change that is might interesting to check to activate the evolution for other mts ?

Right now most of the evolution is only activated to mts960

Bernard

krahabb commented 1 week ago

Well..if you edited the code for the classes in thermostat.py directly then it'll be surely shared with the same entities for the mts200 since the pool of entities is the same

bernardpe commented 1 week ago

Yes this is why i setup a mask on class init to address the fix/evolution !

This should guaranty that i should not break other devices !

Btw any idea to setup timer countdown/cycle ?

krahabb commented 1 week ago

Not really...the TIMER namespace doesn't tell anything ? You could share either a device diagnostic or a debug 'trace' (the one activated from the device 'Diagnostics' menu so that I could see what's going on and get some ideas

bernardpe commented 1 week ago

PR done right now : https://github.com/krahabb/meross_lan/pull/464

Available for any comments

krahabb commented 1 week ago

Hello @bernardpe, I'm starting to review your modifications. I'll try to follow-up step by step in order to simplify the process.

First question: Why did you add the _push_payload_data_as_array to MerossDeviceBase ? I guess this is a patch for Appliance.Control.PhysicalLock management when you send the command to enable/disable the lock. If this is true I'd refactor your patch in order to use the correct mixin since there's already a specialized class for this. Actually the PhysicalLockSwitch class uses the MEDictChannelMixin (which is specialized to send dicts) but this is wrong of course and if the PhysicalLock needs lists I'd just replace the MEDictChannelMixin with MEListChannelMixin without the need for the patch with _push_payload_data_as_array

bernardpe commented 1 week ago

Hi,

This was me initial idea to MEListChannelMixin, but the class PhysicalLockSwitch is used by some other devices and I assumed that for the other devices is working fine !

that we I made this to force always as a array because MTS960 always allow array !

Now we can change to use MEListChannelMixin ?

Let me know Bernard

krahabb commented 1 week ago

Don't worry about the fix, I'll review and edit step-by step while keeping pushing the commits to the repo so taht you can eventually sync whenever you want. They're anyway going to be little fixes I guess.

As for not disrupting other devices I cannot say: to be honest the implementation with the dict was never confirmed to be working and was just a 'guess' so, if the list payload works for your mts960 we're going to use that for now..eventually we will study another solution but I prefer to not break the philosophy of those mixins which are very specialized for the task of formatting the SET payloads.

krahabb commented 1 week ago

I see you've added the classManageAvailableSwitch to put offline the temperature entities (MtsRichTemperatureNumber) when the related switch is off. I really don't like it since I don't see the need to set these entities 'offline' and this could also interfere with the general onlining/offlining of the entities as it is now managed by the underlying device/manager. Also, having some entities in the HA dashboard reported as 'unavailable' might confuse someone else thinking something is not working. I'd rather prefer to eventually disable these entities so that they'll totally disappear from HA UI (this is for example implemented in MSG200 multi-channel garage door device where you can disable any door in the app and this will be replied in meross_lan by totally disabling those entities).

To be honest I don't really like that either because when you enable/disable entities 'on the fly' in HA it always needs some time to refresh (30 sec if I'm not wrong after enabling) and the UI also remains 'dirty' unless you refresh the page...

I want to think a bit about this and listen your arguments pros/cons for the matter.

bernardpe commented 1 week ago

Hi,

I set off this parameter because changing the temperature of Frost when Frost switch of off generate a error !!

This is not allowed and do not make sense, on the app UI we got the same, when Frost Alarm is off we can not change Frost Temperature, only when frost Alarm is on we can set the temperature, and it make sense !

bernardpe commented 1 week ago

available / unavailable is not disable/enable !

Look after 2 days still grey

image

bernardpe commented 1 week ago

And when I put enable it becomes as before : image

There is many integration who works like this, I to now understand you comments about "30 sec if I'm not wrong after enabling" ?

I can refresh, use a other device no problem the entity are still grey. Please explain I'm interesting ?

bernardpe commented 1 week ago

Still Enable when UnAvailable is set :

image

krahabb commented 1 week ago

Ok..that's a very good reason!

In HA you know, you can manually disable/enable entities from UI but this could also be done in code. When an entity is 'disabled' it is almost totally hidden from HA and it doesn't show in the state of the machine: it is like 'non existent' except, you can find it in th elist of disabled entities and eventually re-anable it so to make it 'live' again.

This way, a disabled entity doesn't occupy memory in the whole HA state and this helps performance

krahabb commented 1 week ago

As in my previous post, the problem with enabling/disabling is that the HA UI is not refreshed immediately (while putting the state to 'unavailable' is faster and the UI gets refreshed instantly

bernardpe commented 1 week ago

Yes this is what I'm doing set available/unavailable and I prefer to let the user to setup Enable/disable an entity !

After on the history it is better as well because when Frost Alarm is disable the Frost Temperature is reported as unavailable ! image

krahabb commented 1 week ago

I'll think a bit about the two approaches: available/unavailable <-> enabled/disabled. Both have pros/cons and you're right: using availability seems 'flawless' but in my opinion, in normal usage, the associated switch is a kind of configuration so you either activate/deactivate the function and then you 'forget' about it (I don't think people would turn on/off frost protection every day or every month: they'll maybe use it one time per year. Having access to the temperature charts is no point when you're not using frost protection (switch off) and you have an unused entity on the dashboard

krahabb commented 1 week ago

But you're right, people could always manually disable them ...

krahabb commented 1 week ago

Your idea of enabling/disabling is nice though...I'm going to see if I can implement this kind of behavior at the 'core' of meross_lan so to have this behavior for other devices/entities too.

bernardpe commented 1 week ago

👍 Because I'm on the same situation with AlarmLow & AlarmHigh !

krahabb commented 1 week ago

I guess I've found a solution to mantain the behavior while just simplifying a bit of code. commit done.

krahabb commented 1 week ago

As for today I'm done..we'll see tomorrow the next ;)

bernardpe commented 1 week ago

hi, I think there is a problem on your commit because the Temperature is no more set a unavailable and when starting with unavailable no more set as available ! image image

I will check where the issue is coming !

bernardpe commented 1 week ago

I see the issue is that you only set available / unavailable from Temperature entity but me commit made as the available on/off from the switch entity this was better to be sure that status available/unavailable is aligned to the status of the switch !

That why I send Temperature Entity to switch entity me make this sync always !

krahabb commented 1 week ago

I see..when you toggle the switch from HA the state of the temperature is only refreshed after a while (after polling) I'll fix that I have an idea

bernardpe commented 1 week ago

I do not think that is the issue

Because on your implementation there is no way that the toggle on ha will change the status available

I made the test with http only !

We need to have a mechanism to change the status available from the toggle as I made before to get the think working

krahabb commented 1 week ago

Yep..doing that

krahabb commented 1 week ago

I've fixed (I hope so) the problem. I've also updated the test suite to better manage this new behavior but there's still some issues in testing. The problem is the 'Unauthorized' exception when you select HVACMode -> FAN_ONLY. Why is that? Shouldn't be possible to set the mts_mode -> mc.MTS960_MODE_TIMER ? Does the mts960 accept that?

bernardpe commented 1 week ago

Hi

This is normal Because setting a timer mode need to make some choice Count down on for how long ? Count down off for how long ? Cycle on duration / off duration?

This is not developed!, next steps !

Today fan_only is only a "reported" mode (initiated by meross app for example !) but not initiated by hass

That why there is today a exeption when we choose fan_only mode from hass !

krahabb commented 1 week ago

Yeah..that's an issue..I was guessing so..tomorrow I'll propose you something about it

bernardpe commented 1 week ago

This is not really an issue !

Is report that the fan_only is not authorized (exception generated be me) from now seams not a issue for me.

It is better than before where mts960 integration was not managing at all timers !

Reporting of timers works but not authorized to set a new timer as the exception report !