diff --git a/homeassistant/components/esphome/sensor.py b/homeassistant/components/esphome/sensor.py index 3e8fbc19a4d..c0ea9f0f9c5 100644 --- a/homeassistant/components/esphome/sensor.py +++ b/homeassistant/components/esphome/sensor.py @@ -1,8 +1,6 @@ """Support for esphome sensors.""" from __future__ import annotations -from contextlib import suppress -from datetime import datetime import math from typing import cast @@ -20,13 +18,13 @@ from homeassistant.components.sensor import ( DEVICE_CLASS_TIMESTAMP, DEVICE_CLASSES, STATE_CLASS_MEASUREMENT, + STATE_CLASS_TOTAL_INCREASING, SensorEntity, ) from homeassistant.config_entries import ConfigEntry -from homeassistant.core import HomeAssistant, callback +from homeassistant.core import HomeAssistant import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.restore_state import RestoreEntity from homeassistant.util import dt from . import ( @@ -71,83 +69,14 @@ _STATE_CLASSES: EsphomeEnumMapper[SensorStateClass, str | None] = EsphomeEnumMap { SensorStateClass.NONE: None, SensorStateClass.MEASUREMENT: STATE_CLASS_MEASUREMENT, + SensorStateClass.TOTAL_INCREASING: STATE_CLASS_TOTAL_INCREASING, } ) -class EsphomeSensor( - EsphomeEntity[SensorInfo, SensorState], SensorEntity, RestoreEntity -): +class EsphomeSensor(EsphomeEntity[SensorInfo, SensorState], SensorEntity): """A sensor implementation for esphome.""" - _old_state: float | None = None - - async def async_added_to_hass(self) -> None: - """Register callbacks.""" - await super().async_added_to_hass() - - if self._static_info.last_reset_type != LastResetType.AUTO: - return - - # Logic to restore old state for last_reset_type AUTO: - last_state = await self.async_get_last_state() - if last_state is None: - return - - if "last_reset" in last_state.attributes: - self._attr_last_reset = dt.as_utc( - datetime.fromisoformat(last_state.attributes["last_reset"]) - ) - - with suppress(ValueError): - self._old_state = float(last_state.state) - - @callback - def _on_state_update(self) -> None: - """Check last_reset when new state arrives.""" - if self._static_info.last_reset_type == LastResetType.NEVER: - self._attr_last_reset = dt.utc_from_timestamp(0) - - if self._static_info.last_reset_type != LastResetType.AUTO: - super()._on_state_update() - return - - # Last reset type AUTO logic for the last_reset property - # In this mode we automatically determine if an accumulator reset - # has taken place. - # We compare the last valid value (_old_state) with the new one. - # If the value has reset to 0 or has significantly reduced we say - # it has reset. - new_state: float | None = None - state = cast("str | None", self.state) - if state is not None: - with suppress(ValueError): - new_state = float(state) - - did_reset = False - if new_state is None: - # New state is not a float - we'll detect the reset once we get valid data again - did_reset = False - elif self._old_state is None: - # First measurement we ever got for this sensor, always a reset - did_reset = True - elif new_state == 0: - # don't set reset if both old and new are 0 - # we would already have detected the reset on the last state - did_reset = self._old_state != 0 - elif new_state < self._old_state: - did_reset = True - - # Set last_reset to now if we detected a reset - if did_reset: - self._attr_last_reset = dt.utcnow() - - if new_state is not None: - # Only write to old_state if the new one contains actual data - self._old_state = new_state - - super()._on_state_update() - @property def icon(self) -> str | None: """Return the icon.""" @@ -190,6 +119,14 @@ class EsphomeSensor( """Return the state class of this entity.""" if not self._static_info.state_class: return None + state_class = self._static_info.state_class + reset_type = self._static_info.last_reset_type + if ( + state_class == SensorStateClass.MEASUREMENT + and reset_type == LastResetType.AUTO + ): + # Legacy, last_reset_type auto was the equivalent to the TOTAL_INCREASING state class + return STATE_CLASS_TOTAL_INCREASING return _STATE_CLASSES.from_esphome(self._static_info.state_class)