Climate check target min lower than target high (#124488)

* Guard target high_temp higher than low_temp in ClimateEntity

* Fixes

* Update string

* Forgot to fix tests
This commit is contained in:
G Johansson 2024-09-24 15:56:30 +02:00 committed by GitHub
parent 7517948900
commit 03bba6d0c3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 78 additions and 1 deletions

View File

@ -1008,11 +1008,22 @@ async def async_service_temperature_set(
)
hass = entity.hass
kwargs = {}
kwargs: dict[str, Any] = {}
min_temp = entity.min_temp
max_temp = entity.max_temp
temp_unit = entity.temperature_unit
if (
(target_low_temp := service_call.data.get(ATTR_TARGET_TEMP_LOW))
and (target_high_temp := service_call.data.get(ATTR_TARGET_TEMP_HIGH))
and target_low_temp > target_high_temp
):
# Ensure target_low_temp is not higher than target_high_temp.
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="low_temp_higher_than_high_temp",
)
for value, temp in service_call.data.items():
if value in CONVERTIBLE_ATTRIBUTE:
kwargs[value] = check_temp = TemperatureConverter.convert(

View File

@ -270,6 +270,9 @@
"temp_out_of_range": {
"message": "Provided temperature {check_temp} is not valid. Accepted range is {min_temp} to {max_temp}."
},
"low_temp_higher_than_high_temp": {
"message": "Target temperature low can not be higher than Target temperature high."
},
"humidity_out_of_range": {
"message": "Provided humidity {humidity} is not valid. Accepted range is {min_humidity} to {max_humidity}."
}

View File

@ -1224,3 +1224,66 @@ async def test_temperature_validation(
state = hass.states.get("climate.test")
assert state.attributes.get(ATTR_TARGET_TEMP_LOW) == 10
assert state.attributes.get(ATTR_TARGET_TEMP_HIGH) == 25
async def test_target_temp_high_higher_than_low(
hass: HomeAssistant, register_test_integration: MockConfigEntry
) -> None:
"""Test that target high is higher than target low."""
class MockClimateEntityTemp(MockClimateEntity):
"""Mock climate class with mocked aux heater."""
_attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
)
_attr_current_temperature = 15
_attr_target_temperature = 15
_attr_target_temperature_high = 18
_attr_target_temperature_low = 10
_attr_target_temperature_step = PRECISION_WHOLE
def set_temperature(self, **kwargs: Any) -> None:
"""Set new target temperature."""
if ATTR_TEMPERATURE in kwargs:
self._attr_target_temperature = kwargs[ATTR_TEMPERATURE]
if ATTR_TARGET_TEMP_HIGH in kwargs:
self._attr_target_temperature_high = kwargs[ATTR_TARGET_TEMP_HIGH]
self._attr_target_temperature_low = kwargs[ATTR_TARGET_TEMP_LOW]
test_climate = MockClimateEntityTemp(
name="Test",
unique_id="unique_climate_test",
)
setup_test_component_platform(
hass, DOMAIN, entities=[test_climate], from_config_entry=True
)
await hass.config_entries.async_setup(register_test_integration.entry_id)
await hass.async_block_till_done()
state = hass.states.get("climate.test")
assert state.attributes.get(ATTR_CURRENT_TEMPERATURE) == 15
assert state.attributes.get(ATTR_MIN_TEMP) == 7
assert state.attributes.get(ATTR_MAX_TEMP) == 35
with pytest.raises(
ServiceValidationError,
match="Target temperature low can not be higher than Target temperature high",
) as exc:
await hass.services.async_call(
DOMAIN,
SERVICE_SET_TEMPERATURE,
{
"entity_id": "climate.test",
ATTR_TARGET_TEMP_HIGH: "15",
ATTR_TARGET_TEMP_LOW: "20",
},
blocking=True,
)
assert (
str(exc.value)
== "Target temperature low can not be higher than Target temperature high"
)
assert exc.value.translation_key == "low_temp_higher_than_high_temp"