From c72260835e82be9d05887ee8931558d2ced1cb36 Mon Sep 17 00:00:00 2001 From: impulsio <33810912+impulsio@users.noreply.github.com> Date: Tue, 9 Jul 2024 20:55:25 +0200 Subject: [PATCH 01/14] mfaLockExpire not transmitted by Meross --- meross_iot/http_api.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/meross_iot/http_api.py b/meross_iot/http_api.py index b8536ce..2e9fe07 100644 --- a/meross_iot/http_api.py +++ b/meross_iot/http_api.py @@ -270,6 +270,12 @@ async def async_login(cls, _LOGGER.info(f"Login successful against {api_base_url}") + try: + response_data["mfaLockExpire"] + except NameError: + response_data["mfaLockExpire"]="" + + creds = MerossCloudCreds( token=response_data["token"], key=response_data["key"], From 457d1b758f027e2f021ee949b898ad7d5068a1d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20ROUSSEAU?= Date: Sat, 19 Oct 2024 14:50:55 +0200 Subject: [PATCH 02/14] Add MODEB for MTS960 --- meross_iot/controller/mixins/thermostat.py | 120 +++++++++++++++++++++ meross_iot/model/enums.py | 3 + 2 files changed, 123 insertions(+) diff --git a/meross_iot/controller/mixins/thermostat.py b/meross_iot/controller/mixins/thermostat.py index d10a5ea..60785c6 100644 --- a/meross_iot/controller/mixins/thermostat.py +++ b/meross_iot/controller/mixins/thermostat.py @@ -242,3 +242,123 @@ async def async_set_thermostat_config(self, timeout=timeout) mode_data = result.get('mode') self._update_mode(mode_data) + +class ThermostatModeBMixin: + _execute_command: callable + check_full_update_done: callable + _thermostat_state_by_channel: Dict[int, ThermostatState] + + def __init__(self, device_uuid: str, + manager, + **kwargs): + super().__init__(device_uuid=device_uuid, manager=manager, **kwargs) + self._thermostat_state_by_channel = {} + + def _update_mode(self, mode_data: Dict): + # The MTS200 thermostat does bring a object for every sensor/channel it handles. + for c in mode_data: + channel_index = c['channel'] + state = self._thermostat_state_by_channel.get(channel_index) + if state is None: + state = ThermostatState(c) + self._thermostat_state_by_channel[channel_index] = state + else: + state.update(c) + + async def async_handle_push_notification(self, namespace: Namespace, data: dict) -> bool: + locally_handled = False + + if namespace == Namespace.CONTROL_THERMOSTAT_MODEB: + _LOGGER.debug(f"{self.__class__.__name__} handling push notification for namespace " + f"{namespace}") + mode_data = data.get('modeb') + if mode_data is None: + _LOGGER.error(f"{self.__class__.__name__} could not find 'modeb' attribute in push notification data: " + f"{data}") + locally_handled = False + else: + self._update_mode(mode_data) + locally_handled = True + + # Always call the parent handler when done with local specific logic. This gives the opportunity to all + # ancestors to catch all events. + parent_handled = await super().async_handle_push_notification(namespace=namespace, data=data) + return locally_handled or parent_handled + + async def async_handle_update(self, namespace: Namespace, data: dict) -> bool: + _LOGGER.debug(f"Handling {self.__class__.__name__} mixin data update.") + locally_handled = False + if namespace == Namespace.SYSTEM_ALL: + thermostat_data = data.get('all', {}).get('digest', {}).get('thermostat', {}) + mode_data = thermostat_data.get('modeb') + if mode_data is not None: + self._update_mode(mode_data) + locally_handled = True + + super_handled = await super().async_handle_update(namespace=namespace, data=data) + return super_handled or locally_handled + + def get_thermostat_state(self, channel: int = 0, *args, **kwargs) -> Optional[ThermostatState]: + """ + Returns the current thermostat state + :param channel: + :param args: + :param kwargs: + :return: + """ + self.check_full_update_done() + state = self._thermostat_state_by_channel.get(channel) + return state + + def _align_temp(self, temperature:float, channel: int = 0) -> float: + """ + Given an input temperature for a specific channel, checks if the temperature is within the ranges + of acceptable values and rounds it to the nearest 0.5 value. It also applies the 10x multiplication + as Meross devices requires decimal-degrees + """ + # Retrieve the min/max settable values from the state. + # If this is not available, assume some defaults + channel_state = self._thermostat_state_by_channel.get(channel) + min_settable_temp = _THERMOSTAT_MIN_SETTABLE_TEMP + max_settable_temp = _THERMOSTAT_MIN_SETTABLE_TEMP + if channel_state is not None: + min_settable_temp = channel_state.min_temperature_celsius + max_settable_temp = channel_state.max_temperature_celsius + + if temperature < min_settable_temp or temperature > max_settable_temp: + raise ValueError("The provided temperature value is invalid or out of range for this device.") + + # Round temp value to 0.5 + quotient = temperature/0.5 + quotient = round(quotient) + final_temp = quotient*5 + return final_temp + + async def async_set_thermostat_config(self, + channel: int = 0, + mode: Optional[ThermostatMode] = None, + target_temperature_celsius: Optional[float] = None, + on_not_off: Optional[bool] = None, + timeout: Optional[float] = None, + *args, + **kwargs) -> None: + channel_conf = { + 'channel': channel + } + payload = {'modeb': [channel_conf]} + + # Arg check + if mode is not None: + channel_conf['mode'] = mode.value + if manual_temperature_celsius is not None: + channel_conf['targetTemp'] = self._align_temp(target_temperature_celsius, channel=channel) + if on_not_off is not None: + channel_conf['onoff'] = 1 if on_not_off else 0 + + # This api call will return the updated state of the device. We use it to update the internal state right away. + result = await self._execute_command(method="SET", + namespace=Namespace.CONTROL_THERMOSTAT_MODEB, + payload=payload, + timeout=timeout) + mode_data = result.get('modeb') + self._update_mode(mode_data) diff --git a/meross_iot/model/enums.py b/meross_iot/model/enums.py index 2779638..f1e95bd 100644 --- a/meross_iot/model/enums.py +++ b/meross_iot/model/enums.py @@ -139,6 +139,9 @@ class Namespace(Enum): CONTROL_THERMOSTAT_MODE = 'Appliance.Control.Thermostat.Mode' CONTROL_THERMOSTAT_WINDOWOPENED = 'Appliance.Control.Thermostat.WindowOpened' + # Thermostat / MTS960 + CONTROL_THERMOSTAT_MODEB = 'Appliance.Control.Thermostat.ModeB' + def get_or_parse_namespace(namespace: Union[Namespace, str]): if isinstance(namespace, str): From 44324eb8938669be7a4c70d776c004f319f71fb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20ROUSSEAU?= Date: Sat, 19 Oct 2024 15:29:15 +0200 Subject: [PATCH 03/14] Update http_api.py --- meross_iot/http_api.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/meross_iot/http_api.py b/meross_iot/http_api.py index 4c160bc..dfd705d 100644 --- a/meross_iot/http_api.py +++ b/meross_iot/http_api.py @@ -270,12 +270,6 @@ async def async_login(cls, _LOGGER.info(f"Login successful against {api_base_url}") - try: - response_data["mfaLockExpire"] - except NameError: - response_data["mfaLockExpire"]="" - - creds = MerossCloudCreds( token=response_data["token"], key=response_data["key"], From 347f604ba4778684e739fecf3a73c968a32baf33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20ROUSSEAU?= Date: Sat, 19 Oct 2024 15:32:14 +0200 Subject: [PATCH 04/14] Add ModeB to device factory --- meross_iot/device_factory.py | 1 + 1 file changed, 1 insertion(+) diff --git a/meross_iot/device_factory.py b/meross_iot/device_factory.py index 50ee967..88eaa31 100644 --- a/meross_iot/device_factory.py +++ b/meross_iot/device_factory.py @@ -80,6 +80,7 @@ # Thermostat Namespace.CONTROL_THERMOSTAT_MODE.value: ThermostatModeMixin, + Namespace.CONTROL_THERMOSTAT_MODEB.value: ThermostatModeBMixin, # TODO: BIND, UNBIND, ONLINE, WIFI, ETC! } From 7b33c4d1e485ce22fffe5233cf9e18ecf2b70901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20ROUSSEAU?= Date: Sat, 19 Oct 2024 15:37:38 +0200 Subject: [PATCH 05/14] Update device_factory.py --- meross_iot/device_factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meross_iot/device_factory.py b/meross_iot/device_factory.py index 88eaa31..8f500c0 100644 --- a/meross_iot/device_factory.py +++ b/meross_iot/device_factory.py @@ -15,7 +15,7 @@ from meross_iot.controller.mixins.runtime import SystemRuntimeMixin from meross_iot.controller.mixins.spray import SprayMixin from meross_iot.controller.mixins.system import SystemAllMixin, SystemOnlineMixin -from meross_iot.controller.mixins.thermostat import ThermostatModeMixin +from meross_iot.controller.mixins.thermostat import ThermostatModeMixin, ThermostatModeBMixin from meross_iot.controller.mixins.toggle import ToggleXMixin, ToggleMixin from meross_iot.controller.subdevice import Mts100v3Valve, Ms100Sensor from meross_iot.model.enums import Namespace From 25b44cdb01c3458c84f3fd6f138eaf603511a290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20ROUSSEAU?= Date: Sat, 19 Oct 2024 15:51:48 +0200 Subject: [PATCH 06/14] Update thermostat.py --- meross_iot/controller/mixins/thermostat.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/meross_iot/controller/mixins/thermostat.py b/meross_iot/controller/mixins/thermostat.py index 60785c6..d046d48 100644 --- a/meross_iot/controller/mixins/thermostat.py +++ b/meross_iot/controller/mixins/thermostat.py @@ -271,9 +271,9 @@ async def async_handle_push_notification(self, namespace: Namespace, data: dict) if namespace == Namespace.CONTROL_THERMOSTAT_MODEB: _LOGGER.debug(f"{self.__class__.__name__} handling push notification for namespace " f"{namespace}") - mode_data = data.get('modeb') + mode_data = data.get('modeB') if mode_data is None: - _LOGGER.error(f"{self.__class__.__name__} could not find 'modeb' attribute in push notification data: " + _LOGGER.error(f"{self.__class__.__name__} could not find 'modeB' attribute in push notification data: " f"{data}") locally_handled = False else: @@ -290,7 +290,7 @@ async def async_handle_update(self, namespace: Namespace, data: dict) -> bool: locally_handled = False if namespace == Namespace.SYSTEM_ALL: thermostat_data = data.get('all', {}).get('digest', {}).get('thermostat', {}) - mode_data = thermostat_data.get('modeb') + mode_data = thermostat_data.get('modeB') if mode_data is not None: self._update_mode(mode_data) locally_handled = True @@ -345,7 +345,7 @@ async def async_set_thermostat_config(self, channel_conf = { 'channel': channel } - payload = {'modeb': [channel_conf]} + payload = {'modeB': [channel_conf]} # Arg check if mode is not None: @@ -360,5 +360,5 @@ async def async_set_thermostat_config(self, namespace=Namespace.CONTROL_THERMOSTAT_MODEB, payload=payload, timeout=timeout) - mode_data = result.get('modeb') + mode_data = result.get('modeB') self._update_mode(mode_data) From c50fe6ed975655d01dda42ddabebed5ef96cce03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20ROUSSEAU?= Date: Sat, 19 Oct 2024 17:09:07 +0200 Subject: [PATCH 07/14] Adding working & state for thermostat mode B --- meross_iot/controller/mixins/thermostat.py | 18 +++++++++++++++++- meross_iot/model/enums.py | 10 ++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/meross_iot/controller/mixins/thermostat.py b/meross_iot/controller/mixins/thermostat.py index d046d48..995cf8a 100644 --- a/meross_iot/controller/mixins/thermostat.py +++ b/meross_iot/controller/mixins/thermostat.py @@ -2,7 +2,7 @@ from typing import Optional, List, Dict from meross_iot.controller.device import ChannelInfo -from meross_iot.model.enums import Namespace, ThermostatMode +from meross_iot.model.enums import Namespace, ThermostatMode, ThermostatWorkingMode, ThermostatState _LOGGER = logging.getLogger(__name__) @@ -41,6 +41,22 @@ def mode(self) -> Optional[ThermostatMode]: return None return ThermostatMode(mode) + @property + def workingMode(self) -> Optional[ThermostatWorkingMode]: + """The current thermostat working mode""" + mode = self._state.get('working') + if mode is None: + return None + return ThermostatWorkingMode(mode) + + @property + def state(self) -> Optional[ThermostatState]: + """The current thermostat state""" + state = self._state.get('state') + if state is None: + return None + return ThermostatState(state) + @property def warning(self) -> Optional[bool]: """The warning state of the thermostat""" diff --git a/meross_iot/model/enums.py b/meross_iot/model/enums.py index f1e95bd..9f025f0 100644 --- a/meross_iot/model/enums.py +++ b/meross_iot/model/enums.py @@ -55,6 +55,16 @@ class ThermostatMode(Enum): MANUAL = 4 +class ThermostatWorkingMode(Enum): + HEAT = 1 + COOL = 2 + + +class ThermostatState(Enum): + HEATING_COOLING = 1 + NOT_HEATING_COOLING = 2 + + class RollerShutterState(Enum): UNKNOWN = -1 IDLE = 0 From 534dbb79a14b3eb831cd31618cc98817321a1474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20ROUSSEAU?= Date: Sat, 19 Oct 2024 20:55:05 +0200 Subject: [PATCH 08/14] ThermostatState already exist --- meross_iot/controller/mixins/thermostat.py | 6 +++--- meross_iot/model/enums.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/meross_iot/controller/mixins/thermostat.py b/meross_iot/controller/mixins/thermostat.py index 995cf8a..ddd8d84 100644 --- a/meross_iot/controller/mixins/thermostat.py +++ b/meross_iot/controller/mixins/thermostat.py @@ -2,7 +2,7 @@ from typing import Optional, List, Dict from meross_iot.controller.device import ChannelInfo -from meross_iot.model.enums import Namespace, ThermostatMode, ThermostatWorkingMode, ThermostatState +from meross_iot.model.enums import Namespace, ThermostatMode, ThermostatWorkingMode, ThermostatModeBState _LOGGER = logging.getLogger(__name__) @@ -50,12 +50,12 @@ def workingMode(self) -> Optional[ThermostatWorkingMode]: return ThermostatWorkingMode(mode) @property - def state(self) -> Optional[ThermostatState]: + def state(self) -> Optional[ThermostatModeBState]: """The current thermostat state""" state = self._state.get('state') if state is None: return None - return ThermostatState(state) + return ThermostatModeBState(state) @property def warning(self) -> Optional[bool]: diff --git a/meross_iot/model/enums.py b/meross_iot/model/enums.py index 9f025f0..947e1eb 100644 --- a/meross_iot/model/enums.py +++ b/meross_iot/model/enums.py @@ -60,7 +60,7 @@ class ThermostatWorkingMode(Enum): COOL = 2 -class ThermostatState(Enum): +class ThermostatModeBState(Enum): HEATING_COOLING = 1 NOT_HEATING_COOLING = 2 From 5bc6bc1be7f08fa437eb15df443906f22c76a8a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20ROUSSEAU?= Date: Sat, 19 Oct 2024 21:14:17 +0200 Subject: [PATCH 09/14] Update thermostat.py --- meross_iot/controller/mixins/thermostat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meross_iot/controller/mixins/thermostat.py b/meross_iot/controller/mixins/thermostat.py index ddd8d84..611b732 100644 --- a/meross_iot/controller/mixins/thermostat.py +++ b/meross_iot/controller/mixins/thermostat.py @@ -366,7 +366,7 @@ async def async_set_thermostat_config(self, # Arg check if mode is not None: channel_conf['mode'] = mode.value - if manual_temperature_celsius is not None: + if target_temperature_celsius is not None: channel_conf['targetTemp'] = self._align_temp(target_temperature_celsius, channel=channel) if on_not_off is not None: channel_conf['onoff'] = 1 if on_not_off else 0 From 8224ddc0561c0e83fbf067d3c0f0a1a4f4dbb506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20ROUSSEAU?= Date: Sat, 19 Oct 2024 21:27:04 +0200 Subject: [PATCH 10/14] Update thermostat.py --- meross_iot/controller/mixins/thermostat.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/meross_iot/controller/mixins/thermostat.py b/meross_iot/controller/mixins/thermostat.py index 611b732..cb56343 100644 --- a/meross_iot/controller/mixins/thermostat.py +++ b/meross_iot/controller/mixins/thermostat.py @@ -205,15 +205,15 @@ def _align_temp(self, temperature:float, channel: int = 0) -> float: """ # Retrieve the min/max settable values from the state. # If this is not available, assume some defaults - channel_state = self._thermostat_state_by_channel.get(channel) - min_settable_temp = _THERMOSTAT_MIN_SETTABLE_TEMP - max_settable_temp = _THERMOSTAT_MIN_SETTABLE_TEMP - if channel_state is not None: - min_settable_temp = channel_state.min_temperature_celsius - max_settable_temp = channel_state.max_temperature_celsius - - if temperature < min_settable_temp or temperature > max_settable_temp: - raise ValueError("The provided temperature value is invalid or out of range for this device.") + #channel_state = self._thermostat_state_by_channel.get(channel) + #min_settable_temp = _THERMOSTAT_MIN_SETTABLE_TEMP + #max_settable_temp = _THERMOSTAT_MIN_SETTABLE_TEMP + #if channel_state is not None: + # min_settable_temp = channel_state.min_temperature_celsius + # max_settable_temp = channel_state.max_temperature_celsius + + #if temperature < min_settable_temp or temperature > max_settable_temp: + # raise ValueError("The provided temperature value is invalid or out of range for this device.") # Round temp value to 0.5 quotient = temperature/0.5 From 3abd5a3967e7576a93ee56cb2bf43a55217afb84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20ROUSSEAU?= Date: Sat, 19 Oct 2024 21:27:47 +0200 Subject: [PATCH 11/14] Update thermostat.py --- meross_iot/controller/mixins/thermostat.py | 34 +++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/meross_iot/controller/mixins/thermostat.py b/meross_iot/controller/mixins/thermostat.py index cb56343..598a00d 100644 --- a/meross_iot/controller/mixins/thermostat.py +++ b/meross_iot/controller/mixins/thermostat.py @@ -205,15 +205,15 @@ def _align_temp(self, temperature:float, channel: int = 0) -> float: """ # Retrieve the min/max settable values from the state. # If this is not available, assume some defaults - #channel_state = self._thermostat_state_by_channel.get(channel) - #min_settable_temp = _THERMOSTAT_MIN_SETTABLE_TEMP - #max_settable_temp = _THERMOSTAT_MIN_SETTABLE_TEMP - #if channel_state is not None: - # min_settable_temp = channel_state.min_temperature_celsius - # max_settable_temp = channel_state.max_temperature_celsius + channel_state = self._thermostat_state_by_channel.get(channel) + min_settable_temp = _THERMOSTAT_MIN_SETTABLE_TEMP + max_settable_temp = _THERMOSTAT_MIN_SETTABLE_TEMP + if channel_state is not None: + min_settable_temp = channel_state.min_temperature_celsius + max_settable_temp = channel_state.max_temperature_celsius - #if temperature < min_settable_temp or temperature > max_settable_temp: - # raise ValueError("The provided temperature value is invalid or out of range for this device.") + if temperature < min_settable_temp or temperature > max_settable_temp: + raise ValueError("The provided temperature value is invalid or out of range for this device.") # Round temp value to 0.5 quotient = temperature/0.5 @@ -334,15 +334,15 @@ def _align_temp(self, temperature:float, channel: int = 0) -> float: """ # Retrieve the min/max settable values from the state. # If this is not available, assume some defaults - channel_state = self._thermostat_state_by_channel.get(channel) - min_settable_temp = _THERMOSTAT_MIN_SETTABLE_TEMP - max_settable_temp = _THERMOSTAT_MIN_SETTABLE_TEMP - if channel_state is not None: - min_settable_temp = channel_state.min_temperature_celsius - max_settable_temp = channel_state.max_temperature_celsius - - if temperature < min_settable_temp or temperature > max_settable_temp: - raise ValueError("The provided temperature value is invalid or out of range for this device.") + # channel_state = self._thermostat_state_by_channel.get(channel) + # max_settable_temp = _THERMOSTAT_MIN_SETTABLE_TEMP + # min_settable_temp = _THERMOSTAT_MIN_SETTABLE_TEMP + # if channel_state is not None: + # min_settable_temp = channel_state.min_temperature_celsius + # max_settable_temp = channel_state.max_temperature_celsius + + # if temperature < min_settable_temp or temperature > max_settable_temp: + # raise ValueError("The provided temperature value is invalid or out of range for this device.") # Round temp value to 0.5 quotient = temperature/0.5 From 64a82eecbf1bd4db8a438e3cb10790f714af4549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20ROUSSEAU?= Date: Sat, 19 Oct 2024 21:40:04 +0200 Subject: [PATCH 12/14] Update thermostat.py --- meross_iot/controller/mixins/thermostat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meross_iot/controller/mixins/thermostat.py b/meross_iot/controller/mixins/thermostat.py index 598a00d..b71e499 100644 --- a/meross_iot/controller/mixins/thermostat.py +++ b/meross_iot/controller/mixins/thermostat.py @@ -352,7 +352,7 @@ def _align_temp(self, temperature:float, channel: int = 0) -> float: async def async_set_thermostat_config(self, channel: int = 0, - mode: Optional[ThermostatMode] = None, + mode: Optional[ThermostatWorkingMode] = None, target_temperature_celsius: Optional[float] = None, on_not_off: Optional[bool] = None, timeout: Optional[float] = None, From 88d9807eac83060ce2cb683eecb9de0edd2a47c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20ROUSSEAU?= Date: Sat, 19 Oct 2024 21:45:01 +0200 Subject: [PATCH 13/14] Update thermostat.py --- meross_iot/controller/mixins/thermostat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meross_iot/controller/mixins/thermostat.py b/meross_iot/controller/mixins/thermostat.py index b71e499..f675801 100644 --- a/meross_iot/controller/mixins/thermostat.py +++ b/meross_iot/controller/mixins/thermostat.py @@ -365,7 +365,7 @@ async def async_set_thermostat_config(self, # Arg check if mode is not None: - channel_conf['mode'] = mode.value + channel_conf['working'] = mode.value if target_temperature_celsius is not None: channel_conf['targetTemp'] = self._align_temp(target_temperature_celsius, channel=channel) if on_not_off is not None: From 56a9accebd72e452d1c9f4cd17128cac92e09d65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20ROUSSEAU?= Date: Sat, 19 Oct 2024 21:49:56 +0200 Subject: [PATCH 14/14] Update thermostat.py --- meross_iot/controller/mixins/thermostat.py | 1 + 1 file changed, 1 insertion(+) diff --git a/meross_iot/controller/mixins/thermostat.py b/meross_iot/controller/mixins/thermostat.py index f675801..4b04ba0 100644 --- a/meross_iot/controller/mixins/thermostat.py +++ b/meross_iot/controller/mixins/thermostat.py @@ -371,6 +371,7 @@ async def async_set_thermostat_config(self, if on_not_off is not None: channel_conf['onoff'] = 1 if on_not_off else 0 + _LOGGER.debug("payload:"+str(payload)) # This api call will return the updated state of the device. We use it to update the internal state right away. result = await self._execute_command(method="SET", namespace=Namespace.CONTROL_THERMOSTAT_MODEB,