Split esphome state property decorators (#124332)
This commit is contained in:
parent
ebc49d938a
commit
41b129e990
6 changed files with 49 additions and 36 deletions
|
@ -58,6 +58,7 @@ from homeassistant.core import callback
|
|||
from .entity import (
|
||||
EsphomeEntity,
|
||||
convert_api_error_ha_error,
|
||||
esphome_float_state_property,
|
||||
esphome_state_property,
|
||||
platform_async_setup_entry,
|
||||
)
|
||||
|
@ -227,7 +228,7 @@ class EsphomeClimateEntity(EsphomeEntity[ClimateInfo, ClimateState], ClimateEnti
|
|||
return _SWING_MODES.from_esphome(self._state.swing_mode)
|
||||
|
||||
@property
|
||||
@esphome_state_property
|
||||
@esphome_float_state_property
|
||||
def current_temperature(self) -> float | None:
|
||||
"""Return the current temperature."""
|
||||
return self._state.current_temperature
|
||||
|
@ -241,19 +242,19 @@ class EsphomeClimateEntity(EsphomeEntity[ClimateInfo, ClimateState], ClimateEnti
|
|||
return round(self._state.current_humidity)
|
||||
|
||||
@property
|
||||
@esphome_state_property
|
||||
@esphome_float_state_property
|
||||
def target_temperature(self) -> float | None:
|
||||
"""Return the temperature we try to reach."""
|
||||
return self._state.target_temperature
|
||||
|
||||
@property
|
||||
@esphome_state_property
|
||||
@esphome_float_state_property
|
||||
def target_temperature_low(self) -> float | None:
|
||||
"""Return the lowbound target temperature we try to reach."""
|
||||
return self._state.target_temperature_low
|
||||
|
||||
@property
|
||||
@esphome_state_property
|
||||
@esphome_float_state_property
|
||||
def target_temperature_high(self) -> float | None:
|
||||
"""Return the highbound target temperature we try to reach."""
|
||||
return self._state.target_temperature_high
|
||||
|
|
|
@ -118,20 +118,35 @@ def esphome_state_property[_R, _EntityT: EsphomeEntity[Any, Any]](
|
|||
) -> Callable[[_EntityT], _R | None]:
|
||||
"""Wrap a state property of an esphome entity.
|
||||
|
||||
This checks if the state object in the entity is set, and
|
||||
prevents writing NAN values to the Home Assistant state machine.
|
||||
This checks if the state object in the entity is set
|
||||
and returns None if it is not set.
|
||||
"""
|
||||
|
||||
@functools.wraps(func)
|
||||
def _wrapper(self: _EntityT) -> _R | None:
|
||||
return func(self) if self._has_state else None
|
||||
|
||||
return _wrapper
|
||||
|
||||
|
||||
def esphome_float_state_property[_EntityT: EsphomeEntity[Any, Any]](
|
||||
func: Callable[[_EntityT], float | None],
|
||||
) -> Callable[[_EntityT], float | None]:
|
||||
"""Wrap a state property of an esphome entity that returns a float.
|
||||
|
||||
This checks if the state object in the entity is set, and returns
|
||||
None if its not set. If also prevents writing NAN values to the
|
||||
Home Assistant state machine.
|
||||
"""
|
||||
|
||||
@functools.wraps(func)
|
||||
def _wrapper(self: _EntityT) -> float | None:
|
||||
if not self._has_state:
|
||||
return None
|
||||
val = func(self)
|
||||
if isinstance(val, float) and not math.isfinite(val):
|
||||
# Home Assistant doesn't use NaN or inf values in state machine
|
||||
# (not JSON serializable)
|
||||
return None
|
||||
return val
|
||||
# Home Assistant doesn't use NaN or inf values in state machine
|
||||
# (not JSON serializable)
|
||||
return None if val is None or not math.isfinite(val) else val
|
||||
|
||||
return _wrapper
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ from homeassistant.core import callback
|
|||
from .entity import (
|
||||
EsphomeEntity,
|
||||
convert_api_error_ha_error,
|
||||
esphome_float_state_property,
|
||||
esphome_state_property,
|
||||
platform_async_setup_entry,
|
||||
)
|
||||
|
@ -79,7 +80,7 @@ class EsphomeMediaPlayer(
|
|||
return self._state.muted
|
||||
|
||||
@property
|
||||
@esphome_state_property
|
||||
@esphome_float_state_property
|
||||
def volume_level(self) -> float | None:
|
||||
"""Volume level of the media player (0..1)."""
|
||||
return self._state.volume
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from functools import partial
|
||||
import math
|
||||
|
||||
from aioesphomeapi import (
|
||||
EntityInfo,
|
||||
|
@ -19,7 +18,7 @@ from homeassistant.util.enum import try_parse_enum
|
|||
from .entity import (
|
||||
EsphomeEntity,
|
||||
convert_api_error_ha_error,
|
||||
esphome_state_property,
|
||||
esphome_float_state_property,
|
||||
platform_async_setup_entry,
|
||||
)
|
||||
from .enum_mapper import EsphomeEnumMapper
|
||||
|
@ -57,13 +56,11 @@ class EsphomeNumber(EsphomeEntity[NumberInfo, NumberState], NumberEntity):
|
|||
self._attr_mode = NumberMode.AUTO
|
||||
|
||||
@property
|
||||
@esphome_state_property
|
||||
@esphome_float_state_property
|
||||
def native_value(self) -> float | None:
|
||||
"""Return the state of the entity."""
|
||||
state = self._state
|
||||
if state.missing_state or not math.isfinite(state.state):
|
||||
return None
|
||||
return state.state
|
||||
return None if state.missing_state else state.state
|
||||
|
||||
@convert_api_error_ha_error
|
||||
async def async_set_native_value(self, value: float) -> None:
|
||||
|
|
|
@ -26,7 +26,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|||
from homeassistant.util import dt as dt_util
|
||||
from homeassistant.util.enum import try_parse_enum
|
||||
|
||||
from .entity import EsphomeEntity, esphome_state_property, platform_async_setup_entry
|
||||
from .entity import EsphomeEntity, platform_async_setup_entry
|
||||
from .enum_mapper import EsphomeEnumMapper
|
||||
|
||||
|
||||
|
@ -93,15 +93,16 @@ class EsphomeSensor(EsphomeEntity[SensorInfo, SensorState], SensorEntity):
|
|||
self._attr_state_class = _STATE_CLASSES.from_esphome(state_class)
|
||||
|
||||
@property
|
||||
@esphome_state_property
|
||||
def native_value(self) -> datetime | str | None:
|
||||
"""Return the state of the entity."""
|
||||
state = self._state
|
||||
if state.missing_state or not math.isfinite(state.state):
|
||||
if not self._has_state or (state := self._state).missing_state:
|
||||
return None
|
||||
if self._attr_device_class is SensorDeviceClass.TIMESTAMP:
|
||||
return dt_util.utc_from_timestamp(state.state)
|
||||
return f"{state.state:.{self._static_info.accuracy_decimals}f}"
|
||||
state_float = state.state
|
||||
if not math.isfinite(state_float):
|
||||
return None
|
||||
if self.device_class is SensorDeviceClass.TIMESTAMP:
|
||||
return dt_util.utc_from_timestamp(state_float)
|
||||
return f"{state_float:.{self._static_info.accuracy_decimals}f}"
|
||||
|
||||
|
||||
class EsphomeTextSensor(EsphomeEntity[TextSensorInfo, TextSensorState], SensorEntity):
|
||||
|
@ -117,17 +118,17 @@ class EsphomeTextSensor(EsphomeEntity[TextSensorInfo, TextSensorState], SensorEn
|
|||
)
|
||||
|
||||
@property
|
||||
@esphome_state_property
|
||||
def native_value(self) -> str | datetime | date | None:
|
||||
"""Return the state of the entity."""
|
||||
state = self._state
|
||||
if state.missing_state:
|
||||
if not self._has_state or (state := self._state).missing_state:
|
||||
return None
|
||||
if self._attr_device_class is SensorDeviceClass.TIMESTAMP:
|
||||
return dt_util.parse_datetime(state.state)
|
||||
state_str = state.state
|
||||
device_class = self.device_class
|
||||
if device_class is SensorDeviceClass.TIMESTAMP:
|
||||
return dt_util.parse_datetime(state_str)
|
||||
if (
|
||||
self._attr_device_class is SensorDeviceClass.DATE
|
||||
and (value := dt_util.parse_datetime(state.state)) is not None
|
||||
device_class is SensorDeviceClass.DATE
|
||||
and (value := dt_util.parse_datetime(state_str)) is not None
|
||||
):
|
||||
return value.date()
|
||||
return state.state
|
||||
return state_str
|
||||
|
|
|
@ -43,9 +43,7 @@ class EsphomeText(EsphomeEntity[TextInfo, TextState], TextEntity):
|
|||
def native_value(self) -> str | None:
|
||||
"""Return the state of the entity."""
|
||||
state = self._state
|
||||
if state.missing_state:
|
||||
return None
|
||||
return state.state
|
||||
return None if state.missing_state else state.state
|
||||
|
||||
@convert_api_error_ha_error
|
||||
async def async_set_value(self, value: str) -> None:
|
||||
|
|
Loading…
Add table
Reference in a new issue