Hold mode (#5586)
* Initial commit of hold_mode feature. * Added deprecation warning for climate.away_mode * Add tests to demo environment.
This commit is contained in:
parent
1d4e967106
commit
b732174def
6 changed files with 223 additions and 56 deletions
|
@ -32,6 +32,7 @@ SERVICE_SET_AWAY_MODE = "set_away_mode"
|
||||||
SERVICE_SET_AUX_HEAT = "set_aux_heat"
|
SERVICE_SET_AUX_HEAT = "set_aux_heat"
|
||||||
SERVICE_SET_TEMPERATURE = "set_temperature"
|
SERVICE_SET_TEMPERATURE = "set_temperature"
|
||||||
SERVICE_SET_FAN_MODE = "set_fan_mode"
|
SERVICE_SET_FAN_MODE = "set_fan_mode"
|
||||||
|
SERVICE_SET_HOLD_MODE = "set_hold_mode"
|
||||||
SERVICE_SET_OPERATION_MODE = "set_operation_mode"
|
SERVICE_SET_OPERATION_MODE = "set_operation_mode"
|
||||||
SERVICE_SET_SWING_MODE = "set_swing_mode"
|
SERVICE_SET_SWING_MODE = "set_swing_mode"
|
||||||
SERVICE_SET_HUMIDITY = "set_humidity"
|
SERVICE_SET_HUMIDITY = "set_humidity"
|
||||||
|
@ -56,6 +57,7 @@ ATTR_CURRENT_HUMIDITY = "current_humidity"
|
||||||
ATTR_HUMIDITY = "humidity"
|
ATTR_HUMIDITY = "humidity"
|
||||||
ATTR_MAX_HUMIDITY = "max_humidity"
|
ATTR_MAX_HUMIDITY = "max_humidity"
|
||||||
ATTR_MIN_HUMIDITY = "min_humidity"
|
ATTR_MIN_HUMIDITY = "min_humidity"
|
||||||
|
ATTR_HOLD_MODE = "hold_mode"
|
||||||
ATTR_OPERATION_MODE = "operation_mode"
|
ATTR_OPERATION_MODE = "operation_mode"
|
||||||
ATTR_OPERATION_LIST = "operation_list"
|
ATTR_OPERATION_LIST = "operation_list"
|
||||||
ATTR_SWING_MODE = "swing_mode"
|
ATTR_SWING_MODE = "swing_mode"
|
||||||
|
@ -93,6 +95,10 @@ SET_FAN_MODE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
||||||
vol.Required(ATTR_FAN_MODE): cv.string,
|
vol.Required(ATTR_FAN_MODE): cv.string,
|
||||||
})
|
})
|
||||||
|
SET_HOLD_MODE_SCHEMA = vol.Schema({
|
||||||
|
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
||||||
|
vol.Required(ATTR_HOLD_MODE): cv.string,
|
||||||
|
})
|
||||||
SET_OPERATION_MODE_SCHEMA = vol.Schema({
|
SET_OPERATION_MODE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
||||||
vol.Required(ATTR_OPERATION_MODE): cv.string,
|
vol.Required(ATTR_OPERATION_MODE): cv.string,
|
||||||
|
@ -116,9 +122,23 @@ def set_away_mode(hass, away_mode, entity_id=None):
|
||||||
if entity_id:
|
if entity_id:
|
||||||
data[ATTR_ENTITY_ID] = entity_id
|
data[ATTR_ENTITY_ID] = entity_id
|
||||||
|
|
||||||
|
_LOGGER.warning(
|
||||||
|
'This service has been deprecated; use climate.set_hold_mode')
|
||||||
hass.services.call(DOMAIN, SERVICE_SET_AWAY_MODE, data)
|
hass.services.call(DOMAIN, SERVICE_SET_AWAY_MODE, data)
|
||||||
|
|
||||||
|
|
||||||
|
def set_hold_mode(hass, hold_mode, entity_id=None):
|
||||||
|
"""Set new hold mode."""
|
||||||
|
data = {
|
||||||
|
ATTR_HOLD_MODE: hold_mode
|
||||||
|
}
|
||||||
|
|
||||||
|
if entity_id:
|
||||||
|
data[ATTR_ENTITY_ID] = entity_id
|
||||||
|
|
||||||
|
hass.services.call(DOMAIN, SERVICE_SET_HOLD_MODE, data)
|
||||||
|
|
||||||
|
|
||||||
def set_aux_heat(hass, aux_heat, entity_id=None):
|
def set_aux_heat(hass, aux_heat, entity_id=None):
|
||||||
"""Turn all or specified climate devices auxillary heater on."""
|
"""Turn all or specified climate devices auxillary heater on."""
|
||||||
data = {
|
data = {
|
||||||
|
@ -229,6 +249,8 @@ def async_setup(hass, config):
|
||||||
SERVICE_SET_AWAY_MODE, ATTR_AWAY_MODE)
|
SERVICE_SET_AWAY_MODE, ATTR_AWAY_MODE)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
_LOGGER.warning(
|
||||||
|
'This service has been deprecated; use climate.set_hold_mode')
|
||||||
for climate in target_climate:
|
for climate in target_climate:
|
||||||
if away_mode:
|
if away_mode:
|
||||||
yield from climate.async_turn_away_mode_on()
|
yield from climate.async_turn_away_mode_on()
|
||||||
|
@ -242,6 +264,23 @@ def async_setup(hass, config):
|
||||||
descriptions.get(SERVICE_SET_AWAY_MODE),
|
descriptions.get(SERVICE_SET_AWAY_MODE),
|
||||||
schema=SET_AWAY_MODE_SCHEMA)
|
schema=SET_AWAY_MODE_SCHEMA)
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def async_hold_mode_set_service(service):
|
||||||
|
"""Set hold mode on target climate devices."""
|
||||||
|
target_climate = component.async_extract_from_service(service)
|
||||||
|
|
||||||
|
hold_mode = service.data.get(ATTR_HOLD_MODE)
|
||||||
|
|
||||||
|
for climate in target_climate:
|
||||||
|
yield from climate.async_set_hold_mode(hold_mode)
|
||||||
|
|
||||||
|
yield from _async_update_climate(target_climate)
|
||||||
|
|
||||||
|
hass.services.async_register(
|
||||||
|
DOMAIN, SERVICE_SET_HOLD_MODE, async_hold_mode_set_service,
|
||||||
|
descriptions.get(SERVICE_SET_HOLD_MODE),
|
||||||
|
schema=SET_HOLD_MODE_SCHEMA)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_aux_heat_set_service(service):
|
def async_aux_heat_set_service(service):
|
||||||
"""Set auxillary heater on target climate devices."""
|
"""Set auxillary heater on target climate devices."""
|
||||||
|
@ -446,6 +485,10 @@ class ClimateDevice(Entity):
|
||||||
if self.operation_list:
|
if self.operation_list:
|
||||||
data[ATTR_OPERATION_LIST] = self.operation_list
|
data[ATTR_OPERATION_LIST] = self.operation_list
|
||||||
|
|
||||||
|
is_hold = self.current_hold_mode
|
||||||
|
if is_hold is not None:
|
||||||
|
data[ATTR_HOLD_MODE] = is_hold
|
||||||
|
|
||||||
swing_mode = self.current_swing_mode
|
swing_mode = self.current_swing_mode
|
||||||
if swing_mode is not None:
|
if swing_mode is not None:
|
||||||
data[ATTR_SWING_MODE] = swing_mode
|
data[ATTR_SWING_MODE] = swing_mode
|
||||||
|
@ -517,6 +560,11 @@ class ClimateDevice(Entity):
|
||||||
"""Return true if away mode is on."""
|
"""Return true if away mode is on."""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_hold_mode(self):
|
||||||
|
"""Return the current hold mode, e.g., home, away, temp."""
|
||||||
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_aux_heat_on(self):
|
def is_aux_heat_on(self):
|
||||||
"""Return true if aux heater."""
|
"""Return true if aux heater."""
|
||||||
|
@ -626,6 +674,18 @@ class ClimateDevice(Entity):
|
||||||
return self.hass.loop.run_in_executor(
|
return self.hass.loop.run_in_executor(
|
||||||
None, self.turn_away_mode_off)
|
None, self.turn_away_mode_off)
|
||||||
|
|
||||||
|
def set_hold_mode(self, hold_mode):
|
||||||
|
"""Set new target hold mode."""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def async_set_hold_mode(self, hold_mode):
|
||||||
|
"""Set new target hold mode.
|
||||||
|
|
||||||
|
This method must be run in the event loop and returns a coroutine.
|
||||||
|
"""
|
||||||
|
return self.hass.loop.run_in_executor(
|
||||||
|
None, self.set_hold_mode, hold_mode)
|
||||||
|
|
||||||
def turn_aux_heat_on(self):
|
def turn_aux_heat_on(self):
|
||||||
"""Turn auxillary heater on."""
|
"""Turn auxillary heater on."""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
|
@ -12,11 +12,11 @@ from homeassistant.const import TEMP_CELSIUS, TEMP_FAHRENHEIT, ATTR_TEMPERATURE
|
||||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
"""Setup the Demo climate devices."""
|
"""Setup the Demo climate devices."""
|
||||||
add_devices([
|
add_devices([
|
||||||
DemoClimate("HeatPump", 68, TEMP_FAHRENHEIT, None, 77, "Auto Low",
|
DemoClimate("HeatPump", 68, TEMP_FAHRENHEIT, None, None, 77,
|
||||||
None, None, "Auto", "heat", None, None, None),
|
"Auto Low", None, None, "Auto", "heat", None, None, None),
|
||||||
DemoClimate("Hvac", 21, TEMP_CELSIUS, True, 22, "On High",
|
DemoClimate("Hvac", 21, TEMP_CELSIUS, True, None, 22, "On High",
|
||||||
67, 54, "Off", "cool", False, None, None),
|
67, 54, "Off", "cool", False, None, None),
|
||||||
DemoClimate("Ecobee", None, TEMP_CELSIUS, None, 23, "Auto Low",
|
DemoClimate("Ecobee", None, TEMP_CELSIUS, None, None, 23, "Auto Low",
|
||||||
None, None, "Auto", "auto", None, 24, 21)
|
None, None, "Auto", "auto", None, 24, 21)
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ class DemoClimate(ClimateDevice):
|
||||||
"""Representation of a demo climate device."""
|
"""Representation of a demo climate device."""
|
||||||
|
|
||||||
def __init__(self, name, target_temperature, unit_of_measurement,
|
def __init__(self, name, target_temperature, unit_of_measurement,
|
||||||
away, current_temperature, current_fan_mode,
|
away, hold, current_temperature, current_fan_mode,
|
||||||
target_humidity, current_humidity, current_swing_mode,
|
target_humidity, current_humidity, current_swing_mode,
|
||||||
current_operation, aux, target_temp_high, target_temp_low):
|
current_operation, aux, target_temp_high, target_temp_low):
|
||||||
"""Initialize the climate device."""
|
"""Initialize the climate device."""
|
||||||
|
@ -34,6 +34,7 @@ class DemoClimate(ClimateDevice):
|
||||||
self._target_humidity = target_humidity
|
self._target_humidity = target_humidity
|
||||||
self._unit_of_measurement = unit_of_measurement
|
self._unit_of_measurement = unit_of_measurement
|
||||||
self._away = away
|
self._away = away
|
||||||
|
self._hold = hold
|
||||||
self._current_temperature = current_temperature
|
self._current_temperature = current_temperature
|
||||||
self._current_humidity = current_humidity
|
self._current_humidity = current_humidity
|
||||||
self._current_fan_mode = current_fan_mode
|
self._current_fan_mode = current_fan_mode
|
||||||
|
@ -106,6 +107,11 @@ class DemoClimate(ClimateDevice):
|
||||||
"""Return if away mode is on."""
|
"""Return if away mode is on."""
|
||||||
return self._away
|
return self._away
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_hold_mode(self):
|
||||||
|
"""Return hold mode setting."""
|
||||||
|
return self._hold
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_aux_heat_on(self):
|
def is_aux_heat_on(self):
|
||||||
"""Return true if away mode is on."""
|
"""Return true if away mode is on."""
|
||||||
|
@ -171,6 +177,11 @@ class DemoClimate(ClimateDevice):
|
||||||
self._away = False
|
self._away = False
|
||||||
self.update_ha_state()
|
self.update_ha_state()
|
||||||
|
|
||||||
|
def set_hold_mode(self, hold):
|
||||||
|
"""Update hold mode on."""
|
||||||
|
self._hold = hold
|
||||||
|
self.update_ha_state()
|
||||||
|
|
||||||
def turn_aux_heat_on(self):
|
def turn_aux_heat_on(self):
|
||||||
"""Turn away auxillary heater on."""
|
"""Turn away auxillary heater on."""
|
||||||
self._aux = True
|
self._aux = True
|
||||||
|
|
|
@ -183,6 +183,19 @@ class Thermostat(ClimateDevice):
|
||||||
else:
|
else:
|
||||||
return STATE_OFF
|
return STATE_OFF
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_hold_mode(self):
|
||||||
|
"""Return current hold mode."""
|
||||||
|
if self.is_away_mode_on:
|
||||||
|
hold = 'away'
|
||||||
|
elif self.is_home_mode_on:
|
||||||
|
hold = 'home'
|
||||||
|
elif self.is_temp_hold_on():
|
||||||
|
hold = 'temp'
|
||||||
|
else:
|
||||||
|
hold = None
|
||||||
|
return hold
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def current_operation(self):
|
def current_operation(self):
|
||||||
"""Return current operation."""
|
"""Return current operation."""
|
||||||
|
@ -236,30 +249,94 @@ class Thermostat(ClimateDevice):
|
||||||
"fan_min_on_time": self.fan_min_on_time
|
"fan_min_on_time": self.fan_min_on_time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def is_vacation_on(self):
|
||||||
|
"""Return true if vacation mode is on."""
|
||||||
|
events = self.thermostat['events']
|
||||||
|
return any(event['type'] == 'vacation' and event['running']
|
||||||
|
for event in events)
|
||||||
|
|
||||||
|
def is_temp_hold_on(self):
|
||||||
|
"""Return true if temperature hold is on."""
|
||||||
|
events = self.thermostat['events']
|
||||||
|
return any(event['type'] == 'hold' and event['running']
|
||||||
|
for event in events)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_away_mode_on(self):
|
def is_away_mode_on(self):
|
||||||
"""Return true if away mode is on."""
|
"""Return true if away mode is on."""
|
||||||
mode = self.mode
|
|
||||||
events = self.thermostat['events']
|
events = self.thermostat['events']
|
||||||
for event in events:
|
return any(event['holdClimateRef'] == 'away' or
|
||||||
if event['holdClimateRef'] == 'away' or \
|
event['type'] == 'autoAway'
|
||||||
event['type'] == 'autoAway':
|
for event in events)
|
||||||
mode = "away"
|
|
||||||
break
|
|
||||||
return 'away' in mode
|
|
||||||
|
|
||||||
def turn_away_mode_on(self):
|
def turn_away_mode_on(self):
|
||||||
"""Turn away on."""
|
"""Turn away on."""
|
||||||
if self.hold_temp:
|
self.data.ecobee.set_climate_hold(self.thermostat_index,
|
||||||
self.data.ecobee.set_climate_hold(self.thermostat_index,
|
"away", self.hold_preference())
|
||||||
"away", "indefinite")
|
|
||||||
else:
|
|
||||||
self.data.ecobee.set_climate_hold(self.thermostat_index, "away")
|
|
||||||
self.update_without_throttle = True
|
self.update_without_throttle = True
|
||||||
|
|
||||||
def turn_away_mode_off(self):
|
def turn_away_mode_off(self):
|
||||||
"""Turn away off."""
|
"""Turn away off."""
|
||||||
self.data.ecobee.resume_program(self.thermostat_index)
|
self.set_hold_mode(None)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_home_mode_on(self):
|
||||||
|
"""Return true if home mode is on."""
|
||||||
|
events = self.thermostat['events']
|
||||||
|
return any(event['holdClimateRef'] == 'home' or
|
||||||
|
event['type'] == 'autoHome'
|
||||||
|
for event in events)
|
||||||
|
|
||||||
|
def turn_home_mode_on(self):
|
||||||
|
"""Turn home on."""
|
||||||
|
self.data.ecobee.set_climate_hold(self.thermostat_index,
|
||||||
|
"home", self.hold_preference())
|
||||||
|
self.update_without_throttle = True
|
||||||
|
|
||||||
|
def set_hold_mode(self, hold_mode):
|
||||||
|
"""Set hold mode (away, home, temp)."""
|
||||||
|
hold = self.current_hold_mode
|
||||||
|
|
||||||
|
if hold == hold_mode:
|
||||||
|
return
|
||||||
|
elif hold_mode == 'away':
|
||||||
|
self.turn_away_mode_on()
|
||||||
|
elif hold_mode == 'home':
|
||||||
|
self.turn_home_mode_on()
|
||||||
|
elif hold_mode == 'temp':
|
||||||
|
self.set_temp_hold(int(self.current_temperature))
|
||||||
|
else:
|
||||||
|
self.data.ecobee.resume_program(self.thermostat_index)
|
||||||
|
self.update_without_throttle = True
|
||||||
|
|
||||||
|
def set_auto_temp_hold(self, heat_temp, cool_temp):
|
||||||
|
"""Set temperature hold in auto mode."""
|
||||||
|
self.data.ecobee.set_hold_temp(self.thermostat_index, cool_temp,
|
||||||
|
heat_temp, self.hold_preference())
|
||||||
|
_LOGGER.debug("Setting ecobee hold_temp to: heat=%s, is=%s, "
|
||||||
|
"cool=%s, is=%s", heat_temp, isinstance(
|
||||||
|
heat_temp, (int, float)), cool_temp,
|
||||||
|
isinstance(cool_temp, (int, float)))
|
||||||
|
|
||||||
|
self.update_without_throttle = True
|
||||||
|
|
||||||
|
def set_temp_hold(self, temp):
|
||||||
|
"""Set temperature hold in modes other than auto."""
|
||||||
|
# Set arbitrary range when not in auto mode
|
||||||
|
if self.current_operation == STATE_HEAT:
|
||||||
|
heat_temp = temp
|
||||||
|
cool_temp = temp + 20
|
||||||
|
elif self.current_operation == STATE_COOL:
|
||||||
|
heat_temp = temp - 20
|
||||||
|
cool_temp = temp
|
||||||
|
|
||||||
|
self.data.ecobee.set_hold_temp(self.thermostat_index, cool_temp,
|
||||||
|
heat_temp, self.hold_preference())
|
||||||
|
_LOGGER.debug("Setting ecobee hold_temp to: low=%s, is=%s, "
|
||||||
|
"cool=%s, is=%s", heat_temp, isinstance(
|
||||||
|
heat_temp, (int, float)), cool_temp,
|
||||||
|
isinstance(cool_temp, (int, float)))
|
||||||
|
|
||||||
self.update_without_throttle = True
|
self.update_without_throttle = True
|
||||||
|
|
||||||
def set_temperature(self, **kwargs):
|
def set_temperature(self, **kwargs):
|
||||||
|
@ -268,33 +345,14 @@ class Thermostat(ClimateDevice):
|
||||||
high_temp = kwargs.get(ATTR_TARGET_TEMP_HIGH)
|
high_temp = kwargs.get(ATTR_TARGET_TEMP_HIGH)
|
||||||
temp = kwargs.get(ATTR_TEMPERATURE)
|
temp = kwargs.get(ATTR_TEMPERATURE)
|
||||||
|
|
||||||
if self.current_operation == STATE_HEAT and temp is not None:
|
if self.current_operation == STATE_AUTO and low_temp is not None \
|
||||||
low_temp = temp
|
and high_temp is not None:
|
||||||
high_temp = temp + 20
|
self.set_auto_temp_hold(int(low_temp), int(high_temp))
|
||||||
elif self.current_operation == STATE_COOL and temp is not None:
|
elif temp is not None:
|
||||||
low_temp = temp - 20
|
self.set_temp_hold(int(temp))
|
||||||
high_temp = temp
|
else:
|
||||||
if low_temp is None and high_temp is None:
|
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
'Missing valid arguments for set_temperature in %s', kwargs)
|
'Missing valid arguments for set_temperature in %s', kwargs)
|
||||||
return
|
|
||||||
|
|
||||||
low_temp = int(low_temp)
|
|
||||||
high_temp = int(high_temp)
|
|
||||||
|
|
||||||
if self.hold_temp:
|
|
||||||
self.data.ecobee.set_hold_temp(
|
|
||||||
self.thermostat_index, high_temp, low_temp, "indefinite")
|
|
||||||
else:
|
|
||||||
self.data.ecobee.set_hold_temp(
|
|
||||||
self.thermostat_index, high_temp, low_temp)
|
|
||||||
|
|
||||||
_LOGGER.debug("Setting ecobee hold_temp to: low=%s, is=%s, "
|
|
||||||
"high=%s, is=%s", low_temp, isinstance(
|
|
||||||
low_temp, (int, float)), high_temp,
|
|
||||||
isinstance(high_temp, (int, float)))
|
|
||||||
|
|
||||||
self.update_without_throttle = True
|
|
||||||
|
|
||||||
def set_operation_mode(self, operation_mode):
|
def set_operation_mode(self, operation_mode):
|
||||||
"""Set HVAC mode (auto, auxHeatOnly, cool, heat, off)."""
|
"""Set HVAC mode (auto, auxHeatOnly, cool, heat, off)."""
|
||||||
|
@ -313,15 +371,19 @@ class Thermostat(ClimateDevice):
|
||||||
str(resume_all).lower())
|
str(resume_all).lower())
|
||||||
self.update_without_throttle = True
|
self.update_without_throttle = True
|
||||||
|
|
||||||
# Home and Sleep mode aren't used in UI yet:
|
def hold_preference(self):
|
||||||
|
"""Return user preference setting for hold time."""
|
||||||
|
# Values returned from thermostat are 'useEndTime4hour',
|
||||||
|
# 'useEndTime2hour', 'nextTransition', 'indefinite', 'askMe'
|
||||||
|
default = self.thermostat['settings']['holdAction']
|
||||||
|
if default == 'nextTransition':
|
||||||
|
return default
|
||||||
|
elif default == 'indefinite':
|
||||||
|
return default
|
||||||
|
else:
|
||||||
|
return 'nextTransition'
|
||||||
|
|
||||||
# def turn_home_mode_on(self):
|
# Sleep mode isn't used in UI yet:
|
||||||
# """ Turns home mode on. """
|
|
||||||
# self.data.ecobee.set_climate_hold(self.thermostat_index, "home")
|
|
||||||
|
|
||||||
# def turn_home_mode_off(self):
|
|
||||||
# """ Turns home mode off. """
|
|
||||||
# self.data.ecobee.resume_program(self.thermostat_index)
|
|
||||||
|
|
||||||
# def turn_sleep_mode_on(self):
|
# def turn_sleep_mode_on(self):
|
||||||
# """ Turns sleep mode on. """
|
# """ Turns sleep mode on. """
|
||||||
|
|
|
@ -22,6 +22,18 @@ set_away_mode:
|
||||||
description: New value of away mode
|
description: New value of away mode
|
||||||
example: true
|
example: true
|
||||||
|
|
||||||
|
set_hold_mode:
|
||||||
|
description: Turn hold mode for climate device
|
||||||
|
|
||||||
|
fields:
|
||||||
|
entity_id:
|
||||||
|
description: Name(s) of entities to change
|
||||||
|
example: 'climate.kitchen'
|
||||||
|
|
||||||
|
hold_mode:
|
||||||
|
description: New value of hold mode
|
||||||
|
example: 'away'
|
||||||
|
|
||||||
set_temperature:
|
set_temperature:
|
||||||
description: Set target temperature of climate device
|
description: Set target temperature of climate device
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,11 @@ from homeassistant.components.sun import (
|
||||||
from homeassistant.components.switch.mysensors import (
|
from homeassistant.components.switch.mysensors import (
|
||||||
ATTR_IR_CODE, SERVICE_SEND_IR_CODE)
|
ATTR_IR_CODE, SERVICE_SEND_IR_CODE)
|
||||||
from homeassistant.components.climate import (
|
from homeassistant.components.climate import (
|
||||||
ATTR_AUX_HEAT, ATTR_AWAY_MODE, ATTR_FAN_MODE, ATTR_HUMIDITY,
|
ATTR_AUX_HEAT, ATTR_AWAY_MODE, ATTR_FAN_MODE, ATTR_HOLD_MODE,
|
||||||
ATTR_OPERATION_MODE, ATTR_SWING_MODE,
|
ATTR_HUMIDITY, ATTR_OPERATION_MODE, ATTR_SWING_MODE,
|
||||||
SERVICE_SET_AUX_HEAT, SERVICE_SET_AWAY_MODE, SERVICE_SET_FAN_MODE,
|
SERVICE_SET_AUX_HEAT, SERVICE_SET_AWAY_MODE, SERVICE_SET_HOLD_MODE,
|
||||||
SERVICE_SET_HUMIDITY, SERVICE_SET_OPERATION_MODE, SERVICE_SET_SWING_MODE,
|
SERVICE_SET_FAN_MODE, SERVICE_SET_HUMIDITY, SERVICE_SET_OPERATION_MODE,
|
||||||
SERVICE_SET_TEMPERATURE)
|
SERVICE_SET_SWING_MODE, SERVICE_SET_TEMPERATURE)
|
||||||
from homeassistant.components.climate.ecobee import (
|
from homeassistant.components.climate.ecobee import (
|
||||||
ATTR_FAN_MIN_ON_TIME, SERVICE_SET_FAN_MIN_ON_TIME,
|
ATTR_FAN_MIN_ON_TIME, SERVICE_SET_FAN_MIN_ON_TIME,
|
||||||
ATTR_RESUME_ALL, SERVICE_RESUME_PROGRAM)
|
ATTR_RESUME_ALL, SERVICE_RESUME_PROGRAM)
|
||||||
|
@ -57,6 +57,7 @@ SERVICE_ATTRIBUTES = {
|
||||||
SERVICE_SET_TEMPERATURE: [ATTR_TEMPERATURE],
|
SERVICE_SET_TEMPERATURE: [ATTR_TEMPERATURE],
|
||||||
SERVICE_SET_HUMIDITY: [ATTR_HUMIDITY],
|
SERVICE_SET_HUMIDITY: [ATTR_HUMIDITY],
|
||||||
SERVICE_SET_SWING_MODE: [ATTR_SWING_MODE],
|
SERVICE_SET_SWING_MODE: [ATTR_SWING_MODE],
|
||||||
|
SERVICE_SET_HOLD_MODE: [ATTR_HOLD_MODE],
|
||||||
SERVICE_SET_OPERATION_MODE: [ATTR_OPERATION_MODE],
|
SERVICE_SET_OPERATION_MODE: [ATTR_OPERATION_MODE],
|
||||||
SERVICE_SET_AUX_HEAT: [ATTR_AUX_HEAT],
|
SERVICE_SET_AUX_HEAT: [ATTR_AUX_HEAT],
|
||||||
SERVICE_SELECT_SOURCE: [ATTR_INPUT_SOURCE],
|
SERVICE_SELECT_SOURCE: [ATTR_INPUT_SOURCE],
|
||||||
|
|
|
@ -208,6 +208,27 @@ class TestDemoClimate(unittest.TestCase):
|
||||||
state = self.hass.states.get(ENTITY_CLIMATE)
|
state = self.hass.states.get(ENTITY_CLIMATE)
|
||||||
self.assertEqual('off', state.attributes.get('away_mode'))
|
self.assertEqual('off', state.attributes.get('away_mode'))
|
||||||
|
|
||||||
|
def test_set_hold_mode_home(self):
|
||||||
|
"""Test setting the hold mode home."""
|
||||||
|
climate.set_hold_mode(self.hass, 'home', ENTITY_ECOBEE)
|
||||||
|
self.hass.block_till_done()
|
||||||
|
state = self.hass.states.get(ENTITY_ECOBEE)
|
||||||
|
self.assertEqual('home', state.attributes.get('hold_mode'))
|
||||||
|
|
||||||
|
def test_set_hold_mode_away(self):
|
||||||
|
"""Test setting the hold mode away."""
|
||||||
|
climate.set_hold_mode(self.hass, 'away', ENTITY_ECOBEE)
|
||||||
|
self.hass.block_till_done()
|
||||||
|
state = self.hass.states.get(ENTITY_ECOBEE)
|
||||||
|
self.assertEqual('away', state.attributes.get('hold_mode'))
|
||||||
|
|
||||||
|
def test_set_hold_mode_none(self):
|
||||||
|
"""Test setting the hold mode off/false."""
|
||||||
|
climate.set_hold_mode(self.hass, None, ENTITY_ECOBEE)
|
||||||
|
self.hass.block_till_done()
|
||||||
|
state = self.hass.states.get(ENTITY_ECOBEE)
|
||||||
|
self.assertEqual(None, state.attributes.get('hold_mode'))
|
||||||
|
|
||||||
def test_set_aux_heat_bad_attr(self):
|
def test_set_aux_heat_bad_attr(self):
|
||||||
"""Test setting the auxillary heater without required attribute."""
|
"""Test setting the auxillary heater without required attribute."""
|
||||||
state = self.hass.states.get(ENTITY_CLIMATE)
|
state = self.hass.states.get(ENTITY_CLIMATE)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue