diff --git a/homeassistant/components/evohome/__init__.py b/homeassistant/components/evohome/__init__.py index 2a664986b74..33f7e3200e1 100644 --- a/homeassistant/components/evohome/__init__.py +++ b/homeassistant/components/evohome/__init__.py @@ -1,6 +1,7 @@ -"""Support for (EMEA/EU-based) Honeywell TCC climate systems. +"""Support for (EMEA/EU-based) Honeywell TCC systems. -Such systems include evohome, Round Thermostat, and others. +Such systems provide heating/cooling and DHW and include Evohome, Round Thermostat, and +others. """ from __future__ import annotations @@ -10,7 +11,7 @@ from datetime import datetime, timedelta from http import HTTPStatus import logging import re -from typing import Any +from typing import Any, Final import evohomeasync as ev1 from evohomeasync.schema import SZ_ID, SZ_SESSION_ID, SZ_TEMP @@ -58,21 +59,31 @@ from homeassistant.helpers.storage import Store from homeassistant.helpers.typing import ConfigType import homeassistant.util.dt as dt_util -from .const import DOMAIN, GWS, STORAGE_KEY, STORAGE_VER, TCS, UTC_OFFSET +from .const import ( + ACCESS_TOKEN, + ACCESS_TOKEN_EXPIRES, + ATTR_DURATION_DAYS, + ATTR_DURATION_HOURS, + ATTR_DURATION_UNTIL, + ATTR_SYSTEM_MODE, + ATTR_ZONE_TEMP, + CONF_LOCATION_IDX, + DOMAIN, + GWS, + REFRESH_TOKEN, + SCAN_INTERVAL_DEFAULT, + SCAN_INTERVAL_MINIMUM, + STORAGE_KEY, + STORAGE_VER, + TCS, + USER_DATA, + UTC_OFFSET, + EvoService, +) _LOGGER = logging.getLogger(__name__) -ACCESS_TOKEN = "access_token" -ACCESS_TOKEN_EXPIRES = "access_token_expires" -REFRESH_TOKEN = "refresh_token" -USER_DATA = "user_data" - -CONF_LOCATION_IDX = "location_idx" - -SCAN_INTERVAL_DEFAULT = timedelta(seconds=300) -SCAN_INTERVAL_MINIMUM = timedelta(seconds=60) - -CONFIG_SCHEMA = vol.Schema( +CONFIG_SCHEMA: Final = vol.Schema( { DOMAIN: vol.Schema( { @@ -88,22 +99,12 @@ CONFIG_SCHEMA = vol.Schema( extra=vol.ALLOW_EXTRA, ) -ATTR_SYSTEM_MODE = "mode" -ATTR_DURATION_DAYS = "period" -ATTR_DURATION_HOURS = "duration" +# system mode schemas are built dynamically when the services are regiatered -ATTR_ZONE_TEMP = "setpoint" -ATTR_DURATION_UNTIL = "duration" - -SVC_REFRESH_SYSTEM = "refresh_system" -SVC_SET_SYSTEM_MODE = "set_system_mode" -SVC_RESET_SYSTEM = "reset_system" -SVC_SET_ZONE_OVERRIDE = "set_zone_override" -SVC_RESET_ZONE_OVERRIDE = "clear_zone_override" - - -RESET_ZONE_OVERRIDE_SCHEMA = vol.Schema({vol.Required(ATTR_ENTITY_ID): cv.entity_id}) -SET_ZONE_OVERRIDE_SCHEMA = vol.Schema( +RESET_ZONE_OVERRIDE_SCHEMA: Final = vol.Schema( + {vol.Required(ATTR_ENTITY_ID): cv.entity_id} +) +SET_ZONE_OVERRIDE_SCHEMA: Final = vol.Schema( { vol.Required(ATTR_ENTITY_ID): cv.entity_id, vol.Required(ATTR_ZONE_TEMP): vol.All( @@ -114,7 +115,6 @@ SET_ZONE_OVERRIDE_SCHEMA = vol.Schema( ), } ) -# system mode schemas are built dynamically, below def _dt_local_to_aware(dt_naive: datetime) -> datetime: @@ -358,14 +358,14 @@ def setup_service_functions(hass: HomeAssistant, broker: EvoBroker) -> None: async_dispatcher_send(hass, DOMAIN, payload) - hass.services.async_register(DOMAIN, SVC_REFRESH_SYSTEM, force_refresh) + hass.services.async_register(DOMAIN, EvoService.REFRESH_SYSTEM, force_refresh) # Enumerate which operating modes are supported by this system modes = broker.config[SZ_ALLOWED_SYSTEM_MODES] # Not all systems support "AutoWithReset": register this handler only if required if [m[SZ_SYSTEM_MODE] for m in modes if m[SZ_SYSTEM_MODE] == SZ_AUTO_WITH_RESET]: - hass.services.async_register(DOMAIN, SVC_RESET_SYSTEM, set_system_mode) + hass.services.async_register(DOMAIN, EvoService.RESET_SYSTEM, set_system_mode) system_mode_schemas = [] modes = [m for m in modes if m[SZ_SYSTEM_MODE] != SZ_AUTO_WITH_RESET] @@ -409,7 +409,7 @@ def setup_service_functions(hass: HomeAssistant, broker: EvoBroker) -> None: if system_mode_schemas: hass.services.async_register( DOMAIN, - SVC_SET_SYSTEM_MODE, + EvoService.SET_SYSTEM_MODE, set_system_mode, schema=vol.Schema(vol.Any(*system_mode_schemas)), ) @@ -417,13 +417,13 @@ def setup_service_functions(hass: HomeAssistant, broker: EvoBroker) -> None: # The zone modes are consistent across all systems and use the same schema hass.services.async_register( DOMAIN, - SVC_RESET_ZONE_OVERRIDE, + EvoService.RESET_ZONE_OVERRIDE, set_zone_override, schema=RESET_ZONE_OVERRIDE_SCHEMA, ) hass.services.async_register( DOMAIN, - SVC_SET_ZONE_OVERRIDE, + EvoService.SET_ZONE_OVERRIDE, set_zone_override, schema=SET_ZONE_OVERRIDE_SCHEMA, ) @@ -612,7 +612,10 @@ class EvoDevice(Entity): return if payload["unique_id"] != self._attr_unique_id: return - if payload["service"] in (SVC_SET_ZONE_OVERRIDE, SVC_RESET_ZONE_OVERRIDE): + if payload["service"] in ( + EvoService.SET_ZONE_OVERRIDE, + EvoService.RESET_ZONE_OVERRIDE, + ): await self.async_zone_svc_request(payload["service"], payload["data"]) return await self.async_tcs_svc_request(payload["service"], payload["data"]) diff --git a/homeassistant/components/evohome/climate.py b/homeassistant/components/evohome/climate.py index 2d462b5c525..8b3e8a46e2c 100644 --- a/homeassistant/components/evohome/climate.py +++ b/homeassistant/components/evohome/climate.py @@ -1,4 +1,4 @@ -"""Support for Climate devices of (EMEA/EU-based) Honeywell TCC systems.""" +"""Support for Climate entities of the Evohome integration.""" from __future__ import annotations @@ -37,19 +37,14 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType import homeassistant.util.dt as dt_util -from . import ( +from . import EvoChild, EvoDevice +from .const import ( ATTR_DURATION_DAYS, ATTR_DURATION_HOURS, ATTR_DURATION_UNTIL, ATTR_SYSTEM_MODE, ATTR_ZONE_TEMP, CONF_LOCATION_IDX, - SVC_RESET_ZONE_OVERRIDE, - SVC_SET_SYSTEM_MODE, - EvoChild, - EvoDevice, -) -from .const import ( DOMAIN, EVO_AUTO, EVO_AUTOECO, @@ -61,6 +56,7 @@ from .const import ( EVO_PERMOVER, EVO_RESET, EVO_TEMPOVER, + EvoService, ) if TYPE_CHECKING: @@ -200,11 +196,11 @@ class EvoZone(EvoChild, EvoClimateEntity): async def async_zone_svc_request(self, service: str, data: dict[str, Any]) -> None: """Process a service request (setpoint override) for a zone.""" - if service == SVC_RESET_ZONE_OVERRIDE: + if service == EvoService.RESET_ZONE_OVERRIDE: await self._evo_broker.call_client_api(self._evo_device.reset_mode()) return - # otherwise it is SVC_SET_ZONE_OVERRIDE + # otherwise it is EvoService.SET_ZONE_OVERRIDE temperature = max(min(data[ATTR_ZONE_TEMP], self.max_temp), self.min_temp) if ATTR_DURATION_UNTIL in data: @@ -386,9 +382,9 @@ class EvoController(EvoClimateEntity): Data validation is not required, it will have been done upstream. """ - if service == SVC_SET_SYSTEM_MODE: + if service == EvoService.SET_SYSTEM_MODE: mode = data[ATTR_SYSTEM_MODE] - else: # otherwise it is SVC_RESET_SYSTEM + else: # otherwise it is EvoService.RESET_SYSTEM mode = EVO_RESET if ATTR_DURATION_DAYS in data: diff --git a/homeassistant/components/evohome/const.py b/homeassistant/components/evohome/const.py index 1347c1f797c..15949bc3c37 100644 --- a/homeassistant/components/evohome/const.py +++ b/homeassistant/components/evohome/const.py @@ -1,26 +1,60 @@ -"""Support for (EMEA/EU-based) Honeywell TCC climate systems.""" +"""The constants of the Evohome integration.""" -DOMAIN = "evohome" +from __future__ import annotations -STORAGE_VER = 1 -STORAGE_KEY = DOMAIN +from datetime import timedelta +from enum import StrEnum, unique +from typing import Final -# The Parent's (i.e. TCS, Controller's) operating mode is one of: -EVO_RESET = "AutoWithReset" -EVO_AUTO = "Auto" -EVO_AUTOECO = "AutoWithEco" -EVO_AWAY = "Away" -EVO_DAYOFF = "DayOff" -EVO_CUSTOM = "Custom" -EVO_HEATOFF = "HeatingOff" +DOMAIN: Final = "evohome" -# The Children's operating mode is one of: -EVO_FOLLOW = "FollowSchedule" # the operating mode is 'inherited' from the TCS -EVO_TEMPOVER = "TemporaryOverride" -EVO_PERMOVER = "PermanentOverride" +STORAGE_VER: Final = 1 +STORAGE_KEY: Final = DOMAIN -# These are used only to help prevent E501 (line too long) violations -GWS = "gateways" -TCS = "temperatureControlSystems" +# The Parent's (i.e. TCS, Controller) operating mode is one of: +EVO_RESET: Final = "AutoWithReset" +EVO_AUTO: Final = "Auto" +EVO_AUTOECO: Final = "AutoWithEco" +EVO_AWAY: Final = "Away" +EVO_DAYOFF: Final = "DayOff" +EVO_CUSTOM: Final = "Custom" +EVO_HEATOFF: Final = "HeatingOff" -UTC_OFFSET = "currentOffsetMinutes" +# The Children's (i.e. Dhw, Zone) operating mode is one of: +EVO_FOLLOW: Final = "FollowSchedule" # the operating mode is 'inherited' from the TCS +EVO_TEMPOVER: Final = "TemporaryOverride" +EVO_PERMOVER: Final = "PermanentOverride" + +# These two are used only to help prevent E501 (line too long) violations +GWS: Final = "gateways" +TCS: Final = "temperatureControlSystems" + +UTC_OFFSET: Final = "currentOffsetMinutes" + +CONF_LOCATION_IDX: Final = "location_idx" + +ACCESS_TOKEN: Final = "access_token" +ACCESS_TOKEN_EXPIRES: Final = "access_token_expires" +REFRESH_TOKEN: Final = "refresh_token" +USER_DATA: Final = "user_data" + +SCAN_INTERVAL_DEFAULT: Final = timedelta(seconds=300) +SCAN_INTERVAL_MINIMUM: Final = timedelta(seconds=60) + +ATTR_SYSTEM_MODE: Final = "mode" +ATTR_DURATION_DAYS: Final = "period" +ATTR_DURATION_HOURS: Final = "duration" + +ATTR_ZONE_TEMP: Final = "setpoint" +ATTR_DURATION_UNTIL: Final = "duration" + + +@unique +class EvoService(StrEnum): + """The Evohome services.""" + + REFRESH_SYSTEM: Final = "refresh_system" + SET_SYSTEM_MODE: Final = "set_system_mode" + RESET_SYSTEM: Final = "reset_system" + SET_ZONE_OVERRIDE: Final = "set_zone_override" + RESET_ZONE_OVERRIDE: Final = "clear_zone_override" diff --git a/homeassistant/components/evohome/water_heater.py b/homeassistant/components/evohome/water_heater.py index 26be4b47a36..66ba7f46a70 100644 --- a/homeassistant/components/evohome/water_heater.py +++ b/homeassistant/components/evohome/water_heater.py @@ -1,4 +1,4 @@ -"""Support for WaterHeater devices of (EMEA/EU) Honeywell TCC systems.""" +"""Support for WaterHeater entities of the Evohome integration.""" from __future__ import annotations