mirror of
https://github.com/home-assistant/core.git
synced 2026-08-24 10:13:52 -05:00
Use EntityStateAttribute enum in helpers (#175836)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
db0d5da9b3
commit
a3c58649d8
@@ -7,7 +7,7 @@ from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from typing import TYPE_CHECKING, Any, Literal, TypedDict, override
|
||||
|
||||
from homeassistant.const import ATTR_DEVICE_CLASS
|
||||
from homeassistant.const import EntityStateAttribute
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.util.dt import utc_from_timestamp, utcnow
|
||||
from homeassistant.util.event_type import EventType
|
||||
@@ -581,7 +581,8 @@ def _validate_temperature_entity(hass: HomeAssistant, entity_id: str) -> None:
|
||||
|
||||
if (
|
||||
state.domain != "sensor"
|
||||
or state.attributes.get(ATTR_DEVICE_CLASS) != SensorDeviceClass.TEMPERATURE
|
||||
or state.attributes.get(EntityStateAttribute.DEVICE_CLASS)
|
||||
!= SensorDeviceClass.TEMPERATURE
|
||||
):
|
||||
raise ValueError(f"Entity {entity_id} is not a temperature sensor")
|
||||
|
||||
@@ -595,6 +596,7 @@ def _validate_humidity_entity(hass: HomeAssistant, entity_id: str) -> None:
|
||||
|
||||
if (
|
||||
state.domain != "sensor"
|
||||
or state.attributes.get(ATTR_DEVICE_CLASS) != SensorDeviceClass.HUMIDITY
|
||||
or state.attributes.get(EntityStateAttribute.DEVICE_CLASS)
|
||||
!= SensorDeviceClass.HUMIDITY
|
||||
):
|
||||
raise ValueError(f"Entity {entity_id} is not a humidity sensor")
|
||||
|
||||
@@ -31,8 +31,6 @@ from typing import (
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
CONF_ABOVE,
|
||||
CONF_AFTER,
|
||||
CONF_ATTRIBUTE,
|
||||
@@ -56,6 +54,7 @@ from homeassistant.const import (
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
WEEKDAYS,
|
||||
EntityStateAttribute,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, State, callback, split_entity_id
|
||||
from homeassistant.exceptions import (
|
||||
@@ -989,7 +988,7 @@ class EntityNumericalConditionBase(EntityConditionBase):
|
||||
# Entity not found
|
||||
return None
|
||||
if not self._is_valid_unit(
|
||||
entity_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||
entity_state.attributes.get(EntityStateAttribute.UNIT_OF_MEASUREMENT)
|
||||
):
|
||||
# Entity unit does not match the expected unit
|
||||
return None
|
||||
@@ -1007,7 +1006,7 @@ class EntityNumericalConditionBase(EntityConditionBase):
|
||||
domain_spec = self._domain_specs[entity_state.domain]
|
||||
if domain_spec.value_source is None:
|
||||
if not self._is_valid_unit(
|
||||
entity_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||
entity_state.attributes.get(EntityStateAttribute.UNIT_OF_MEASUREMENT)
|
||||
):
|
||||
return None
|
||||
return entity_state.state
|
||||
@@ -1095,7 +1094,7 @@ class EntityNumericalConditionWithUnitBase(EntityNumericalConditionBase):
|
||||
|
||||
def _get_entity_unit(self, entity_state: State) -> str | None:
|
||||
"""Get the unit of an entity from its state."""
|
||||
return entity_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||
return entity_state.attributes.get(EntityStateAttribute.UNIT_OF_MEASUREMENT)
|
||||
|
||||
@override
|
||||
def _get_threshold_value(self, threshold: ThresholdConfig | None) -> float | None:
|
||||
@@ -1121,7 +1120,7 @@ class EntityNumericalConditionWithUnitBase(EntityNumericalConditionBase):
|
||||
try:
|
||||
return self._unit_converter.convert(
|
||||
value,
|
||||
entity_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT),
|
||||
entity_state.attributes.get(EntityStateAttribute.UNIT_OF_MEASUREMENT),
|
||||
self._base_unit,
|
||||
)
|
||||
except HomeAssistantError:
|
||||
@@ -1851,7 +1850,7 @@ def time(
|
||||
):
|
||||
after = datetime.strptime(after_entity.state, "%H:%M:%S").time()
|
||||
elif (
|
||||
after_entity.attributes.get(ATTR_DEVICE_CLASS)
|
||||
after_entity.attributes.get(EntityStateAttribute.DEVICE_CLASS)
|
||||
in (SensorDeviceClass.TIMESTAMP, SensorDeviceClass.UPTIME)
|
||||
) and after_entity.state not in (
|
||||
STATE_UNAVAILABLE,
|
||||
@@ -1881,7 +1880,7 @@ def time(
|
||||
except ValueError:
|
||||
return False
|
||||
elif (
|
||||
before_entity.attributes.get(ATTR_DEVICE_CLASS)
|
||||
before_entity.attributes.get(EntityStateAttribute.DEVICE_CLASS)
|
||||
in (SensorDeviceClass.TIMESTAMP, SensorDeviceClass.UPTIME)
|
||||
) and before_entity.state not in (
|
||||
STATE_UNAVAILABLE,
|
||||
|
||||
@@ -14,11 +14,7 @@ from propcache.api import cached_property
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.homeassistant.exposed_entities import async_should_expose
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_SUPPORTED_FEATURES,
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, EntityStateAttribute
|
||||
from homeassistant.core import Context, HomeAssistant, State, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.util.hass_dict import HassKey
|
||||
@@ -455,7 +451,9 @@ def _filter_by_features(
|
||||
yield candidate
|
||||
continue
|
||||
|
||||
supported_features = candidate.state.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
||||
supported_features = candidate.state.attributes.get(
|
||||
EntityStateAttribute.SUPPORTED_FEATURES, 0
|
||||
)
|
||||
if (supported_features & features) == features:
|
||||
yield candidate
|
||||
|
||||
@@ -474,7 +472,7 @@ def _filter_by_device_classes(
|
||||
yield candidate
|
||||
continue
|
||||
|
||||
device_class = candidate.state.attributes.get(ATTR_DEVICE_CLASS)
|
||||
device_class = candidate.state.attributes.get(EntityStateAttribute.DEVICE_CLASS)
|
||||
if device_class and (device_class in device_classes):
|
||||
yield candidate
|
||||
|
||||
@@ -811,7 +809,7 @@ def async_match_states(
|
||||
@callback
|
||||
def async_test_feature(state: State, feature: int, feature_name: str) -> None:
|
||||
"""Test if state supports a feature."""
|
||||
if state.attributes.get(ATTR_SUPPORTED_FEATURES, 0) & feature == 0:
|
||||
if state.attributes.get(EntityStateAttribute.SUPPORTED_FEATURES, 0) & feature == 0:
|
||||
raise IntentHandleError(f"Entity {state.name} does not support {feature_name}")
|
||||
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ from homeassistant.const import (
|
||||
ATTR_SERVICE,
|
||||
EVENT_HOMEASSISTANT_CLOSE,
|
||||
EVENT_SERVICE_REMOVED,
|
||||
EntityStateAttribute,
|
||||
)
|
||||
from homeassistant.core import Context, Event, HomeAssistant, callback, split_entity_id
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
@@ -731,7 +732,10 @@ def _get_exposed_entities(
|
||||
info["state"] = async_rounded_state(hass, state.entity_id, state)
|
||||
|
||||
# Convert timestamp device_class states from UTC to local time
|
||||
if state.attributes.get("device_class") == "timestamp" and state.state:
|
||||
if (
|
||||
state.attributes.get(EntityStateAttribute.DEVICE_CLASS) == "timestamp"
|
||||
and state.state
|
||||
):
|
||||
if (parsed_utc := dt_util.parse_datetime(state.state)) is not None:
|
||||
info["state"] = dt_util.as_local(parsed_utc).isoformat()
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ from typing import Any, override
|
||||
from lru import LRU
|
||||
from propcache.api import under_cached_property
|
||||
|
||||
from homeassistant.const import ATTR_UNIT_OF_MEASUREMENT, STATE_UNKNOWN
|
||||
from homeassistant.const import STATE_UNKNOWN, EntityStateAttribute
|
||||
from homeassistant.core import (
|
||||
Context,
|
||||
HomeAssistant,
|
||||
@@ -182,7 +182,7 @@ class StateTranslated:
|
||||
|
||||
state_value = state.state
|
||||
domain = state.domain
|
||||
device_class = state.attributes.get("device_class")
|
||||
device_class = state.attributes.get(EntityStateAttribute.DEVICE_CLASS)
|
||||
entry = er.async_get(self._hass).async_get(entity_id)
|
||||
platform = None if entry is None else entry.platform
|
||||
translation_key = None if entry is None else entry.translation_key
|
||||
@@ -219,7 +219,7 @@ class StateAttrTranslated:
|
||||
return attr_value
|
||||
|
||||
domain = state.domain
|
||||
device_class = state.attributes.get("device_class")
|
||||
device_class = state.attributes.get(EntityStateAttribute.DEVICE_CLASS)
|
||||
entry = er.async_get(self._hass).async_get(entity_id)
|
||||
platform = None if entry is None else entry.platform
|
||||
translation_key = None if entry is None else entry.translation_key
|
||||
@@ -413,7 +413,9 @@ class TemplateStateBase(State):
|
||||
state = async_rounded_state(self._hass, self._entity_id, self._state)
|
||||
else:
|
||||
state = self._state.state
|
||||
if with_unit and (unit := self._state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)):
|
||||
if with_unit and (
|
||||
unit := self._state.attributes.get(EntityStateAttribute.UNIT_OF_MEASUREMENT)
|
||||
):
|
||||
return f"{state} {unit}"
|
||||
return state
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ import voluptuous as vol
|
||||
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
CONF_ALIAS,
|
||||
CONF_DEVICE_ID,
|
||||
CONF_ENABLED,
|
||||
@@ -42,6 +41,7 @@ from homeassistant.const import (
|
||||
CONF_ZONE,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
EntityStateAttribute,
|
||||
)
|
||||
from homeassistant.core import (
|
||||
CALLBACK_TYPE,
|
||||
@@ -856,7 +856,7 @@ class EntityNumericalStateTriggerBase(EntityTriggerBase):
|
||||
entity_id=threshold.entity,
|
||||
)
|
||||
return None
|
||||
unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||
unit = state.attributes.get(EntityStateAttribute.UNIT_OF_MEASUREMENT)
|
||||
if not self._is_valid_unit(unit):
|
||||
# Entity unit does not match the expected unit
|
||||
report_not_triggered(
|
||||
@@ -882,7 +882,9 @@ class EntityNumericalStateTriggerBase(EntityTriggerBase):
|
||||
domain_spec = self._domain_specs[state.domain]
|
||||
raw_value: Any
|
||||
if domain_spec.value_source is None:
|
||||
if not self._is_valid_unit(state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)):
|
||||
if not self._is_valid_unit(
|
||||
state.attributes.get(EntityStateAttribute.UNIT_OF_MEASUREMENT)
|
||||
):
|
||||
return None
|
||||
raw_value = state.state
|
||||
else:
|
||||
@@ -907,7 +909,7 @@ class EntityNumericalStateTriggerBase(EntityTriggerBase):
|
||||
domain_spec = self._domain_specs[state.domain]
|
||||
raw_value: Any
|
||||
if domain_spec.value_source is None:
|
||||
unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||
unit = state.attributes.get(EntityStateAttribute.UNIT_OF_MEASUREMENT)
|
||||
if not self._is_valid_unit(unit):
|
||||
report_not_triggered(
|
||||
"entity_unit_not_supported",
|
||||
@@ -984,7 +986,7 @@ class EntityNumericalStateTriggerWithUnitBase(EntityNumericalStateTriggerBase):
|
||||
|
||||
def _get_entity_unit(self, state: State) -> str | None:
|
||||
"""Get the unit of an entity from its state."""
|
||||
return state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||
return state.attributes.get(EntityStateAttribute.UNIT_OF_MEASUREMENT)
|
||||
|
||||
@override
|
||||
def _report_tracked_value_problem(
|
||||
@@ -1050,7 +1052,7 @@ class EntityNumericalStateTriggerWithUnitBase(EntityNumericalStateTriggerBase):
|
||||
)
|
||||
return None
|
||||
|
||||
unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||
unit = state.attributes.get(EntityStateAttribute.UNIT_OF_MEASUREMENT)
|
||||
try:
|
||||
return self._unit_converter.convert(value, unit, self._base_unit)
|
||||
except HomeAssistantError:
|
||||
|
||||
@@ -18,14 +18,12 @@ from homeassistant.components.sensor.helpers import ( # pylint: disable=home-as
|
||||
async_parse_date_datetime,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_PICTURE,
|
||||
ATTR_FRIENDLY_NAME,
|
||||
ATTR_ICON,
|
||||
CONF_DEVICE_CLASS,
|
||||
CONF_ICON,
|
||||
CONF_NAME,
|
||||
CONF_UNIQUE_ID,
|
||||
CONF_UNIT_OF_MEASUREMENT,
|
||||
EntityStateAttribute,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import TemplateError
|
||||
@@ -48,9 +46,9 @@ CONF_ATTRIBUTES = "attributes"
|
||||
CONF_PICTURE = "picture"
|
||||
|
||||
CONF_TO_ATTRIBUTE = {
|
||||
CONF_ICON: ATTR_ICON,
|
||||
CONF_NAME: ATTR_FRIENDLY_NAME,
|
||||
CONF_PICTURE: ATTR_ENTITY_PICTURE,
|
||||
CONF_ICON: EntityStateAttribute.ICON,
|
||||
CONF_NAME: EntityStateAttribute.FRIENDLY_NAME,
|
||||
CONF_PICTURE: EntityStateAttribute.ENTITY_PICTURE,
|
||||
}
|
||||
|
||||
TEMPLATE_ENTITY_BASE_SCHEMA = vol.Schema(
|
||||
|
||||
Reference in New Issue
Block a user