1 """Sensor platform for Ista EcoTrend integration."""
3 from __future__
import annotations
6 from dataclasses
import dataclass
8 from enum
import StrEnum
16 async_add_external_statistics,
23 SensorEntityDescription,
37 from .
import IstaConfigEntry
38 from .const
import DOMAIN
39 from .coordinator
import IstaCoordinator
40 from .util
import IstaConsumptionType, IstaValueType, get_native_value, get_statistics
42 _LOGGER = logging.getLogger(__name__)
45 @dataclass(kw_only=True, frozen=True)
47 """Ista EcoTrend Sensor Description."""
49 consumption_type: IstaConsumptionType
50 value_type: IstaValueType |
None =
None
54 """Ista EcoTrend Entities."""
57 HEATING_ENERGY =
"heating_energy"
58 HEATING_COST =
"heating_cost"
60 HOT_WATER =
"hot_water"
61 HOT_WATER_ENERGY =
"hot_water_energy"
62 HOT_WATER_COST =
"hot_water_cost"
65 WATER_COST =
"water_cost"
68 SENSOR_DESCRIPTIONS: tuple[IstaSensorEntityDescription, ...] = (
70 key=IstaSensorEntity.HEATING,
71 translation_key=IstaSensorEntity.HEATING,
72 suggested_display_precision=0,
73 consumption_type=IstaConsumptionType.HEATING,
74 native_unit_of_measurement=
"units",
75 state_class=SensorStateClass.TOTAL,
78 key=IstaSensorEntity.HEATING_ENERGY,
79 translation_key=IstaSensorEntity.HEATING_ENERGY,
80 device_class=SensorDeviceClass.ENERGY,
81 native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
82 state_class=SensorStateClass.TOTAL,
83 suggested_display_precision=1,
84 consumption_type=IstaConsumptionType.HEATING,
85 value_type=IstaValueType.ENERGY,
88 key=IstaSensorEntity.HEATING_COST,
89 translation_key=IstaSensorEntity.HEATING_COST,
90 device_class=SensorDeviceClass.MONETARY,
91 native_unit_of_measurement=
"EUR",
92 state_class=SensorStateClass.TOTAL,
93 suggested_display_precision=0,
94 entity_registry_enabled_default=
False,
95 consumption_type=IstaConsumptionType.HEATING,
96 value_type=IstaValueType.COSTS,
99 key=IstaSensorEntity.HOT_WATER,
100 translation_key=IstaSensorEntity.HOT_WATER,
101 device_class=SensorDeviceClass.WATER,
102 native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
103 state_class=SensorStateClass.TOTAL,
104 suggested_display_precision=1,
105 consumption_type=IstaConsumptionType.HOT_WATER,
108 key=IstaSensorEntity.HOT_WATER_ENERGY,
109 translation_key=IstaSensorEntity.HOT_WATER_ENERGY,
110 device_class=SensorDeviceClass.ENERGY,
111 native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
112 state_class=SensorStateClass.TOTAL,
113 suggested_display_precision=1,
114 consumption_type=IstaConsumptionType.HOT_WATER,
115 value_type=IstaValueType.ENERGY,
118 key=IstaSensorEntity.HOT_WATER_COST,
119 translation_key=IstaSensorEntity.HOT_WATER_COST,
120 device_class=SensorDeviceClass.MONETARY,
121 native_unit_of_measurement=
"EUR",
122 state_class=SensorStateClass.TOTAL,
123 suggested_display_precision=0,
124 entity_registry_enabled_default=
False,
125 consumption_type=IstaConsumptionType.HOT_WATER,
126 value_type=IstaValueType.COSTS,
129 key=IstaSensorEntity.WATER,
130 translation_key=IstaSensorEntity.WATER,
131 device_class=SensorDeviceClass.WATER,
132 native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
133 state_class=SensorStateClass.TOTAL,
134 suggested_display_precision=1,
135 entity_registry_enabled_default=
False,
136 consumption_type=IstaConsumptionType.WATER,
139 key=IstaSensorEntity.WATER_COST,
140 translation_key=IstaSensorEntity.WATER_COST,
141 device_class=SensorDeviceClass.MONETARY,
142 native_unit_of_measurement=
"EUR",
143 state_class=SensorStateClass.TOTAL,
144 suggested_display_precision=0,
145 entity_registry_enabled_default=
False,
146 consumption_type=IstaConsumptionType.WATER,
147 value_type=IstaValueType.COSTS,
154 config_entry: IstaConfigEntry,
155 async_add_entities: AddEntitiesCallback,
157 """Set up the ista EcoTrend sensors."""
159 coordinator = config_entry.runtime_data
162 IstaSensor(coordinator, description, consumption_unit)
163 for description
in SENSOR_DESCRIPTIONS
164 for consumption_unit
in coordinator.data
169 """Ista EcoTrend sensor."""
171 entity_description: IstaSensorEntityDescription
172 _attr_has_entity_name =
True
173 device_entry: DeviceEntry
177 coordinator: IstaCoordinator,
178 entity_description: IstaSensorEntityDescription,
179 consumption_unit: str,
181 """Initialize the ista EcoTrend sensor."""
187 entry_type=DeviceEntryType.SERVICE,
188 manufacturer=
"ista SE",
189 model=
"ista EcoTrend",
190 name=f
"{coordinator.details[consumption_unit]["address
"]["street
"]} "
191 f
"{coordinator.details[consumption_unit]["address
"]["houseNumber
"]}".strip(),
192 configuration_url=
"https://ecotrend.ista.de/",
193 identifiers={(DOMAIN, consumption_unit)},
198 """Return the state of the device."""
207 """When added to hass."""
214 """Handle coordinator update."""
218 """Import ista EcoTrend historical statistics."""
223 name = self.coordinator.config_entry.options.get(
224 f
"lts_{self.entity_description.key}_{self.consumption_unit}"
227 name = self.
entity_identity_id.removeprefix(
"sensor.")
228 self.
hasshasshass.config_entries.async_update_entry(
229 entry=self.coordinator.config_entry,
231 **self.coordinator.config_entry.options,
232 f
"lts_{self.entity_description.key}_{self.consumption_unit}": name,
236 statistic_id = f
"{DOMAIN}:{name}"
238 statistics_since =
None
249 _LOGGER.debug(
"Last statistics: %s", last_stats)
252 statistics_sum = last_stats[statistic_id][0].
get(
"sum")
or 0.0
253 statistics_since = datetime.datetime.fromtimestamp(
254 last_stats[statistic_id][0].
get(
"end")
or 0, tz=datetime.UTC
255 ) + datetime.timedelta(days=1)
262 statistics: list[StatisticData] = [
264 "start": consumptions[
"date"],
265 "state": consumptions[
"value"],
266 "sum": (statistics_sum := statistics_sum + consumptions[
"value"]),
268 for consumptions
in monthly_consumptions
269 if statistics_since
is None or consumptions[
"date"] > statistics_since
272 metadata: StatisticMetaData = {
275 "name": f
"{self.device_entry.name} {self.name}",
277 "statistic_id": statistic_id,
278 "unit_of_measurement": self.
entity_descriptionentity_description.native_unit_of_measurement,
281 _LOGGER.debug(
"Insert statistics: %s %s", metadata, statistics)
StateType native_value(self)
None update_statistics(self)
None async_added_to_hass(self)
None __init__(self, IstaCoordinator coordinator, IstaSensorEntityDescription entity_description, str consumption_unit)
None _handle_coordinator_update(self)
web.Response get(self, web.Request request, str config_key)
None async_setup_entry(HomeAssistant hass, IstaConfigEntry config_entry, AddEntitiesCallback async_add_entities)
list[dict[str, Any]]|None get_statistics(data, IstaConsumptionType consumption_type, IstaValueType|None value_type=None)
int|float|None get_native_value(data, IstaConsumptionType consumption_type, IstaValueType|None value_type=None)
None async_add_external_statistics(HomeAssistant hass, StatisticMetaData metadata, Iterable[StatisticData] statistics)
Recorder get_instance(HomeAssistant hass)