From 0985ad64f29dbf5b526b28415d5a9bed5c7de4d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Villagra?= Date: Tue, 10 Aug 2021 19:17:56 +0100 Subject: [PATCH 01/16] add climate implementation --- custom_components/localtuya/climate.py | 371 ++++++++++++++++++ custom_components/localtuya/const.py | 21 +- .../localtuya/translations/en.json | 40 +- 3 files changed, 429 insertions(+), 3 deletions(-) create mode 100644 custom_components/localtuya/climate.py diff --git a/custom_components/localtuya/climate.py b/custom_components/localtuya/climate.py new file mode 100644 index 0000000..fe4eab3 --- /dev/null +++ b/custom_components/localtuya/climate.py @@ -0,0 +1,371 @@ +"""Platform to locally control Tuya-based climate devices.""" +import asyncio +import logging +import json +from functools import partial +import json + +import voluptuous as vol +from homeassistant.components.climate import ( + DEFAULT_MAX_TEMP, + DEFAULT_MIN_TEMP, + DOMAIN, + ClimateEntity, +) +from homeassistant.components.climate.const import ( + HVAC_MODE_AUTO, + HVAC_MODE_HEAT, + HVAC_MODE_OFF, + HVAC_MODE_COOL, + HVAC_MODE_HEAT_COOL, + HVAC_MODE_DRY, + HVAC_MODE_FAN_ONLY, + SUPPORT_FAN_MODE, + SUPPORT_PRESET_MODE, + SUPPORT_TARGET_TEMPERATURE, + SUPPORT_TARGET_TEMPERATURE_RANGE, + CURRENT_HVAC_OFF, + CURRENT_HVAC_HEAT, + PRESET_NONE, + PRESET_ECO, + PRESET_AWAY, + PRESET_BOOST, + PRESET_COMFORT, + PRESET_HOME, + PRESET_SLEEP, + PRESET_ACTIVITY, +) +from homeassistant.const import ( + ATTR_TEMPERATURE, + CONF_TEMPERATURE_UNIT, + PRECISION_HALVES, + PRECISION_TENTHS, + PRECISION_WHOLE, + TEMP_CELSIUS, + TEMP_FAHRENHEIT, +) + +from .common import LocalTuyaEntity, async_setup_entry +from .const import ( + CONF_CURRENT_TEMPERATURE_DP, + CONF_FAN_MODE_DP, + CONF_MAX_TEMP_DP, + CONF_MIN_TEMP_DP, + CONF_PRECISION, + CONF_TARGET_PRECISION, + CONF_TARGET_TEMPERATURE_DP, + CONF_TEMPERATURE_STEP, + CONF_HVAC_MODE_DP, + CONF_HVAC_MODE_SET, + CONF_EURISTIC_ACTION, + CONF_HVAC_ACTION_DP, + CONF_HVAC_ACTION_SET, + CONF_ECO_DP, + CONF_ECO_VALUE, + CONF_PRESET_DP, + CONF_PRESET_SET, +) + +from . import pytuya + +_LOGGER = logging.getLogger(__name__) + +HVAC_MODE_SETS = { + "manual/auto": { + HVAC_MODE_HEAT: "manual", + HVAC_MODE_AUTO: "auto", + }, + "Manual/Auto": { + HVAC_MODE_HEAT: "Manual", + HVAC_MODE_AUTO: "Auto", + }, +} +HVAC_ACTION_SETS = { + "True/False": { + CURRENT_HVAC_HEAT: True, + CURRENT_HVAC_OFF: False, + }, + "open/close": { + CURRENT_HVAC_HEAT: "open", + CURRENT_HVAC_OFF: "close", + }, + "heating/no_heating": { + CURRENT_HVAC_HEAT: "heating", + CURRENT_HVAC_OFF: "no_heating", + }, +} +PRESET_SETS = { + "Manual/Holiday/Program": { + PRESET_NONE: "Manual", + PRESET_AWAY: "Holiday", + PRESET_HOME: "Program", + }, +} + +TEMPERATURE_CELSIUS = "celsius" +TEMPERATURE_FAHRENHEIT = "fahrenheit" +DEFAULT_TEMPERATURE_UNIT = TEMPERATURE_CELSIUS +DEFAULT_PRECISION = PRECISION_TENTHS +DEFAULT_TEMPERATURE_STEP = PRECISION_HALVES +MODE_WAIT = 0.1 + +def flow_schema(dps): + """Return schema used in config flow.""" + return { + vol.Optional(CONF_TARGET_TEMPERATURE_DP): vol.In(dps), + vol.Optional(CONF_CURRENT_TEMPERATURE_DP): vol.In(dps), + vol.Optional(CONF_TEMPERATURE_STEP): vol.In( + [PRECISION_WHOLE, PRECISION_HALVES, PRECISION_TENTHS] + ), + vol.Optional(CONF_MAX_TEMP_DP): vol.In(dps), + vol.Optional(CONF_MIN_TEMP_DP): vol.In(dps), + vol.Optional(CONF_PRECISION): vol.In( + [PRECISION_WHOLE, PRECISION_HALVES, PRECISION_TENTHS] + ), + vol.Optional(CONF_HVAC_MODE_DP): vol.In(dps), + vol.Optional(CONF_HVAC_MODE_SET): vol.In( + list(HVAC_MODE_SETS.keys()) + ), + vol.Optional(CONF_HVAC_ACTION_DP): vol.In(dps), + vol.Optional(CONF_HVAC_ACTION_SET): vol.In( + list(HVAC_ACTION_SETS.keys()) + ), + vol.Optional(CONF_ECO_DP): vol.In(dps), + vol.Optional(CONF_ECO_VALUE): str, + vol.Optional(CONF_PRESET_DP): vol.In(dps), + vol.Optional(CONF_PRESET_SET): vol.In( + list(PRESET_SETS.keys()) + ), + vol.Optional(CONF_TEMPERATURE_UNIT): vol.In( + [TEMPERATURE_CELSIUS, TEMPERATURE_FAHRENHEIT] + ), + vol.Optional(CONF_TARGET_PRECISION): vol.In( + [PRECISION_WHOLE, PRECISION_HALVES, PRECISION_TENTHS] + ), + vol.Optional(CONF_EURISTIC_ACTION, default=False): bool, + vol.Optional(CONF_FAN_MODE_DP): vol.In(dps), + } + + +class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): + """Tuya climate device.""" + + def __init__( + self, + device, + config_entry, + switchid, + **kwargs, + ): + """Initialize a new LocaltuyaClimate.""" + super().__init__(device, config_entry, switchid, _LOGGER, **kwargs) + self._state = None + self._target_temperature = None + self._current_temperature = None + self._hvac_mode = None + self._preset_mode = None + self._hvac_action = None + self._precision = self._config.get(CONF_PRECISION, DEFAULT_PRECISION) + self._target_precision = self._config.get(CONF_TARGET_PRECISION, self._precision) + self._conf_hvac_mode_dp = self._config.get(CONF_HVAC_MODE_DP) + self._conf_hvac_mode_set = HVAC_MODE_SETS.get(self._config.get(CONF_HVAC_MODE_SET), {}) + self._conf_preset_dp = self._config.get(CONF_PRESET_DP) + self._conf_preset_set = PRESET_SETS.get(self._config.get(CONF_PRESET_SET), {}) + self._conf_hvac_action_dp = self._config.get(CONF_HVAC_ACTION_DP) + self._conf_hvac_action_set = HVAC_ACTION_SETS.get(self._config.get(CONF_HVAC_ACTION_SET), {}) + self._conf_eco_dp = self._config.get(CONF_ECO_DP) + self._conf_eco_value = self._config.get(CONF_ECO_VALUE, "ECO") + self._has_presets = self.has_config(CONF_ECO_DP) or self.has_config(CONF_PRESET_DP) + print("Initialized climate [{}]".format(self.name)) + + @property + def supported_features(self): + """Flag supported features.""" + supported_features = 0 + if self.has_config(CONF_TARGET_TEMPERATURE_DP): + supported_features = supported_features | SUPPORT_TARGET_TEMPERATURE + if self.has_config(CONF_MAX_TEMP_DP): + supported_features = supported_features | SUPPORT_TARGET_TEMPERATURE_RANGE + if self.has_config(CONF_FAN_MODE_DP): + supported_features = supported_features | SUPPORT_FAN_MODE + if self.has_config(CONF_PRESET_DP) or self.has_config(CONF_ECO_DP): + supported_features = supported_features | SUPPORT_PRESET_MODE + return supported_features + + @property + def precision(self): + """Return the precision of the system.""" + return self._precision + + @property + def target_recision(self): + """Return the precision of the target.""" + return self._target_precision + + @property + def temperature_unit(self): + """Return the unit of measurement used by the platform.""" + if ( + self._config.get(CONF_TEMPERATURE_UNIT, DEFAULT_TEMPERATURE_UNIT) + == TEMPERATURE_FAHRENHEIT + ): + return TEMP_FAHRENHEIT + return TEMP_CELSIUS + + @property + def hvac_mode(self): + """Return current operation ie. heat, cool, idle.""" + return self._hvac_mode + + @property + def hvac_modes(self): + """Return the list of available operation modes.""" + if not self.has_config(CONF_HVAC_MODE_DP): + return None + return list(self._conf_hvac_mode_set) + [HVAC_MODE_OFF] + + @property + def hvac_action(self): + """Return the current running hvac operation if supported. + Need to be one of CURRENT_HVAC_*. + """ + if self._config[CONF_EURISTIC_ACTION]: + if self._hvac_mode == HVAC_MODE_HEAT: + if self._current_temperature < (self._target_temperature - self._precision): + self._hvac_action = CURRENT_HVAC_HEAT + if self._current_temperature == (self._target_temperature - self._precision): + if self._hvac_action == CURRENT_HVAC_HEAT: + self._hvac_action = CURRENT_HVAC_HEAT + if self._hvac_action == CURRENT_HVAC_OFF: + self._hvac_action = CURRENT_HVAC_OFF + if (self._current_temperature + self._precision) > self._target_temperature: + self._hvac_action = CURRENT_HVAC_OFF + return self._hvac_action + return self._hvac_action + + @property + def preset_mode(self): + """Return current preset""" + return self._preset_mode + + @property + def preset_modes(self): + """Return the list of available presets modes.""" + if not self._has_presets: + return None + presets = list(self._conf_preset_set) + if self._conf_eco_dp: + presets.append(PRESET_ECO) + return presets + + @property + def current_temperature(self): + """Return the current temperature.""" + return self._current_temperature + + @property + def target_temperature(self): + """Return the temperature we try to reach.""" + return self._target_temperature + + @property + def target_temperature_step(self): + """Return the supported step of target temperature.""" + return self._config.get(CONF_TEMPERATURE_STEP, DEFAULT_TEMPERATURE_STEP) + + @property + def fan_mode(self): + """Return the fan setting.""" + return NotImplementedError() + + @property + def fan_modes(self): + """Return the list of available fan modes.""" + return NotImplementedError() + + async def async_set_temperature(self, **kwargs): + """Set new target temperature.""" + if ATTR_TEMPERATURE in kwargs and self.has_config(CONF_TARGET_TEMPERATURE_DP): + temperature = round(kwargs[ATTR_TEMPERATURE] / self._target_precision) + await self._device.set_dp(temperature, self._config[CONF_TARGET_TEMPERATURE_DP]) + + def set_fan_mode(self, fan_mode): + """Set new target fan mode.""" + return NotImplementedError() + + async def async_set_hvac_mode(self, hvac_mode): + """Set new target operation mode.""" + if hvac_mode == HVAC_MODE_OFF: + await self._device.set_dp(False, self._dp_id) + return + if not self._state: + await self._device.set_dp(True, self._dp_id) + await asyncio.sleep(MODE_WAIT) + await self._device.set_dp(self._conf_hvac_mode_set[hvac_mode], self._conf_hvac_mode_dp) + + async def async_set_preset_mode(self, preset_mode): + """Set new target preset mode.""" + if preset_mode == PRESET_ECO: + await self._device.set_dp(self._conf_eco_value, self._conf_eco_dp) + return + await self._device.set_dp(self._conf_preset_set[preset_mode], self._conf_preset_dp) + + @property + def min_temp(self): + """Return the minimum temperature.""" + if self.has_config(CONF_MIN_TEMP_DP): + return self.dps_conf(CONF_MIN_TEMP_DP) + return DEFAULT_MIN_TEMP + + @property + def max_temp(self): + """Return the maximum temperature.""" + if self.has_config(CONF_MAX_TEMP_DP): + return self.dps_conf(CONF_MAX_TEMP_DP) + return DEFAULT_MAX_TEMP + + def status_updated(self): + """Device status was updated.""" + self._state = self.dps(self._dp_id) + + if self.has_config(CONF_TARGET_TEMPERATURE_DP): + self._target_temperature = ( + self.dps_conf(CONF_TARGET_TEMPERATURE_DP) * self._target_precision + ) + + if self.has_config(CONF_CURRENT_TEMPERATURE_DP): + self._current_temperature = ( + self.dps_conf(CONF_CURRENT_TEMPERATURE_DP) * self._precision + ) + + #_LOGGER.debug("the test is %s", test)he preset status""" + if self._has_presets: + if self.has_config(CONF_ECO_DP) and self.dps_conf(CONF_ECO_DP) == self._conf_eco_value: + self._preset_mode = PRESET_ECO + else: + for preset,value in self._conf_preset_set.items(): # todo remove + if self.dps_conf(CONF_PRESET_DP) == value: + self._preset_mode = preset + break + else: + self._preset_mode = PRESET_NONE + + """Update the HVAC status""" + if self.has_config(CONF_HVAC_MODE_DP): + if not self._state: + self._hvac_mode = HVAC_MODE_OFF + else: + for mode,value in self._conf_hvac_mode_set.items(): + if self.dps_conf(CONF_HVAC_MODE_DP) == value: + self._hvac_mode = mode + break + else: + # in case hvac mode and preset share the same dp + self._hvac_mode = HVAC_MODE_AUTO + + """Update the current action""" + for action,value in self._conf_hvac_action_set.items(): + if self.dps_conf(CONF_HVAC_ACTION_DP) == value: + self._hvac_action = action + +async_setup_entry = partial(async_setup_entry, DOMAIN, LocaltuyaClimate, flow_schema) diff --git a/custom_components/localtuya/const.py b/custom_components/localtuya/const.py index bd8a5d3..6c03420 100644 --- a/custom_components/localtuya/const.py +++ b/custom_components/localtuya/const.py @@ -41,11 +41,30 @@ CONF_FAN_SPEED_HIGH = "fan_speed_high" # sensor CONF_SCALING = "scaling" +# climate +CONF_TARGET_TEMPERATURE_DP = "target_temperature_dp" +CONF_CURRENT_TEMPERATURE_DP = "current_temperature_dp" +CONF_TEMPERATURE_STEP = "temperature_step" +CONF_MAX_TEMP_DP = "max_temperature_dp" +CONF_MIN_TEMP_DP = "min_temperature_dp" +CONF_FAN_MODE_DP = "fan_mode_dp" +CONF_PRECISION = "precision" +CONF_TARGET_PRECISION = "target_precision" +CONF_HVAC_MODE_DP = "hvac_mode_dp" +CONF_HVAC_MODE_SET = "hvac_mode_set" +CONF_PRESET_DP = "preset_dp" +CONF_PRESET_SET = "preset_set" +CONF_EURISTIC_ACTION = "euristic_action" +CONF_HVAC_ACTION_DP = "hvac_action_dp" +CONF_HVAC_ACTION_SET = "hvac_action_set" +CONF_ECO_DP = "eco_dp" +CONF_ECO_VALUE = "eco_value" + DATA_DISCOVERY = "discovery" DOMAIN = "localtuya" # Platforms in this list must support config flows -PLATFORMS = ["binary_sensor", "cover", "fan", "light", "sensor", "switch"] +PLATFORMS = ["binary_sensor", "cover", "climate", "fan", "light", "sensor", "switch"] TUYA_DEVICE = "tuya_device" diff --git a/custom_components/localtuya/translations/en.json b/custom_components/localtuya/translations/en.json index 6ce233a..8ede6fe 100644 --- a/custom_components/localtuya/translations/en.json +++ b/custom_components/localtuya/translations/en.json @@ -74,7 +74,25 @@ "fan_oscillating_control": "Fan Oscillating Control", "fan_speed_low": "Fan Low Speed Setting", "fan_speed_medium": "Fan Medium Speed Setting", - "fan_speed_high": "Fan High Speed Setting" + "fan_speed_high": "Fan High Speed Setting", + "current_temperature_dp": "Current Temperature", + "target_temperature_dp": "Target Temperature", + "fan_mode_dp": "Fan Mode (optional)", + "temperature_step": "Temperature Step (optional)", + "max_temperature_dp": "Max Temperature (optional)", + "min_temperature_dp": "Min Temperature (optional)", + "precision": "Precision (optional, for DPs values)", + "target_precision": "Target Precision (optional, for DPs values)", + "temperature_unit": "Temperature Unit (optional)", + "hvac_mode_dp": "HVAC Mode DP (optional)", + "hvac_mode_set": "HVAC Mode Set (optional)", + "hvac_action_dp": "HVAC Current Action DP (optional)", + "hvac_action_set": "HVAC Current Action Set (optional)", + "preset_dp": "Presets DP (optional)", + "preset_set": "Presets Set (optional)", + "eco_dp": "Eco DP (optional)", + "eco_value": "Eco value (optional)", + "euristic_action": "Enable euristic action (optional)" } } } @@ -126,7 +144,25 @@ "fan_oscillating_control": "Fan Oscillating Control", "fan_speed_low": "Fan Low Speed Setting", "fan_speed_medium": "Fan Medium Speed Setting", - "fan_speed_high": "Fan High Speed Setting" + "fan_speed_high": "Fan High Speed Setting", + "current_temperature_dp": "Current Temperature", + "target_temperature_dp": "Target Temperature", + "fan_mode_dp": "Fan Mode (optional)", + "temperature_step": "Temperature Step (optional)", + "max_temperature_dp": "Max Temperature (optional)", + "min_temperature_dp": "Min Temperature (optional)", + "precision": "Precision (optional, for DPs values)", + "target_precision": "Target Precision (optional, for DPs values)", + "temperature_unit": "Temperature Unit (optional)", + "hvac_mode_dp": "HVAC Mode DP (optional)", + "hvac_mode_set": "HVAC Mode Set (optional)", + "hvac_action_dp": "HVAC Current Action DP (optional)", + "hvac_action_set": "HVAC Current Action Set (optional)", + "preset_dp": "Presets DP (optional)", + "preset_set": "Presets Set (optional)", + "eco_dp": "Eco DP (optional)", + "eco_value": "Eco value (optional)", + "euristic_action": "Enable euristic action (optional)" } }, "yaml_import": { From d9f0d1ecab10a5245122e09c668ce780bdee968d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Villagra?= Date: Mon, 16 Aug 2021 17:51:44 +0100 Subject: [PATCH 02/16] add simple on/off mode --- custom_components/localtuya/climate.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/custom_components/localtuya/climate.py b/custom_components/localtuya/climate.py index fe4eab3..b8221c9 100644 --- a/custom_components/localtuya/climate.py +++ b/custom_components/localtuya/climate.py @@ -79,6 +79,9 @@ HVAC_MODE_SETS = { HVAC_MODE_HEAT: "Manual", HVAC_MODE_AUTO: "Auto", }, + "True/False": { + HVAC_MODE_HEAT: True, + }, } HVAC_ACTION_SETS = { "True/False": { @@ -298,7 +301,7 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): if hvac_mode == HVAC_MODE_OFF: await self._device.set_dp(False, self._dp_id) return - if not self._state: + if not self._state and self._conf_hvac_mode_dp != self._dp_id: await self._device.set_dp(True, self._dp_id) await asyncio.sleep(MODE_WAIT) await self._device.set_dp(self._conf_hvac_mode_set[hvac_mode], self._conf_hvac_mode_dp) From 2335bb12fa6e8b9cc0f6140095c2317d250f9793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Villagra?= Date: Tue, 2 Nov 2021 14:48:14 +0000 Subject: [PATCH 03/16] reorder imports Co-authored-by: Jelle Spijker --- custom_components/localtuya/climate.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/custom_components/localtuya/climate.py b/custom_components/localtuya/climate.py index b8221c9..ab27462 100644 --- a/custom_components/localtuya/climate.py +++ b/custom_components/localtuya/climate.py @@ -13,27 +13,27 @@ from homeassistant.components.climate import ( ClimateEntity, ) from homeassistant.components.climate.const import ( + CURRENT_HVAC_HEAT, + CURRENT_HVAC_OFF, HVAC_MODE_AUTO, - HVAC_MODE_HEAT, - HVAC_MODE_OFF, HVAC_MODE_COOL, - HVAC_MODE_HEAT_COOL, HVAC_MODE_DRY, HVAC_MODE_FAN_ONLY, + HVAC_MODE_HEAT, + HVAC_MODE_HEAT_COOL, + HVAC_MODE_OFF, + PRESET_ACTIVITY, + PRESET_AWAY, + PRESET_BOOST, + PRESET_COMFORT, + PRESET_ECO, + PRESET_HOME, + PRESET_NONE, + PRESET_SLEEP, SUPPORT_FAN_MODE, SUPPORT_PRESET_MODE, SUPPORT_TARGET_TEMPERATURE, SUPPORT_TARGET_TEMPERATURE_RANGE, - CURRENT_HVAC_OFF, - CURRENT_HVAC_HEAT, - PRESET_NONE, - PRESET_ECO, - PRESET_AWAY, - PRESET_BOOST, - PRESET_COMFORT, - PRESET_HOME, - PRESET_SLEEP, - PRESET_ACTIVITY, ) from homeassistant.const import ( ATTR_TEMPERATURE, From ea5244de74b1bc70dc02d23da5a9ad2c3303e291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Villagra?= Date: Tue, 2 Nov 2021 14:48:36 +0000 Subject: [PATCH 04/16] reorder imports2 Co-authored-by: Jelle Spijker --- custom_components/localtuya/climate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/localtuya/climate.py b/custom_components/localtuya/climate.py index ab27462..2186164 100644 --- a/custom_components/localtuya/climate.py +++ b/custom_components/localtuya/climate.py @@ -7,10 +7,10 @@ import json import voluptuous as vol from homeassistant.components.climate import ( + ClimateEntity, DEFAULT_MAX_TEMP, DEFAULT_MIN_TEMP, DOMAIN, - ClimateEntity, ) from homeassistant.components.climate.const import ( CURRENT_HVAC_HEAT, From e184942c11d92926d6bd10e7f302a5af21b17c3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Villagra?= Date: Tue, 2 Nov 2021 14:48:53 +0000 Subject: [PATCH 05/16] reorder dict Co-authored-by: Jelle Spijker --- custom_components/localtuya/climate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/localtuya/climate.py b/custom_components/localtuya/climate.py index 2186164..5c8894c 100644 --- a/custom_components/localtuya/climate.py +++ b/custom_components/localtuya/climate.py @@ -72,8 +72,8 @@ _LOGGER = logging.getLogger(__name__) HVAC_MODE_SETS = { "manual/auto": { - HVAC_MODE_HEAT: "manual", HVAC_MODE_AUTO: "auto", + HVAC_MODE_HEAT: "manual", }, "Manual/Auto": { HVAC_MODE_HEAT: "Manual", From 39b6ffa616647eaa6a566414f02c3e1840198a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Villagra?= Date: Tue, 2 Nov 2021 14:49:07 +0000 Subject: [PATCH 06/16] reorder dict2 Co-authored-by: Jelle Spijker --- custom_components/localtuya/climate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/localtuya/climate.py b/custom_components/localtuya/climate.py index 5c8894c..69b32ec 100644 --- a/custom_components/localtuya/climate.py +++ b/custom_components/localtuya/climate.py @@ -76,8 +76,8 @@ HVAC_MODE_SETS = { HVAC_MODE_HEAT: "manual", }, "Manual/Auto": { - HVAC_MODE_HEAT: "Manual", HVAC_MODE_AUTO: "Auto", + HVAC_MODE_HEAT: "Manual", }, "True/False": { HVAC_MODE_HEAT: True, From b6fe88211a3fd8beafa8d04f0b3b521244c00a2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Villagra?= Date: Tue, 2 Nov 2021 14:50:02 +0000 Subject: [PATCH 07/16] reorder imports3 Co-authored-by: Jelle Spijker --- custom_components/localtuya/climate.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/custom_components/localtuya/climate.py b/custom_components/localtuya/climate.py index 69b32ec..a4f6a73 100644 --- a/custom_components/localtuya/climate.py +++ b/custom_components/localtuya/climate.py @@ -48,22 +48,22 @@ from homeassistant.const import ( from .common import LocalTuyaEntity, async_setup_entry from .const import ( CONF_CURRENT_TEMPERATURE_DP, + CONF_ECO_DP, + CONF_ECO_VALUE, + CONF_EURISTIC_ACTION, CONF_FAN_MODE_DP, + CONF_HVAC_ACTION_DP, + CONF_HVAC_ACTION_SET, + CONF_HVAC_MODE_DP, + CONF_HVAC_MODE_SET, CONF_MAX_TEMP_DP, CONF_MIN_TEMP_DP, CONF_PRECISION, + CONF_PRESET_DP, + CONF_PRESET_SET, CONF_TARGET_PRECISION, CONF_TARGET_TEMPERATURE_DP, CONF_TEMPERATURE_STEP, - CONF_HVAC_MODE_DP, - CONF_HVAC_MODE_SET, - CONF_EURISTIC_ACTION, - CONF_HVAC_ACTION_DP, - CONF_HVAC_ACTION_SET, - CONF_ECO_DP, - CONF_ECO_VALUE, - CONF_PRESET_DP, - CONF_PRESET_SET, ) from . import pytuya From 0550f54fe33003353cb49630da0ce2b416bd6518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Villagra?= Date: Tue, 2 Nov 2021 14:50:39 +0000 Subject: [PATCH 08/16] format comment Co-authored-by: Jelle Spijker --- custom_components/localtuya/climate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/localtuya/climate.py b/custom_components/localtuya/climate.py index a4f6a73..a28b028 100644 --- a/custom_components/localtuya/climate.py +++ b/custom_components/localtuya/climate.py @@ -353,7 +353,7 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): else: self._preset_mode = PRESET_NONE - """Update the HVAC status""" + # Update the HVAC status if self.has_config(CONF_HVAC_MODE_DP): if not self._state: self._hvac_mode = HVAC_MODE_OFF From 6dcb5a5056c26e86a57c6a5521191669e353f47c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Villagra?= Date: Tue, 2 Nov 2021 14:50:49 +0000 Subject: [PATCH 09/16] format comment2 Co-authored-by: Jelle Spijker --- custom_components/localtuya/climate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/localtuya/climate.py b/custom_components/localtuya/climate.py index a28b028..3410deb 100644 --- a/custom_components/localtuya/climate.py +++ b/custom_components/localtuya/climate.py @@ -366,7 +366,7 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): # in case hvac mode and preset share the same dp self._hvac_mode = HVAC_MODE_AUTO - """Update the current action""" + # Update the current action for action,value in self._conf_hvac_action_set.items(): if self.dps_conf(CONF_HVAC_ACTION_DP) == value: self._hvac_action = action From 7251d62035c17d9c0962514f9fc1897bc8b158e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Villagra?= Date: Tue, 2 Nov 2021 16:57:30 +0000 Subject: [PATCH 10/16] use _LOGGER Co-authored-by: Jelle Spijker --- custom_components/localtuya/climate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/localtuya/climate.py b/custom_components/localtuya/climate.py index 3410deb..7c3d3f1 100644 --- a/custom_components/localtuya/climate.py +++ b/custom_components/localtuya/climate.py @@ -179,7 +179,7 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): self._conf_eco_dp = self._config.get(CONF_ECO_DP) self._conf_eco_value = self._config.get(CONF_ECO_VALUE, "ECO") self._has_presets = self.has_config(CONF_ECO_DP) or self.has_config(CONF_PRESET_DP) - print("Initialized climate [{}]".format(self.name)) + _LOGGER.debug(f"Initialized climate [{self.name}]") @property def supported_features(self): From ae3f305db032dbb10aabd10b04b4968662591da7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Villagra?= Date: Tue, 23 Nov 2021 19:59:38 +0000 Subject: [PATCH 11/16] addressed all pending suggestions --- custom_components/localtuya/climate.py | 66 +++++++++---------- custom_components/localtuya/const.py | 1 - .../localtuya/translations/en.json | 2 - 3 files changed, 31 insertions(+), 38 deletions(-) diff --git a/custom_components/localtuya/climate.py b/custom_components/localtuya/climate.py index 7c3d3f1..3deea4f 100644 --- a/custom_components/localtuya/climate.py +++ b/custom_components/localtuya/climate.py @@ -7,33 +7,32 @@ import json import voluptuous as vol from homeassistant.components.climate import ( - ClimateEntity, DEFAULT_MAX_TEMP, DEFAULT_MIN_TEMP, DOMAIN, + ClimateEntity, ) from homeassistant.components.climate.const import ( - CURRENT_HVAC_HEAT, - CURRENT_HVAC_OFF, HVAC_MODE_AUTO, + HVAC_MODE_HEAT, + HVAC_MODE_OFF, HVAC_MODE_COOL, + HVAC_MODE_HEAT_COOL, HVAC_MODE_DRY, HVAC_MODE_FAN_ONLY, - HVAC_MODE_HEAT, - HVAC_MODE_HEAT_COOL, - HVAC_MODE_OFF, - PRESET_ACTIVITY, - PRESET_AWAY, - PRESET_BOOST, - PRESET_COMFORT, - PRESET_ECO, - PRESET_HOME, - PRESET_NONE, - PRESET_SLEEP, - SUPPORT_FAN_MODE, SUPPORT_PRESET_MODE, SUPPORT_TARGET_TEMPERATURE, SUPPORT_TARGET_TEMPERATURE_RANGE, + CURRENT_HVAC_OFF, + CURRENT_HVAC_HEAT, + PRESET_NONE, + PRESET_ECO, + PRESET_AWAY, + PRESET_BOOST, + PRESET_COMFORT, + PRESET_HOME, + PRESET_SLEEP, + PRESET_ACTIVITY, ) from homeassistant.const import ( ATTR_TEMPERATURE, @@ -48,22 +47,21 @@ from homeassistant.const import ( from .common import LocalTuyaEntity, async_setup_entry from .const import ( CONF_CURRENT_TEMPERATURE_DP, - CONF_ECO_DP, - CONF_ECO_VALUE, - CONF_EURISTIC_ACTION, - CONF_FAN_MODE_DP, - CONF_HVAC_ACTION_DP, - CONF_HVAC_ACTION_SET, - CONF_HVAC_MODE_DP, - CONF_HVAC_MODE_SET, CONF_MAX_TEMP_DP, CONF_MIN_TEMP_DP, CONF_PRECISION, - CONF_PRESET_DP, - CONF_PRESET_SET, CONF_TARGET_PRECISION, CONF_TARGET_TEMPERATURE_DP, CONF_TEMPERATURE_STEP, + CONF_HVAC_MODE_DP, + CONF_HVAC_MODE_SET, + CONF_EURISTIC_ACTION, + CONF_HVAC_ACTION_DP, + CONF_HVAC_ACTION_SET, + CONF_ECO_DP, + CONF_ECO_VALUE, + CONF_PRESET_DP, + CONF_PRESET_SET, ) from . import pytuya @@ -72,12 +70,12 @@ _LOGGER = logging.getLogger(__name__) HVAC_MODE_SETS = { "manual/auto": { - HVAC_MODE_AUTO: "auto", HVAC_MODE_HEAT: "manual", + HVAC_MODE_AUTO: "auto", }, "Manual/Auto": { - HVAC_MODE_AUTO: "Auto", HVAC_MODE_HEAT: "Manual", + HVAC_MODE_AUTO: "Auto", }, "True/False": { HVAC_MODE_HEAT: True, @@ -99,9 +97,9 @@ HVAC_ACTION_SETS = { } PRESET_SETS = { "Manual/Holiday/Program": { - PRESET_NONE: "Manual", PRESET_AWAY: "Holiday", PRESET_HOME: "Program", + PRESET_NONE: "Manual", }, } @@ -110,6 +108,7 @@ TEMPERATURE_FAHRENHEIT = "fahrenheit" DEFAULT_TEMPERATURE_UNIT = TEMPERATURE_CELSIUS DEFAULT_PRECISION = PRECISION_TENTHS DEFAULT_TEMPERATURE_STEP = PRECISION_HALVES +# Empirically tested to work for AVATTO thermostat MODE_WAIT = 0.1 def flow_schema(dps): @@ -146,7 +145,6 @@ def flow_schema(dps): [PRECISION_WHOLE, PRECISION_HALVES, PRECISION_TENTHS] ), vol.Optional(CONF_EURISTIC_ACTION, default=False): bool, - vol.Optional(CONF_FAN_MODE_DP): vol.In(dps), } @@ -179,7 +177,7 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): self._conf_eco_dp = self._config.get(CONF_ECO_DP) self._conf_eco_value = self._config.get(CONF_ECO_VALUE, "ECO") self._has_presets = self.has_config(CONF_ECO_DP) or self.has_config(CONF_PRESET_DP) - _LOGGER.debug(f"Initialized climate [{self.name}]") + print("Initialized climate [{}]".format(self.name)) @property def supported_features(self): @@ -189,8 +187,6 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): supported_features = supported_features | SUPPORT_TARGET_TEMPERATURE if self.has_config(CONF_MAX_TEMP_DP): supported_features = supported_features | SUPPORT_TARGET_TEMPERATURE_RANGE - if self.has_config(CONF_FAN_MODE_DP): - supported_features = supported_features | SUPPORT_FAN_MODE if self.has_config(CONF_PRESET_DP) or self.has_config(CONF_ECO_DP): supported_features = supported_features | SUPPORT_PRESET_MODE return supported_features @@ -303,6 +299,7 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): return if not self._state and self._conf_hvac_mode_dp != self._dp_id: await self._device.set_dp(True, self._dp_id) + # Some thermostats need a small wait before sending another update await asyncio.sleep(MODE_WAIT) await self._device.set_dp(self._conf_hvac_mode_set[hvac_mode], self._conf_hvac_mode_dp) @@ -341,7 +338,6 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): self.dps_conf(CONF_CURRENT_TEMPERATURE_DP) * self._precision ) - #_LOGGER.debug("the test is %s", test)he preset status""" if self._has_presets: if self.has_config(CONF_ECO_DP) and self.dps_conf(CONF_ECO_DP) == self._conf_eco_value: self._preset_mode = PRESET_ECO @@ -353,7 +349,7 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): else: self._preset_mode = PRESET_NONE - # Update the HVAC status + """Update the HVAC status""" if self.has_config(CONF_HVAC_MODE_DP): if not self._state: self._hvac_mode = HVAC_MODE_OFF @@ -366,7 +362,7 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): # in case hvac mode and preset share the same dp self._hvac_mode = HVAC_MODE_AUTO - # Update the current action + """Update the current action""" for action,value in self._conf_hvac_action_set.items(): if self.dps_conf(CONF_HVAC_ACTION_DP) == value: self._hvac_action = action diff --git a/custom_components/localtuya/const.py b/custom_components/localtuya/const.py index 6c03420..131891c 100644 --- a/custom_components/localtuya/const.py +++ b/custom_components/localtuya/const.py @@ -47,7 +47,6 @@ CONF_CURRENT_TEMPERATURE_DP = "current_temperature_dp" CONF_TEMPERATURE_STEP = "temperature_step" CONF_MAX_TEMP_DP = "max_temperature_dp" CONF_MIN_TEMP_DP = "min_temperature_dp" -CONF_FAN_MODE_DP = "fan_mode_dp" CONF_PRECISION = "precision" CONF_TARGET_PRECISION = "target_precision" CONF_HVAC_MODE_DP = "hvac_mode_dp" diff --git a/custom_components/localtuya/translations/en.json b/custom_components/localtuya/translations/en.json index 8ede6fe..0c39ff4 100644 --- a/custom_components/localtuya/translations/en.json +++ b/custom_components/localtuya/translations/en.json @@ -77,7 +77,6 @@ "fan_speed_high": "Fan High Speed Setting", "current_temperature_dp": "Current Temperature", "target_temperature_dp": "Target Temperature", - "fan_mode_dp": "Fan Mode (optional)", "temperature_step": "Temperature Step (optional)", "max_temperature_dp": "Max Temperature (optional)", "min_temperature_dp": "Min Temperature (optional)", @@ -147,7 +146,6 @@ "fan_speed_high": "Fan High Speed Setting", "current_temperature_dp": "Current Temperature", "target_temperature_dp": "Target Temperature", - "fan_mode_dp": "Fan Mode (optional)", "temperature_step": "Temperature Step (optional)", "max_temperature_dp": "Max Temperature (optional)", "min_temperature_dp": "Min Temperature (optional)", From 20369577f3403b99dab298979d3c35398640cff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Villagra?= Date: Tue, 23 Nov 2021 20:37:58 +0000 Subject: [PATCH 12/16] fix linter issues --- custom_components/localtuya/climate.py | 90 ++++++++++--------- custom_components/localtuya/const.py | 2 +- .../localtuya/translations/en.json | 4 +- 3 files changed, 52 insertions(+), 44 deletions(-) diff --git a/custom_components/localtuya/climate.py b/custom_components/localtuya/climate.py index 3deea4f..eaf6903 100644 --- a/custom_components/localtuya/climate.py +++ b/custom_components/localtuya/climate.py @@ -1,9 +1,7 @@ """Platform to locally control Tuya-based climate devices.""" import asyncio import logging -import json from functools import partial -import json import voluptuous as vol from homeassistant.components.climate import ( @@ -16,10 +14,6 @@ from homeassistant.components.climate.const import ( HVAC_MODE_AUTO, HVAC_MODE_HEAT, HVAC_MODE_OFF, - HVAC_MODE_COOL, - HVAC_MODE_HEAT_COOL, - HVAC_MODE_DRY, - HVAC_MODE_FAN_ONLY, SUPPORT_PRESET_MODE, SUPPORT_TARGET_TEMPERATURE, SUPPORT_TARGET_TEMPERATURE_RANGE, @@ -28,11 +22,7 @@ from homeassistant.components.climate.const import ( PRESET_NONE, PRESET_ECO, PRESET_AWAY, - PRESET_BOOST, - PRESET_COMFORT, PRESET_HOME, - PRESET_SLEEP, - PRESET_ACTIVITY, ) from homeassistant.const import ( ATTR_TEMPERATURE, @@ -55,7 +45,7 @@ from .const import ( CONF_TEMPERATURE_STEP, CONF_HVAC_MODE_DP, CONF_HVAC_MODE_SET, - CONF_EURISTIC_ACTION, + CONF_HEURISTIC_ACTION, CONF_HVAC_ACTION_DP, CONF_HVAC_ACTION_SET, CONF_ECO_DP, @@ -64,8 +54,6 @@ from .const import ( CONF_PRESET_SET, ) -from . import pytuya - _LOGGER = logging.getLogger(__name__) HVAC_MODE_SETS = { @@ -111,6 +99,7 @@ DEFAULT_TEMPERATURE_STEP = PRECISION_HALVES # Empirically tested to work for AVATTO thermostat MODE_WAIT = 0.1 + def flow_schema(dps): """Return schema used in config flow.""" return { @@ -125,26 +114,20 @@ def flow_schema(dps): [PRECISION_WHOLE, PRECISION_HALVES, PRECISION_TENTHS] ), vol.Optional(CONF_HVAC_MODE_DP): vol.In(dps), - vol.Optional(CONF_HVAC_MODE_SET): vol.In( - list(HVAC_MODE_SETS.keys()) - ), + vol.Optional(CONF_HVAC_MODE_SET): vol.In(list(HVAC_MODE_SETS.keys())), vol.Optional(CONF_HVAC_ACTION_DP): vol.In(dps), - vol.Optional(CONF_HVAC_ACTION_SET): vol.In( - list(HVAC_ACTION_SETS.keys()) - ), + vol.Optional(CONF_HVAC_ACTION_SET): vol.In(list(HVAC_ACTION_SETS.keys())), vol.Optional(CONF_ECO_DP): vol.In(dps), vol.Optional(CONF_ECO_VALUE): str, vol.Optional(CONF_PRESET_DP): vol.In(dps), - vol.Optional(CONF_PRESET_SET): vol.In( - list(PRESET_SETS.keys()) - ), + vol.Optional(CONF_PRESET_SET): vol.In(list(PRESET_SETS.keys())), vol.Optional(CONF_TEMPERATURE_UNIT): vol.In( [TEMPERATURE_CELSIUS, TEMPERATURE_FAHRENHEIT] ), vol.Optional(CONF_TARGET_PRECISION): vol.In( [PRECISION_WHOLE, PRECISION_HALVES, PRECISION_TENTHS] ), - vol.Optional(CONF_EURISTIC_ACTION, default=False): bool, + vol.Optional(CONF_HEURISTIC_ACTION): bool, } @@ -167,16 +150,24 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): self._preset_mode = None self._hvac_action = None self._precision = self._config.get(CONF_PRECISION, DEFAULT_PRECISION) - self._target_precision = self._config.get(CONF_TARGET_PRECISION, self._precision) + self._target_precision = self._config.get( + CONF_TARGET_PRECISION, self._precision + ) self._conf_hvac_mode_dp = self._config.get(CONF_HVAC_MODE_DP) - self._conf_hvac_mode_set = HVAC_MODE_SETS.get(self._config.get(CONF_HVAC_MODE_SET), {}) + self._conf_hvac_mode_set = HVAC_MODE_SETS.get( + self._config.get(CONF_HVAC_MODE_SET), {} + ) self._conf_preset_dp = self._config.get(CONF_PRESET_DP) self._conf_preset_set = PRESET_SETS.get(self._config.get(CONF_PRESET_SET), {}) self._conf_hvac_action_dp = self._config.get(CONF_HVAC_ACTION_DP) - self._conf_hvac_action_set = HVAC_ACTION_SETS.get(self._config.get(CONF_HVAC_ACTION_SET), {}) + self._conf_hvac_action_set = HVAC_ACTION_SETS.get( + self._config.get(CONF_HVAC_ACTION_SET), {} + ) self._conf_eco_dp = self._config.get(CONF_ECO_DP) self._conf_eco_value = self._config.get(CONF_ECO_VALUE, "ECO") - self._has_presets = self.has_config(CONF_ECO_DP) or self.has_config(CONF_PRESET_DP) + self._has_presets = self.has_config(CONF_ECO_DP) or self.has_config( + CONF_PRESET_DP + ) print("Initialized climate [{}]".format(self.name)) @property @@ -226,25 +217,32 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): @property def hvac_action(self): """Return the current running hvac operation if supported. + Need to be one of CURRENT_HVAC_*. """ - if self._config[CONF_EURISTIC_ACTION]: + if self._config.get(CONF_HEURISTIC_ACTION, False): if self._hvac_mode == HVAC_MODE_HEAT: - if self._current_temperature < (self._target_temperature - self._precision): + if self._current_temperature < ( + self._target_temperature - self._precision + ): self._hvac_action = CURRENT_HVAC_HEAT - if self._current_temperature == (self._target_temperature - self._precision): + if self._current_temperature == ( + self._target_temperature - self._precision + ): if self._hvac_action == CURRENT_HVAC_HEAT: self._hvac_action = CURRENT_HVAC_HEAT if self._hvac_action == CURRENT_HVAC_OFF: self._hvac_action = CURRENT_HVAC_OFF - if (self._current_temperature + self._precision) > self._target_temperature: + if ( + self._current_temperature + self._precision + ) > self._target_temperature: self._hvac_action = CURRENT_HVAC_OFF return self._hvac_action return self._hvac_action @property def preset_mode(self): - """Return current preset""" + """Return current preset.""" return self._preset_mode @property @@ -286,7 +284,9 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): """Set new target temperature.""" if ATTR_TEMPERATURE in kwargs and self.has_config(CONF_TARGET_TEMPERATURE_DP): temperature = round(kwargs[ATTR_TEMPERATURE] / self._target_precision) - await self._device.set_dp(temperature, self._config[CONF_TARGET_TEMPERATURE_DP]) + await self._device.set_dp( + temperature, self._config[CONF_TARGET_TEMPERATURE_DP] + ) def set_fan_mode(self, fan_mode): """Set new target fan mode.""" @@ -301,14 +301,18 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): await self._device.set_dp(True, self._dp_id) # Some thermostats need a small wait before sending another update await asyncio.sleep(MODE_WAIT) - await self._device.set_dp(self._conf_hvac_mode_set[hvac_mode], self._conf_hvac_mode_dp) + await self._device.set_dp( + self._conf_hvac_mode_set[hvac_mode], self._conf_hvac_mode_dp + ) async def async_set_preset_mode(self, preset_mode): """Set new target preset mode.""" if preset_mode == PRESET_ECO: await self._device.set_dp(self._conf_eco_value, self._conf_eco_dp) return - await self._device.set_dp(self._conf_preset_set[preset_mode], self._conf_preset_dp) + await self._device.set_dp( + self._conf_preset_set[preset_mode], self._conf_preset_dp + ) @property def min_temp(self): @@ -339,22 +343,25 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): ) if self._has_presets: - if self.has_config(CONF_ECO_DP) and self.dps_conf(CONF_ECO_DP) == self._conf_eco_value: + if ( + self.has_config(CONF_ECO_DP) + and self.dps_conf(CONF_ECO_DP) == self._conf_eco_value + ): self._preset_mode = PRESET_ECO else: - for preset,value in self._conf_preset_set.items(): # todo remove + for preset, value in self._conf_preset_set.items(): # todo remove if self.dps_conf(CONF_PRESET_DP) == value: self._preset_mode = preset break else: self._preset_mode = PRESET_NONE - """Update the HVAC status""" + # Update the HVAC status if self.has_config(CONF_HVAC_MODE_DP): if not self._state: self._hvac_mode = HVAC_MODE_OFF else: - for mode,value in self._conf_hvac_mode_set.items(): + for mode, value in self._conf_hvac_mode_set.items(): if self.dps_conf(CONF_HVAC_MODE_DP) == value: self._hvac_mode = mode break @@ -362,9 +369,10 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): # in case hvac mode and preset share the same dp self._hvac_mode = HVAC_MODE_AUTO - """Update the current action""" - for action,value in self._conf_hvac_action_set.items(): + # Update the current action + for action, value in self._conf_hvac_action_set.items(): if self.dps_conf(CONF_HVAC_ACTION_DP) == value: self._hvac_action = action + async_setup_entry = partial(async_setup_entry, DOMAIN, LocaltuyaClimate, flow_schema) diff --git a/custom_components/localtuya/const.py b/custom_components/localtuya/const.py index 131891c..8bc26cb 100644 --- a/custom_components/localtuya/const.py +++ b/custom_components/localtuya/const.py @@ -53,7 +53,7 @@ CONF_HVAC_MODE_DP = "hvac_mode_dp" CONF_HVAC_MODE_SET = "hvac_mode_set" CONF_PRESET_DP = "preset_dp" CONF_PRESET_SET = "preset_set" -CONF_EURISTIC_ACTION = "euristic_action" +CONF_HEURISTIC_ACTION = "heuristic_action" CONF_HVAC_ACTION_DP = "hvac_action_dp" CONF_HVAC_ACTION_SET = "hvac_action_set" CONF_ECO_DP = "eco_dp" diff --git a/custom_components/localtuya/translations/en.json b/custom_components/localtuya/translations/en.json index 0c39ff4..a7fe191 100644 --- a/custom_components/localtuya/translations/en.json +++ b/custom_components/localtuya/translations/en.json @@ -91,7 +91,7 @@ "preset_set": "Presets Set (optional)", "eco_dp": "Eco DP (optional)", "eco_value": "Eco value (optional)", - "euristic_action": "Enable euristic action (optional)" + "heuristic_action": "Enable heuristic action (optional)" } } } @@ -160,7 +160,7 @@ "preset_set": "Presets Set (optional)", "eco_dp": "Eco DP (optional)", "eco_value": "Eco value (optional)", - "euristic_action": "Enable euristic action (optional)" + "heuristic_action": "Enable heuristic action (optional)" } }, "yaml_import": { From a8883a5d8ed1a41c25f315facc208e4885c4aab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Villagra?= Date: Mon, 10 Jan 2022 17:03:21 -0300 Subject: [PATCH 13/16] add Heat/Warming HVAC actions --- custom_components/localtuya/climate.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/custom_components/localtuya/climate.py b/custom_components/localtuya/climate.py index eaf6903..3eec336 100644 --- a/custom_components/localtuya/climate.py +++ b/custom_components/localtuya/climate.py @@ -82,6 +82,10 @@ HVAC_ACTION_SETS = { CURRENT_HVAC_HEAT: "heating", CURRENT_HVAC_OFF: "no_heating", }, + "Heat/Warming": { + CURRENT_HVAC_HEAT: "Heat", + CURRENT_HVAC_OFF: "Warming", + }, } PRESET_SETS = { "Manual/Holiday/Program": { From b19682cfd96af407d496ef7fd0cb94a81b4c1173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Villagra?= Date: Mon, 10 Jan 2022 17:18:51 -0300 Subject: [PATCH 14/16] use idle instead of off HVAC state --- custom_components/localtuya/climate.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/custom_components/localtuya/climate.py b/custom_components/localtuya/climate.py index 3eec336..84e2317 100644 --- a/custom_components/localtuya/climate.py +++ b/custom_components/localtuya/climate.py @@ -17,7 +17,7 @@ from homeassistant.components.climate.const import ( SUPPORT_PRESET_MODE, SUPPORT_TARGET_TEMPERATURE, SUPPORT_TARGET_TEMPERATURE_RANGE, - CURRENT_HVAC_OFF, + CURRENT_HVAC_IDLE, CURRENT_HVAC_HEAT, PRESET_NONE, PRESET_ECO, @@ -72,19 +72,19 @@ HVAC_MODE_SETS = { HVAC_ACTION_SETS = { "True/False": { CURRENT_HVAC_HEAT: True, - CURRENT_HVAC_OFF: False, + CURRENT_HVAC_IDLE: False, }, "open/close": { CURRENT_HVAC_HEAT: "open", - CURRENT_HVAC_OFF: "close", + CURRENT_HVAC_IDLE: "close", }, "heating/no_heating": { CURRENT_HVAC_HEAT: "heating", - CURRENT_HVAC_OFF: "no_heating", + CURRENT_HVAC_IDLE: "no_heating", }, "Heat/Warming": { CURRENT_HVAC_HEAT: "Heat", - CURRENT_HVAC_OFF: "Warming", + CURRENT_HVAC_IDLE: "Warming", }, } PRESET_SETS = { @@ -235,12 +235,12 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): ): if self._hvac_action == CURRENT_HVAC_HEAT: self._hvac_action = CURRENT_HVAC_HEAT - if self._hvac_action == CURRENT_HVAC_OFF: - self._hvac_action = CURRENT_HVAC_OFF + if self._hvac_action == CURRENT_HVAC_IDLE: + self._hvac_action = CURRENT_HVAC_IDLE if ( self._current_temperature + self._precision ) > self._target_temperature: - self._hvac_action = CURRENT_HVAC_OFF + self._hvac_action = CURRENT_HVAC_IDLE return self._hvac_action return self._hvac_action From cf125ae616a4ad74a439cd8b0a9ae3825cf844fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Villagra?= Date: Mon, 10 Jan 2022 17:19:17 -0300 Subject: [PATCH 15/16] add Manual/Program HVAC mode --- custom_components/localtuya/climate.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/custom_components/localtuya/climate.py b/custom_components/localtuya/climate.py index 84e2317..2e78d4f 100644 --- a/custom_components/localtuya/climate.py +++ b/custom_components/localtuya/climate.py @@ -65,6 +65,10 @@ HVAC_MODE_SETS = { HVAC_MODE_HEAT: "Manual", HVAC_MODE_AUTO: "Auto", }, + "Manual/Program": { + HVAC_MODE_HEAT: "Manual", + HVAC_MODE_AUTO: "Program", + }, "True/False": { HVAC_MODE_HEAT: True, }, From c7ee5fdb78c7d31060c9304cf75eaa8317606b21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Villagra?= Date: Thu, 13 Jan 2022 17:15:49 -0300 Subject: [PATCH 16/16] add turn on/off method --- custom_components/localtuya/climate.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/custom_components/localtuya/climate.py b/custom_components/localtuya/climate.py index 2e78d4f..7b03f31 100644 --- a/custom_components/localtuya/climate.py +++ b/custom_components/localtuya/climate.py @@ -313,6 +313,14 @@ class LocaltuyaClimate(LocalTuyaEntity, ClimateEntity): self._conf_hvac_mode_set[hvac_mode], self._conf_hvac_mode_dp ) + async def async_turn_on(self) -> None: + """Turn the entity on.""" + await self._device.set_dp(True, self._dp_id) + + async def async_turn_off(self) -> None: + """Turn the entity off.""" + await self._device.set_dp(False, self._dp_id) + async def async_set_preset_mode(self, preset_mode): """Set new target preset mode.""" if preset_mode == PRESET_ECO: