mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 05:37:44 +00:00
Add check that sensor state classes are used only with valid unit of measurements (#141444)
This commit is contained in:
parent
aa493ff97d
commit
f842640249
@ -44,6 +44,7 @@ from .const import ( # noqa: F401
|
||||
DEVICE_CLASSES_SCHEMA,
|
||||
DOMAIN,
|
||||
NON_NUMERIC_DEVICE_CLASSES,
|
||||
STATE_CLASS_UNITS,
|
||||
STATE_CLASSES,
|
||||
STATE_CLASSES_SCHEMA,
|
||||
UNIT_CONVERTERS,
|
||||
@ -713,6 +714,18 @@ class SensorEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
||||
report_issue,
|
||||
)
|
||||
|
||||
# Validate unit of measurement used for sensors with a state class
|
||||
if (
|
||||
state_class
|
||||
and (units := STATE_CLASS_UNITS.get(state_class)) is not None
|
||||
and native_unit_of_measurement not in units
|
||||
):
|
||||
raise ValueError(
|
||||
f"Sensor {self.entity_id} ({type(self)}) is using native unit of "
|
||||
f"measurement '{native_unit_of_measurement}' which is not a valid unit "
|
||||
f"for the state class ('{state_class}') it is using; expected one of {units};"
|
||||
)
|
||||
|
||||
return value
|
||||
|
||||
def _display_precision_or_none(self) -> int | None:
|
||||
|
@ -699,3 +699,8 @@ DEVICE_CLASS_STATE_CLASSES: dict[SensorDeviceClass, set[SensorStateClass]] = {
|
||||
SensorDeviceClass.WIND_DIRECTION: {SensorStateClass.MEASUREMENT_ANGLE},
|
||||
SensorDeviceClass.WIND_SPEED: {SensorStateClass.MEASUREMENT},
|
||||
}
|
||||
|
||||
|
||||
STATE_CLASS_UNITS: dict[SensorStateClass | str, set[type[StrEnum] | str | None]] = {
|
||||
SensorStateClass.MEASUREMENT_ANGLE: {DEGREE},
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ from homeassistant.components.sensor import (
|
||||
async_rounded_state,
|
||||
async_update_suggested_units,
|
||||
)
|
||||
from homeassistant.components.sensor.const import STATE_CLASS_UNITS
|
||||
from homeassistant.config_entries import ConfigEntry, ConfigFlow
|
||||
from homeassistant.const import (
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
@ -2005,6 +2006,7 @@ async def test_non_numeric_device_class_with_unit_of_measurement(
|
||||
SensorDeviceClass.VOLUME,
|
||||
SensorDeviceClass.WATER,
|
||||
SensorDeviceClass.WEIGHT,
|
||||
SensorDeviceClass.WIND_DIRECTION,
|
||||
SensorDeviceClass.WIND_SPEED,
|
||||
],
|
||||
)
|
||||
@ -2035,6 +2037,37 @@ async def test_device_classes_with_invalid_unit_of_measurement(
|
||||
) in caplog.text
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"state_class",
|
||||
[SensorStateClass.MEASUREMENT_ANGLE],
|
||||
)
|
||||
async def test_state_classes_with_invalid_unit_of_measurement(
|
||||
hass: HomeAssistant,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
state_class: SensorStateClass,
|
||||
) -> None:
|
||||
"""Test error when unit of measurement is not valid for used state class."""
|
||||
entity0 = MockSensor(
|
||||
name="Test",
|
||||
native_value="1.0",
|
||||
state_class=state_class,
|
||||
native_unit_of_measurement="INVALID!",
|
||||
)
|
||||
setup_test_component_platform(hass, sensor.DOMAIN, [entity0])
|
||||
units = {
|
||||
str(unit) if unit else "no unit of measurement"
|
||||
for unit in STATE_CLASS_UNITS.get(state_class, set())
|
||||
}
|
||||
assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert (
|
||||
f"Sensor sensor.test ({entity0.__class__}) is using native unit of "
|
||||
"measurement 'INVALID!' which is not a valid unit "
|
||||
f"for the state class ('{state_class}') it is using; expected one of {units};"
|
||||
) in caplog.text
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("device_class", "state_class", "unit"),
|
||||
[
|
||||
|
Loading…
x
Reference in New Issue
Block a user