mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
commit
8a2fdb5045
@ -12,7 +12,7 @@ from homeassistant.components.climate.const import (
|
||||
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)
|
||||
@ -20,7 +20,8 @@ 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__)
|
||||
|
||||
@ -49,7 +50,7 @@ DAIKIN_TO_HA_STATE = {
|
||||
|
||||
HA_PRESET_TO_DAIKIN = {
|
||||
PRESET_AWAY: 'on',
|
||||
PRESET_HOME: 'off'
|
||||
PRESET_NONE: 'off'
|
||||
}
|
||||
|
||||
HA_ATTR_TO_DAIKIN = {
|
||||
@ -142,9 +143,10 @@ class DaikinClimate(ClimateDevice):
|
||||
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)
|
||||
@ -164,7 +166,7 @@ class DaikinClimate(ClimateDevice):
|
||||
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
|
||||
@ -173,8 +175,6 @@ class DaikinClimate(ClimateDevice):
|
||||
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:
|
||||
@ -273,16 +273,19 @@ class DaikinClimate(ClimateDevice):
|
||||
|
||||
@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):
|
||||
|
@ -5,6 +5,9 @@ ATTR_TARGET_TEMPERATURE = 'target_temperature'
|
||||
ATTR_INSIDE_TEMPERATURE = 'inside_temperature'
|
||||
ATTR_OUTSIDE_TEMPERATURE = 'outside_temperature'
|
||||
|
||||
ATTR_STATE_ON = 'on'
|
||||
ATTR_STATE_OFF = 'off'
|
||||
|
||||
SENSOR_TYPE_TEMPERATURE = 'temperature'
|
||||
|
||||
SENSOR_TYPES = {
|
||||
|
@ -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": [
|
||||
|
@ -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]]:
|
||||
@ -190,9 +193,9 @@ class EvoZone(EvoClimateDevice):
|
||||
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]:
|
||||
|
@ -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}
|
||||
|
@ -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",
|
||||
|
@ -12,8 +12,9 @@ from homeassistant.components.climate.const import (
|
||||
ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW,
|
||||
FAN_AUTO, FAN_DIFFUSE, FAN_ON,
|
||||
SUPPORT_AUX_HEAT, SUPPORT_FAN_MODE, SUPPORT_PRESET_MODE,
|
||||
SUPPORT_TARGET_HUMIDITY, SUPPORT_TARGET_TEMPERATURE_RANGE,
|
||||
CURRENT_HVAC_COOL, CURRENT_HVAC_HEAT, CURRENT_HVAC_IDLE, CURRENT_HVAC_OFF,
|
||||
SUPPORT_TARGET_HUMIDITY, SUPPORT_TARGET_TEMPERATURE,
|
||||
SUPPORT_TARGET_TEMPERATURE_RANGE,
|
||||
CURRENT_HVAC_COOL, CURRENT_HVAC_HEAT, CURRENT_HVAC_IDLE, CURRENT_HVAC_FAN,
|
||||
HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_COOL, HVAC_MODE_HEAT_COOL,
|
||||
PRESET_AWAY, PRESET_NONE,
|
||||
)
|
||||
@ -58,8 +59,8 @@ HW_MODE_TO_HVAC_MODE = {
|
||||
'auto': HVAC_MODE_HEAT_COOL,
|
||||
}
|
||||
HW_MODE_TO_HA_HVAC_ACTION = {
|
||||
'off': CURRENT_HVAC_OFF,
|
||||
'fan': CURRENT_HVAC_IDLE,
|
||||
'off': CURRENT_HVAC_IDLE,
|
||||
'fan': CURRENT_HVAC_FAN,
|
||||
'heat': CURRENT_HVAC_HEAT,
|
||||
'cool': CURRENT_HVAC_COOL,
|
||||
}
|
||||
@ -126,31 +127,34 @@ class HoneywellUSThermostat(ClimateDevice):
|
||||
self._username = username
|
||||
self._password = password
|
||||
|
||||
self._supported_features = (SUPPORT_PRESET_MODE |
|
||||
SUPPORT_TARGET_TEMPERATURE_RANGE)
|
||||
_LOGGER.debug("latestData = %s ", device._data) # noqa; pylint: disable=protected-access
|
||||
|
||||
# pylint: disable=protected-access
|
||||
_LOGGER.debug("uiData = %s ", device._data['uiData'])
|
||||
|
||||
# not all honeywell HVACs upport all modes
|
||||
# not all honeywell HVACs support all modes
|
||||
mappings = [v for k, v in HVAC_MODE_TO_HW_MODE.items()
|
||||
if k in device._data['uiData']]
|
||||
if device.raw_ui_data[k]]
|
||||
self._hvac_mode_map = {k: v for d in mappings for k, v in d.items()}
|
||||
|
||||
if device._data['canControlHumidification']:
|
||||
self._supported_features = \
|
||||
SUPPORT_PRESET_MODE | \
|
||||
SUPPORT_TARGET_TEMPERATURE | \
|
||||
SUPPORT_TARGET_TEMPERATURE_RANGE
|
||||
|
||||
if device._data['canControlHumidification']: # noqa; pylint: disable=protected-access
|
||||
self._supported_features |= SUPPORT_TARGET_HUMIDITY
|
||||
if device._data['uiData']['SwitchEmergencyHeatAllowed']:
|
||||
|
||||
if device.raw_ui_data['SwitchEmergencyHeatAllowed']:
|
||||
self._supported_features |= SUPPORT_AUX_HEAT
|
||||
|
||||
if not device._data['hasFan']:
|
||||
if not device._data['hasFan']: # pylint: disable=protected-access
|
||||
return
|
||||
|
||||
self._supported_features |= SUPPORT_FAN_MODE
|
||||
# not all honeywell fans support all modes
|
||||
mappings = [v for k, v in FAN_MODE_TO_HW.items()
|
||||
if k in device._data['fanData']]
|
||||
if device.raw_fan_data[k]]
|
||||
self._fan_mode_map = {k: v for d in mappings for k, v in d.items()}
|
||||
|
||||
self._supported_features |= SUPPORT_FAN_MODE
|
||||
|
||||
@property
|
||||
def name(self) -> Optional[str]:
|
||||
"""Return the name of the honeywell, if any."""
|
||||
@ -159,11 +163,11 @@ class HoneywellUSThermostat(ClimateDevice):
|
||||
@property
|
||||
def device_state_attributes(self) -> Dict[str, Any]:
|
||||
"""Return the device specific state attributes."""
|
||||
# pylint: disable=protected-access
|
||||
data = {}
|
||||
if self._device._data['hasFan']:
|
||||
data[ATTR_FAN_ACTION] = \
|
||||
'running' if self._device.fan_running else 'idle'
|
||||
data[ATTR_FAN_ACTION] = \
|
||||
'running' if self._device.fan_running else 'idle'
|
||||
if self._device.raw_dr_data:
|
||||
data['dr_phase'] = self._device.raw_dr_data.get('Phase')
|
||||
return data
|
||||
|
||||
@property
|
||||
@ -171,6 +175,24 @@ class HoneywellUSThermostat(ClimateDevice):
|
||||
"""Return the list of supported features."""
|
||||
return self._supported_features
|
||||
|
||||
@property
|
||||
def min_temp(self) -> float:
|
||||
"""Return the minimum temperature."""
|
||||
if self.hvac_mode in [HVAC_MODE_COOL, HVAC_MODE_HEAT_COOL]:
|
||||
return self._device.raw_ui_data['CoolLowerSetptLimit']
|
||||
if self.hvac_mode == HVAC_MODE_HEAT:
|
||||
return self._device.raw_ui_data['HeatLowerSetptLimit']
|
||||
return None
|
||||
|
||||
@property
|
||||
def max_temp(self) -> float:
|
||||
"""Return the maximum temperature."""
|
||||
if self.hvac_mode == HVAC_MODE_COOL:
|
||||
return self._device.raw_ui_data['CoolUpperSetptLimit']
|
||||
if self.hvac_mode in [HVAC_MODE_HEAT, HVAC_MODE_HEAT_COOL]:
|
||||
return self._device.raw_ui_data['HeatUpperSetptLimit']
|
||||
return None
|
||||
|
||||
@property
|
||||
def temperature_unit(self) -> str:
|
||||
"""Return the unit of measurement."""
|
||||
@ -195,6 +217,8 @@ class HoneywellUSThermostat(ClimateDevice):
|
||||
@property
|
||||
def hvac_action(self) -> Optional[str]:
|
||||
"""Return the current running hvac operation if supported."""
|
||||
if self.hvac_mode == HVAC_MODE_OFF:
|
||||
return None
|
||||
return HW_MODE_TO_HA_HVAC_ACTION[self._device.equipment_output_status]
|
||||
|
||||
@property
|
||||
@ -207,19 +231,23 @@ class HoneywellUSThermostat(ClimateDevice):
|
||||
"""Return the temperature we try to reach."""
|
||||
if self.hvac_mode == HVAC_MODE_COOL:
|
||||
return self._device.setpoint_cool
|
||||
if self.hvac_mode != HVAC_MODE_HEAT:
|
||||
if self.hvac_mode == HVAC_MODE_HEAT:
|
||||
return self._device.setpoint_heat
|
||||
return None
|
||||
|
||||
@property
|
||||
def target_temperature_high(self) -> Optional[float]:
|
||||
"""Return the highbound target temperature we try to reach."""
|
||||
return self._device.setpoint_cool
|
||||
if self.hvac_mode == HVAC_MODE_HEAT_COOL:
|
||||
return self._device.setpoint_cool
|
||||
return None
|
||||
|
||||
@property
|
||||
def target_temperature_low(self) -> Optional[float]:
|
||||
"""Return the lowbound target temperature we try to reach."""
|
||||
return self._device.setpoint_heat
|
||||
if self.hvac_mode == HVAC_MODE_HEAT_COOL:
|
||||
return self._device.setpoint_heat
|
||||
return None
|
||||
|
||||
@property
|
||||
def preset_mode(self) -> Optional[str]:
|
||||
@ -348,7 +376,10 @@ class HoneywellUSThermostat(ClimateDevice):
|
||||
|
||||
def turn_aux_heat_off(self) -> None:
|
||||
"""Turn auxiliary heater off."""
|
||||
self._device.system_mode = 'auto'
|
||||
if HVAC_MODE_HEAT in self.hvac_modes:
|
||||
self.set_hvac_mode(HVAC_MODE_HEAT)
|
||||
else:
|
||||
self.set_hvac_mode(HVAC_MODE_OFF)
|
||||
|
||||
def _retry(self) -> bool:
|
||||
"""Recreate a new somecomfort client.
|
||||
@ -396,3 +427,5 @@ class HoneywellUSThermostat(ClimateDevice):
|
||||
raise exp
|
||||
_LOGGER.error(
|
||||
"SomeComfort update failed, Retrying - Error: %s", exp)
|
||||
|
||||
_LOGGER.debug("latestData = %s ", self._device._data) # noqa; pylint: disable=protected-access
|
||||
|
@ -484,13 +484,55 @@ class ThermostatData:
|
||||
.get("battery_level"))
|
||||
|
||||
if batterylevel:
|
||||
batterypct = interpolate(
|
||||
batterylevel, roomstatus["module_type"])
|
||||
if roomstatus.get("battery_level") is None:
|
||||
roomstatus["battery_level"] = batterylevel
|
||||
elif batterylevel < roomstatus["battery_level"]:
|
||||
roomstatus["battery_level"] = batterylevel
|
||||
roomstatus["battery_level"] = batterypct
|
||||
elif batterypct < roomstatus["battery_level"]:
|
||||
roomstatus["battery_level"] = batterypct
|
||||
self.room_status[room] = roomstatus
|
||||
except KeyError as err:
|
||||
_LOGGER.error("Update of room %s failed. Error: %s", room, err)
|
||||
self.away_temperature = self.homestatus.getAwaytemp(self.home)
|
||||
self.hg_temperature = self.homestatus.getHgtemp(self.home)
|
||||
self.setpoint_duration = self.homedata.setpoint_duration[self.home]
|
||||
|
||||
|
||||
def interpolate(batterylevel, module_type):
|
||||
"""Interpolate battery level depending on device type."""
|
||||
na_battery_levels = {
|
||||
NA_THERM: {
|
||||
'full': 4100,
|
||||
'high': 3600,
|
||||
'medium': 3300,
|
||||
'low': 3000,
|
||||
'empty': 2800},
|
||||
NA_VALVE: {
|
||||
'full': 3200,
|
||||
'high': 2700,
|
||||
'medium': 2400,
|
||||
'low': 2200,
|
||||
'empty': 2200},
|
||||
}
|
||||
|
||||
levels = sorted(na_battery_levels[module_type].values())
|
||||
steps = [20, 50, 80, 100]
|
||||
|
||||
na_battery_level = na_battery_levels[module_type]
|
||||
if batterylevel >= na_battery_level['full']:
|
||||
return 100
|
||||
if batterylevel >= na_battery_level['high']:
|
||||
i = 3
|
||||
elif batterylevel >= na_battery_level['medium']:
|
||||
i = 2
|
||||
elif batterylevel >= na_battery_level['low']:
|
||||
i = 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
pct = steps[i-1] + (
|
||||
(steps[i] - steps[i-1]) *
|
||||
(batterylevel - levels[i]) /
|
||||
(levels[i+1] - levels[i])
|
||||
)
|
||||
return int(pct)
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "Netatmo",
|
||||
"documentation": "https://www.home-assistant.io/components/netatmo",
|
||||
"requirements": [
|
||||
"pyatmo==2.1.1"
|
||||
"pyatmo==2.1.2"
|
||||
],
|
||||
"dependencies": [
|
||||
"webhook"
|
||||
|
@ -4,7 +4,7 @@
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/components/sonos",
|
||||
"requirements": [
|
||||
"pysonos==0.0.21"
|
||||
"pysonos==0.0.22"
|
||||
],
|
||||
"dependencies": [],
|
||||
"ssdp": {
|
||||
|
@ -2,7 +2,7 @@
|
||||
"""Constants used by Home Assistant components."""
|
||||
MAJOR_VERSION = 0
|
||||
MINOR_VERSION = 96
|
||||
PATCH_VERSION = '3'
|
||||
PATCH_VERSION = '4'
|
||||
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
|
||||
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
|
||||
REQUIRED_PYTHON_VER = (3, 5, 3)
|
||||
|
@ -10,7 +10,7 @@ certifi>=2019.6.16
|
||||
cryptography==2.7
|
||||
distro==1.4.0
|
||||
hass-nabucasa==0.15
|
||||
home-assistant-frontend==20190721.0
|
||||
home-assistant-frontend==20190721.1
|
||||
importlib-metadata==0.18
|
||||
jinja2>=2.10.1
|
||||
netdisco==2.6.0
|
||||
|
@ -610,7 +610,7 @@ hole==0.3.0
|
||||
holidays==0.9.10
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20190721.0
|
||||
home-assistant-frontend==20190721.1
|
||||
|
||||
# homeassistant.components.zwave
|
||||
homeassistant-pyozw==0.1.4
|
||||
@ -1033,7 +1033,7 @@ pyalarmdotcom==0.3.2
|
||||
pyarlo==0.2.3
|
||||
|
||||
# homeassistant.components.netatmo
|
||||
pyatmo==2.1.1
|
||||
pyatmo==2.1.2
|
||||
|
||||
# homeassistant.components.apple_tv
|
||||
pyatv==0.3.12
|
||||
@ -1078,7 +1078,7 @@ pycsspeechtts==1.0.2
|
||||
# pycups==1.9.73
|
||||
|
||||
# homeassistant.components.daikin
|
||||
pydaikin==1.4.6
|
||||
pydaikin==1.5.1
|
||||
|
||||
# homeassistant.components.danfoss_air
|
||||
pydanfossair==0.1.0
|
||||
@ -1378,7 +1378,7 @@ pysmarty==0.8
|
||||
pysnmp==4.4.9
|
||||
|
||||
# homeassistant.components.sonos
|
||||
pysonos==0.0.21
|
||||
pysonos==0.0.22
|
||||
|
||||
# homeassistant.components.spc
|
||||
pyspcwebgw==0.4.0
|
||||
|
@ -165,7 +165,7 @@ hdate==0.8.8
|
||||
holidays==0.9.10
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20190721.0
|
||||
home-assistant-frontend==20190721.1
|
||||
|
||||
# homeassistant.components.homekit_controller
|
||||
homekit[IP]==0.14.0
|
||||
@ -298,7 +298,7 @@ pysmartapp==0.3.2
|
||||
pysmartthings==0.6.9
|
||||
|
||||
# homeassistant.components.sonos
|
||||
pysonos==0.0.21
|
||||
pysonos==0.0.22
|
||||
|
||||
# homeassistant.components.spc
|
||||
pyspcwebgw==0.4.0
|
||||
|
Loading…
x
Reference in New Issue
Block a user