mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 13:47:35 +00:00
Tweak evohome migration (#25281)
* Initial commit add hvac_action to zones, remove target_temp from controller fix incorrect hvac_action de-lint Initial commit de-lint & minor refactor tweak docstrings, and type hints tweak docstrings * refactor setpoints property * tweak docstring * tweak docstring * avoid a unnecessary I/O * avoid unnecessary I/O * refactor schedule/setpoints * remove type hint * remove type hint 2 * tweak code * delint type hints * fix regression
This commit is contained in:
parent
11c74cd0d7
commit
bf37cc8371
@ -22,6 +22,7 @@ from homeassistant.helpers.dispatcher import (
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.event import (
|
||||
async_track_point_in_utc_time, track_time_interval)
|
||||
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
||||
from homeassistant.util.dt import parse_datetime, utcnow
|
||||
|
||||
from .const import DOMAIN, STORAGE_VERSION, STORAGE_KEY, GWS, TCS
|
||||
@ -101,7 +102,7 @@ def _handle_exception(err) -> bool:
|
||||
raise # we don't expect/handle any other HTTPErrors
|
||||
|
||||
|
||||
def setup(hass, hass_config) -> bool:
|
||||
def setup(hass: HomeAssistantType, hass_config: ConfigType) -> bool:
|
||||
"""Create a (EMEA/EU-based) Honeywell evohome system."""
|
||||
broker = EvoBroker(hass, hass_config[DOMAIN])
|
||||
if not broker.init_client():
|
||||
@ -270,29 +271,29 @@ class EvoDevice(Entity):
|
||||
self._state_attributes = []
|
||||
|
||||
self._supported_features = None
|
||||
self._setpoints = None
|
||||
self._schedule = {}
|
||||
|
||||
@callback
|
||||
def _refresh(self, packet):
|
||||
if packet['signal'] == 'refresh':
|
||||
self.async_schedule_update_ha_state(force_refresh=True)
|
||||
|
||||
def get_setpoints(self) -> Optional[Dict[str, Any]]:
|
||||
"""Return the current/next scheduled switchpoints.
|
||||
@property
|
||||
def setpoints(self) -> Dict[str, Any]:
|
||||
"""Return the current/next setpoints from the schedule.
|
||||
|
||||
Only Zones & DHW controllers (but not the TCS) have schedules.
|
||||
Only Zones & DHW controllers (but not the TCS) can have schedules.
|
||||
"""
|
||||
switchpoints = {}
|
||||
schedule = self._evo_device.schedule()
|
||||
if not self._schedule['DailySchedules']:
|
||||
return {}
|
||||
|
||||
if not schedule['DailySchedules']:
|
||||
return None
|
||||
switchpoints = {}
|
||||
|
||||
day_time = datetime.now()
|
||||
day_of_week = int(day_time.strftime('%w')) # 0 is Sunday
|
||||
|
||||
# Iterate today's switchpoints until past the current time of day...
|
||||
day = schedule['DailySchedules'][day_of_week]
|
||||
day = self._schedule['DailySchedules'][day_of_week]
|
||||
sp_idx = -1 # last switchpoint of the day before
|
||||
for i, tmp in enumerate(day['Switchpoints']):
|
||||
if day_time.strftime('%H:%M:%S') > tmp['TimeOfDay']:
|
||||
@ -311,7 +312,7 @@ class EvoDevice(Entity):
|
||||
spt = switchpoints[key] = {}
|
||||
|
||||
sp_date = (day_time + timedelta(days=offset)).strftime('%Y-%m-%d')
|
||||
day = schedule['DailySchedules'][(day_of_week + offset) % 7]
|
||||
day = self._schedule['DailySchedules'][(day_of_week + offset) % 7]
|
||||
switchpoint = day['Switchpoints'][idx]
|
||||
|
||||
dt_naive = datetime.strptime(
|
||||
@ -345,7 +346,7 @@ class EvoDevice(Entity):
|
||||
status[attr] = getattr(self._evo_device, attr)
|
||||
|
||||
if 'setpoints' in self._state_attributes:
|
||||
status['setpoints'] = self._setpoints
|
||||
status['setpoints'] = self.setpoints
|
||||
|
||||
return {'status': status}
|
||||
|
||||
@ -373,6 +374,12 @@ class EvoDevice(Entity):
|
||||
"""Return the temperature unit to use in the frontend UI."""
|
||||
return TEMP_CELSIUS
|
||||
|
||||
def _update_schedule(self) -> None:
|
||||
"""Get the latest state data."""
|
||||
if not self._schedule.get('DailySchedules') or \
|
||||
parse_datetime(self.setpoints['next']['from']) < utcnow():
|
||||
self._schedule = self._evo_device.schedule()
|
||||
|
||||
def update(self) -> None:
|
||||
"""Get the latest state data."""
|
||||
self._setpoints = self.get_setpoints()
|
||||
self._update_schedule()
|
||||
|
@ -8,16 +8,17 @@ import evohomeclient2
|
||||
|
||||
from homeassistant.components.climate import ClimateDevice
|
||||
from homeassistant.components.climate.const import (
|
||||
HVAC_MODE_HEAT, HVAC_MODE_AUTO, HVAC_MODE_OFF,
|
||||
CURRENT_HVAC_HEAT, CURRENT_HVAC_IDLE, CURRENT_HVAC_OFF,
|
||||
HVAC_MODE_AUTO, HVAC_MODE_HEAT, HVAC_MODE_OFF,
|
||||
PRESET_AWAY, PRESET_ECO, PRESET_HOME, PRESET_NONE,
|
||||
SUPPORT_TARGET_TEMPERATURE, SUPPORT_PRESET_MODE)
|
||||
from homeassistant.const import PRECISION_TENTHS
|
||||
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
||||
from homeassistant.util.dt import parse_datetime
|
||||
|
||||
from . import CONF_LOCATION_IDX, _handle_exception, EvoDevice
|
||||
from .const import (
|
||||
DOMAIN, EVO_RESET, EVO_AUTO, EVO_AUTOECO, EVO_AWAY, EVO_DAYOFF, EVO_CUSTOM,
|
||||
DOMAIN, EVO_RESET, EVO_AUTO, EVO_AUTOECO, EVO_AWAY, EVO_CUSTOM, EVO_DAYOFF,
|
||||
EVO_HEATOFF, EVO_FOLLOW, EVO_TEMPOVER, EVO_PERMOVER)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -30,14 +31,15 @@ HA_HVAC_TO_TCS = {
|
||||
HVAC_MODE_HEAT: EVO_AUTO,
|
||||
}
|
||||
|
||||
HA_PRESET_TO_TCS = {
|
||||
PRESET_AWAY: EVO_AWAY,
|
||||
PRESET_CUSTOM: EVO_CUSTOM,
|
||||
PRESET_ECO: EVO_AUTOECO,
|
||||
PRESET_HOME: EVO_DAYOFF,
|
||||
PRESET_RESET: EVO_RESET,
|
||||
}
|
||||
TCS_PRESET_TO_HA = {v: k for k, v in HA_PRESET_TO_TCS.items()}
|
||||
TCS_PRESET_TO_HA = {
|
||||
EVO_AWAY: PRESET_AWAY,
|
||||
EVO_CUSTOM: PRESET_CUSTOM,
|
||||
EVO_AUTOECO: PRESET_ECO,
|
||||
EVO_DAYOFF: PRESET_HOME,
|
||||
EVO_RESET: PRESET_RESET,
|
||||
} # EVO_AUTO: None,
|
||||
|
||||
HA_PRESET_TO_TCS = {v: k for k, v in TCS_PRESET_TO_HA.items()}
|
||||
|
||||
EVO_PRESET_TO_HA = {
|
||||
EVO_FOLLOW: PRESET_NONE,
|
||||
@ -47,8 +49,8 @@ EVO_PRESET_TO_HA = {
|
||||
HA_PRESET_TO_EVO = {v: k for k, v in EVO_PRESET_TO_HA.items()}
|
||||
|
||||
|
||||
def setup_platform(hass, hass_config, add_entities,
|
||||
discovery_info=None) -> None:
|
||||
def setup_platform(hass: HomeAssistantType, hass_config: ConfigType,
|
||||
add_entities, discovery_info=None) -> None:
|
||||
"""Create the evohome Controller, and its Zones, if any."""
|
||||
broker = hass.data[DOMAIN]['broker']
|
||||
loc_idx = broker.params[CONF_LOCATION_IDX]
|
||||
@ -102,21 +104,22 @@ class EvoClimateDevice(EvoDevice, ClimateDevice):
|
||||
_handle_exception(err)
|
||||
|
||||
def _set_zone_mode(self, op_mode: str) -> None:
|
||||
"""Set the Zone to one of its native EVO_* operating modes.
|
||||
"""Set a Zone to one of its native EVO_* operating modes.
|
||||
|
||||
NB: evohome Zones 'inherit' their operating mode from the Controller.
|
||||
Zones inherit their _effective_ operating mode from the Controller.
|
||||
|
||||
Usually, Zones are in 'FollowSchedule' mode, where their setpoints are
|
||||
a function of their schedule, and the Controller's operating_mode, e.g.
|
||||
Economy mode is their scheduled setpoint less (usually) 3C.
|
||||
a function of their own schedule and the Controller's operating mode,
|
||||
e.g. 'AutoWithEco' mode means their setpoint is (by default) 3C less
|
||||
than scheduled.
|
||||
|
||||
However, Zones can override these setpoints, either for a specified
|
||||
period of time, 'TemporaryOverride', after which they will revert back
|
||||
to 'FollowSchedule' mode, or indefinitely, 'PermanentOverride'.
|
||||
However, Zones can _override_ these setpoints, either indefinitely,
|
||||
'PermanentOverride' mode, or for a period of time, 'TemporaryOverride',
|
||||
after which they will revert back to 'FollowSchedule'.
|
||||
|
||||
Some of the Controller's operating_mode are 'forced' upon the Zone,
|
||||
regardless of its override state, e.g. 'HeatingOff' (Zones to min_temp)
|
||||
and 'Away' (Zones to 12C).
|
||||
Finally, some of the Controller's operating modes are _forced_ upon the
|
||||
Zones, regardless of any override mode, e.g. 'HeatingOff', Zones to
|
||||
(by default) 5C, and 'Away', Zones to (by default) 12C.
|
||||
"""
|
||||
if op_mode == EVO_FOLLOW:
|
||||
try:
|
||||
@ -129,10 +132,10 @@ class EvoClimateDevice(EvoDevice, ClimateDevice):
|
||||
temperature = self._evo_device.setpointStatus['targetHeatTemperature']
|
||||
until = None # EVO_PERMOVER
|
||||
|
||||
if op_mode == EVO_TEMPOVER:
|
||||
self._setpoints = self.get_setpoints()
|
||||
if self._setpoints:
|
||||
until = parse_datetime(self._setpoints['next']['from'])
|
||||
if op_mode == EVO_TEMPOVER and self._schedule['DailySchedules']:
|
||||
self._update_schedule()
|
||||
if self._schedule['DailySchedules']:
|
||||
until = parse_datetime(self.setpoints['next']['from'])
|
||||
|
||||
self._set_temperature(temperature, until=until)
|
||||
|
||||
@ -147,7 +150,7 @@ class EvoClimateDevice(EvoDevice, ClimateDevice):
|
||||
@property
|
||||
def hvac_modes(self) -> List[str]:
|
||||
"""Return the list of available hvac operation modes."""
|
||||
return [HVAC_MODE_OFF, HVAC_MODE_HEAT]
|
||||
return list(HA_HVAC_TO_TCS)
|
||||
|
||||
@property
|
||||
def preset_modes(self) -> Optional[List[str]]:
|
||||
|
@ -75,10 +75,10 @@ class EvoDHW(EvoDevice, WaterHeaterDevice):
|
||||
state = '' if op_mode == EVO_FOLLOW else HA_STATE_TO_EVO[STATE_OFF]
|
||||
until = None # EVO_FOLLOW, EVO_PERMOVER
|
||||
|
||||
if op_mode == EVO_TEMPOVER:
|
||||
self._setpoints = self.get_setpoints()
|
||||
if self._setpoints:
|
||||
until = parse_datetime(self._setpoints['next']['from'])
|
||||
if op_mode == EVO_TEMPOVER and self._schedule['DailySchedules']:
|
||||
self._update_schedule()
|
||||
if self._schedule['DailySchedules']:
|
||||
until = parse_datetime(self.setpoints['next']['from'])
|
||||
until = until.strftime(EVO_STRFTIME)
|
||||
|
||||
data = {'Mode': op_mode, 'State': state, 'UntilTime': until}
|
||||
|
Loading…
x
Reference in New Issue
Block a user