mirror of
https://github.com/home-assistant/core.git
synced 2026-06-25 08:05:21 +02:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e7cd537d9c | |||
| 8f0614f152 | |||
| 00e108fb1d | |||
| e82244e8cf | |||
| 59eef5253c | |||
| 430277d101 | |||
| ce243d0929 | |||
| efa15c94b1 | |||
| 1fba029242 | |||
| 36a2213a21 |
@@ -28,12 +28,12 @@ from homeassistant.components.sensor import (
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
ATTR_ATTRIBUTION,
|
||||
CONF_LATITUDE,
|
||||
CONF_LONGITUDE,
|
||||
CONF_NAME,
|
||||
DEGREE,
|
||||
PERCENTAGE,
|
||||
EntityStateAttribute,
|
||||
Platform,
|
||||
UnitOfIrradiance,
|
||||
UnitOfLength,
|
||||
@@ -906,14 +906,14 @@ class BrSensor(SensorEntity):
|
||||
# update all other sensors
|
||||
self._attr_native_value = data.get(sensor_type)
|
||||
if sensor_type.startswith(PRECIPITATION_FORECAST):
|
||||
result = {ATTR_ATTRIBUTION: data.get(ATTRIBUTION)}
|
||||
result = {EntityStateAttribute.ATTRIBUTION: data.get(ATTRIBUTION)}
|
||||
if self._timeframe is not None:
|
||||
result[TIMEFRAME_LABEL] = f"{self._timeframe} min"
|
||||
|
||||
self._attr_extra_state_attributes = result
|
||||
|
||||
result = {
|
||||
ATTR_ATTRIBUTION: data.get(ATTRIBUTION),
|
||||
EntityStateAttribute.ATTRIBUTION: data.get(ATTRIBUTION),
|
||||
STATIONNAME_LABEL: data.get(STATIONNAME),
|
||||
}
|
||||
if self._measured is not None:
|
||||
|
||||
@@ -12,8 +12,6 @@ from homeassistant.components.sensor import (
|
||||
SensorEntity,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
CONF_ATTRIBUTE,
|
||||
CONF_DEVICE_CLASS,
|
||||
CONF_MAXIMUM,
|
||||
@@ -24,6 +22,7 @@ from homeassistant.const import (
|
||||
CONF_UNIT_OF_MEASUREMENT,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
EntityStateAttribute,
|
||||
)
|
||||
from homeassistant.core import (
|
||||
Event,
|
||||
@@ -172,11 +171,11 @@ class CompensationSensor(SensorEntity):
|
||||
|
||||
if self.native_unit_of_measurement is None and self._source_attribute is None:
|
||||
self._attr_native_unit_of_measurement = new_state.attributes.get(
|
||||
ATTR_UNIT_OF_MEASUREMENT
|
||||
EntityStateAttribute.UNIT_OF_MEASUREMENT
|
||||
)
|
||||
|
||||
if self._attr_device_class is None and (
|
||||
device_class := new_state.attributes.get(ATTR_DEVICE_CLASS)
|
||||
device_class := new_state.attributes.get(EntityStateAttribute.DEVICE_CLASS)
|
||||
):
|
||||
self._attr_device_class = device_class
|
||||
|
||||
|
||||
@@ -18,13 +18,12 @@ from homeassistant.components.sensor import (
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
CONF_NAME,
|
||||
CONF_SOURCE,
|
||||
CONF_UNIQUE_ID,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
EntityStateAttribute,
|
||||
Platform,
|
||||
UnitOfTime,
|
||||
)
|
||||
@@ -243,7 +242,9 @@ class DerivativeSensor(RestoreSensor, SensorEntity):
|
||||
if not source_state:
|
||||
return
|
||||
|
||||
source_class_raw = source_state.attributes.get(ATTR_DEVICE_CLASS)
|
||||
source_class_raw = source_state.attributes.get(
|
||||
EntityStateAttribute.DEVICE_CLASS
|
||||
)
|
||||
source_class: SensorDeviceClass | None = None
|
||||
if isinstance(source_class_raw, str):
|
||||
try:
|
||||
@@ -252,7 +253,9 @@ class DerivativeSensor(RestoreSensor, SensorEntity):
|
||||
source_class = None
|
||||
if self._string_unit_prefix is not None and self._string_unit_time is not None:
|
||||
original_unit = self._attr_native_unit_of_measurement
|
||||
source_unit = source_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||
source_unit = source_state.attributes.get(
|
||||
EntityStateAttribute.UNIT_OF_MEASUREMENT
|
||||
)
|
||||
if (
|
||||
(
|
||||
source_class
|
||||
@@ -366,7 +369,9 @@ class DerivativeSensor(RestoreSensor, SensorEntity):
|
||||
|
||||
last_state = await self.async_get_last_state()
|
||||
if last_state:
|
||||
self._attr_device_class = last_state.attributes.get(ATTR_DEVICE_CLASS)
|
||||
self._attr_device_class = last_state.attributes.get(
|
||||
EntityStateAttribute.DEVICE_CLASS
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_added_to_hass(self) -> None:
|
||||
|
||||
@@ -974,6 +974,22 @@ PRECISION_HALVES: Final = 0.5
|
||||
PRECISION_TENTHS: Final = 0.1
|
||||
|
||||
|
||||
class EntityStateAttribute(StrEnum):
|
||||
"""State attribute for the base entity.
|
||||
|
||||
Used to read or write base state attributes of an entity.
|
||||
"""
|
||||
|
||||
ASSUMED_STATE = "assumed_state"
|
||||
ATTRIBUTION = "attribution"
|
||||
DEVICE_CLASS = "device_class"
|
||||
ENTITY_PICTURE = "entity_picture"
|
||||
FRIENDLY_NAME = "friendly_name"
|
||||
ICON = "icon"
|
||||
SUPPORTED_FEATURES = "supported_features"
|
||||
UNIT_OF_MEASUREMENT = "unit_of_measurement"
|
||||
|
||||
|
||||
class EntityCategory(StrEnum):
|
||||
"""Category of an entity.
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -30,21 +30,14 @@ from propcache.api import cached_property
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import (
|
||||
ATTR_ASSUMED_STATE,
|
||||
ATTR_ATTRIBUTION,
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_ENTITY_PICTURE,
|
||||
ATTR_FRIENDLY_NAME,
|
||||
ATTR_GROUP_ENTITIES,
|
||||
ATTR_ICON,
|
||||
ATTR_SUPPORTED_FEATURES,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
DEVICE_DEFAULT_NAME,
|
||||
STATE_OFF,
|
||||
STATE_ON,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
EntityCategory,
|
||||
EntityStateAttribute,
|
||||
)
|
||||
from homeassistant.core import (
|
||||
CALLBACK_TYPE,
|
||||
@@ -167,7 +160,7 @@ def get_device_class(hass: HomeAssistant, entity_id: str) -> str | None:
|
||||
First try the statemachine, then entity registry.
|
||||
"""
|
||||
if state := hass.states.get(entity_id):
|
||||
return state.attributes.get(ATTR_DEVICE_CLASS)
|
||||
return state.attributes.get(EntityStateAttribute.DEVICE_CLASS)
|
||||
|
||||
entity_registry = er.async_get(hass)
|
||||
if not (entry := entity_registry.async_get(entity_id)):
|
||||
@@ -192,7 +185,7 @@ def get_supported_features(hass: HomeAssistant, entity_id: str) -> int:
|
||||
First try the statemachine, then entity registry.
|
||||
"""
|
||||
if state := hass.states.get(entity_id):
|
||||
return state.attributes.get(ATTR_SUPPORTED_FEATURES, 0) # type: ignore[no-any-return]
|
||||
return state.attributes.get(EntityStateAttribute.SUPPORTED_FEATURES, 0) # type: ignore[no-any-return]
|
||||
|
||||
entity_registry = er.async_get(hass)
|
||||
if not (entry := entity_registry.async_get(entity_id)):
|
||||
@@ -207,7 +200,7 @@ def get_unit_of_measurement(hass: HomeAssistant, entity_id: str) -> str | None:
|
||||
First try the statemachine, then entity registry.
|
||||
"""
|
||||
if state := hass.states.get(entity_id):
|
||||
return state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||
return state.attributes.get(EntityStateAttribute.UNIT_OF_MEASUREMENT)
|
||||
|
||||
entity_registry = er.async_get(hass)
|
||||
if not (entry := entity_registry.async_get(entity_id)):
|
||||
@@ -1129,25 +1122,25 @@ class Entity(
|
||||
attr |= extra_state_attributes
|
||||
|
||||
if (unit_of_measurement := self.unit_of_measurement) is not None:
|
||||
attr[ATTR_UNIT_OF_MEASUREMENT] = unit_of_measurement
|
||||
attr[EntityStateAttribute.UNIT_OF_MEASUREMENT.value] = unit_of_measurement
|
||||
|
||||
if assumed_state := self.assumed_state:
|
||||
attr[ATTR_ASSUMED_STATE] = assumed_state
|
||||
attr[EntityStateAttribute.ASSUMED_STATE.value] = assumed_state
|
||||
|
||||
if (attribution := self.attribution) is not None:
|
||||
attr[ATTR_ATTRIBUTION] = attribution
|
||||
attr[EntityStateAttribute.ATTRIBUTION.value] = attribution
|
||||
|
||||
original_device_class = self.device_class
|
||||
if (
|
||||
device_class := (entry and entry.device_class) or original_device_class
|
||||
) is not None:
|
||||
attr[ATTR_DEVICE_CLASS] = str(device_class)
|
||||
attr[EntityStateAttribute.DEVICE_CLASS.value] = str(device_class)
|
||||
|
||||
if (entity_picture := self.entity_picture) is not None:
|
||||
attr[ATTR_ENTITY_PICTURE] = entity_picture
|
||||
attr[EntityStateAttribute.ENTITY_PICTURE.value] = entity_picture
|
||||
|
||||
if (icon := (entry and entry.icon) or self.icon) is not None:
|
||||
attr[ATTR_ICON] = icon
|
||||
attr[EntityStateAttribute.ICON.value] = icon
|
||||
|
||||
original_name = self.name
|
||||
if original_name is UNDEFINED:
|
||||
@@ -1169,10 +1162,10 @@ class Entity(
|
||||
self._cached_friendly_name = (original_name, name)
|
||||
|
||||
if name:
|
||||
attr[ATTR_FRIENDLY_NAME] = name
|
||||
attr[EntityStateAttribute.FRIENDLY_NAME.value] = name
|
||||
|
||||
if (supported_features := self.supported_features) is not None:
|
||||
attr[ATTR_SUPPORTED_FEATURES] = supported_features
|
||||
attr[EntityStateAttribute.SUPPORTED_FEATURES.value] = supported_features
|
||||
|
||||
return (
|
||||
state,
|
||||
|
||||
@@ -20,18 +20,14 @@ import attr
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_FRIENDLY_NAME,
|
||||
ATTR_ICON,
|
||||
ATTR_RESTORED,
|
||||
ATTR_SUPPORTED_FEATURES,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
EVENT_HOMEASSISTANT_START,
|
||||
EVENT_HOMEASSISTANT_STOP,
|
||||
MAX_LENGTH_STATE_DOMAIN,
|
||||
MAX_LENGTH_STATE_ENTITY_ID,
|
||||
STATE_UNAVAILABLE,
|
||||
EntityCategory,
|
||||
EntityStateAttribute,
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.core import (
|
||||
@@ -436,21 +432,25 @@ class RegistryEntry:
|
||||
|
||||
device_class = self.device_class or self.original_device_class
|
||||
if device_class is not None:
|
||||
attrs[ATTR_DEVICE_CLASS] = device_class
|
||||
attrs[EntityStateAttribute.DEVICE_CLASS.value] = device_class
|
||||
|
||||
icon = self.icon or self.original_icon
|
||||
if icon is not None:
|
||||
attrs[ATTR_ICON] = icon
|
||||
attrs[EntityStateAttribute.ICON.value] = icon
|
||||
|
||||
name = self.name or self.original_name
|
||||
if name is not None:
|
||||
attrs[ATTR_FRIENDLY_NAME] = name
|
||||
attrs[EntityStateAttribute.FRIENDLY_NAME.value] = name
|
||||
|
||||
if self.supported_features is not None:
|
||||
attrs[ATTR_SUPPORTED_FEATURES] = self.supported_features
|
||||
attrs[EntityStateAttribute.SUPPORTED_FEATURES.value] = (
|
||||
self.supported_features
|
||||
)
|
||||
|
||||
if self.unit_of_measurement is not None:
|
||||
attrs[ATTR_UNIT_OF_MEASUREMENT] = self.unit_of_measurement
|
||||
attrs[EntityStateAttribute.UNIT_OF_MEASUREMENT.value] = (
|
||||
self.unit_of_measurement
|
||||
)
|
||||
|
||||
hass.states.async_set(self.entity_id, STATE_UNAVAILABLE, attrs)
|
||||
|
||||
|
||||
@@ -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,
|
||||
@@ -813,7 +813,9 @@ class EntityNumericalStateTriggerBase(EntityTriggerBase):
|
||||
if not (state := self._hass.states.get(threshold.entity)): # type: ignore[arg-type]
|
||||
# Entity not found
|
||||
return 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)
|
||||
):
|
||||
# Entity unit does not match the expected unit
|
||||
return None
|
||||
try:
|
||||
@@ -828,7 +830,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:
|
||||
@@ -883,7 +887,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 _get_threshold_value(self, threshold: ThresholdConfig | None) -> float | None:
|
||||
@@ -908,7 +912,9 @@ class EntityNumericalStateTriggerWithUnitBase(EntityNumericalStateTriggerBase):
|
||||
|
||||
try:
|
||||
return self._unit_converter.convert(
|
||||
value, state.attributes.get(ATTR_UNIT_OF_MEASUREMENT), self._base_unit
|
||||
value,
|
||||
state.attributes.get(EntityStateAttribute.UNIT_OF_MEASUREMENT),
|
||||
self._base_unit,
|
||||
)
|
||||
except HomeAssistantError:
|
||||
# Unit conversion failed (i.e. incompatible units), treat as invalid number
|
||||
|
||||
@@ -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, State, 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