From 8db7541737bb54c00ff591cf6967d676b7916f56 Mon Sep 17 00:00:00 2001 From: fustom Date: Fri, 14 Feb 2025 20:02:24 +0000 Subject: [PATCH] Refactor. Code cleanup. Small fixes. --- ariston/__init__.py | 34 ++++++-- ariston/ariston_api.py | 170 +++++++++++++++++++++++++-------------- ariston/bsb_device.py | 106 ++++++++++++++++++------ ariston/const.py | 150 ++++++++++++++++++++-------------- ariston/galevo_device.py | 151 ++++++++++++++++++---------------- 5 files changed, 390 insertions(+), 221 deletions(-) diff --git a/ariston/__init__.py b/ariston/__init__.py index 3f3b64c..fcfd805 100644 --- a/ariston/__init__.py +++ b/ariston/__init__.py @@ -1,7 +1,8 @@ """Ariston module""" + import asyncio import logging -from typing import Any, Optional +from typing import Any, Optional, Type from .ariston_api import AristonAPI, ConnectionException from .const import ( @@ -21,10 +22,11 @@ from .lydos_hybrid_device import AristonLydosHybridDevice from .nuos_split_device import AristonNuosSplitDevice from .base_device import AristonBaseDevice +from .velis_base_device import AristonVelisBaseDevice _LOGGER = logging.getLogger(__name__) -_MAP_WHE_TYPES_TO_CLASS = { +_MAP_WHE_TYPES_TO_CLASS: dict[int, Type[AristonVelisBaseDevice]] = { WheType.Evo.value: AristonEvoOneDevice, WheType.LydosHybrid.value: AristonLydosHybridDevice, WheType.Lydos.value: AristonEvoDevice, @@ -43,7 +45,11 @@ def __init__(self) -> None: self.cloud_devices: list[dict[str, Any]] = [] async def async_connect( - self, username: str, password: str, api_url: str = ARISTON_API_URL, user_agent: str = ARISTON_USER_AGENT + self, + username: str, + password: str, + api_url: str = ARISTON_API_URL, + user_agent: str = ARISTON_USER_AGENT, ) -> bool: """Connect to the ariston cloud""" self.api = AristonAPI(username, password, api_url, user_agent) @@ -115,7 +121,12 @@ def _get_device( return None -def _connect(username: str, password: str, api_url: str = ARISTON_API_URL, user_agent: str = ARISTON_USER_AGENT) -> AristonAPI: +def _connect( + username: str, + password: str, + api_url: str = ARISTON_API_URL, + user_agent: str = ARISTON_USER_AGENT, +) -> AristonAPI: """Connect to ariston api""" api = AristonAPI(username, password, api_url, user_agent) api.connect() @@ -131,7 +142,9 @@ def _discover(api: AristonAPI) -> list[dict[str, Any]]: return cloud_devices -def discover(username: str, password: str, api_url: str = ARISTON_API_URL) -> list[dict[str, Any]]: +def discover( + username: str, password: str, api_url: str = ARISTON_API_URL +) -> list[dict[str, Any]]: """Retreive ariston devices from the cloud""" api = _connect(username, password, api_url) return _discover(api) @@ -151,7 +164,12 @@ def hello( return _get_device(cloud_devices, api, gateway, is_metric, language_tag) -async def _async_connect(username: str, password: str, api_url: str = ARISTON_API_URL, user_agent: str = ARISTON_USER_AGENT) -> AristonAPI: +async def _async_connect( + username: str, + password: str, + api_url: str = ARISTON_API_URL, + user_agent: str = ARISTON_USER_AGENT, +) -> AristonAPI: """Async connect to ariston api""" api = AristonAPI(username, password, api_url, user_agent) if not await api.async_connect(): @@ -174,7 +192,9 @@ async def _async_discover(api: AristonAPI) -> list[dict[str, Any]]: return cloud_devices -async def async_discover(username: str, password: str, api_url: str = ARISTON_API_URL) -> list[dict[str, Any]]: +async def async_discover( + username: str, password: str, api_url: str = ARISTON_API_URL +) -> list[dict[str, Any]]: """Retreive ariston devices from the cloud""" api = await _async_connect(username, password, api_url) return await _async_discover(api) diff --git a/ariston/ariston_api.py b/ariston/ariston_api.py index 17dfbad..465e078 100644 --- a/ariston/ariston_api.py +++ b/ariston/ariston_api.py @@ -1,4 +1,5 @@ """Ariston API""" + from __future__ import annotations import logging @@ -33,7 +34,7 @@ ThermostatProperties, WaterHeaterMode, ZoneAttribute, - MenuItemNames + MenuItemNames, ) _LOGGER = logging.getLogger(__name__) @@ -46,7 +47,13 @@ class ConnectionException(Exception): class AristonAPI: """Ariston API class""" - def __init__(self, username: str, password: str, api_url: str = ARISTON_API_URL, user_agent: str = ARISTON_USER_AGENT) -> None: + def __init__( + self, + username: str, + password: str, + api_url: str = ARISTON_API_URL, + user_agent: str = ARISTON_USER_AGENT, + ) -> None: """Constructor for Ariston API.""" self.__username = username self.__password = password @@ -147,24 +154,9 @@ def set_consumptions_settings( @staticmethod def get_items(features: dict[str, Any]) -> list[dict[str, int]]: """Get the Final[str] strings from DeviceProperies and ThermostatProperties""" - device_props = [ - getattr(DeviceProperties, device_property) - for device_property in dir(DeviceProperties) - if not device_property.startswith("__") - ] - thermostat_props = [ - getattr(ThermostatProperties, thermostat_properties) - for thermostat_properties in dir(ThermostatProperties) - if not thermostat_properties.startswith("__") - ] - - items: list[dict[str, int]] = list() - for device_prop in device_props: - items.append({"id": device_prop, "zn": 0}) - + items: list[dict[str, Any]] = DeviceProperties.list(0) for zone in features[DeviceFeatures.ZONES]: - for thermostat_prop in thermostat_props: - items.append({"id": thermostat_prop, "zn": zone[ZoneAttribute.NUM]}) + items.extend(ThermostatProperties.list(zone[ZoneAttribute.NUM])) return items def get_properties( @@ -186,7 +178,9 @@ def get_properties( def get_bsb_plant_data(self, gw_id: str) -> dict[str, Any]: """Get BSB plant data.""" - data = self._get(f"{self.__api_url}{ARISTON_REMOTE}/{PlantData.Bsb.value}/{gw_id}") + data = self._get( + f"{self.__api_url}{ARISTON_REMOTE}/{PlantData.Bsb.value}/{gw_id}" + ) if data is not None: return data return dict() @@ -212,7 +206,7 @@ def get_velis_plant_settings( def get_menu_items(self, gw_id: str) -> list[dict[str, Any]]: """Get menu items""" items = self._get( - f"{self.__api_url}{ARISTON_MENU_ITEMS}/{gw_id}?menuItems={MenuItemNames()}" + f"{self.__api_url}{ARISTON_MENU_ITEMS}/{gw_id}?menuItems={MenuItemNames.values()}" ) if items is not None: return items @@ -289,14 +283,18 @@ def set_bsb_mode(self, gw_id: str, value: BsbOperativeMode) -> None: }, ) - def set_bsb_zone_mode(self, gw_id: str, zone: int, value: BsbZoneMode, old_value: BsbZoneMode, is_cooling: bool) -> None: + def set_bsb_zone_mode( + self, + gw_id: str, + zone: int, + value: BsbZoneMode, + old_value: BsbZoneMode, + is_cooling: bool, + ) -> None: """Set Bsb zone mode""" self._post( f"{self.__api_url}{ARISTON_REMOTE}/{ARISTON_BSB_ZONES}/{gw_id}/{zone}/mode?isCooling={is_cooling}", - { - "new": value.value, - "old": old_value.value - }, + {"new": value.value, "old": old_value.value}, ) def set_evo_temperature(self, gw_id: str, value: float) -> None: @@ -317,7 +315,14 @@ def set_lydos_temperature(self, gw_id: str, value: float) -> None: }, ) - def set_nuos_temperature(self, gw_id: str, comfort: float, reduced: float, old_comfort: Optional[float], old_reduced: Optional[float]) -> None: + def set_nuos_temperature( + self, + gw_id: str, + comfort: float, + reduced: float, + old_comfort: Optional[float], + old_reduced: Optional[float], + ) -> None: """Set Nuos temperature""" self._post( f"{self.__api_url}{ARISTON_VELIS}/{PlantData.Slp.value}/{gw_id}/temperatures", @@ -329,11 +334,18 @@ def set_nuos_temperature(self, gw_id: str, comfort: float, reduced: float, old_c "old": { "comfort": old_comfort, "reduced": old_reduced, - } + }, }, ) - def set_bsb_temperature(self, gw_id: str, comfort: float, reduced: float, old_comfort: Optional[float], old_reduced: Optional[float]) -> None: + def set_bsb_temperature( + self, + gw_id: str, + comfort: float, + reduced: float, + old_comfort: Optional[float], + old_reduced: Optional[float], + ) -> None: """Set Bsb temperature""" self._post( f"{self.__api_url}{ARISTON_REMOTE}/{PlantData.Bsb.value}/{gw_id}/dhwTemp", @@ -345,12 +357,19 @@ def set_bsb_temperature(self, gw_id: str, comfort: float, reduced: float, old_co "old": { "comf": old_comfort, "econ": old_reduced, - } + }, }, ) def set_bsb_zone_temperature( - self, gw_id: str, zone: int, comfort: float, reduced: float, old_comfort: Optional[float], old_reduced: Optional[float], is_cooling: bool + self, + gw_id: str, + zone: int, + comfort: float, + reduced: float, + old_comfort: Optional[float], + old_reduced: Optional[float], + is_cooling: bool, ) -> None: """Set Bsb zone temperature""" self._post( @@ -363,7 +382,7 @@ def set_bsb_zone_temperature( "old": { "comf": old_comfort, "econ": old_reduced, - } + }, }, ) @@ -435,7 +454,9 @@ def set_holiday( def get_bus_errors(self, gw_id: str) -> list[Any]: """Get bus errors""" - bus_errors = self._get(f"{self.__api_url}{ARISTON_BUS_ERRORS}?gatewayId={gw_id}&blockingOnly=False&culture=en-US") + bus_errors = self._get( + f"{self.__api_url}{ARISTON_BUS_ERRORS}?gatewayId={gw_id}&blockingOnly=False&culture=en-US" + ) if bus_errors is not None: return list(bus_errors) return [] @@ -449,7 +470,10 @@ def __request( is_retry: bool = False, ) -> Optional[dict[str, Any]]: """Request with requests""" - headers = {"User-Agent": self.__user_agent, "ar.authToken": self.__token} + headers: dict[str, Any] = { + "User-Agent": self.__user_agent, + "ar.authToken": self.__token, + } _LOGGER.debug( "Request method %s, path: %s, params: %s", @@ -466,18 +490,18 @@ def __request( if not is_retry: if self.connect(): return self.__request(method, path, params, body, True) - raise Exception("Login failed (password changed?)") - raise Exception("Invalid token") + raise ConnectionException("Login failed (password changed?)") + raise ConnectionException("Invalid token") case 404: return None case 429: content = response.content.decode() - raise Exception(response.status_code, content) + raise ConnectionException(response.status_code, content) case _: if not is_retry: time.sleep(5) return self.__request(method, path, params, body, True) - raise Exception(response.status_code) + raise ConnectionException(response.status_code) if len(response.content) > 0: json = response.json() @@ -490,9 +514,7 @@ def _post(self, path: str, body: Any) -> Any: """POST request""" return self.__request("POST", path, None, body) - def _get( - self, path: str, params: Optional[dict[str, Any]] = None - ) -> Any: + def _get(self, path: str, params: Optional[dict[str, Any]] = None) -> Any: """GET request""" return self.__request("GET", path, params, None) @@ -642,7 +664,7 @@ async def async_get_velis_plant_settings( async def async_get_menu_items(self, gw_id: str) -> list[dict[str, Any]]: """Async get menu items""" items = await self._async_get( - f"{self.__api_url}{ARISTON_MENU_ITEMS}/{gw_id}?menuItems={MenuItemNames()}" + f"{self.__api_url}{ARISTON_MENU_ITEMS}/{gw_id}?menuItems={MenuItemNames.values()}" ) if items is not None: return items @@ -674,7 +696,9 @@ async def async_set_property( }, ) - async def async_set_evo_number_of_showers(self, gw_id: str, number_of_showers: int) -> None: + async def async_set_evo_number_of_showers( + self, gw_id: str, number_of_showers: int + ) -> None: """Set Velis Evo number of showers""" await self._async_post( f"{self.__api_url}{ARISTON_VELIS}/{PlantData.PD.value}/{gw_id}/showers", @@ -722,15 +746,17 @@ async def async_set_bsb_mode(self, gw_id: str, value: BsbOperativeMode) -> None: ) async def async_set_bsb_zone_mode( - self, gw_id: str, zone: int, value: BsbZoneMode, old_value: BsbZoneMode, is_cooling: bool + self, + gw_id: str, + zone: int, + value: BsbZoneMode, + old_value: BsbZoneMode, + is_cooling: bool, ) -> None: """Async set Bsb zone mode""" await self._async_post( f"{self.__api_url}{ARISTON_REMOTE}/{ARISTON_BSB_ZONES}/{gw_id}/{zone}/mode?isCooling={is_cooling}", - { - "new": value.value, - "old": old_value.value - }, + {"new": value.value, "old": old_value.value}, ) async def async_set_evo_temperature(self, gw_id: str, value: float) -> None: @@ -752,7 +778,12 @@ async def async_set_lydos_temperature(self, gw_id: str, value: float) -> None: ) async def async_set_nuos_temperature( - self, gw_id: str, comfort: float, reduced: float, old_comfort: Optional[float], old_reduced: Optional[float] + self, + gw_id: str, + comfort: float, + reduced: float, + old_comfort: Optional[float], + old_reduced: Optional[float], ) -> None: """Async set Velis Lydos temperature""" await self._async_post( @@ -765,12 +796,17 @@ async def async_set_nuos_temperature( "old": { "comfort": old_comfort, "reduced": old_reduced, - } + }, }, ) async def async_set_bsb_temperature( - self, gw_id: str, comfort: float, reduced: float, old_comfort: Optional[float], old_reduced: Optional[float] + self, + gw_id: str, + comfort: float, + reduced: float, + old_comfort: Optional[float], + old_reduced: Optional[float], ) -> None: """Async set Bsb temperature""" await self._async_post( @@ -783,12 +819,19 @@ async def async_set_bsb_temperature( "old": { "comf": old_comfort, "econ": old_reduced, - } + }, }, ) async def async_set_bsb_zone_temperature( - self, gw_id: str, zone: int, comfort: float, reduced: float, old_comfort: Optional[float], old_reduced: Optional[float], is_cooling: bool + self, + gw_id: str, + zone: int, + comfort: float, + reduced: float, + old_comfort: Optional[float], + old_reduced: Optional[float], + is_cooling: bool, ) -> None: """Async set Bsb zone temperature""" await self._async_post( @@ -801,7 +844,7 @@ async def async_set_bsb_zone_temperature( "old": { "comf": old_comfort, "econ": old_reduced, - } + }, }, ) @@ -873,7 +916,9 @@ async def async_set_holiday( async def async_get_bus_errors(self, gw_id: str) -> list[Any]: """Async get bus errors""" - bus_errors = await self._async_get(f"{self.__api_url}{ARISTON_BUS_ERRORS}?gatewayId={gw_id}&blockingOnly=False&culture=en-US") + bus_errors = await self._async_get( + f"{self.__api_url}{ARISTON_BUS_ERRORS}?gatewayId={gw_id}&blockingOnly=False&culture=en-US" + ) if bus_errors is not None: return list(bus_errors) return [] @@ -887,7 +932,10 @@ async def __async_request( is_retry: bool = False, ) -> Optional[dict[str, Any]]: """Async request with aiohttp""" - headers = {"User-Agent": self.__user_agent, "ar.authToken": self.__token} + headers: dict[str, Any] = { + "User-Agent": self.__user_agent, + "ar.authToken": self.__token, + } _LOGGER.debug( "Request method %s, path: %s, params: %s", @@ -909,20 +957,22 @@ async def __async_request( return await self.__async_request( method, path, params, body, True ) - raise Exception("Login failed (password changed?)") - raise Exception("Invalid token") + raise ConnectionException( + "Login failed (password changed?)" + ) + raise ConnectionException("Invalid token") case 404: return None case 429: content = await response.content.read() - raise Exception(response.status, content) + raise ConnectionException(response.status, content) case _: if not is_retry: await asyncio.sleep(5) return await self.__async_request( method, path, params, body, True ) - raise Exception(response.status) + raise ConnectionException(response.status) if response.content_length and response.content_length > 0: json = await response.json() diff --git a/ariston/bsb_device.py b/ariston/bsb_device.py index 9f13cc3..c3ee5f3 100644 --- a/ariston/bsb_device.py +++ b/ariston/bsb_device.py @@ -1,4 +1,5 @@ """BSB device class for Ariston module.""" + import logging from typing import Any, Optional @@ -21,11 +22,11 @@ class AristonBsbDevice(AristonDevice): @property def consumption_type(self) -> str: """String to get consumption type""" - return f"Ch{'%2CDhw'}" + return "Ch%2CDhw" @property def plant_mode_supported(self) -> bool: - """Returns is plant mode supported""" + """Returns whether plant mode is supported""" return False def update_state(self) -> None: @@ -58,7 +59,7 @@ def zone_numbers(self) -> list[int]: @property def zones(self) -> dict[str, dict[str, Any]]: """Get device zones wrapper""" - return self.data.get(BsbDeviceProperties.ZONES, dict[str, dict[str, Any]]()) + return self.data.get(BsbDeviceProperties.ZONES, {}) def get_zone(self, zone: int) -> dict[str, Any]: """Get device zone""" @@ -74,17 +75,12 @@ def get_zone_ch_red_temp(self, zone: int) -> dict[str, Any]: def get_zone_mode(self, zone: int) -> BsbZoneMode: """Get zone mode on value""" - zone_mode = ( + return BsbZoneMode( self.get_zone(zone) .get(BsbZoneProperties.MODE, dict[str, Any]()) - .get(PropertyType.VALUE, None) + .get(PropertyType.VALUE, None) or BsbZoneMode.UNDEFINED ) - if zone_mode is None: - return BsbZoneMode.UNDEFINED - - return BsbZoneMode(zone_mode) - def get_zone_mode_options(self, zone: int) -> list[int]: """Get zone mode on options""" return ( @@ -120,9 +116,9 @@ def is_zone_in_time_program_mode(self, zone: int) -> bool: def is_zone_mode_options_contains_manual(self, zone: int) -> bool: """Is zone mode options contains manual mode""" - return ( - BsbZoneMode.MANUAL.value or BsbZoneMode.MANUAL_NIGHT.value - ) in self.get_zone_mode_options(zone) + return BsbZoneMode.MANUAL.value in self.get_zone_mode_options( + zone + ) or BsbZoneMode.MANUAL_NIGHT.value in self.get_zone_mode_options(zone) def is_zone_mode_options_contains_time_program(self, zone: int) -> bool: """Is zone mode options contains time program mode""" @@ -269,11 +265,11 @@ def get_measured_temp_value(self, zone: int) -> int: """Get zone measured temp value""" return self.get_zone(zone).get(BsbZoneProperties.ROOM_TEMP, 0) - def get_measured_temp_decimals(self, zone: int) -> int: + def get_measured_temp_decimals(self, _) -> int: """Get zone measured temp decimals""" return 1 - def get_measured_temp_unit(self, zone: int) -> str: + def get_measured_temp_unit(self, _) -> str: """Get zone measured temp unit""" return "°C" @@ -298,12 +294,16 @@ async def async_set_water_heater_temperature(self, temperature: float): def set_water_heater_operation_mode(self, operation_mode: str) -> None: """Set water heater operation mode""" self.api.set_bsb_mode(self.gw, BsbOperativeMode[operation_mode]) - self.data[BsbDeviceProperties.DHW_MODE][PropertyType.VALUE] = BsbOperativeMode[operation_mode].value + self.data[BsbDeviceProperties.DHW_MODE][PropertyType.VALUE] = BsbOperativeMode[ + operation_mode + ].value async def async_set_water_heater_operation_mode(self, operation_mode: str) -> None: """Async set water heater operation mode""" await self.api.async_set_bsb_mode(self.gw, BsbOperativeMode[operation_mode]) - self.data[BsbDeviceProperties.DHW_MODE][PropertyType.VALUE] = BsbOperativeMode[operation_mode].value + self.data[BsbDeviceProperties.DHW_MODE][PropertyType.VALUE] = BsbOperativeMode[ + operation_mode + ].value def set_water_heater_reduced_temperature(self, temperature: float): """Set water heater reduced temperature""" @@ -325,7 +325,13 @@ async def async_set_water_heater_reduced_temperature(self, temperature: float): def _set_water_heater_temperature(self, temperature: float, reduced: float): """Set water heater temperature""" - self.api.set_bsb_temperature(self.gw, temperature, reduced, self.water_heater_target_temperature, self.water_heater_reduced_temperature) + self.api.set_bsb_temperature( + self.gw, + temperature, + reduced, + self.water_heater_target_temperature, + self.water_heater_reduced_temperature, + ) self.data[BsbDeviceProperties.DHW_COMF_TEMP][PropertyType.VALUE] = temperature self.data[BsbDeviceProperties.DHW_REDU_TEMP][PropertyType.VALUE] = reduced @@ -333,18 +339,36 @@ async def _async_set_water_heater_temperature( self, temperature: float, reduced: float ): """Async set water heater temperature""" - await self.api.async_set_bsb_temperature(self.gw, temperature, reduced, self.water_heater_target_temperature, self.water_heater_reduced_temperature) + await self.api.async_set_bsb_temperature( + self.gw, + temperature, + reduced, + self.water_heater_target_temperature, + self.water_heater_reduced_temperature, + ) self.data[BsbDeviceProperties.DHW_COMF_TEMP][PropertyType.VALUE] = temperature self.data[BsbDeviceProperties.DHW_REDU_TEMP][PropertyType.VALUE] = reduced def set_zone_mode(self, zone_mode: BsbZoneMode, zone: int): """Set zone mode""" - self.api.set_bsb_zone_mode(self.gw, zone, zone_mode, self.get_zone_mode(zone), self.is_plant_in_cool_mode) + self.api.set_bsb_zone_mode( + self.gw, + zone, + zone_mode, + self.get_zone_mode(zone), + self.is_plant_in_cool_mode, + ) self.get_zone(zone)[BsbZoneProperties.MODE][PropertyType.VALUE] = zone_mode async def async_set_zone_mode(self, zone_mode: BsbZoneMode, zone: int): """Async set zone mode""" - await self.api.async_set_bsb_zone_mode(self.gw, zone, zone_mode, self.get_zone_mode(zone), self.is_plant_in_cool_mode) + await self.api.async_set_bsb_zone_mode( + self.gw, + zone, + zone_mode, + self.get_zone_mode(zone), + self.is_plant_in_cool_mode, + ) self.get_zone(zone)[BsbZoneProperties.MODE][PropertyType.VALUE] = zone_mode @property @@ -362,7 +386,15 @@ def set_comfort_temp(self, temp: float, zone: int): if len(self.data) == 0: self.update_state() reduced = self.get_reduced_temp_value(zone) - self.api.set_bsb_zone_temperature(self.gw, zone, temp, reduced, self.get_comfort_temp_value(zone), self.get_reduced_temp_value(zone), self.is_plant_in_cool_mode) + self.api.set_bsb_zone_temperature( + self.gw, + zone, + temp, + reduced, + self.get_comfort_temp_value(zone), + self.get_reduced_temp_value(zone), + self.is_plant_in_cool_mode, + ) self.get_zone_ch_comf_temp(zone)[PropertyType.VALUE] = temp async def async_set_comfort_temp(self, temp: float, zone: int): @@ -370,7 +402,15 @@ async def async_set_comfort_temp(self, temp: float, zone: int): if len(self.data) == 0: await self.async_update_state() reduced = self.get_reduced_temp_value(zone) - await self.api.async_set_bsb_zone_temperature(self.gw, zone, temp, reduced, self.get_comfort_temp_value(zone), self.get_reduced_temp_value(zone), self.is_plant_in_cool_mode) + await self.api.async_set_bsb_zone_temperature( + self.gw, + zone, + temp, + reduced, + self.get_comfort_temp_value(zone), + self.get_reduced_temp_value(zone), + self.is_plant_in_cool_mode, + ) self.get_zone_ch_comf_temp(zone)[PropertyType.VALUE] = temp def set_reduced_temp(self, temp: float, zone: int): @@ -378,7 +418,15 @@ def set_reduced_temp(self, temp: float, zone: int): if len(self.data) == 0: self.update_state() comfort = self.get_comfort_temp_value(zone) - self.api.set_bsb_zone_temperature(self.gw, zone, comfort, temp, self.get_comfort_temp_value(zone), self.get_reduced_temp_value(zone), self.is_plant_in_cool_mode) + self.api.set_bsb_zone_temperature( + self.gw, + zone, + comfort, + temp, + self.get_comfort_temp_value(zone), + self.get_reduced_temp_value(zone), + self.is_plant_in_cool_mode, + ) self.get_zone_ch_red_temp(zone)[PropertyType.VALUE] = temp async def async_set_reduced_temp(self, temp: float, zone: int): @@ -386,5 +434,13 @@ async def async_set_reduced_temp(self, temp: float, zone: int): if len(self.data) == 0: await self.async_update_state() comfort = self.get_comfort_temp_value(zone) - await self.api.async_set_bsb_zone_temperature(self.gw, zone, comfort, temp, self.get_comfort_temp_value(zone), self.get_reduced_temp_value(zone), self.is_plant_in_cool_mode) + await self.api.async_set_bsb_zone_temperature( + self.gw, + zone, + comfort, + temp, + self.get_comfort_temp_value(zone), + self.get_reduced_temp_value(zone), + self.is_plant_in_cool_mode, + ) self.get_zone_ch_red_temp(zone)[PropertyType.VALUE] = temp diff --git a/ariston/const.py b/ariston/const.py index 4dc30e6..13f9b09 100644 --- a/ariston/const.py +++ b/ariston/const.py @@ -1,6 +1,7 @@ """Constants for ariston module""" -from enum import Enum, IntEnum, unique -from typing import Final + +from enum import Enum, IntEnum, StrEnum, unique +from typing import Final, Any ARISTON_API_URL: Final[str] = "https://www.ariston-net.remotethermo.com/api/v2/" ARISTON_LOGIN: Final[str] = "accounts/login" @@ -17,8 +18,18 @@ ARISTON_MENU_ITEMS: Final[str] = "menuItems" ARISTON_USER_AGENT: Final[str] = "RestSharp/106.11.7.0" + +class ExtendedStrEnum(StrEnum): + """Extended Enum class""" + + @classmethod + def list(cls, zn: int) -> list[dict[str, Any]]: + """Return all enum values""" + return [{"id": c.value, "zn": zn} for c in cls] + + @unique -class PlantData(str, Enum): +class PlantData(StrEnum): """Plant data enum""" PD = "plantData" @@ -52,6 +63,7 @@ class ZoneMode(Enum): MANUAL = 2 TIME_PROGRAM = 3 + @unique class BsbZoneMode(Enum): """BSB zone mode enum""" @@ -59,8 +71,9 @@ class BsbZoneMode(Enum): UNDEFINED = -1 OFF = 0 TIME_PROGRAM = 1 - MANUAL = 2 - MANUAL_NIGHT = 3 + MANUAL_NIGHT = 2 + MANUAL = 3 + @unique class DhwMode(Enum): @@ -105,7 +118,7 @@ class GasEnergyUnit(IntEnum): @unique class GasType(IntEnum): - """Gas type enu,""" + """Gas type enum""" NATURAL_GAS = 0 LPG = 1 @@ -166,7 +179,7 @@ class Brands(Enum): class WaterHeaterMode(Enum): - """Base class for plant modes""" + """Base class for water heater modes""" @unique @@ -176,6 +189,7 @@ class BsbOperativeMode(WaterHeaterMode): OFF = 0 ON = 1 + @unique class LuxPlantMode(WaterHeaterMode): """Lux plant mode enum""" @@ -373,12 +387,15 @@ class DeviceFeatures: ZONES: Final[str] = "zones" WEATHER_PROVIDER: Final[str] = "weatherProvider" + class VelisBaseDeviceProperties: """Contants for VelisBase device properties""" + GW: Final[str] = "gw" MODE: Final[str] = "mode" ON: Final[str] = "on" + class EvoOneDeviceProperties(VelisBaseDeviceProperties): """Contants for Velis Evo device properties""" @@ -394,6 +411,7 @@ class EvoOneDeviceProperties(VelisBaseDeviceProperties): TEMP: Final[str] = "temp" TM_P1: Final[str] = "tmP1" + class VelisDeviceProperties(VelisBaseDeviceProperties): """Contants for Velis device properties""" @@ -434,6 +452,7 @@ class LydosDeviceProperties(EvoLydosDeviceProperties): BOOST_REQ_TEMP: Final[str] = "boostReqTemp" + class BsbDeviceProperties: """Constants for bsb device properties.""" @@ -472,7 +491,10 @@ class BsbZoneProperties: MODE: Final[str] = "mode" ROOM_TEMP: Final[str] = "roomTemp" ROOM_TEMP_ERROR: Final[str] = "roomTempError" - USE_REDUCED_OPERATION_MODE_ON_HOLIDAY: Final[str] = "useReducedOperationModeOnHoliday" + USE_REDUCED_OPERATION_MODE_ON_HOLIDAY: Final[str] = ( + "useReducedOperationModeOnHoliday" + ) + class MedDeviceSettings: """Constatns for Med device settings""" @@ -523,58 +545,58 @@ class SlpDeviceSettings: SLP_HC_HP_MODE: Final[str] = "SlpHcHpMode" -class DeviceProperties: +class DeviceProperties(ExtendedStrEnum): """Constants for device properties""" - PLANT_MODE: Final[str] = "PlantMode" - IS_FLAME_ON: Final[str] = "IsFlameOn" - IS_HEATING_PUMP_ON: Final[str] = "IsHeatingPumpOn" - HOLIDAY: Final[str] = "Holiday" - OUTSIDE_TEMP: Final[str] = "OutsideTemp" - WEATHER: Final[str] = "Weather" - HEATING_CIRCUIT_PRESSURE: Final[str] = "HeatingCircuitPressure" - CH_FLOW_TEMP: Final[str] = "ChFlowTemp" - CH_FLOW_SETPOINT_TEMP: Final[str] = "ChFlowSetpointTemp" - DHW_TEMP: Final[str] = "DhwTemp" - DHW_STORAGE_TEMPERATURE: Final[str] = "DhwStorageTemperature" - DHW_TIMEPROG_COMFORT_TEMP: Final[str] = "DhwTimeProgComfortTemp" - DHW_TIMEPROG_ECONOMY_TEMP: Final[str] = "DhwTimeProgEconomyTemp" - DHW_MODE: Final[str] = "DhwMode" - AUTOMATIC_THERMOREGULATION: Final[str] = "AutomaticThermoregulation" - ANTILEGIONELLA_ON_OFF: Final[str] = "AntilegionellaOnOff" - ANTILEGIONELLA_TEMP: Final[str] = "AntilegionellaTemp" - ANTILEGIONELLA_FREQ: Final[str] = "AntilegionellaFreq" - HYBRID_MODE: Final[str] = "HybridMode" - BUFFER_CONTROL_MODE: Final[str] = "BufferControlMode" - BUFFER_TIME_PROG_COMFORT_HEATING_TEMP: Final[str] = "BufferTimeProgComfortHeatingTemp" - BUFFER_TIME_PROG_ECONOMY_HEATING_TEMP: Final[str] = "BufferTimeProgEconomyHeatingTemp" - BUFFER_TIME_PROG_COMFORT_COOLING_TEMP: Final[str] = "BufferTimeProgComfortCoolingTemp" - BUFFER_TIME_PROG_ECONOMY_COOLING_TEMP: Final[str] = "BufferTimeProgEconomyCoolingTemp" - IS_QUIET: Final[str] = "IsQuite" # ariston misspelled IsQuiet - - -class ThermostatProperties: + PLANT_MODE = "PlantMode" + IS_FLAME_ON = "IsFlameOn" + IS_HEATING_PUMP_ON = "IsHeatingPumpOn" + HOLIDAY = "Holiday" + OUTSIDE_TEMP = "OutsideTemp" + WEATHER = "Weather" + HEATING_CIRCUIT_PRESSURE = "HeatingCircuitPressure" + CH_FLOW_TEMP = "ChFlowTemp" + CH_FLOW_SETPOINT_TEMP = "ChFlowSetpointTemp" + DHW_TEMP = "DhwTemp" + DHW_STORAGE_TEMPERATURE = "DhwStorageTemperature" + DHW_TIMEPROG_COMFORT_TEMP = "DhwTimeProgComfortTemp" + DHW_TIMEPROG_ECONOMY_TEMP = "DhwTimeProgEconomyTemp" + DHW_MODE = "DhwMode" + AUTOMATIC_THERMOREGULATION = "AutomaticThermoregulation" + ANTILEGIONELLA_ON_OFF = "AntilegionellaOnOff" + ANTILEGIONELLA_TEMP = "AntilegionellaTemp" + ANTILEGIONELLA_FREQ = "AntilegionellaFreq" + HYBRID_MODE = "HybridMode" + BUFFER_CONTROL_MODE = "BufferControlMode" + BUFFER_TIME_PROG_COMFORT_HEATING_TEMP = "BufferTimeProgComfortHeatingTemp" + BUFFER_TIME_PROG_ECONOMY_HEATING_TEMP = "BufferTimeProgEconomyHeatingTemp" + BUFFER_TIME_PROG_COMFORT_COOLING_TEMP = "BufferTimeProgComfortCoolingTemp" + BUFFER_TIME_PROG_ECONOMY_COOLING_TEMP = "BufferTimeProgEconomyCoolingTemp" + IS_QUIET = "IsQuite" # ariston misspelled IsQuiet + + +class ThermostatProperties(ExtendedStrEnum): """Constants for thermostat properties""" - ZONE_MEASURED_TEMP: Final[str] = "ZoneMeasuredTemp" - ZONE_DESIRED_TEMP: Final[str] = "ZoneDesiredTemp" - ZONE_COMFORT_TEMP: Final[str] = "ZoneComfortTemp" - ZONE_MODE: Final[str] = "ZoneMode" - ZONE_HEAT_REQUEST: Final[str] = "ZoneHeatRequest" - ZONE_ECONOMY_TEMP: Final[str] = "ZoneEconomyTemp" - ZONE_DEROGA: Final[str] = "ZoneDeroga" - ZONE_IS_ZONE_PILOT_ON: Final[str] = "IsZonePilotOn" - ZONE_VIRT_TEMP_OFFSET_HEAT: Final[str] = "VirtTempOffsetHeat" - HEATING_FLOW_TEMP: Final[str] = "HeatingFlowTemp" - HEATING_FLOW_OFFSET: Final[str] = "HeatingFlowOffset" - COOLING_FLOW_TEMP: Final[str] = "CoolingFlowTemp" - COOLING_FLOW_OFFSET: Final[str] = "CoolingFlowOffset" - ZONE_NAME: Final[str] = "ZoneName" - VIRT_TEMP_SETPOINT_HEAT: Final[str] = "VirtTempSetpointHeat" - VIRT_TEMP_SETPOINT_COOL: Final[str] = "VirtTempSetpointCool" - VIRT_COMFORT_TEMP: Final[str] = "VirtComfortTemp" - VIRT_REDUCED_TEMP: Final[str] = "VirtReducedTemp" - ZONE_VIRT_TEMP_OFFSET_COOL: Final[str] = "VirtTempOffsetCool" + ZONE_MEASURED_TEMP = "ZoneMeasuredTemp" + ZONE_DESIRED_TEMP = "ZoneDesiredTemp" + ZONE_COMFORT_TEMP = "ZoneComfortTemp" + ZONE_MODE = "ZoneMode" + ZONE_HEAT_REQUEST = "ZoneHeatRequest" + ZONE_ECONOMY_TEMP = "ZoneEconomyTemp" + ZONE_DEROGA = "ZoneDeroga" + ZONE_IS_ZONE_PILOT_ON = "IsZonePilotOn" + ZONE_VIRT_TEMP_OFFSET_HEAT = "VirtTempOffsetHeat" + HEATING_FLOW_TEMP = "HeatingFlowTemp" + HEATING_FLOW_OFFSET = "HeatingFlowOffset" + COOLING_FLOW_TEMP = "CoolingFlowTemp" + COOLING_FLOW_OFFSET = "CoolingFlowOffset" + ZONE_NAME = "ZoneName" + VIRT_TEMP_SETPOINT_HEAT = "VirtTempSetpointHeat" + VIRT_TEMP_SETPOINT_COOL = "VirtTempSetpointCool" + VIRT_COMFORT_TEMP = "VirtComfortTemp" + VIRT_REDUCED_TEMP = "VirtReducedTemp" + ZONE_VIRT_TEMP_OFFSET_COOL = "VirtTempOffsetCool" class ConsumptionProperties: @@ -602,8 +624,10 @@ class PropertyType: EXPIRES_ON: Final[str] = "expiresOn" ALLOWED_OPTIONS: Final[str] = "allowedOptions" + class BusErrorsProperties: """Constants for bus errors properties""" + GW: Final[str] = "gw" TIMESTAMP: Final[str] = "timestamp" FAULT: Final[str] = "fault" @@ -614,10 +638,14 @@ class BusErrorsProperties: RES: Final[str] = "res" BLK: Final[str] = "blk" -class MenuItemNames: + +class MenuItemNames(IntEnum): """Constants for menu items""" - CH_RETURN_TEMP: Final[int] = 124 - SIGNAL_STRENGTH: Final[int] = 119 - def __str__(self): - return ','.join([str(getattr(self, names)) for names in dir(self) if not names.startswith("__")]) + CH_RETURN_TEMP = 124 + SIGNAL_STRENGTH = 119 + + @classmethod + def values(cls) -> str: + """Return all menu items values""" + return ",".join(str(c.value) for c in cls) diff --git a/ariston/galevo_device.py b/ariston/galevo_device.py index b2c771d..59c489b 100644 --- a/ariston/galevo_device.py +++ b/ariston/galevo_device.py @@ -1,4 +1,5 @@ """Galevo device class for Ariston module.""" + from __future__ import annotations import asyncio @@ -22,7 +23,7 @@ ThermostatProperties, ZoneAttribute, ZoneMode, - MenuItemNames + MenuItemNames, ) from .device import AristonDevice @@ -53,7 +54,7 @@ def consumption_type(self) -> str: @property def plant_mode_supported(self) -> bool: - """Returns is plant mode supported""" + """Returns whether plant mode is supported""" return True def _update_state(self) -> None: @@ -80,8 +81,12 @@ def _update_state(self) -> None: storage_temp is not None and storage_temp != max_storage_temp ) - self.custom_features[DeviceProperties.CH_FLOW_TEMP] = self.ch_flow_temp_value is not None - self.custom_features[DeviceProperties.IS_QUIET] = self.is_quiet_value is not None + self.custom_features[DeviceProperties.CH_FLOW_TEMP] = ( + self.ch_flow_temp_value is not None + ) + self.custom_features[DeviceProperties.IS_QUIET] = ( + self.is_quiet_value is not None + ) def update_state(self) -> None: """Update the device states from the cloud""" @@ -109,17 +114,17 @@ async def async_update_state(self) -> None: self.language_tag, self.umsys, ), - self.api.async_get_menu_items(self.gw) + self.api.async_get_menu_items(self.gw), ) self._update_state() def _get_features(self) -> None: """Set custom features""" self.custom_features[CustomDeviceFeatures.HAS_DHW] = ( - self.features.get(DeviceFeatures.HAS_BOILER, False) or - self.features.get(DeviceFeatures.DHW_BOILER_PRESENT, False) or - self.features.get(DeviceFeatures.DHW_MODE_CHANGEABLE, False) or - self.features.get(DeviceFeatures.DHW_PROG_SUPPORTED, False) + self.features.get(DeviceFeatures.HAS_BOILER, False) + or self.features.get(DeviceFeatures.DHW_BOILER_PRESENT, False) + or self.features.get(DeviceFeatures.DHW_MODE_CHANGEABLE, False) + or self.features.get(DeviceFeatures.DHW_PROG_SUPPORTED, False) ) def get_features(self) -> None: @@ -135,7 +140,7 @@ async def async_get_features(self) -> None: @property def zones(self) -> list[dict[str, Any]]: """Get device zones wrapper""" - return self.features.get(DeviceFeatures.ZONES, list[dict[str, Any]]()) + return self.features.get(DeviceFeatures.ZONES, list[dict[str, Any]]) @property def zone_numbers(self) -> list[int]: @@ -239,9 +244,9 @@ def is_zone_in_time_program_mode(self, zone: int) -> bool: def is_zone_mode_options_contains_manual(self, zone: int) -> bool: """Is zone mode options contains manual mode""" - return (ZoneMode.MANUAL.value or ZoneMode.MANUAL_NIGHT.value) in self.get_zone_mode_options( + return ZoneMode.MANUAL.value in self.get_zone_mode_options( zone - ) + ) or ZoneMode.MANUAL_NIGHT.value in self.get_zone_mode_options(zone) def is_zone_mode_options_contains_time_program(self, zone: int) -> bool: """Is zone mode options contains time program mode""" @@ -260,8 +265,9 @@ def is_plant_mode_options_contains_off(self) -> bool: def is_plant_mode_options_contains_cooling(self) -> bool: """Is plant mode options contains cooling mode""" return ( - PlantMode.COOLING.value or PlantMode.COOLING_ONLY.value - ) in self.plant_mode_options + PlantMode.COOLING.value in self.plant_mode_options + or PlantMode.COOLING_ONLY.value in self.plant_mode_options + ) @property def holiday_expires_on(self) -> str: @@ -292,21 +298,19 @@ def heating_circuit_pressure_unit(self) -> str: @property def hybrid_mode(self) -> str: """Get hybrid mode value""" - return self.hybrid_mode_opt_texts[self.hybrid_mode_options.index(self.hybrid_mode_value)] + return self.hybrid_mode_opt_texts[ + self.hybrid_mode_options.index(self.hybrid_mode_value) + ] @property def hybrid_mode_value(self) -> str: """Get hybrid mode value""" - return self._get_item_by_id( - DeviceProperties.HYBRID_MODE, PropertyType.VALUE - ) + return self._get_item_by_id(DeviceProperties.HYBRID_MODE, PropertyType.VALUE) @property def hybrid_mode_options(self) -> str: """Get hybrid mode options""" - return self._get_item_by_id( - DeviceProperties.HYBRID_MODE, PropertyType.OPTIONS - ) + return self._get_item_by_id(DeviceProperties.HYBRID_MODE, PropertyType.OPTIONS) @property def hybrid_mode_opt_texts(self) -> str: @@ -318,7 +322,9 @@ def hybrid_mode_opt_texts(self) -> str: @property def buffer_control_mode(self) -> str: """Get buffer control mode""" - return self.buffer_control_mode_opt_texts[self.buffer_control_mode_options.index(self.buffer_control_mode_value)] + return self.buffer_control_mode_opt_texts[ + self.buffer_control_mode_options.index(self.buffer_control_mode_value) + ] @property def buffer_control_mode_value(self) -> str: @@ -344,9 +350,7 @@ def buffer_control_mode_opt_texts(self) -> str: @property def is_quiet_value(self) -> Optional[str]: """Get is quiet value""" - return self._get_item_by_id( - DeviceProperties.IS_QUIET, PropertyType.VALUE - ) + return self._get_item_by_id(DeviceProperties.IS_QUIET, PropertyType.VALUE) @property def ch_flow_setpoint_temp_value(self) -> str: @@ -390,7 +394,9 @@ def is_flame_on_value(self) -> bool: @property def is_heating_pump_on_value(self) -> bool: """Get is heating pump on value""" - return self._get_item_by_id(DeviceProperties.IS_HEATING_PUMP_ON, PropertyType.VALUE) + return self._get_item_by_id( + DeviceProperties.IS_HEATING_PUMP_ON, PropertyType.VALUE + ) @property def holiday_mode_value(self) -> bool: @@ -399,16 +405,12 @@ def holiday_mode_value(self) -> bool: def get_zone_mode(self, zone: int) -> ZoneMode: """Get zone mode on value""" - zone_mode = self._get_item_by_id( - ThermostatProperties.ZONE_MODE, PropertyType.VALUE, zone - ) - - if zone_mode is None: - return ZoneMode.UNDEFINED - return ZoneMode( self._get_item_by_id( - ThermostatProperties.ZONE_MODE, PropertyType.VALUE, zone + ThermostatProperties.ZONE_MODE, + PropertyType.VALUE, + zone, + ZoneMode.UNDEFINED, ) ) @@ -420,16 +422,15 @@ def get_zone_mode_options(self, zone: int) -> list[int]: @property def plant_mode(self) -> PlantMode: - """Get plant mode on value""" - plant_mode = self._get_item_by_id( - DeviceProperties.PLANT_MODE, PropertyType.VALUE + """Get plant mode value""" + return PlantMode( + self._get_item_by_id( + DeviceProperties.PLANT_MODE, + PropertyType.VALUE, + default=PlantMode.UNDEFINED, + ) ) - if plant_mode is None: - return PlantMode.UNDEFINED - - return PlantMode(plant_mode) - @property def plant_mode_options(self) -> list[int]: """Get plant mode on options""" @@ -455,22 +456,30 @@ def plant_mode_text(self) -> str: @property def signal_strength_value(self) -> Any: """Get signal strength value""" - return self._get_menu_item_by_id(MenuItemNames.SIGNAL_STRENGTH, PropertyType.VALUE) + return self._get_menu_item_by_id( + MenuItemNames.SIGNAL_STRENGTH.value, PropertyType.VALUE + ) @property def signal_strength_unit(self) -> Any: """Get signal strength unit""" - return self._get_menu_item_by_id(MenuItemNames.SIGNAL_STRENGTH, PropertyType.UNIT) + return self._get_menu_item_by_id( + MenuItemNames.SIGNAL_STRENGTH.value, PropertyType.UNIT + ) @property def ch_return_temp_value(self) -> Any: """Get ch return temp value""" - return self._get_menu_item_by_id(MenuItemNames.CH_RETURN_TEMP, PropertyType.VALUE) + return self._get_menu_item_by_id( + MenuItemNames.CH_RETURN_TEMP.value, PropertyType.VALUE + ) @property def ch_return_temp_unit(self) -> Any: """Get ch return temp unit""" - return self._get_menu_item_by_id(MenuItemNames.CH_RETURN_TEMP, PropertyType.UNIT) + return self._get_menu_item_by_id( + MenuItemNames.CH_RETURN_TEMP.value, PropertyType.UNIT + ) def get_measured_temp_unit(self, zone: int) -> str: """Get zone measured temp unit""" @@ -599,22 +608,20 @@ def get_heating_flow_temp_decimals(self, zone: int) -> int: ) def _get_item_by_id( - self, item_id: str, item_value: str, zone_number: int = 0 + self, item_id: str, item_value: str, zone_number: int = 0, default: Any = None ) -> Any: """Get item attribute from data""" return next( ( item.get(item_value) - for item in self.data.get("items", list[dict[str, Any]]()) + for item in self.data.get("items", []) if item.get("id") == item_id and item.get(PropertyType.ZONE) == zone_number ), - None, + default, ) - def _get_menu_item_by_id( - self, menu_item_id: int, item_value: str - ) -> Any: + def _get_menu_item_by_id(self, menu_item_id: int, item_value: str) -> Any: """Get item attribute from data""" return next( ( @@ -644,7 +651,7 @@ def gas_type(self) -> Optional[str]: return None @staticmethod - def get_gas_types() -> list[Optional[str]]: + def get_gas_types() -> list[str]: """Get all gas types""" return [c.name for c in GasType] @@ -669,7 +676,7 @@ def currency(self) -> Optional[str]: return None @staticmethod - def get_currencies() -> list[Optional[str]]: + def get_currencies() -> list[str]: """Get all currency""" return [c.name for c in Currency] @@ -688,13 +695,15 @@ async def async_set_currency(self, selected: str): @property def gas_energy_unit(self) -> Optional[str]: """Get gas energy unit""" - gas_energy_unit = self.consumptions_settings.get(ConsumptionProperties.GAS_ENERGY_UNIT, None) + gas_energy_unit = self.consumptions_settings.get( + ConsumptionProperties.GAS_ENERGY_UNIT, None + ) if gas_energy_unit in list(GasEnergyUnit): return GasEnergyUnit(gas_energy_unit).name return None @staticmethod - def get_gas_energy_units() -> list[Optional[str]]: + def get_gas_energy_units() -> list[str]: """Get all gas energy unit""" return [c.name for c in GasEnergyUnit] @@ -862,9 +871,7 @@ async def async_set_buffer_control_mode(self, buffer_control_mode: str): def set_is_quiet(self, is_quiet: bool): """Set is quiet""" - self.set_item_by_id( - DeviceProperties.IS_QUIET, 1.0 if is_quiet else 0.0 - ) + self.set_item_by_id(DeviceProperties.IS_QUIET, 1.0 if is_quiet else 0.0) async def async_set_is_quiet(self, is_quiet: bool): """Async set is quiet""" @@ -886,7 +893,9 @@ def set_zone_mode(self, zone_mode: ZoneMode, zone: int): async def async_set_zone_mode(self, zone_mode: ZoneMode, zone: int): """Async set zone mode""" - await self.async_set_item_by_id(ThermostatProperties.ZONE_MODE, zone_mode.value, zone) + await self.async_set_item_by_id( + ThermostatProperties.ZONE_MODE, zone_mode.value, zone + ) def set_comfort_temp(self, temp: float, zone: int): """Set comfort temp""" @@ -1000,14 +1009,20 @@ def _calc_energy_account(self) -> dict[str, Any]: calculated_cooling_energy = 0 for sequence in self.consumptions_sequences: - if sequence['p'] == ConsumptionTimeInterval.LAST_MONTH.value: - if sequence['k'] == ConsumptionType.CENTRAL_COOLING_TOTAL_ENERGY.value: - calculated_cooling_energy = sum(sequence['v']) + if sequence["p"] == ConsumptionTimeInterval.LAST_MONTH.value: + if sequence["k"] == ConsumptionType.CENTRAL_COOLING_TOTAL_ENERGY.value: + calculated_cooling_energy = sum(sequence["v"]) - elif sequence['k'] == ConsumptionType.CENTRAL_HEATING_TOTAL_ENERGY.value: - calculated_heating_energy = sum(sequence['v']) + elif ( + sequence["k"] == ConsumptionType.CENTRAL_HEATING_TOTAL_ENERGY.value + ): + calculated_heating_energy = sum(sequence["v"]) - return {'LastMonth': [{'elect': calculated_heating_energy,'cool': calculated_cooling_energy}] } + return { + "LastMonth": [ + {"elect": calculated_heating_energy, "cool": calculated_cooling_energy} + ] + } def update_energy(self) -> None: """Update the device energy settings from the cloud""" @@ -1018,7 +1033,7 @@ def update_energy(self) -> None: # Last month consumption in kwh self.energy_account = self.api.get_energy_account(self.gw) - if not self.energy_account.get('LastMonth'): + if not self.energy_account.get("LastMonth"): self.energy_account = self._calc_energy_account() async def async_update_energy(self) -> None: @@ -1031,5 +1046,5 @@ async def async_update_energy(self) -> None: self.api.async_get_energy_account(self.gw), ) - if not self.energy_account.get('LastMonth'): + if not self.energy_account.get("LastMonth"): self.energy_account = self._calc_energy_account()