Fix mqtt number state validation (#135621)

pull/136092/head
Jan Bouwhuis 2025-01-15 10:13:27 +01:00 committed by Franck Nijhof
parent 44046c5f83
commit cc0989b50e
No known key found for this signature in database
GPG Key ID: D62583BA8AB11CA3
2 changed files with 99 additions and 3 deletions

View File

@ -179,14 +179,14 @@ class MqttNumber(MqttEntity, RestoreNumber):
return
if num_value is not None and (
num_value < self.min_value or num_value > self.max_value
num_value < self.native_min_value or num_value > self.native_max_value
):
_LOGGER.error(
"Invalid value for %s: %s (range %s - %s)",
self.entity_id,
num_value,
self.min_value,
self.max_value,
self.native_min_value,
self.native_max_value,
)
return

View File

@ -29,6 +29,7 @@ from homeassistant.const import (
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, State
from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM
from .test_common import (
help_custom_config,
@ -157,6 +158,101 @@ async def test_run_number_setup(
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == unit_of_measurement
@pytest.mark.parametrize(
"hass_config",
[
{
mqtt.DOMAIN: {
number.DOMAIN: {
"state_topic": "test/state_number",
"command_topic": "test/cmd_number",
"name": "Test Number",
"min": 15,
"max": 28,
"device_class": "temperature",
"unit_of_measurement": UnitOfTemperature.CELSIUS.value,
}
}
}
],
)
async def test_native_value_validation(
hass: HomeAssistant,
mqtt_mock_entry: MqttMockHAClientGenerator,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test state validation and native value conversion."""
mqtt_mock = await mqtt_mock_entry()
async_fire_mqtt_message(hass, "test/state_number", "23.5")
state = hass.states.get("number.test_number")
assert state is not None
assert state.attributes.get(ATTR_MIN) == 15
assert state.attributes.get(ATTR_MAX) == 28
assert (
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
== UnitOfTemperature.CELSIUS.value
)
assert state.state == "23.5"
# Test out of range validation
async_fire_mqtt_message(hass, "test/state_number", "29.5")
state = hass.states.get("number.test_number")
assert state is not None
assert state.attributes.get(ATTR_MIN) == 15
assert state.attributes.get(ATTR_MAX) == 28
assert (
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
== UnitOfTemperature.CELSIUS.value
)
assert state.state == "23.5"
assert (
"Invalid value for number.test_number: 29.5 (range 15.0 - 28.0)" in caplog.text
)
caplog.clear()
# Check if validation still works when changing unit system
hass.config.units = US_CUSTOMARY_SYSTEM
await hass.async_block_till_done()
async_fire_mqtt_message(hass, "test/state_number", "24.5")
state = hass.states.get("number.test_number")
assert state is not None
assert state.attributes.get(ATTR_MIN) == 59.0
assert state.attributes.get(ATTR_MAX) == 82.4
assert (
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
== UnitOfTemperature.FAHRENHEIT.value
)
assert state.state == "76.1"
# Test out of range validation again
async_fire_mqtt_message(hass, "test/state_number", "29.5")
state = hass.states.get("number.test_number")
assert state is not None
assert state.attributes.get(ATTR_MIN) == 59.0
assert state.attributes.get(ATTR_MAX) == 82.4
assert (
state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
== UnitOfTemperature.FAHRENHEIT.value
)
assert state.state == "76.1"
assert (
"Invalid value for number.test_number: 29.5 (range 15.0 - 28.0)" in caplog.text
)
caplog.clear()
await hass.services.async_call(
NUMBER_DOMAIN,
SERVICE_SET_VALUE,
{ATTR_ENTITY_ID: "number.test_number", ATTR_VALUE: 68},
blocking=True,
)
mqtt_mock.async_publish.assert_called_once_with("test/cmd_number", "20", 0, False)
mqtt_mock.async_publish.reset_mock()
@pytest.mark.parametrize(
"hass_config",
[