Skip to content

Commit a8e0848

Browse files
authored
Refactor classes to remove unnecessary EvoOne properties and methods (#141)
1 parent f5787b4 commit a8e0848

File tree

8 files changed

+490
-462
lines changed

8 files changed

+490
-462
lines changed

ariston/__init__.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from .galevo_device import AristonGalevoDevice
2020
from .lydos_hybrid_device import AristonLydosHybridDevice
2121
from .nuos_split_device import AristonNuosSplitDevice
22-
from .device import AristonDevice
22+
from .base_device import AristonBaseDevice
2323

2424
_LOGGER = logging.getLogger(__name__)
2525

@@ -59,7 +59,7 @@ async def async_discover(self) -> Optional[list[dict[str, Any]]]:
5959

6060
async def async_hello(
6161
self, gateway: str, is_metric: bool = True, language_tag: str = "en-US"
62-
) -> Optional[AristonDevice]:
62+
) -> Optional[AristonBaseDevice]:
6363
"""Get ariston device"""
6464
if self.api is None:
6565
_LOGGER.exception("Call async_connect() first")
@@ -79,7 +79,7 @@ def _get_device(
7979
gateway: str,
8080
is_metric: bool = True,
8181
language_tag: str = "en-US",
82-
) -> Optional[AristonDevice]:
82+
) -> Optional[AristonBaseDevice]:
8383
"""Get ariston device"""
8484
device = next(
8585
(dev for dev in cloud_devices if dev.get(DeviceAttribute.GW) == gateway),
@@ -142,7 +142,7 @@ def hello(
142142
gateway: str,
143143
is_metric: bool = True,
144144
language_tag: str = "en-US",
145-
) -> Optional[AristonDevice]:
145+
) -> Optional[AristonBaseDevice]:
146146
"""Get ariston device"""
147147
api = _connect(username, password)
148148
cloud_devices = _discover(api)
@@ -184,7 +184,7 @@ async def async_hello(
184184
gateway: str,
185185
is_metric: bool = True,
186186
language_tag: str = "en-US",
187-
) -> Optional[AristonDevice]:
187+
) -> Optional[AristonBaseDevice]:
188188
"""Get ariston device"""
189189
api = await _async_connect(username, password)
190190
cloud_devices = await _async_discover(api)

ariston/base_device.py

Lines changed: 341 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,341 @@
1+
"""Device class for Ariston module."""
2+
from __future__ import annotations
3+
4+
import datetime as dt
5+
import logging
6+
from abc import ABC, abstractmethod
7+
from typing import Any, Optional
8+
9+
from .ariston_api import AristonAPI
10+
from .const import (
11+
ConsumptionTimeInterval,
12+
ConsumptionType,
13+
CustomDeviceFeatures,
14+
DeviceFeatures,
15+
DeviceAttribute,
16+
GalevoDeviceAttribute,
17+
SystemType,
18+
VelisDeviceAttribute,
19+
WheType,
20+
)
21+
22+
_LOGGER = logging.getLogger(__name__)
23+
24+
25+
class AristonBaseDevice(ABC):
26+
"""Class representing a physical device, it's state and properties."""
27+
28+
def __init__(
29+
self,
30+
api: AristonAPI,
31+
attributes: dict[str, Any],
32+
) -> None:
33+
self.api = api
34+
self.attributes = attributes
35+
36+
self.features: dict[str, Any] = dict()
37+
self.custom_features: dict[str, Any] = dict()
38+
self.consumptions_sequences: list[dict[str, Any]] = list()
39+
self.data: dict[str, Any] = dict()
40+
self.consumption_sequence_last_changed_utc: dt.datetime = (
41+
dt.datetime.utcfromtimestamp(0).replace(tzinfo=dt.timezone.utc)
42+
)
43+
self.gw: str = self.attributes.get(DeviceAttribute.GW, "")
44+
self.bus_errors_list: list[dict[str, Any]] = []
45+
46+
@property
47+
@abstractmethod
48+
def consumption_type(self) -> str:
49+
"""String to get consumption type"""
50+
51+
def _get_consumptions_sequences(self) -> None:
52+
"""Get consumption sequence"""
53+
self.consumptions_sequences = self.api.get_consumptions_sequences(
54+
self.gw,
55+
self.consumption_type,
56+
)
57+
58+
async def _async_get_consumptions_sequences(self) -> None:
59+
"""Async get consumption sequence"""
60+
self.consumptions_sequences = await self.api.async_get_consumptions_sequences(
61+
self.gw,
62+
self.consumption_type,
63+
)
64+
65+
@property
66+
def system_type(self) -> SystemType:
67+
"""Get device system type wrapper"""
68+
return SystemType(self.attributes.get(DeviceAttribute.SYS, SystemType.UNKNOWN))
69+
70+
@property
71+
def whe_type(self) -> WheType:
72+
"""Get device whe type wrapper"""
73+
return WheType(
74+
self.attributes.get(VelisDeviceAttribute.WHE_TYPE, WheType.Unknown)
75+
)
76+
77+
@property
78+
def whe_model_type(self) -> int:
79+
"""Get device whe model type wrapper"""
80+
return self.attributes.get(VelisDeviceAttribute.WHE_MODEL_TYPE, 0)
81+
82+
@property
83+
def gateway(self) -> str:
84+
"""Get device gateway wrapper"""
85+
return self.gw
86+
87+
@property
88+
def has_metering(self) -> Optional[bool]:
89+
"""Get device has metering wrapper"""
90+
return self.features.get(DeviceFeatures.HAS_METERING, None)
91+
92+
@property
93+
def name(self) -> Optional[str]:
94+
"""Get device name wrapper"""
95+
return self.attributes.get(DeviceAttribute.NAME, None)
96+
97+
@property
98+
def has_dhw(self)-> Optional[bool]:
99+
"""Get device has domestic hot water"""
100+
return self.custom_features.get(CustomDeviceFeatures.HAS_DHW, None)
101+
102+
@property
103+
def dhw_mode_changeable(self) -> Optional[bool]:
104+
"""Get device domestic hot water mode changeable wrapper"""
105+
return self.features.get(DeviceFeatures.DHW_MODE_CHANGEABLE, None)
106+
107+
@property
108+
def serial_number(self) -> Optional[str]:
109+
"""Get device serial number wrapper"""
110+
return self.attributes.get(DeviceAttribute.SN, None)
111+
112+
@property
113+
def firmware_version(self) -> Optional[str]:
114+
"""Get device firmware version wrapper"""
115+
return self.attributes.get(GalevoDeviceAttribute.FW_VER, None)
116+
117+
@property
118+
def bus_errors(self) -> list[dict[str, Any]]:
119+
"""Get bus errors list wrapper"""
120+
return self.bus_errors_list
121+
122+
@property
123+
def hpmp_sys(self) -> Optional[bool]:
124+
"""Get device heat pump multi power system"""
125+
return self.attributes.get(DeviceAttribute.HPMP_SYS, None)
126+
127+
def get_features(self) -> None:
128+
"""Get device features wrapper"""
129+
self.features = self.api.get_features_for_device(self.gw)
130+
131+
async def async_get_features(self) -> None:
132+
"""Async get device features wrapper"""
133+
features = await self.api.async_get_features_for_device(self.gw)
134+
if features is not None:
135+
self.features = features
136+
137+
@property
138+
def water_heater_current_mode_text(self) -> str:
139+
"""Get water heater current mode text"""
140+
mode = self.water_heater_mode_value
141+
if mode in self.water_heater_mode_options:
142+
index = self.water_heater_mode_options.index(mode)
143+
return self.water_heater_mode_operation_texts[index]
144+
return "UNKNOWN"
145+
146+
@abstractmethod
147+
def update_state(self) -> None:
148+
"""Update the device states from the cloud"""
149+
raise NotImplementedError
150+
151+
@abstractmethod
152+
async def async_update_state(self) -> None:
153+
"""Async update the device states from the cloud"""
154+
raise NotImplementedError
155+
156+
@property
157+
@abstractmethod
158+
def water_heater_current_temperature(self) -> Optional[float]:
159+
"""Abstract method for get water heater current temperature"""
160+
raise NotImplementedError
161+
162+
@property
163+
@abstractmethod
164+
def water_heater_mode_operation_texts(self) -> list[str]:
165+
"""Abstract method for get water heater operation texts"""
166+
raise NotImplementedError
167+
168+
@property
169+
@abstractmethod
170+
def water_heater_mode_options(self) -> list[int]:
171+
"""Abstract method for get water heater mode options"""
172+
raise NotImplementedError
173+
174+
@property
175+
@abstractmethod
176+
def water_heater_mode_value(self) -> Optional[int]:
177+
"""Abstract method for get water heater mode value"""
178+
raise NotImplementedError
179+
180+
@abstractmethod
181+
def set_water_heater_operation_mode(self, operation_mode: str) -> None:
182+
"""Abstract method for set water heater operation mode"""
183+
raise NotImplementedError
184+
185+
@abstractmethod
186+
async def async_set_water_heater_operation_mode(self, operation_mode: str) -> None:
187+
"""Abstract method for async set water heater operation mode"""
188+
raise NotImplementedError
189+
190+
@property
191+
def central_heating_total_energy_consumption(self) -> Any:
192+
"""Get central heating total energy consumption"""
193+
return self._get_consumption_sequence_last_value(
194+
ConsumptionType.CENTRAL_HEATING_TOTAL_ENERGY,
195+
ConsumptionTimeInterval.LAST_DAY,
196+
)
197+
198+
@property
199+
def domestic_hot_water_total_energy_consumption(self) -> Any:
200+
"""Get domestic hot water total energy consumption"""
201+
return self._get_consumption_sequence_last_value(
202+
ConsumptionType.DOMESTIC_HOT_WATER_TOTAL_ENERGY,
203+
ConsumptionTimeInterval.LAST_DAY,
204+
)
205+
206+
@property
207+
def central_heating_gas_consumption(self) -> Any:
208+
"""Get central heating gas consumption"""
209+
return self._get_consumption_sequence_last_value(
210+
ConsumptionType.CENTRAL_HEATING_GAS,
211+
ConsumptionTimeInterval.LAST_DAY,
212+
)
213+
214+
@property
215+
def domestic_hot_water_heating_pump_electricity_consumption(self) -> Any:
216+
"""Get domestic hot water heating pump electricity consumption"""
217+
return self._get_consumption_sequence_last_value(
218+
ConsumptionType.DOMESTIC_HOT_WATER_HEATING_PUMP_ELECTRICITY,
219+
ConsumptionTimeInterval.LAST_DAY,
220+
)
221+
222+
@property
223+
def domestic_hot_water_resistor_electricity_consumption(self) -> Any:
224+
"""Get domestic hot water resistor electricity consumption"""
225+
return self._get_consumption_sequence_last_value(
226+
ConsumptionType.DOMESTIC_HOT_WATER_RESISTOR_ELECTRICITY,
227+
ConsumptionTimeInterval.LAST_DAY,
228+
)
229+
230+
@property
231+
def domestic_hot_water_gas_consumption(self) -> Any:
232+
"""Get domestic hot water gas consumption"""
233+
return self._get_consumption_sequence_last_value(
234+
ConsumptionType.DOMESTIC_HOT_WATER_GAS,
235+
ConsumptionTimeInterval.LAST_DAY,
236+
)
237+
238+
@property
239+
def central_heating_electricity_consumption(self) -> Any:
240+
"""Get central heating electricity consumption"""
241+
return self._get_consumption_sequence_last_value(
242+
ConsumptionType.CENTRAL_HEATING_ELECTRICITY,
243+
ConsumptionTimeInterval.LAST_DAY,
244+
)
245+
246+
@property
247+
def domestic_hot_water_electricity_consumption(self) -> Any:
248+
"""Get domestic hot water electricity consumption"""
249+
return self._get_consumption_sequence_last_value(
250+
ConsumptionType.DOMESTIC_HOT_WATER_ELECTRICITY,
251+
ConsumptionTimeInterval.LAST_DAY,
252+
)
253+
254+
def _get_consumption_sequence_last_value(
255+
self,
256+
consumption_type: ConsumptionType,
257+
time_interval: ConsumptionTimeInterval,
258+
) -> Any:
259+
"""Get last value for consumption sequence"""
260+
for sequence in self.consumptions_sequences:
261+
if sequence["k"] == consumption_type.value and sequence["p"] == time_interval.value:
262+
return sequence["v"][-1]
263+
264+
return None
265+
266+
def _update_energy(self, old_consumptions_sequences: Optional[list[dict[str, Any]]]) -> None:
267+
"""Update the device energy settings"""
268+
if (
269+
self.custom_features.get(
270+
ConsumptionType.DOMESTIC_HOT_WATER_ELECTRICITY.name
271+
)
272+
is None
273+
):
274+
self._set_energy_features()
275+
276+
if (
277+
old_consumptions_sequences is not None
278+
and len(old_consumptions_sequences) > 0
279+
and old_consumptions_sequences != self.consumptions_sequences
280+
):
281+
self.consumption_sequence_last_changed_utc = dt.datetime.now(
282+
dt.timezone.utc
283+
) - dt.timedelta(hours=1)
284+
285+
def update_energy(self) -> None:
286+
"""Update the device energy settings from the cloud"""
287+
old_consumptions_sequences = self.consumptions_sequences
288+
self._get_consumptions_sequences()
289+
self._update_energy(old_consumptions_sequences)
290+
291+
async def async_update_energy(self) -> None:
292+
"""Async update the device energy settings from the cloud"""
293+
old_consumptions_sequences = self.consumptions_sequences
294+
await self._async_get_consumptions_sequences()
295+
self._update_energy(old_consumptions_sequences)
296+
297+
def get_bus_errors(self) -> None:
298+
"""Get bus errors from the cloud"""
299+
self.bus_errors_list = self.api.get_bus_errors(self.gw)
300+
301+
async def async_get_bus_errors(self) -> None:
302+
"""Async get bus errors from the cloud"""
303+
self.bus_errors_list = await self.api.async_get_bus_errors(self.gw)
304+
305+
def _set_energy_features(self):
306+
"""Set energy features"""
307+
for consumption_type in ConsumptionType:
308+
if (
309+
self._get_consumption_sequence_last_value(
310+
consumption_type,
311+
ConsumptionTimeInterval.LAST_DAY,
312+
)
313+
is not None
314+
):
315+
self.custom_features[consumption_type.name] = True
316+
else:
317+
self.custom_features[consumption_type.name] = False
318+
319+
def are_device_features_available(
320+
self,
321+
device_features: Optional[list[DeviceFeatures | CustomDeviceFeatures | DeviceAttribute]],
322+
system_types: Optional[list[SystemType]],
323+
whe_types: Optional[list[WheType]],
324+
) -> bool:
325+
"""Checks features availability"""
326+
if system_types is not None and self.system_type not in system_types:
327+
return False
328+
329+
if whe_types is not None and self.whe_type not in whe_types:
330+
return False
331+
332+
if device_features is not None:
333+
for device_feature in device_features:
334+
if (
335+
self.features.get(str(device_feature)) is not True
336+
and self.custom_features.get(str(device_feature)) is not True
337+
and self.attributes.get(str(device_feature)) is not True
338+
):
339+
return False
340+
341+
return True

0 commit comments

Comments
 (0)