Add last reset to Shelly's energy entities (#53710)

This commit is contained in:
Simone Chemelli 2021-07-29 21:10:53 +02:00 committed by GitHub
parent fb3b8b6686
commit e9a00ad4ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 23 additions and 7 deletions

View File

@ -92,3 +92,6 @@ KELVIN_MIN_VALUE_WHITE: Final = 2700
KELVIN_MIN_VALUE_COLOR: Final = 3000 KELVIN_MIN_VALUE_COLOR: Final = 3000
UPTIME_DEVIATION: Final = 5 UPTIME_DEVIATION: Final = 5
LAST_RESET_UPTIME: Final = "uptime"
LAST_RESET_NEVER: Final = "never"

View File

@ -3,7 +3,6 @@ from __future__ import annotations
import asyncio import asyncio
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime
import logging import logging
from typing import Any, Callable, Final, cast from typing import Any, Callable, Final, cast
@ -180,7 +179,7 @@ class BlockAttributeDescription:
# Callable (settings, block), return true if entity should be removed # Callable (settings, block), return true if entity should be removed
removal_condition: Callable[[dict, aioshelly.Block], bool] | None = None removal_condition: Callable[[dict, aioshelly.Block], bool] | None = None
extra_state_attributes: Callable[[aioshelly.Block], dict | None] | None = None extra_state_attributes: Callable[[aioshelly.Block], dict | None] | None = None
last_reset: datetime | None = None last_reset: str | None = None
@dataclass @dataclass
@ -286,6 +285,7 @@ class ShellyBlockAttributeEntity(ShellyBlockEntity, entity.Entity):
self._unit: None | str | Callable[[dict], str] = unit self._unit: None | str | Callable[[dict], str] = unit
self._unique_id: str = f"{super().unique_id}-{self.attribute}" self._unique_id: str = f"{super().unique_id}-{self.attribute}"
self._name = get_entity_name(wrapper.device, block, self.description.name) self._name = get_entity_name(wrapper.device, block, self.description.name)
self._last_value: str | None = None
@property @property
def unique_id(self) -> str: def unique_id(self) -> str:

View File

@ -23,7 +23,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType from homeassistant.helpers.typing import StateType
from homeassistant.util import dt from homeassistant.util import dt
from .const import SHAIR_MAX_WORK_HOURS from .const import LAST_RESET_NEVER, LAST_RESET_UPTIME, SHAIR_MAX_WORK_HOURS
from .entity import ( from .entity import (
BlockAttributeDescription, BlockAttributeDescription,
RestAttributeDescription, RestAttributeDescription,
@ -114,6 +114,7 @@ SENSORS: Final = {
value=lambda value: round(value / 60 / 1000, 2), value=lambda value: round(value / 60 / 1000, 2),
device_class=sensor.DEVICE_CLASS_ENERGY, device_class=sensor.DEVICE_CLASS_ENERGY,
state_class=sensor.STATE_CLASS_MEASUREMENT, state_class=sensor.STATE_CLASS_MEASUREMENT,
last_reset=LAST_RESET_UPTIME,
), ),
("emeter", "energy"): BlockAttributeDescription( ("emeter", "energy"): BlockAttributeDescription(
name="Energy", name="Energy",
@ -121,7 +122,7 @@ SENSORS: Final = {
value=lambda value: round(value / 1000, 2), value=lambda value: round(value / 1000, 2),
device_class=sensor.DEVICE_CLASS_ENERGY, device_class=sensor.DEVICE_CLASS_ENERGY,
state_class=sensor.STATE_CLASS_MEASUREMENT, state_class=sensor.STATE_CLASS_MEASUREMENT,
last_reset=dt.utc_from_timestamp(0), last_reset=LAST_RESET_NEVER,
), ),
("emeter", "energyReturned"): BlockAttributeDescription( ("emeter", "energyReturned"): BlockAttributeDescription(
name="Energy Returned", name="Energy Returned",
@ -129,7 +130,7 @@ SENSORS: Final = {
value=lambda value: round(value / 1000, 2), value=lambda value: round(value / 1000, 2),
device_class=sensor.DEVICE_CLASS_ENERGY, device_class=sensor.DEVICE_CLASS_ENERGY,
state_class=sensor.STATE_CLASS_MEASUREMENT, state_class=sensor.STATE_CLASS_MEASUREMENT,
last_reset=dt.utc_from_timestamp(0), last_reset=LAST_RESET_NEVER,
), ),
("light", "energy"): BlockAttributeDescription( ("light", "energy"): BlockAttributeDescription(
name="Energy", name="Energy",
@ -138,6 +139,7 @@ SENSORS: Final = {
device_class=sensor.DEVICE_CLASS_ENERGY, device_class=sensor.DEVICE_CLASS_ENERGY,
state_class=sensor.STATE_CLASS_MEASUREMENT, state_class=sensor.STATE_CLASS_MEASUREMENT,
default_enabled=False, default_enabled=False,
last_reset=LAST_RESET_UPTIME,
), ),
("relay", "energy"): BlockAttributeDescription( ("relay", "energy"): BlockAttributeDescription(
name="Energy", name="Energy",
@ -145,6 +147,7 @@ SENSORS: Final = {
value=lambda value: round(value / 60 / 1000, 2), value=lambda value: round(value / 60 / 1000, 2),
device_class=sensor.DEVICE_CLASS_ENERGY, device_class=sensor.DEVICE_CLASS_ENERGY,
state_class=sensor.STATE_CLASS_MEASUREMENT, state_class=sensor.STATE_CLASS_MEASUREMENT,
last_reset=LAST_RESET_UPTIME,
), ),
("roller", "rollerEnergy"): BlockAttributeDescription( ("roller", "rollerEnergy"): BlockAttributeDescription(
name="Energy", name="Energy",
@ -152,6 +155,7 @@ SENSORS: Final = {
value=lambda value: round(value / 60 / 1000, 2), value=lambda value: round(value / 60 / 1000, 2),
device_class=sensor.DEVICE_CLASS_ENERGY, device_class=sensor.DEVICE_CLASS_ENERGY,
state_class=sensor.STATE_CLASS_MEASUREMENT, state_class=sensor.STATE_CLASS_MEASUREMENT,
last_reset=LAST_RESET_UPTIME,
), ),
("sensor", "concentration"): BlockAttributeDescription( ("sensor", "concentration"): BlockAttributeDescription(
name="Gas Concentration", name="Gas Concentration",
@ -264,7 +268,16 @@ class ShellySensor(ShellyBlockAttributeEntity, SensorEntity):
@property @property
def last_reset(self) -> datetime | None: def last_reset(self) -> datetime | None:
"""State class of sensor.""" """State class of sensor."""
return self.description.last_reset if self.description.last_reset == LAST_RESET_UPTIME:
self._last_value = get_device_uptime(
self.wrapper.device.status, self._last_value
)
return dt.parse_datetime(self._last_value)
if self.description.last_reset == LAST_RESET_NEVER:
return dt.utc_from_timestamp(0)
return None
@property @property
def unit_of_measurement(self) -> str | None: def unit_of_measurement(self) -> str | None:

View File

@ -136,7 +136,7 @@ def is_momentary_input(settings: dict[str, Any], block: aioshelly.Block) -> bool
return button_type in ["momentary", "momentary_on_release"] return button_type in ["momentary", "momentary_on_release"]
def get_device_uptime(status: dict[str, Any], last_uptime: str) -> str: def get_device_uptime(status: dict[str, Any], last_uptime: str | None) -> str:
"""Return device uptime string, tolerate up to 5 seconds deviation.""" """Return device uptime string, tolerate up to 5 seconds deviation."""
delta_uptime = utcnow() - timedelta(seconds=status["uptime"]) delta_uptime = utcnow() - timedelta(seconds=status["uptime"])