Skip to content

Commit

Permalink
Merge pull request #25452 from home-assistant/rc
Browse files Browse the repository at this point in the history
0.96.4
  • Loading branch information
balloob authored Jul 24, 2019
2 parents a652a4d + 065a5c5 commit 8a2fdb5
Show file tree
Hide file tree
Showing 15 changed files with 190 additions and 99 deletions.
29 changes: 16 additions & 13 deletions homeassistant/components/daikin/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@
SUPPORT_SWING_MODE,
HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_COOL, HVAC_MODE_HEAT_COOL,
HVAC_MODE_DRY, HVAC_MODE_FAN_ONLY,
PRESET_AWAY, PRESET_HOME,
PRESET_AWAY, PRESET_NONE,
ATTR_CURRENT_TEMPERATURE, ATTR_FAN_MODE,
ATTR_HVAC_MODE, ATTR_SWING_MODE,
ATTR_PRESET_MODE)
import homeassistant.helpers.config_validation as cv

from . import DOMAIN as DAIKIN_DOMAIN
from .const import (
ATTR_INSIDE_TEMPERATURE, ATTR_OUTSIDE_TEMPERATURE, ATTR_TARGET_TEMPERATURE)
ATTR_INSIDE_TEMPERATURE, ATTR_OUTSIDE_TEMPERATURE, ATTR_STATE_OFF,
ATTR_STATE_ON, ATTR_TARGET_TEMPERATURE)

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -49,7 +50,7 @@

HA_PRESET_TO_DAIKIN = {
PRESET_AWAY: 'on',
PRESET_HOME: 'off'
PRESET_NONE: 'off'
}

HA_ATTR_TO_DAIKIN = {
Expand Down Expand Up @@ -142,9 +143,10 @@ def get(self, key):
ha_mode = DAIKIN_TO_HA_STATE.get(daikin_mode)
value = ha_mode
elif key == ATTR_PRESET_MODE:
away = (self._api.device.represent(daikin_attr)[1]
!= HA_STATE_TO_DAIKIN[HVAC_MODE_OFF])
value = PRESET_AWAY if away else PRESET_HOME
if self._api.device.represent(
daikin_attr)[1] == HA_PRESET_TO_DAIKIN[PRESET_AWAY]:
return PRESET_AWAY
return PRESET_NONE

if value is None:
_LOGGER.error("Invalid value requested for key %s", key)
Expand All @@ -164,7 +166,7 @@ async def _set(self, settings):
values = {}

for attr in [ATTR_TEMPERATURE, ATTR_FAN_MODE, ATTR_SWING_MODE,
ATTR_HVAC_MODE, ATTR_PRESET_MODE]:
ATTR_HVAC_MODE]:
value = settings.get(attr)
if value is None:
continue
Expand All @@ -173,8 +175,6 @@ async def _set(self, settings):
if daikin_attr is not None:
if attr == ATTR_HVAC_MODE:
values[daikin_attr] = HA_STATE_TO_DAIKIN[value]
elif attr == ATTR_PRESET_MODE:
values[daikin_attr] = HA_PRESET_TO_DAIKIN[value]
elif value in self._list[attr]:
values[daikin_attr] = value.lower()
else:
Expand Down Expand Up @@ -273,16 +273,19 @@ def swing_modes(self):

@property
def preset_mode(self):
"""Return the fan setting."""
"""Return the preset_mode."""
return self.get(ATTR_PRESET_MODE)

async def async_set_preset_mode(self, preset_mode):
"""Set new target temperature."""
await self._set({ATTR_PRESET_MODE: preset_mode})
"""Set preset mode."""
if preset_mode == PRESET_AWAY:
await self._api.device.set_holiday(ATTR_STATE_ON)
else:
await self._api.device.set_holiday(ATTR_STATE_OFF)

@property
def preset_modes(self):
"""List of available swing modes."""
"""List of available preset modes."""
return list(HA_PRESET_TO_DAIKIN)

async def async_update(self):
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/daikin/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
ATTR_INSIDE_TEMPERATURE = 'inside_temperature'
ATTR_OUTSIDE_TEMPERATURE = 'outside_temperature'

ATTR_STATE_ON = 'on'
ATTR_STATE_OFF = 'off'

SENSOR_TYPE_TEMPERATURE = 'temperature'

SENSOR_TYPES = {
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/daikin/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/components/daikin",
"requirements": [
"pydaikin==1.4.6"
"pydaikin==1.5.1"
],
"dependencies": [],
"codeowners": [
Expand Down
33 changes: 20 additions & 13 deletions homeassistant/components/evohome/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
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
Expand Down Expand Up @@ -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():
Expand Down Expand Up @@ -270,29 +271,29 @@ def __init__(self, evo_broker, evo_device) -> None:
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']:
Expand All @@ -311,7 +312,7 @@ def get_setpoints(self) -> Optional[Dict[str, Any]]:
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(
Expand Down Expand Up @@ -345,7 +346,7 @@ def device_state_attributes(self) -> Dict[str, Any]:
status[attr] = getattr(self._evo_device, attr)

if 'setpoints' in self._state_attributes:
status['setpoints'] = self._setpoints
status['setpoints'] = self.setpoints

return {'status': status}

Expand Down Expand Up @@ -373,6 +374,12 @@ def temperature_unit(self) -> str:
"""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()
63 changes: 33 additions & 30 deletions homeassistant/components/evohome/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@

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__)
Expand All @@ -30,14 +31,15 @@
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,
Expand All @@ -47,8 +49,8 @@
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]
Expand Down Expand Up @@ -102,21 +104,22 @@ def _set_temperature(self, temperature: float,
_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:
Expand All @@ -129,10 +132,10 @@ def _set_zone_mode(self, op_mode: str) -> None:
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)

Expand All @@ -147,7 +150,7 @@ def _set_tcs_mode(self, op_mode: str) -> None:
@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]]:
Expand Down Expand Up @@ -190,9 +193,9 @@ def hvac_action(self) -> Optional[str]:
return CURRENT_HVAC_OFF
if self.target_temperature <= self.min_temp:
return CURRENT_HVAC_OFF
if self.target_temperature <= self.current_temperature:
return CURRENT_HVAC_HEAT
return CURRENT_HVAC_IDLE
if self.target_temperature < self.current_temperature:
return CURRENT_HVAC_IDLE
return CURRENT_HVAC_HEAT

@property
def current_temperature(self) -> Optional[float]:
Expand Down
8 changes: 4 additions & 4 deletions homeassistant/components/evohome/water_heater.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ def set_operation_mode(self, operation_mode: str) -> None:
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}
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/frontend/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "Home Assistant Frontend",
"documentation": "https://www.home-assistant.io/components/frontend",
"requirements": [
"home-assistant-frontend==20190721.0"
"home-assistant-frontend==20190721.1"
],
"dependencies": [
"api",
Expand Down
Loading

0 comments on commit 8a2fdb5

Please sign in to comment.