diff --git a/custom_components/askoheat/const.py b/custom_components/askoheat/const.py index 7366919..1238354 100644 --- a/custom_components/askoheat/const.py +++ b/custom_components/askoheat/const.py @@ -442,3 +442,10 @@ class DeviceKey(StrEnum): ENERGY_MANAGER = "energy_manager" WATER_HEATER_CONTROL_UNIT = "water_heater_control_unit" LEGIO_PROTECTION_CONTROL_UNIT = "legio_protection_control_unit" + + +class AttributeKeys(StrEnum): + """Additional attributes keys.""" + + API_DESCRIPTOR = "api_descriptor" + FORMATTED = "formatted" diff --git a/custom_components/askoheat/entity.py b/custom_components/askoheat/entity.py index b99d994..4ebab62 100644 --- a/custom_components/askoheat/entity.py +++ b/custom_components/askoheat/entity.py @@ -10,7 +10,7 @@ from custom_components.askoheat.model import AskoheatEntityDescription -from .const import ATTRIBUTION, DeviceKey +from .const import ATTRIBUTION, AttributeKeys, DeviceKey from .coordinator import AskoheatDataUpdateCoordinator if TYPE_CHECKING: @@ -26,6 +26,8 @@ class AskoheatEntity[E](CoordinatorEntity[AskoheatDataUpdateCoordinator]): _attr_attribution = ATTRIBUTION entity_description: E + _unrecorded_attributes = frozenset({AttributeKeys.API_DESCRIPTOR}) + def __init__( self, entry: AskoheatConfigEntry, @@ -48,6 +50,9 @@ def __init__( DeviceKey.WATER_HEATER_CONTROL_UNIT, ), ) + self._attr_extra_state_attributes = { + AttributeKeys.API_DESCRIPTOR: f"{entity_description.api_descriptor}" # type: ignore # noqa: PGH003 + } self.entity_description = entity_description self.translation_key = ( entity_description.translation_key or entity_description.key.value # type: ignore # noqa: PGH003 diff --git a/custom_components/askoheat/sensor.py b/custom_components/askoheat/sensor.py index 791c480..6d298bf 100644 --- a/custom_components/askoheat/sensor.py +++ b/custom_components/askoheat/sensor.py @@ -2,6 +2,7 @@ from __future__ import annotations +from datetime import timedelta from typing import TYPE_CHECKING, Any import numpy as np @@ -13,6 +14,7 @@ from custom_components.askoheat.api_ema_desc import EMA_REGISTER_BLOCK_DESCRIPTOR from custom_components.askoheat.api_op_desc import DATA_REGISTER_BLOCK_DESCRIPTOR from custom_components.askoheat.api_par_desc import PARAM_REGISTER_BLOCK_DESCRIPTOR +from custom_components.askoheat.const import LOGGER, AttributeKeys from custom_components.askoheat.model import ( AskoheatDurationSensorEntityDescription, AskoheatSensorEntityDescription, @@ -142,6 +144,8 @@ def _convert_value(self, value: Any) -> StateType | date | datetime | Decimal: class AskoheatDurationSensor(AskoheatSensor): """askoheat Sensor class representing a duration.""" + _unrecorded_attributes = frozenset({AttributeKeys.FORMATTED}) + def __init__( self, entry: AskoheatConfigEntry, @@ -150,6 +154,7 @@ def __init__( ) -> None: """Initialize the duration sensor class.""" super().__init__(entry, coordinator, entity_description) + self._attr_extra_state_attributes[AttributeKeys.FORMATTED] = None def _convert_value(self, value: Any) -> StateType | date | datetime | Decimal: time_as_int = int(value) @@ -157,11 +162,18 @@ def _convert_value(self, value: Any) -> StateType | date | datetime | Decimal: hours = int(time_as_int / 2**8) & 0xFF days = int(time_as_int / 2**16) & 0xFFFF + # write formatted value additionally to attributes + self._attr_extra_state_attributes[AttributeKeys.FORMATTED] = timedelta( + days=days, hours=hours, minutes=minutes + ).__str__() + match self.entity_description.native_unit_of_measurement: case UnitOfTime.DAYS: - return (minutes / (60 * 24)) + (hours / 24) + days + converted_value = (minutes / (60 * 24)) + (hours / 24) + days case UnitOfTime.HOURS: - return (minutes / 60) + hours + (days * 24) + converted_value = (minutes / 60) + hours + (days * 24) case _: # by default convert to minutes - return minutes + (hours * 60) + (days * 24 * 60) + converted_value = minutes + (hours * 60) + (days * 24 * 60) + + return converted_value