Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions homeassistant/components/sensor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,15 +271,18 @@ def device_class(self) -> SensorDeviceClass | None:
@property
def _numeric_state_expected(self) -> bool:
"""Return true if the sensor must be numeric."""
device_class = try_parse_enum(SensorDeviceClass, self.device_class)
Comment thread
balloob marked this conversation as resolved.
if device_class in NON_NUMERIC_DEVICE_CLASSES:
return False
if (
self.state_class is not None
or self.native_unit_of_measurement is not None
or self.suggested_display_precision is not None
):
return True
# Sensors with custom device classes are not considered numeric
device_class = try_parse_enum(SensorDeviceClass, self.device_class)
return device_class not in {None, *NON_NUMERIC_DEVICE_CLASSES}
# Sensors with custom device classes will have the device class
# converted to None and are not considered numeric
return device_class is not None

@property
def options(self) -> list[str] | None:
Expand Down
41 changes: 41 additions & 0 deletions tests/components/sensor/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,47 @@ async def test_datetime_conversion(
assert state.state == test_timestamp.isoformat()


async def test_a_sensor_with_a_non_numeric_device_class(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
enable_custom_integrations: None,
) -> None:
"""Test that a sensor with a non numeric device class will be non numeric.

A non numeric sensor with a valid device class should never be
handled as numeric because it has a device class.
"""
test_timestamp = datetime(2017, 12, 19, 18, 29, 42, tzinfo=timezone.utc)
test_local_timestamp = test_timestamp.astimezone(
dt_util.get_time_zone("Europe/Amsterdam")
)

platform = getattr(hass.components, "test.sensor")
platform.init(empty=True)
platform.ENTITIES["0"] = platform.MockSensor(
name="Test",
native_value=test_local_timestamp,
native_unit_of_measurement="",
device_class=SensorDeviceClass.TIMESTAMP,
)

platform.ENTITIES["1"] = platform.MockSensor(
name="Test",
native_value=test_local_timestamp,
state_class="",
device_class=SensorDeviceClass.TIMESTAMP,
)

assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}})
await hass.async_block_till_done()

state = hass.states.get(platform.ENTITIES["0"].entity_id)
assert state.state == test_timestamp.isoformat()

state = hass.states.get(platform.ENTITIES["1"].entity_id)
assert state.state == test_timestamp.isoformat()


@pytest.mark.parametrize(
("device_class", "state_value", "provides"),
[
Expand Down