mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 06:07:17 +00:00
Fix Tado fan speed for AC (#122415)
* change capabilities * fix tests 2 * improve usability with capabilities * fix swings management * Update homeassistant/components/tado/climate.py Co-authored-by: Erwin Douna <e.douna@gmail.com> * fix after Erwin's review * fix after joostlek's review * use constant * use in instead of get --------- Co-authored-by: Erwin Douna <e.douna@gmail.com>
This commit is contained in:
parent
ae1f53775f
commit
92c1fb77e9
@ -16,6 +16,7 @@ from homeassistant.components.climate import (
|
|||||||
SWING_BOTH,
|
SWING_BOTH,
|
||||||
SWING_HORIZONTAL,
|
SWING_HORIZONTAL,
|
||||||
SWING_OFF,
|
SWING_OFF,
|
||||||
|
SWING_ON,
|
||||||
SWING_VERTICAL,
|
SWING_VERTICAL,
|
||||||
ClimateEntity,
|
ClimateEntity,
|
||||||
ClimateEntityFeature,
|
ClimateEntityFeature,
|
||||||
@ -47,7 +48,6 @@ from .const import (
|
|||||||
HA_TO_TADO_FAN_MODE_MAP,
|
HA_TO_TADO_FAN_MODE_MAP,
|
||||||
HA_TO_TADO_FAN_MODE_MAP_LEGACY,
|
HA_TO_TADO_FAN_MODE_MAP_LEGACY,
|
||||||
HA_TO_TADO_HVAC_MODE_MAP,
|
HA_TO_TADO_HVAC_MODE_MAP,
|
||||||
HA_TO_TADO_SWING_MODE_MAP,
|
|
||||||
ORDERED_KNOWN_TADO_MODES,
|
ORDERED_KNOWN_TADO_MODES,
|
||||||
PRESET_AUTO,
|
PRESET_AUTO,
|
||||||
SIGNAL_TADO_UPDATE_RECEIVED,
|
SIGNAL_TADO_UPDATE_RECEIVED,
|
||||||
@ -55,17 +55,20 @@ from .const import (
|
|||||||
SUPPORT_PRESET_MANUAL,
|
SUPPORT_PRESET_MANUAL,
|
||||||
TADO_DEFAULT_MAX_TEMP,
|
TADO_DEFAULT_MAX_TEMP,
|
||||||
TADO_DEFAULT_MIN_TEMP,
|
TADO_DEFAULT_MIN_TEMP,
|
||||||
TADO_FAN_LEVELS,
|
TADO_FANLEVEL_SETTING,
|
||||||
TADO_FAN_SPEEDS,
|
TADO_FANSPEED_SETTING,
|
||||||
|
TADO_HORIZONTAL_SWING_SETTING,
|
||||||
TADO_HVAC_ACTION_TO_HA_HVAC_ACTION,
|
TADO_HVAC_ACTION_TO_HA_HVAC_ACTION,
|
||||||
TADO_MODES_WITH_NO_TEMP_SETTING,
|
TADO_MODES_WITH_NO_TEMP_SETTING,
|
||||||
TADO_SWING_OFF,
|
TADO_SWING_OFF,
|
||||||
TADO_SWING_ON,
|
TADO_SWING_ON,
|
||||||
|
TADO_SWING_SETTING,
|
||||||
TADO_TO_HA_FAN_MODE_MAP,
|
TADO_TO_HA_FAN_MODE_MAP,
|
||||||
TADO_TO_HA_FAN_MODE_MAP_LEGACY,
|
TADO_TO_HA_FAN_MODE_MAP_LEGACY,
|
||||||
TADO_TO_HA_HVAC_MODE_MAP,
|
TADO_TO_HA_HVAC_MODE_MAP,
|
||||||
TADO_TO_HA_OFFSET_MAP,
|
TADO_TO_HA_OFFSET_MAP,
|
||||||
TADO_TO_HA_SWING_MODE_MAP,
|
TADO_TO_HA_SWING_MODE_MAP,
|
||||||
|
TADO_VERTICAL_SWING_SETTING,
|
||||||
TEMP_OFFSET,
|
TEMP_OFFSET,
|
||||||
TYPE_AIR_CONDITIONING,
|
TYPE_AIR_CONDITIONING,
|
||||||
TYPE_HEATING,
|
TYPE_HEATING,
|
||||||
@ -166,29 +169,30 @@ def create_climate_entity(
|
|||||||
|
|
||||||
supported_hvac_modes.append(TADO_TO_HA_HVAC_MODE_MAP[mode])
|
supported_hvac_modes.append(TADO_TO_HA_HVAC_MODE_MAP[mode])
|
||||||
if (
|
if (
|
||||||
capabilities[mode].get("swings")
|
TADO_SWING_SETTING in capabilities[mode]
|
||||||
or capabilities[mode].get("verticalSwing")
|
or TADO_VERTICAL_SWING_SETTING in capabilities[mode]
|
||||||
or capabilities[mode].get("horizontalSwing")
|
or TADO_VERTICAL_SWING_SETTING in capabilities[mode]
|
||||||
):
|
):
|
||||||
support_flags |= ClimateEntityFeature.SWING_MODE
|
support_flags |= ClimateEntityFeature.SWING_MODE
|
||||||
supported_swing_modes = []
|
supported_swing_modes = []
|
||||||
if capabilities[mode].get("swings"):
|
if TADO_SWING_SETTING in capabilities[mode]:
|
||||||
supported_swing_modes.append(
|
supported_swing_modes.append(
|
||||||
TADO_TO_HA_SWING_MODE_MAP[TADO_SWING_ON]
|
TADO_TO_HA_SWING_MODE_MAP[TADO_SWING_ON]
|
||||||
)
|
)
|
||||||
if capabilities[mode].get("verticalSwing"):
|
if TADO_VERTICAL_SWING_SETTING in capabilities[mode]:
|
||||||
supported_swing_modes.append(SWING_VERTICAL)
|
supported_swing_modes.append(SWING_VERTICAL)
|
||||||
if capabilities[mode].get("horizontalSwing"):
|
if TADO_HORIZONTAL_SWING_SETTING in capabilities[mode]:
|
||||||
supported_swing_modes.append(SWING_HORIZONTAL)
|
supported_swing_modes.append(SWING_HORIZONTAL)
|
||||||
if (
|
if (
|
||||||
SWING_HORIZONTAL in supported_swing_modes
|
SWING_HORIZONTAL in supported_swing_modes
|
||||||
and SWING_HORIZONTAL in supported_swing_modes
|
and SWING_VERTICAL in supported_swing_modes
|
||||||
):
|
):
|
||||||
supported_swing_modes.append(SWING_BOTH)
|
supported_swing_modes.append(SWING_BOTH)
|
||||||
supported_swing_modes.append(TADO_TO_HA_SWING_MODE_MAP[TADO_SWING_OFF])
|
supported_swing_modes.append(TADO_TO_HA_SWING_MODE_MAP[TADO_SWING_OFF])
|
||||||
|
|
||||||
if not capabilities[mode].get("fanSpeeds") and not capabilities[mode].get(
|
if (
|
||||||
"fanLevel"
|
TADO_FANSPEED_SETTING not in capabilities[mode]
|
||||||
|
and TADO_FANLEVEL_SETTING not in capabilities[mode]
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -197,14 +201,15 @@ def create_climate_entity(
|
|||||||
if supported_fan_modes:
|
if supported_fan_modes:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if capabilities[mode].get("fanSpeeds"):
|
if TADO_FANSPEED_SETTING in capabilities[mode]:
|
||||||
supported_fan_modes = generate_supported_fanmodes(
|
supported_fan_modes = generate_supported_fanmodes(
|
||||||
TADO_TO_HA_FAN_MODE_MAP_LEGACY, capabilities[mode]["fanSpeeds"]
|
TADO_TO_HA_FAN_MODE_MAP_LEGACY,
|
||||||
|
capabilities[mode][TADO_FANSPEED_SETTING],
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
supported_fan_modes = generate_supported_fanmodes(
|
supported_fan_modes = generate_supported_fanmodes(
|
||||||
TADO_TO_HA_FAN_MODE_MAP, capabilities[mode]["fanLevel"]
|
TADO_TO_HA_FAN_MODE_MAP, capabilities[mode][TADO_FANLEVEL_SETTING]
|
||||||
)
|
)
|
||||||
|
|
||||||
cool_temperatures = capabilities[CONST_MODE_COOL]["temperatures"]
|
cool_temperatures = capabilities[CONST_MODE_COOL]["temperatures"]
|
||||||
@ -316,12 +321,16 @@ class TadoClimate(TadoZoneEntity, ClimateEntity):
|
|||||||
self._target_temp: float | None = None
|
self._target_temp: float | None = None
|
||||||
|
|
||||||
self._current_tado_fan_speed = CONST_FAN_OFF
|
self._current_tado_fan_speed = CONST_FAN_OFF
|
||||||
|
self._current_tado_fan_level = CONST_FAN_OFF
|
||||||
self._current_tado_hvac_mode = CONST_MODE_OFF
|
self._current_tado_hvac_mode = CONST_MODE_OFF
|
||||||
self._current_tado_hvac_action = HVACAction.OFF
|
self._current_tado_hvac_action = HVACAction.OFF
|
||||||
self._current_tado_swing_mode = TADO_SWING_OFF
|
self._current_tado_swing_mode = TADO_SWING_OFF
|
||||||
self._current_tado_vertical_swing = TADO_SWING_OFF
|
self._current_tado_vertical_swing = TADO_SWING_OFF
|
||||||
self._current_tado_horizontal_swing = TADO_SWING_OFF
|
self._current_tado_horizontal_swing = TADO_SWING_OFF
|
||||||
|
|
||||||
|
capabilities = tado.get_capabilities(zone_id)
|
||||||
|
self._current_tado_capabilities = capabilities
|
||||||
|
|
||||||
self._tado_zone_data: PyTado.TadoZone = {}
|
self._tado_zone_data: PyTado.TadoZone = {}
|
||||||
self._tado_geofence_data: dict[str, str] | None = None
|
self._tado_geofence_data: dict[str, str] | None = None
|
||||||
|
|
||||||
@ -382,20 +391,23 @@ class TadoClimate(TadoZoneEntity, ClimateEntity):
|
|||||||
def fan_mode(self) -> str | None:
|
def fan_mode(self) -> str | None:
|
||||||
"""Return the fan setting."""
|
"""Return the fan setting."""
|
||||||
if self._ac_device:
|
if self._ac_device:
|
||||||
return TADO_TO_HA_FAN_MODE_MAP.get(
|
if self._is_valid_setting_for_hvac_mode(TADO_FANSPEED_SETTING):
|
||||||
self._current_tado_fan_speed,
|
return TADO_TO_HA_FAN_MODE_MAP_LEGACY.get(
|
||||||
TADO_TO_HA_FAN_MODE_MAP_LEGACY.get(
|
|
||||||
self._current_tado_fan_speed, FAN_AUTO
|
self._current_tado_fan_speed, FAN_AUTO
|
||||||
),
|
)
|
||||||
)
|
if self._is_valid_setting_for_hvac_mode(TADO_FANLEVEL_SETTING):
|
||||||
|
return TADO_TO_HA_FAN_MODE_MAP.get(
|
||||||
|
self._current_tado_fan_level, FAN_AUTO
|
||||||
|
)
|
||||||
|
return FAN_AUTO
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def set_fan_mode(self, fan_mode: str) -> None:
|
def set_fan_mode(self, fan_mode: str) -> None:
|
||||||
"""Turn fan on/off."""
|
"""Turn fan on/off."""
|
||||||
if self._current_tado_fan_speed in TADO_FAN_LEVELS:
|
if self._is_valid_setting_for_hvac_mode(TADO_FANSPEED_SETTING):
|
||||||
self._control_hvac(fan_mode=HA_TO_TADO_FAN_MODE_MAP[fan_mode])
|
|
||||||
else:
|
|
||||||
self._control_hvac(fan_mode=HA_TO_TADO_FAN_MODE_MAP_LEGACY[fan_mode])
|
self._control_hvac(fan_mode=HA_TO_TADO_FAN_MODE_MAP_LEGACY[fan_mode])
|
||||||
|
elif self._is_valid_setting_for_hvac_mode(TADO_FANLEVEL_SETTING):
|
||||||
|
self._control_hvac(fan_mode=HA_TO_TADO_FAN_MODE_MAP[fan_mode])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def preset_mode(self) -> str:
|
def preset_mode(self) -> str:
|
||||||
@ -555,24 +567,30 @@ class TadoClimate(TadoZoneEntity, ClimateEntity):
|
|||||||
swing = None
|
swing = None
|
||||||
if self._attr_swing_modes is None:
|
if self._attr_swing_modes is None:
|
||||||
return
|
return
|
||||||
if (
|
if swing_mode == SWING_OFF:
|
||||||
SWING_VERTICAL in self._attr_swing_modes
|
if self._is_valid_setting_for_hvac_mode(TADO_SWING_SETTING):
|
||||||
or SWING_HORIZONTAL in self._attr_swing_modes
|
swing = TADO_SWING_OFF
|
||||||
):
|
if self._is_valid_setting_for_hvac_mode(TADO_HORIZONTAL_SWING_SETTING):
|
||||||
if swing_mode == SWING_VERTICAL:
|
horizontal_swing = TADO_SWING_OFF
|
||||||
|
if self._is_valid_setting_for_hvac_mode(TADO_VERTICAL_SWING_SETTING):
|
||||||
|
vertical_swing = TADO_SWING_OFF
|
||||||
|
if swing_mode == SWING_ON:
|
||||||
|
swing = TADO_SWING_ON
|
||||||
|
if swing_mode == SWING_VERTICAL:
|
||||||
|
if self._is_valid_setting_for_hvac_mode(TADO_VERTICAL_SWING_SETTING):
|
||||||
vertical_swing = TADO_SWING_ON
|
vertical_swing = TADO_SWING_ON
|
||||||
elif swing_mode == SWING_HORIZONTAL:
|
if self._is_valid_setting_for_hvac_mode(TADO_HORIZONTAL_SWING_SETTING):
|
||||||
|
horizontal_swing = TADO_SWING_OFF
|
||||||
|
if swing_mode == SWING_HORIZONTAL:
|
||||||
|
if self._is_valid_setting_for_hvac_mode(TADO_VERTICAL_SWING_SETTING):
|
||||||
|
vertical_swing = TADO_SWING_OFF
|
||||||
|
if self._is_valid_setting_for_hvac_mode(TADO_HORIZONTAL_SWING_SETTING):
|
||||||
horizontal_swing = TADO_SWING_ON
|
horizontal_swing = TADO_SWING_ON
|
||||||
elif swing_mode == SWING_BOTH:
|
if swing_mode == SWING_BOTH:
|
||||||
|
if self._is_valid_setting_for_hvac_mode(TADO_VERTICAL_SWING_SETTING):
|
||||||
vertical_swing = TADO_SWING_ON
|
vertical_swing = TADO_SWING_ON
|
||||||
|
if self._is_valid_setting_for_hvac_mode(TADO_HORIZONTAL_SWING_SETTING):
|
||||||
horizontal_swing = TADO_SWING_ON
|
horizontal_swing = TADO_SWING_ON
|
||||||
elif swing_mode == SWING_OFF:
|
|
||||||
if SWING_VERTICAL in self._attr_swing_modes:
|
|
||||||
vertical_swing = TADO_SWING_OFF
|
|
||||||
if SWING_HORIZONTAL in self._attr_swing_modes:
|
|
||||||
horizontal_swing = TADO_SWING_OFF
|
|
||||||
else:
|
|
||||||
swing = HA_TO_TADO_SWING_MODE_MAP[swing_mode]
|
|
||||||
|
|
||||||
self._control_hvac(
|
self._control_hvac(
|
||||||
swing_mode=swing,
|
swing_mode=swing,
|
||||||
@ -596,21 +614,23 @@ class TadoClimate(TadoZoneEntity, ClimateEntity):
|
|||||||
self._device_id
|
self._device_id
|
||||||
][TEMP_OFFSET][offset_key]
|
][TEMP_OFFSET][offset_key]
|
||||||
|
|
||||||
self._current_tado_fan_speed = (
|
|
||||||
self._tado_zone_data.current_fan_level
|
|
||||||
if self._tado_zone_data.current_fan_level is not None
|
|
||||||
else self._tado_zone_data.current_fan_speed
|
|
||||||
)
|
|
||||||
|
|
||||||
self._current_tado_hvac_mode = self._tado_zone_data.current_hvac_mode
|
self._current_tado_hvac_mode = self._tado_zone_data.current_hvac_mode
|
||||||
self._current_tado_hvac_action = self._tado_zone_data.current_hvac_action
|
self._current_tado_hvac_action = self._tado_zone_data.current_hvac_action
|
||||||
self._current_tado_swing_mode = self._tado_zone_data.current_swing_mode
|
|
||||||
self._current_tado_vertical_swing = (
|
if self._is_valid_setting_for_hvac_mode(TADO_FANLEVEL_SETTING):
|
||||||
self._tado_zone_data.current_vertical_swing_mode
|
self._current_tado_fan_level = self._tado_zone_data.current_fan_level
|
||||||
)
|
if self._is_valid_setting_for_hvac_mode(TADO_FANSPEED_SETTING):
|
||||||
self._current_tado_horizontal_swing = (
|
self._current_tado_fan_speed = self._tado_zone_data.current_fan_speed
|
||||||
self._tado_zone_data.current_horizontal_swing_mode
|
if self._is_valid_setting_for_hvac_mode(TADO_SWING_SETTING):
|
||||||
)
|
self._current_tado_swing_mode = self._tado_zone_data.current_swing_mode
|
||||||
|
if self._is_valid_setting_for_hvac_mode(TADO_VERTICAL_SWING_SETTING):
|
||||||
|
self._current_tado_vertical_swing = (
|
||||||
|
self._tado_zone_data.current_vertical_swing_mode
|
||||||
|
)
|
||||||
|
if self._is_valid_setting_for_hvac_mode(TADO_HORIZONTAL_SWING_SETTING):
|
||||||
|
self._current_tado_horizontal_swing = (
|
||||||
|
self._tado_zone_data.current_horizontal_swing_mode
|
||||||
|
)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_zone_callback(self) -> None:
|
def _async_update_zone_callback(self) -> None:
|
||||||
@ -665,7 +685,10 @@ class TadoClimate(TadoZoneEntity, ClimateEntity):
|
|||||||
self._target_temp = target_temp
|
self._target_temp = target_temp
|
||||||
|
|
||||||
if fan_mode:
|
if fan_mode:
|
||||||
self._current_tado_fan_speed = fan_mode
|
if self._is_valid_setting_for_hvac_mode(TADO_FANSPEED_SETTING):
|
||||||
|
self._current_tado_fan_speed = fan_mode
|
||||||
|
if self._is_valid_setting_for_hvac_mode(TADO_FANLEVEL_SETTING):
|
||||||
|
self._current_tado_fan_level = fan_mode
|
||||||
|
|
||||||
if swing_mode:
|
if swing_mode:
|
||||||
self._current_tado_swing_mode = swing_mode
|
self._current_tado_swing_mode = swing_mode
|
||||||
@ -735,21 +758,32 @@ class TadoClimate(TadoZoneEntity, ClimateEntity):
|
|||||||
fan_speed = None
|
fan_speed = None
|
||||||
fan_level = None
|
fan_level = None
|
||||||
if self.supported_features & ClimateEntityFeature.FAN_MODE:
|
if self.supported_features & ClimateEntityFeature.FAN_MODE:
|
||||||
if self._current_tado_fan_speed in TADO_FAN_LEVELS:
|
if self._is_current_setting_supported_by_current_hvac_mode(
|
||||||
fan_level = self._current_tado_fan_speed
|
TADO_FANSPEED_SETTING, self._current_tado_fan_speed
|
||||||
elif self._current_tado_fan_speed in TADO_FAN_SPEEDS:
|
):
|
||||||
fan_speed = self._current_tado_fan_speed
|
fan_speed = self._current_tado_fan_speed
|
||||||
|
if self._is_current_setting_supported_by_current_hvac_mode(
|
||||||
|
TADO_FANLEVEL_SETTING, self._current_tado_fan_level
|
||||||
|
):
|
||||||
|
fan_level = self._current_tado_fan_level
|
||||||
|
|
||||||
swing = None
|
swing = None
|
||||||
vertical_swing = None
|
vertical_swing = None
|
||||||
horizontal_swing = None
|
horizontal_swing = None
|
||||||
if (
|
if (
|
||||||
self.supported_features & ClimateEntityFeature.SWING_MODE
|
self.supported_features & ClimateEntityFeature.SWING_MODE
|
||||||
) and self._attr_swing_modes is not None:
|
) and self._attr_swing_modes is not None:
|
||||||
if SWING_VERTICAL in self._attr_swing_modes:
|
if self._is_current_setting_supported_by_current_hvac_mode(
|
||||||
|
TADO_VERTICAL_SWING_SETTING, self._current_tado_vertical_swing
|
||||||
|
):
|
||||||
vertical_swing = self._current_tado_vertical_swing
|
vertical_swing = self._current_tado_vertical_swing
|
||||||
if SWING_HORIZONTAL in self._attr_swing_modes:
|
if self._is_current_setting_supported_by_current_hvac_mode(
|
||||||
|
TADO_HORIZONTAL_SWING_SETTING, self._current_tado_horizontal_swing
|
||||||
|
):
|
||||||
horizontal_swing = self._current_tado_horizontal_swing
|
horizontal_swing = self._current_tado_horizontal_swing
|
||||||
if vertical_swing is None and horizontal_swing is None:
|
if self._is_current_setting_supported_by_current_hvac_mode(
|
||||||
|
TADO_SWING_SETTING, self._current_tado_swing_mode
|
||||||
|
):
|
||||||
swing = self._current_tado_swing_mode
|
swing = self._current_tado_swing_mode
|
||||||
|
|
||||||
self._tado.set_zone_overlay(
|
self._tado.set_zone_overlay(
|
||||||
@ -765,3 +799,20 @@ class TadoClimate(TadoZoneEntity, ClimateEntity):
|
|||||||
vertical_swing=vertical_swing, # api defaults to not sending verticalSwing if swing not None
|
vertical_swing=vertical_swing, # api defaults to not sending verticalSwing if swing not None
|
||||||
horizontal_swing=horizontal_swing, # api defaults to not sending horizontalSwing if swing not None
|
horizontal_swing=horizontal_swing, # api defaults to not sending horizontalSwing if swing not None
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _is_valid_setting_for_hvac_mode(self, setting: str) -> bool:
|
||||||
|
return (
|
||||||
|
self._current_tado_capabilities.get(self._current_tado_hvac_mode, {}).get(
|
||||||
|
setting
|
||||||
|
)
|
||||||
|
is not None
|
||||||
|
)
|
||||||
|
|
||||||
|
def _is_current_setting_supported_by_current_hvac_mode(
|
||||||
|
self, setting: str, current_state: str | None
|
||||||
|
) -> bool:
|
||||||
|
if self._is_valid_setting_for_hvac_mode(setting):
|
||||||
|
return current_state in self._current_tado_capabilities[
|
||||||
|
self._current_tado_hvac_mode
|
||||||
|
].get(setting, [])
|
||||||
|
return False
|
||||||
|
@ -234,3 +234,10 @@ CONF_READING = "reading"
|
|||||||
ATTR_MESSAGE = "message"
|
ATTR_MESSAGE = "message"
|
||||||
|
|
||||||
WATER_HEATER_FALLBACK_REPAIR = "water_heater_fallback"
|
WATER_HEATER_FALLBACK_REPAIR = "water_heater_fallback"
|
||||||
|
|
||||||
|
TADO_SWING_SETTING = "swings"
|
||||||
|
TADO_FANSPEED_SETTING = "fanSpeeds"
|
||||||
|
|
||||||
|
TADO_FANLEVEL_SETTING = "fanLevel"
|
||||||
|
TADO_VERTICAL_SWING_SETTING = "verticalSwing"
|
||||||
|
TADO_HORIZONTAL_SWING_SETTING = "horizontalSwing"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user