Home Assistant Unofficial Reference 2024.12.1
util.py
Go to the documentation of this file.
1 """Utility functions for Ista EcoTrend integration."""
2 
3 from __future__ import annotations
4 
5 import datetime
6 from enum import StrEnum
7 from typing import Any
8 
9 from homeassistant.util import dt as dt_util
10 
11 
12 class IstaConsumptionType(StrEnum):
13  """Types of consumptions from ista."""
14 
15  HEATING = "heating"
16  HOT_WATER = "warmwater"
17  WATER = "water"
18 
19 
20 class IstaValueType(StrEnum):
21  """Values type Costs or energy."""
22 
23  COSTS = "costs"
24  ENERGY = "energy"
25 
26 
28  data: dict[str, Any], value_type: IstaValueType | None = None
29 ) -> list[dict[str, Any]]:
30  """Get consumption readings and sort in ascending order by date."""
31  result: list = []
32  if consumptions := data.get(
33  "costs" if value_type == IstaValueType.COSTS else "consumptions", []
34  ):
35  result = [
36  {
37  "readings": readings.get("costsByEnergyType")
38  if value_type == IstaValueType.COSTS
39  else readings.get("readings"),
40  "date": last_day_of_month(**readings["date"]),
41  }
42  for readings in consumptions
43  ]
44  result.sort(key=lambda d: d["date"])
45  return result
46 
47 
49  consumptions: dict[str, Any], consumption_type: IstaConsumptionType
50 ) -> dict[str, Any]:
51  """Get the readings of a certain type."""
52 
53  readings: list = consumptions.get("readings", []) or consumptions.get(
54  "costsByEnergyType", []
55  )
56 
57  return next(
58  (values for values in readings if values.get("type") == consumption_type.value),
59  {},
60  )
61 
62 
63 def as_number(value: str | float | None) -> float | int | None:
64  """Convert readings to float or int.
65 
66  Readings in the json response are returned as strings,
67  float values have comma as decimal separator
68  """
69  if isinstance(value, str):
70  return int(value) if value.isdigit() else float(value.replace(",", "."))
71 
72  return value
73 
74 
75 def last_day_of_month(month: int, year: int) -> datetime.datetime:
76  """Get the last day of the month."""
77 
78  return dt_util.as_local(
79  datetime.datetime(
80  month=month + 1 if month < 12 else 1,
81  year=year if month < 12 else year + 1,
82  day=1,
83  tzinfo=datetime.UTC,
84  )
85  + datetime.timedelta(days=-1)
86  )
87 
88 
90  data,
91  consumption_type: IstaConsumptionType,
92  value_type: IstaValueType | None = None,
93 ) -> int | float | None:
94  """Determine the latest value for the sensor."""
95 
96  if last_value := get_statistics(data, consumption_type, value_type):
97  return last_value[-1].get("value")
98  return None
99 
100 
102  data,
103  consumption_type: IstaConsumptionType,
104  value_type: IstaValueType | None = None,
105 ) -> list[dict[str, Any]] | None:
106  """Determine the latest value for the sensor."""
107 
108  if monthly_consumptions := get_consumptions(data, value_type):
109  return [
110  {
111  "value": as_number(
113  consumptions=consumptions,
114  consumption_type=consumption_type,
115  ).get(
116  "additionalValue"
117  if value_type == IstaValueType.ENERGY
118  else "value"
119  )
120  ),
121  "date": consumptions["date"],
122  }
123  for consumptions in monthly_consumptions
125  consumptions=consumptions,
126  consumption_type=consumption_type,
127  ).get("additionalValue" if value_type == IstaValueType.ENERGY else "value")
128  ]
129  return None
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
list[dict[str, Any]]|None get_statistics(data, IstaConsumptionType consumption_type, IstaValueType|None value_type=None)
Definition: util.py:105
float|int|None as_number(str|float|None value)
Definition: util.py:63
dict[str, Any] get_values_by_type(dict[str, Any] consumptions, IstaConsumptionType consumption_type)
Definition: util.py:50
list[dict[str, Any]] get_consumptions(dict[str, Any] data, IstaValueType|None value_type=None)
Definition: util.py:29
int|float|None get_native_value(data, IstaConsumptionType consumption_type, IstaValueType|None value_type=None)
Definition: util.py:93
datetime.datetime last_day_of_month(int month, int year)
Definition: util.py:75