diff --git a/config/configuration.yaml b/config/configuration.yaml index 6cf1dc6..ee6e291 100644 --- a/config/configuration.yaml +++ b/config/configuration.yaml @@ -242,6 +242,36 @@ climate: target_temp_high: 20.5 target_temp_low: 19.5 + - platform: dual_smart_thermostat + name: Edge Case 178 + unique_id: edge_case_178 + heater: switch.heater + cooler: switch.cooler + target_sensor: sensor.room_temp + heat_cool_mode: true + target_temp_step: 0.5 + min_temp: 9 + max_temp: 32 + target_temp: 19.5 + target_temp_high: 20.5 + target_temp_low: 19.5 + away: + temperature: 12 + target_temp_low: 12 + target_temp_high: 22.5 + home: + temperature: 20 + target_temp_low: 19 + target_temp_high: 20.5 + sleep: + temperature: 17 + target_temp_low: 17 + target_temp_high: 21 + eco: + temperature: 19 + target_temp_low: 19 + target_temp_high: 21.5 + - platform: dual_smart_thermostat name: AUX Heat Room unique_id: aux_heat_room diff --git a/custom_components/dual_smart_thermostat/managers/feature_manager.py b/custom_components/dual_smart_thermostat/managers/feature_manager.py index 86361dd..b5ade26 100644 --- a/custom_components/dual_smart_thermostat/managers/feature_manager.py +++ b/custom_components/dual_smart_thermostat/managers/feature_manager.py @@ -155,8 +155,12 @@ def set_support_flags( HVACMode.HEAT, ): if self.is_range_mode and preset_mode != PRESET_NONE: - self.temperatures.target_temp_low = self._saved_target_temp_low - self.temperatures.target_temp_high = self._saved_target_temp_high + self.temperatures.target_temp_low = ( + self.temperatures.saved_target_temp_low + ) + self.temperatures.target_temp_high = ( + self.temperatures.saved_target_temp_high + ) self._supported_features = ( self._default_support_flags | ClimateEntityFeature.TARGET_TEMPERATURE ) diff --git a/tests/__init__.py b/tests/__init__.py index 7e2b884..32831cb 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -784,6 +784,66 @@ async def setup_comp_heat_cool_presets(hass: HomeAssistant) -> None: await hass.async_block_till_done() +@pytest.fixture +async def setup_comp_heat_cool_fan_presets(hass: HomeAssistant) -> None: + """Initialize components.""" + hass.config.units = METRIC_SYSTEM + assert await async_setup_component( + hass, + CLIMATE, + { + "climate": { + "platform": DOMAIN, + "name": "test", + "cold_tolerance": 2, + "hot_tolerance": 4, + "heat_cool_mode": True, + "heater": common.ENT_HEATER, + "cooler": common.ENT_COOLER, + "fan": common.ENT_FAN, + "target_sensor": common.ENT_SENSOR, + "initial_hvac_mode": HVACMode.HEAT_COOL, + PRESET_AWAY: { + "temperature": 16, + "target_temp_low": 16, + "target_temp_high": 30, + }, + PRESET_COMFORT: { + "temperature": 20, + "target_temp_low": 20, + "target_temp_high": 27, + }, + PRESET_ECO: { + "temperature": 18, + "target_temp_low": 18, + "target_temp_high": 29, + }, + PRESET_HOME: { + "temperature": 19, + "target_temp_low": 19, + "target_temp_high": 23, + }, + PRESET_SLEEP: { + "temperature": 17, + "target_temp_low": 17, + "target_temp_high": 24, + }, + PRESET_ACTIVITY: { + "temperature": 21, + "target_temp_low": 21, + "target_temp_high": 28, + }, + "anti_freeze": { + "temperature": 5, + "target_temp_low": 5, + "target_temp_high": 32, + }, + } + }, + ) + await hass.async_block_till_done() + + async def setup_component(hass: HomeAssistant, mock_config: dict) -> MockConfigEntry: """Initialize knmi for tests.""" config_entry = MockConfigEntry(domain=DOMAIN, data=mock_config, entry_id="test") diff --git a/tests/test_dual_mode.py b/tests/test_dual_mode.py index 19fcfe3..6e9c449 100644 --- a/tests/test_dual_mode.py +++ b/tests/test_dual_mode.py @@ -53,6 +53,7 @@ setup_comp_heat_cool_2, setup_comp_heat_cool_fan_config, setup_comp_heat_cool_fan_config_2, + setup_comp_heat_cool_fan_presets, setup_comp_heat_cool_presets, setup_floor_sensor, setup_sensor, @@ -749,6 +750,117 @@ async def test_heat_cool_set_preset_mode_set_temp_keeps_preset_mode( 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_heat_cool_fan_set_preset_mode_set_temp_keeps_preset_mode( + hass: HomeAssistant, + setup_comp_heat_cool_fan_presets, # noqa: F811 + preset, + temp_low, + temp_high, +) -> None: + """Test the setting preset mode then set temperature. + + Verify preset mode preserved while temperature updated. + """ + test_target_temp_low = 3 + test_target_temp_high = 33 + await common.async_set_temperature(hass, 18, 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_temperature( + hass, + test_target_temp_low, + common.ENTITY, + test_target_temp_high, + test_target_temp_low, + ) + state = hass.states.get(common.ENTITY) + assert state.attributes.get("target_temp_low") == test_target_temp_low + assert state.attributes.get("target_temp_high") == test_target_temp_high + assert state.attributes.get("preset_mode") == preset + assert state.attributes.get("supported_features") == 402 + await common.async_set_preset_mode(hass, PRESET_NONE) + state = hass.states.get(common.ENTITY) + if preset == PRESET_NONE: + assert state.attributes.get("target_temp_low") == test_target_temp_low + assert state.attributes.get("target_temp_high") == test_target_temp_high + else: + assert state.attributes.get("target_temp_low") == 18 + 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_heat_cool_fan_set_preset_mode_change_hvac_mode( + hass: HomeAssistant, + setup_comp_heat_cool_fan_presets, # noqa: F811 + preset, + temp_low, + temp_high, +) -> None: + """Test the setting preset mode then set temperature. + + Verify preset mode preserved while temperature updated. + """ + await common.async_set_temperature(hass, 18, 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_hvac_mode(hass, HVACMode.HEAT) + await hass.async_block_till_done() + + state = hass.states.get(common.ENTITY) + assert state.attributes.get("preset_mode") == preset + assert state.attributes.get("temperature") == 18 + assert state.attributes.get("target_temp_low") is None + assert state.attributes.get("target_temp_high") is None + + await common.async_set_hvac_mode(hass, HVACMode.COOL) + await hass.async_block_till_done() + + state = hass.states.get(common.ENTITY) + assert state.attributes.get("preset_mode") == preset + assert state.attributes.get("temperature") == 18 + assert state.attributes.get("target_temp_low") is None + assert state.attributes.get("target_temp_high") is None + + await common.async_set_hvac_mode(hass, HVACMode.FAN_ONLY) + await hass.async_block_till_done() + + state = hass.states.get(common.ENTITY) + assert state.attributes.get("preset_mode") == preset + assert state.attributes.get("temperature") == 18 + assert state.attributes.get("target_temp_low") is None + assert state.attributes.get("target_temp_high") is None + + ################### # HVAC OPERATIONS # ###################