Generic thermostat presets (#56080)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
fb04b19960
commit
27e3a5ba83
2 changed files with 85 additions and 26 deletions
|
@ -15,8 +15,12 @@ from homeassistant.components.climate.const import (
|
|||
HVAC_MODE_COOL,
|
||||
HVAC_MODE_HEAT,
|
||||
HVAC_MODE_OFF,
|
||||
PRESET_ACTIVITY,
|
||||
PRESET_AWAY,
|
||||
PRESET_COMFORT,
|
||||
PRESET_HOME,
|
||||
PRESET_NONE,
|
||||
PRESET_SLEEP,
|
||||
SUPPORT_PRESET_MODE,
|
||||
SUPPORT_TARGET_TEMPERATURE,
|
||||
)
|
||||
|
@ -64,10 +68,20 @@ CONF_COLD_TOLERANCE = "cold_tolerance"
|
|||
CONF_HOT_TOLERANCE = "hot_tolerance"
|
||||
CONF_KEEP_ALIVE = "keep_alive"
|
||||
CONF_INITIAL_HVAC_MODE = "initial_hvac_mode"
|
||||
CONF_AWAY_TEMP = "away_temp"
|
||||
CONF_PRECISION = "precision"
|
||||
SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE
|
||||
|
||||
CONF_PRESETS = {
|
||||
p: f"{p}_temp"
|
||||
for p in (
|
||||
PRESET_AWAY,
|
||||
PRESET_COMFORT,
|
||||
PRESET_HOME,
|
||||
PRESET_SLEEP,
|
||||
PRESET_ACTIVITY,
|
||||
)
|
||||
}
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(CONF_HEATER): cv.entity_id,
|
||||
|
@ -84,13 +98,12 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
|||
vol.Optional(CONF_INITIAL_HVAC_MODE): vol.In(
|
||||
[HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_OFF]
|
||||
),
|
||||
vol.Optional(CONF_AWAY_TEMP): vol.Coerce(float),
|
||||
vol.Optional(CONF_PRECISION): vol.In(
|
||||
[PRECISION_TENTHS, PRECISION_HALVES, PRECISION_WHOLE]
|
||||
),
|
||||
vol.Optional(CONF_UNIQUE_ID): cv.string,
|
||||
}
|
||||
)
|
||||
).extend({vol.Optional(v): vol.Coerce(float) for (k, v) in CONF_PRESETS.items()})
|
||||
|
||||
|
||||
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
||||
|
@ -110,7 +123,9 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
|
|||
hot_tolerance = config.get(CONF_HOT_TOLERANCE)
|
||||
keep_alive = config.get(CONF_KEEP_ALIVE)
|
||||
initial_hvac_mode = config.get(CONF_INITIAL_HVAC_MODE)
|
||||
away_temp = config.get(CONF_AWAY_TEMP)
|
||||
presets = {
|
||||
key: config[value] for key, value in CONF_PRESETS.items() if value in config
|
||||
}
|
||||
precision = config.get(CONF_PRECISION)
|
||||
unit = hass.config.units.temperature_unit
|
||||
unique_id = config.get(CONF_UNIQUE_ID)
|
||||
|
@ -130,7 +145,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
|
|||
hot_tolerance,
|
||||
keep_alive,
|
||||
initial_hvac_mode,
|
||||
away_temp,
|
||||
presets,
|
||||
precision,
|
||||
unit,
|
||||
unique_id,
|
||||
|
@ -156,7 +171,7 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
|
|||
hot_tolerance,
|
||||
keep_alive,
|
||||
initial_hvac_mode,
|
||||
away_temp,
|
||||
presets,
|
||||
precision,
|
||||
unit,
|
||||
unique_id,
|
||||
|
@ -171,7 +186,7 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
|
|||
self._hot_tolerance = hot_tolerance
|
||||
self._keep_alive = keep_alive
|
||||
self._hvac_mode = initial_hvac_mode
|
||||
self._saved_target_temp = target_temp or away_temp
|
||||
self._saved_target_temp = target_temp or next(iter(presets.values()), None)
|
||||
self._temp_precision = precision
|
||||
if self.ac_mode:
|
||||
self._hvac_list = [HVAC_MODE_COOL, HVAC_MODE_OFF]
|
||||
|
@ -187,12 +202,12 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
|
|||
self._unit = unit
|
||||
self._unique_id = unique_id
|
||||
self._support_flags = SUPPORT_FLAGS
|
||||
if away_temp:
|
||||
if len(presets):
|
||||
self._support_flags = SUPPORT_FLAGS | SUPPORT_PRESET_MODE
|
||||
self._attr_preset_modes = [PRESET_NONE, PRESET_AWAY]
|
||||
self._attr_preset_modes = [PRESET_NONE] + list(presets.keys())
|
||||
else:
|
||||
self._attr_preset_modes = [PRESET_NONE]
|
||||
self._away_temp = away_temp
|
||||
self._presets = presets
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Run when entity about to be added."""
|
||||
|
@ -528,14 +543,15 @@ class GenericThermostat(ClimateEntity, RestoreEntity):
|
|||
if preset_mode == self._attr_preset_mode:
|
||||
# I don't think we need to call async_write_ha_state if we didn't change the state
|
||||
return
|
||||
if preset_mode == PRESET_AWAY:
|
||||
self._attr_preset_mode = PRESET_AWAY
|
||||
self._saved_target_temp = self._target_temp
|
||||
self._target_temp = self._away_temp
|
||||
await self._async_control_heating(force=True)
|
||||
elif preset_mode == PRESET_NONE:
|
||||
if preset_mode == PRESET_NONE:
|
||||
self._attr_preset_mode = PRESET_NONE
|
||||
self._target_temp = self._saved_target_temp
|
||||
await self._async_control_heating(force=True)
|
||||
else:
|
||||
if self._attr_preset_mode == PRESET_NONE:
|
||||
self._saved_target_temp = self._target_temp
|
||||
self._attr_preset_mode = preset_mode
|
||||
self._target_temp = self._presets[preset_mode]
|
||||
await self._async_control_heating(force=True)
|
||||
|
||||
self.async_write_ha_state()
|
||||
|
|
|
@ -13,8 +13,12 @@ from homeassistant.components.climate.const import (
|
|||
HVAC_MODE_COOL,
|
||||
HVAC_MODE_HEAT,
|
||||
HVAC_MODE_OFF,
|
||||
PRESET_ACTIVITY,
|
||||
PRESET_AWAY,
|
||||
PRESET_COMFORT,
|
||||
PRESET_HOME,
|
||||
PRESET_NONE,
|
||||
PRESET_SLEEP,
|
||||
)
|
||||
from homeassistant.components.generic_thermostat import (
|
||||
DOMAIN as GENERIC_THERMOSTAT_DOMAIN,
|
||||
|
@ -209,6 +213,10 @@ async def setup_comp_2(hass):
|
|||
"heater": ENT_SWITCH,
|
||||
"target_sensor": ENT_SENSOR,
|
||||
"away_temp": 16,
|
||||
"sleep_temp": 17,
|
||||
"home_temp": 19,
|
||||
"comfort_temp": 20,
|
||||
"activity_temp": 21,
|
||||
"initial_hvac_mode": HVAC_MODE_HEAT,
|
||||
}
|
||||
},
|
||||
|
@ -288,38 +296,73 @@ async def test_set_target_temp(hass, setup_comp_2):
|
|||
assert state.attributes.get("temperature") == 30.0
|
||||
|
||||
|
||||
async def test_set_away_mode(hass, setup_comp_2):
|
||||
@pytest.mark.parametrize(
|
||||
"preset,temp",
|
||||
[
|
||||
(PRESET_NONE, 23),
|
||||
(PRESET_AWAY, 16),
|
||||
(PRESET_COMFORT, 20),
|
||||
(PRESET_HOME, 19),
|
||||
(PRESET_SLEEP, 17),
|
||||
(PRESET_ACTIVITY, 21),
|
||||
],
|
||||
)
|
||||
async def test_set_away_mode(hass, setup_comp_2, preset, temp):
|
||||
"""Test the setting away mode."""
|
||||
await common.async_set_temperature(hass, 23)
|
||||
await common.async_set_preset_mode(hass, PRESET_AWAY)
|
||||
await common.async_set_preset_mode(hass, preset)
|
||||
state = hass.states.get(ENTITY)
|
||||
assert state.attributes.get("temperature") == 16
|
||||
assert state.attributes.get("temperature") == temp
|
||||
|
||||
|
||||
async def test_set_away_mode_and_restore_prev_temp(hass, setup_comp_2):
|
||||
@pytest.mark.parametrize(
|
||||
"preset,temp",
|
||||
[
|
||||
(PRESET_NONE, 23),
|
||||
(PRESET_AWAY, 16),
|
||||
(PRESET_COMFORT, 20),
|
||||
(PRESET_HOME, 19),
|
||||
(PRESET_SLEEP, 17),
|
||||
(PRESET_ACTIVITY, 21),
|
||||
],
|
||||
)
|
||||
async def test_set_away_mode_and_restore_prev_temp(hass, setup_comp_2, preset, temp):
|
||||
"""Test the setting and removing away mode.
|
||||
|
||||
Verify original temperature is restored.
|
||||
"""
|
||||
await common.async_set_temperature(hass, 23)
|
||||
await common.async_set_preset_mode(hass, PRESET_AWAY)
|
||||
await common.async_set_preset_mode(hass, preset)
|
||||
state = hass.states.get(ENTITY)
|
||||
assert state.attributes.get("temperature") == 16
|
||||
assert state.attributes.get("temperature") == temp
|
||||
await common.async_set_preset_mode(hass, PRESET_NONE)
|
||||
state = hass.states.get(ENTITY)
|
||||
assert state.attributes.get("temperature") == 23
|
||||
|
||||
|
||||
async def test_set_away_mode_twice_and_restore_prev_temp(hass, setup_comp_2):
|
||||
@pytest.mark.parametrize(
|
||||
"preset,temp",
|
||||
[
|
||||
(PRESET_NONE, 23),
|
||||
(PRESET_AWAY, 16),
|
||||
(PRESET_COMFORT, 20),
|
||||
(PRESET_HOME, 19),
|
||||
(PRESET_SLEEP, 17),
|
||||
(PRESET_ACTIVITY, 21),
|
||||
],
|
||||
)
|
||||
async def test_set_away_mode_twice_and_restore_prev_temp(
|
||||
hass, setup_comp_2, preset, temp
|
||||
):
|
||||
"""Test the setting away mode twice in a row.
|
||||
|
||||
Verify original temperature is restored.
|
||||
"""
|
||||
await common.async_set_temperature(hass, 23)
|
||||
await common.async_set_preset_mode(hass, PRESET_AWAY)
|
||||
await common.async_set_preset_mode(hass, PRESET_AWAY)
|
||||
await common.async_set_preset_mode(hass, preset)
|
||||
await common.async_set_preset_mode(hass, preset)
|
||||
state = hass.states.get(ENTITY)
|
||||
assert state.attributes.get("temperature") == 16
|
||||
assert state.attributes.get("temperature") == temp
|
||||
await common.async_set_preset_mode(hass, PRESET_NONE)
|
||||
state = hass.states.get(ENTITY)
|
||||
assert state.attributes.get("temperature") == 23
|
||||
|
|
Loading…
Add table
Reference in a new issue