Adjust ManualTriggerSensorEntity to handle timestamp device classes (#145909)

This commit is contained in:
G Johansson 2025-07-18 13:49:12 +02:00 committed by GitHub
parent 17034f4d6a
commit 277241c4d3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 65 additions and 42 deletions

View File

@ -10,8 +10,6 @@ from typing import Any
from jsonpath import jsonpath
from homeassistant.components.sensor import SensorDeviceClass
from homeassistant.components.sensor.helpers import async_parse_date_datetime
from homeassistant.const import (
CONF_COMMAND,
CONF_NAME,
@ -188,16 +186,7 @@ class CommandSensor(ManualTriggerSensorEntity):
self.entity_id, variables, None
)
if self.device_class not in {
SensorDeviceClass.DATE,
SensorDeviceClass.TIMESTAMP,
}:
self._attr_native_value = value
elif value is not None:
self._attr_native_value = async_parse_date_datetime(
value, self.entity_id, self.device_class
)
self._set_native_value_with_possible_timestamp(value)
self._process_manual_data(variables)
self.async_write_ha_state()

View File

@ -13,9 +13,7 @@ from homeassistant.components.sensor import (
CONF_STATE_CLASS,
DOMAIN as SENSOR_DOMAIN,
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorDeviceClass,
)
from homeassistant.components.sensor.helpers import async_parse_date_datetime
from homeassistant.const import (
CONF_DEVICE_CLASS,
CONF_FORCE_UPDATE,
@ -181,18 +179,6 @@ class RestSensor(ManualTriggerSensorEntity, RestEntity):
self.entity_id, variables, None
)
if value is None or self.device_class not in (
SensorDeviceClass.DATE,
SensorDeviceClass.TIMESTAMP,
):
self._attr_native_value = value
self._process_manual_data(variables)
self.async_write_ha_state()
return
self._attr_native_value = async_parse_date_datetime(
value, self.entity_id, self.device_class
)
self._set_native_value_with_possible_timestamp(value)
self._process_manual_data(variables)
self.async_write_ha_state()

View File

@ -7,8 +7,7 @@ from typing import Any, cast
import voluptuous as vol
from homeassistant.components.sensor import CONF_STATE_CLASS, SensorDeviceClass
from homeassistant.components.sensor.helpers import async_parse_date_datetime
from homeassistant.components.sensor import CONF_STATE_CLASS
from homeassistant.const import (
CONF_ATTRIBUTE,
CONF_DEVICE_CLASS,
@ -218,17 +217,7 @@ class ScrapeSensor(CoordinatorEntity[ScrapeCoordinator], ManualTriggerSensorEnti
self.entity_id, variables, None
)
if self.device_class not in {
SensorDeviceClass.DATE,
SensorDeviceClass.TIMESTAMP,
}:
self._attr_native_value = value
self._process_manual_data(variables)
return
self._attr_native_value = async_parse_date_datetime(
value, self.entity_id, self.device_class
)
self._set_native_value_with_possible_timestamp(value)
self._process_manual_data(variables)
@property

View File

@ -217,7 +217,7 @@ class SnmpSensor(ManualTriggerSensorEntity):
self.entity_id, variables, STATE_UNKNOWN
)
self._attr_native_value = value
self._set_native_value_with_possible_timestamp(value)
self._process_manual_data(variables)

View File

@ -401,9 +401,10 @@ class SQLSensor(ManualTriggerSensorEntity):
if data is not None and self._template is not None:
variables = self._template_variables_with_value(data)
if self._render_availability_template(variables):
self._attr_native_value = self._template.async_render_as_value_template(
_value = self._template.async_render_as_value_template(
self.entity_id, variables, None
)
self._set_native_value_with_possible_timestamp(_value)
self._process_manual_data(variables)
else:
self._attr_native_value = data

View File

@ -13,8 +13,10 @@ from homeassistant.components.sensor import (
CONF_STATE_CLASS,
DEVICE_CLASSES_SCHEMA,
STATE_CLASSES_SCHEMA,
SensorDeviceClass,
SensorEntity,
)
from homeassistant.components.sensor.helpers import async_parse_date_datetime
from homeassistant.const import (
ATTR_ENTITY_PICTURE,
ATTR_FRIENDLY_NAME,
@ -389,3 +391,20 @@ class ManualTriggerSensorEntity(ManualTriggerEntity, SensorEntity):
ManualTriggerEntity.__init__(self, hass, config)
self._attr_native_unit_of_measurement = config.get(CONF_UNIT_OF_MEASUREMENT)
self._attr_state_class = config.get(CONF_STATE_CLASS)
@callback
def _set_native_value_with_possible_timestamp(self, value: Any) -> None:
"""Set native value with possible timestamp.
If self.device_class is `date` or `timestamp`,
it will try to parse the value to a date/datetime object.
"""
if self.device_class not in (
SensorDeviceClass.DATE,
SensorDeviceClass.TIMESTAMP,
):
self._attr_native_value = value
elif value is not None:
self._attr_native_value = async_parse_date_datetime(
value, self.entity_id, self.device_class
)

View File

@ -4,7 +4,10 @@ from typing import Any
import pytest
from homeassistant.components.sensor import SensorDeviceClass
from homeassistant.components.sensor.helpers import async_parse_date_datetime
from homeassistant.const import (
CONF_DEVICE_CLASS,
CONF_ICON,
CONF_NAME,
CONF_STATE,
@ -20,6 +23,7 @@ from homeassistant.helpers.trigger_template_entity import (
CONF_AVAILABILITY,
CONF_PICTURE,
ManualTriggerEntity,
ManualTriggerSensorEntity,
ValueTemplate,
)
@ -288,3 +292,38 @@ async def test_trigger_template_complex(hass: HomeAssistant) -> None:
await hass.async_block_till_done()
assert entity.some_other_key == {"test_key": "test_data"}
async def test_manual_trigger_sensor_entity_with_date(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
) -> None:
"""Test manual trigger template entity when availability template isn't used."""
config = {
CONF_NAME: template.Template("test_entity", hass),
CONF_STATE: template.Template("{{ as_datetime(value) }}", hass),
CONF_DEVICE_CLASS: SensorDeviceClass.TIMESTAMP,
}
class TestEntity(ManualTriggerSensorEntity):
"""Test entity class."""
extra_template_keys = (CONF_STATE,)
@property
def state(self) -> bool | None:
"""Return extra attributes."""
return "2025-01-01T00:00:00+00:00"
entity = TestEntity(hass, config)
entity.entity_id = "test.entity"
variables = entity._template_variables_with_value("2025-01-01T00:00:00+00:00")
assert entity._render_availability_template(variables) is True
assert entity.available is True
entity._set_native_value_with_possible_timestamp(entity.state)
await hass.async_block_till_done()
assert entity.native_value == async_parse_date_datetime(
"2025-01-01T00:00:00+00:00", entity.entity_id, entity.device_class
)
assert entity.state == "2025-01-01T00:00:00+00:00"
assert entity.device_class == SensorDeviceClass.TIMESTAMP