Skip to content

Commit

Permalink
fix: set temps don't restore on HA boot if a preset is set when HA re…
Browse files Browse the repository at this point in the history
…starts

Fixes #184
  • Loading branch information
= authored and swingerman committed May 8, 2024
1 parent 9c6cd5b commit 9defd2b
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 6 deletions.
3 changes: 2 additions & 1 deletion config/configuration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,8 @@ climate:
- platform: dual_smart_thermostat
name: FAN Only Room
unique_id: fan_only_room
fan: switch.fan
heater: switch.fan
fan_mode: true
fan_hot_tolerance: 2
fan_on_with_ac: true
target_sensor: sensor.room_temp
Expand Down
1 change: 1 addition & 0 deletions custom_components/dual_smart_thermostat/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ async def _async_startup(*_) -> None:

else:
# No previous state, try and restore defaults
_LOGGER.debug("No previous state found, setting defaults")
if not self.hvac_device.hvac_mode:
self.hvac_device.hvac_mode = HVACMode.OFF
if self.hvac_device.hvac_mode == HVACMode.OFF:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
import math
from typing import Any

from homeassistant.components.climate import DEFAULT_MAX_TEMP, DEFAULT_MIN_TEMP
from homeassistant.components.climate import (
ATTR_TARGET_TEMP_HIGH,
ATTR_TARGET_TEMP_LOW,
DEFAULT_MAX_TEMP,
DEFAULT_MIN_TEMP,
)
from homeassistant.components.climate.const import HVACMode
from homeassistant.const import ATTR_TEMPERATURE, PRECISION_WHOLE, UnitOfTemperature
from homeassistant.core import HomeAssistant, State, callback
Expand Down Expand Up @@ -387,16 +392,21 @@ def _set_default_temps_range_mode(self) -> None:
self._target_temp_high += PRECISION_WHOLE

def apply_old_state(self, old_state: State) -> None:
_LOGGER.debug("Applying old state: %s", old_state)
if old_state is None:
return

# If we have no initial temperature, restore
if self._target_temp_low is None:
old_target_min = old_state.attributes.get(ATTR_PREV_TARGET_LOW)
old_target_min = old_state.attributes.get(
ATTR_PREV_TARGET_LOW
) or old_state.attributes.get(ATTR_TARGET_TEMP_LOW)
if old_target_min is not None:
self._target_temp_low = float(old_target_min)
if self._target_temp_high is None:
old_target_max = old_state.attributes.get(ATTR_PREV_TARGET_HIGH)
old_target_max = old_state.attributes.get(
ATTR_PREV_TARGET_HIGH
) or old_state.attributes.get(ATTR_TARGET_TEMP_HIGH)
if old_target_max is not None:
self._target_temp_high = float(old_target_max)
if self._target_temp is None:
Expand Down
152 changes: 150 additions & 2 deletions tests/test_dual_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,21 @@
HVACAction,
HVACMode,
)
from homeassistant.components.climate.const import ATTR_PRESET_MODE, DOMAIN as CLIMATE
from homeassistant.components.climate.const import (
ATTR_PRESET_MODE,
ATTR_TARGET_TEMP_HIGH,
ATTR_TARGET_TEMP_LOW,
DOMAIN as CLIMATE,
)
from homeassistant.const import (
ATTR_TEMPERATURE,
ENTITY_MATCH_ALL,
STATE_CLOSED,
STATE_OFF,
STATE_ON,
STATE_OPEN,
)
from homeassistant.core import HomeAssistant
from homeassistant.core import CoreState, HomeAssistant, State
from homeassistant.exceptions import ServiceValidationError
from homeassistant.helpers import entity_registry as er
from homeassistant.setup import async_setup_component
Expand Down Expand Up @@ -554,6 +560,148 @@ async def test_set_heat_cool_preset_mode_and_restore_prev_temp(
assert state.attributes.get("target_temp_high") == 22


@pytest.mark.parametrize(
("preset", "temp_low", "temp_high"),
[
(PRESET_NONE, 18, 22),
(PRESET_AWAY, 16, 30),
(PRESET_COMFORT, 20, 27),
(PRESET_ECO, 18, 29),
(PRESET_HOME, 19, 23),
(PRESET_SLEEP, 17, 24),
(PRESET_ACTIVITY, 21, 28),
(PRESET_ANTI_FREEZE, 5, 32),
],
)
async def test_set_heat_cool_fan_preset_mode_and_restore_prev_temp(
hass: HomeAssistant,
setup_comp_heat_cool_fan_presets, # noqa: F811
preset,
temp_low,
temp_high,
) -> None:
"""Test the setting preset mode.
Verify original temperature is restored.
"""
await common.async_set_temperature(hass, 23, common.ENTITY, 22, 18)
await common.async_set_preset_mode(hass, preset)
state = hass.states.get(common.ENTITY)
assert state.attributes.get("target_temp_low") == temp_low
assert state.attributes.get("target_temp_high") == temp_high
await common.async_set_preset_mode(hass, PRESET_NONE)
state = hass.states.get(common.ENTITY)
assert state.attributes.get("target_temp_low") == 18
assert state.attributes.get("target_temp_high") == 22


@pytest.mark.parametrize(
"preset",
[PRESET_NONE, PRESET_AWAY],
)
async def test_set_heat_cool_fan_restore_state(
hass: HomeAssistant, preset # noqa: F811
) -> None:
common.mock_restore_cache(
hass,
(
State(
"climate.test_thermostat",
HVACMode.HEAT_COOL,
{
ATTR_TARGET_TEMP_HIGH: "20",
ATTR_TARGET_TEMP_LOW: "18",
ATTR_PRESET_MODE: preset,
},
),
),
)

hass.set_state(CoreState.starting)

await async_setup_component(
hass,
CLIMATE,
{
"climate": {
"platform": DOMAIN,
"name": "test_thermostat",
"heater": common.ENT_SWITCH,
"cooler": common.ENT_COOLER,
"fan": common.ENT_FAN,
"heat_cool_mode": True,
"target_sensor": common.ENT_SENSOR,
PRESET_AWAY: {
"temperature": 14,
"target_temp_high": 20,
"target_temp_low": 18,
},
}
},
)
await hass.async_block_till_done()
state = hass.states.get("climate.test_thermostat")
assert state.attributes[ATTR_TARGET_TEMP_HIGH] == 20
assert state.attributes[ATTR_TARGET_TEMP_LOW] == 18
assert state.attributes[ATTR_PRESET_MODE] == preset
assert state.state == HVACMode.HEAT_COOL


@pytest.mark.parametrize(
["preset", "hvac_mode"],
[
[PRESET_NONE, HVACMode.HEAT],
[PRESET_AWAY, HVACMode.HEAT],
[PRESET_NONE, HVACMode.COOL],
[PRESET_AWAY, HVACMode.COOL],
],
)
async def test_set_heat_cool_fan_restore_state_2(
hass: HomeAssistant, preset, hvac_mode # noqa: F811
) -> None:
common.mock_restore_cache(
hass,
(
State(
"climate.test_thermostat",
hvac_mode,
{
ATTR_TEMPERATURE: "20",
ATTR_PRESET_MODE: preset,
},
),
),
)

hass.set_state(CoreState.starting)

await async_setup_component(
hass,
CLIMATE,
{
"climate": {
"platform": DOMAIN,
"name": "test_thermostat",
"heater": common.ENT_SWITCH,
"cooler": common.ENT_COOLER,
"fan": common.ENT_FAN,
"heat_cool_mode": True,
"target_sensor": common.ENT_SENSOR,
PRESET_AWAY: {
"temperature": 14,
"target_temp_high": 20,
"target_temp_low": 18,
},
}
},
)
await hass.async_block_till_done()
state = hass.states.get("climate.test_thermostat")
assert state.attributes[ATTR_TEMPERATURE] == 20
assert state.attributes[ATTR_PRESET_MODE] == preset
assert state.state == hvac_mode


@pytest.mark.parametrize(
("preset", "temperature"),
[
Expand Down

0 comments on commit 9defd2b

Please sign in to comment.