mirror of
https://github.com/home-assistant/core.git
synced 2025-07-26 06:37:52 +00:00
Merge pull request #988 from auchter/thermostat-fan
Add service to control a thermostat's fan
This commit is contained in:
commit
4abc5c97cd
@ -27,6 +27,7 @@ SCAN_INTERVAL = 60
|
|||||||
|
|
||||||
SERVICE_SET_AWAY_MODE = "set_away_mode"
|
SERVICE_SET_AWAY_MODE = "set_away_mode"
|
||||||
SERVICE_SET_TEMPERATURE = "set_temperature"
|
SERVICE_SET_TEMPERATURE = "set_temperature"
|
||||||
|
SERVICE_SET_FAN_MODE = "set_fan_mode"
|
||||||
|
|
||||||
STATE_HEAT = "heat"
|
STATE_HEAT = "heat"
|
||||||
STATE_COOL = "cool"
|
STATE_COOL = "cool"
|
||||||
@ -34,6 +35,7 @@ STATE_IDLE = "idle"
|
|||||||
|
|
||||||
ATTR_CURRENT_TEMPERATURE = "current_temperature"
|
ATTR_CURRENT_TEMPERATURE = "current_temperature"
|
||||||
ATTR_AWAY_MODE = "away_mode"
|
ATTR_AWAY_MODE = "away_mode"
|
||||||
|
ATTR_FAN = "fan"
|
||||||
ATTR_MAX_TEMP = "max_temp"
|
ATTR_MAX_TEMP = "max_temp"
|
||||||
ATTR_MIN_TEMP = "min_temp"
|
ATTR_MIN_TEMP = "min_temp"
|
||||||
ATTR_TEMPERATURE_LOW = "target_temp_low"
|
ATTR_TEMPERATURE_LOW = "target_temp_low"
|
||||||
@ -69,59 +71,100 @@ def set_temperature(hass, temperature, entity_id=None):
|
|||||||
hass.services.call(DOMAIN, SERVICE_SET_TEMPERATURE, data)
|
hass.services.call(DOMAIN, SERVICE_SET_TEMPERATURE, data)
|
||||||
|
|
||||||
|
|
||||||
|
def set_fan_mode(hass, fan_mode, entity_id=None):
|
||||||
|
""" Turn all or specified thermostat fan mode on. """
|
||||||
|
data = {
|
||||||
|
ATTR_FAN: fan_mode
|
||||||
|
}
|
||||||
|
|
||||||
|
if entity_id:
|
||||||
|
data[ATTR_ENTITY_ID] = entity_id
|
||||||
|
|
||||||
|
hass.services.call(DOMAIN, SERVICE_SET_FAN_MODE, data)
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=too-many-branches
|
||||||
def setup(hass, config):
|
def setup(hass, config):
|
||||||
""" Setup thermostats. """
|
""" Setup thermostats. """
|
||||||
component = EntityComponent(_LOGGER, DOMAIN, hass,
|
component = EntityComponent(_LOGGER, DOMAIN, hass,
|
||||||
SCAN_INTERVAL, DISCOVERY_PLATFORMS)
|
SCAN_INTERVAL, DISCOVERY_PLATFORMS)
|
||||||
component.setup(config)
|
component.setup(config)
|
||||||
|
|
||||||
def thermostat_service(service):
|
|
||||||
""" Handles calls to the services. """
|
|
||||||
|
|
||||||
# Convert the entity ids to valid light ids
|
|
||||||
target_thermostats = component.extract_from_service(service)
|
|
||||||
|
|
||||||
if service.service == SERVICE_SET_AWAY_MODE:
|
|
||||||
away_mode = service.data.get(ATTR_AWAY_MODE)
|
|
||||||
|
|
||||||
if away_mode is None:
|
|
||||||
_LOGGER.error(
|
|
||||||
"Received call to %s without attribute %s",
|
|
||||||
SERVICE_SET_AWAY_MODE, ATTR_AWAY_MODE)
|
|
||||||
|
|
||||||
elif away_mode:
|
|
||||||
for thermostat in target_thermostats:
|
|
||||||
thermostat.turn_away_mode_on()
|
|
||||||
else:
|
|
||||||
for thermostat in target_thermostats:
|
|
||||||
thermostat.turn_away_mode_off()
|
|
||||||
|
|
||||||
elif service.service == SERVICE_SET_TEMPERATURE:
|
|
||||||
temperature = util.convert(
|
|
||||||
service.data.get(ATTR_TEMPERATURE), float)
|
|
||||||
|
|
||||||
if temperature is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
for thermostat in target_thermostats:
|
|
||||||
thermostat.set_temperature(convert(
|
|
||||||
temperature, hass.config.temperature_unit,
|
|
||||||
thermostat.unit_of_measurement))
|
|
||||||
|
|
||||||
for thermostat in target_thermostats:
|
|
||||||
thermostat.update_ha_state(True)
|
|
||||||
|
|
||||||
descriptions = load_yaml_config_file(
|
descriptions = load_yaml_config_file(
|
||||||
os.path.join(os.path.dirname(__file__), 'services.yaml'))
|
os.path.join(os.path.dirname(__file__), 'services.yaml'))
|
||||||
|
|
||||||
hass.services.register(
|
def away_mode_set_service(service):
|
||||||
DOMAIN, SERVICE_SET_AWAY_MODE, thermostat_service,
|
""" Set away mode on target thermostats """
|
||||||
descriptions.get(SERVICE_SET_AWAY_MODE))
|
|
||||||
|
target_thermostats = component.extract_from_service(service)
|
||||||
|
|
||||||
|
away_mode = service.data.get(ATTR_AWAY_MODE)
|
||||||
|
|
||||||
|
if away_mode is None:
|
||||||
|
_LOGGER.error(
|
||||||
|
"Received call to %s without attribute %s",
|
||||||
|
SERVICE_SET_AWAY_MODE, ATTR_AWAY_MODE)
|
||||||
|
return
|
||||||
|
|
||||||
|
for thermostat in target_thermostats:
|
||||||
|
if away_mode:
|
||||||
|
thermostat.turn_away_mode_on()
|
||||||
|
else:
|
||||||
|
thermostat.turn_away_mode_off()
|
||||||
|
|
||||||
|
thermostat.update_ha_state(True)
|
||||||
|
|
||||||
hass.services.register(
|
hass.services.register(
|
||||||
DOMAIN, SERVICE_SET_TEMPERATURE, thermostat_service,
|
DOMAIN, SERVICE_SET_AWAY_MODE, away_mode_set_service,
|
||||||
|
descriptions.get(SERVICE_SET_AWAY_MODE))
|
||||||
|
|
||||||
|
def temperature_set_service(service):
|
||||||
|
""" Set temperature on the target thermostats """
|
||||||
|
|
||||||
|
target_thermostats = component.extract_from_service(service)
|
||||||
|
|
||||||
|
temperature = util.convert(
|
||||||
|
service.data.get(ATTR_TEMPERATURE), float)
|
||||||
|
|
||||||
|
if temperature is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
for thermostat in target_thermostats:
|
||||||
|
thermostat.set_temperature(convert(
|
||||||
|
temperature, hass.config.temperature_unit,
|
||||||
|
thermostat.unit_of_measurement))
|
||||||
|
|
||||||
|
thermostat.update_ha_state(True)
|
||||||
|
|
||||||
|
hass.services.register(
|
||||||
|
DOMAIN, SERVICE_SET_TEMPERATURE, temperature_set_service,
|
||||||
descriptions.get(SERVICE_SET_TEMPERATURE))
|
descriptions.get(SERVICE_SET_TEMPERATURE))
|
||||||
|
|
||||||
|
def fan_mode_set_service(service):
|
||||||
|
""" Set fan mode on target thermostats """
|
||||||
|
|
||||||
|
target_thermostats = component.extract_from_service(service)
|
||||||
|
|
||||||
|
fan_mode = service.data.get(ATTR_FAN)
|
||||||
|
|
||||||
|
if fan_mode is None:
|
||||||
|
_LOGGER.error(
|
||||||
|
"Received call to %s without attribute %s",
|
||||||
|
SERVICE_SET_FAN_MODE, ATTR_FAN)
|
||||||
|
return
|
||||||
|
|
||||||
|
for thermostat in target_thermostats:
|
||||||
|
if fan_mode:
|
||||||
|
thermostat.turn_fan_on()
|
||||||
|
else:
|
||||||
|
thermostat.turn_fan_off()
|
||||||
|
|
||||||
|
thermostat.update_ha_state(True)
|
||||||
|
|
||||||
|
hass.services.register(
|
||||||
|
DOMAIN, SERVICE_SET_FAN_MODE, fan_mode_set_service,
|
||||||
|
descriptions.get(SERVICE_SET_FAN_MODE))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@ -164,6 +207,10 @@ class ThermostatDevice(Entity):
|
|||||||
if is_away is not None:
|
if is_away is not None:
|
||||||
data[ATTR_AWAY_MODE] = STATE_ON if is_away else STATE_OFF
|
data[ATTR_AWAY_MODE] = STATE_ON if is_away else STATE_OFF
|
||||||
|
|
||||||
|
is_fan_on = self.is_fan_on
|
||||||
|
if is_fan_on is not None:
|
||||||
|
data[ATTR_FAN] = STATE_ON if is_fan_on else STATE_OFF
|
||||||
|
|
||||||
device_attr = self.device_state_attributes
|
device_attr = self.device_state_attributes
|
||||||
|
|
||||||
if device_attr is not None:
|
if device_attr is not None:
|
||||||
@ -209,6 +256,14 @@ class ThermostatDevice(Entity):
|
|||||||
"""
|
"""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_fan_on(self):
|
||||||
|
"""
|
||||||
|
Returns if the fan is on
|
||||||
|
Return None if not available.
|
||||||
|
"""
|
||||||
|
return None
|
||||||
|
|
||||||
def set_temperate(self, temperature):
|
def set_temperate(self, temperature):
|
||||||
""" Set new target temperature. """
|
""" Set new target temperature. """
|
||||||
pass
|
pass
|
||||||
@ -221,6 +276,14 @@ class ThermostatDevice(Entity):
|
|||||||
""" Turns away mode off. """
|
""" Turns away mode off. """
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def turn_fan_on(self):
|
||||||
|
""" Turns fan on. """
|
||||||
|
pass
|
||||||
|
|
||||||
|
def turn_fan_off(self):
|
||||||
|
""" Turns fan off. """
|
||||||
|
pass
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def min_temp(self):
|
def min_temp(self):
|
||||||
""" Return minimum temperature. """
|
""" Return minimum temperature. """
|
||||||
|
@ -66,7 +66,6 @@ class NestThermostat(ThermostatDevice):
|
|||||||
return {
|
return {
|
||||||
"humidity": self.device.humidity,
|
"humidity": self.device.humidity,
|
||||||
"target_humidity": self.device.target_humidity,
|
"target_humidity": self.device.target_humidity,
|
||||||
"fan": self.device.fan,
|
|
||||||
"mode": self.device.mode
|
"mode": self.device.mode
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,6 +142,19 @@ class NestThermostat(ThermostatDevice):
|
|||||||
""" Turns away off. """
|
""" Turns away off. """
|
||||||
self.structure.away = False
|
self.structure.away = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_fan_on(self):
|
||||||
|
""" Returns whether the fan is on """
|
||||||
|
return self.device.fan
|
||||||
|
|
||||||
|
def turn_fan_on(self):
|
||||||
|
""" Turns fan on """
|
||||||
|
self.device.fan = True
|
||||||
|
|
||||||
|
def turn_fan_off(self):
|
||||||
|
""" Turns fan off """
|
||||||
|
self.device.fan = False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def min_temp(self):
|
def min_temp(self):
|
||||||
""" Identifies min_temp in Nest API or defaults if not available. """
|
""" Identifies min_temp in Nest API or defaults if not available. """
|
||||||
|
@ -22,3 +22,15 @@ set_temperature:
|
|||||||
temperature:
|
temperature:
|
||||||
description: New target temperature for thermostat
|
description: New target temperature for thermostat
|
||||||
example: 25
|
example: 25
|
||||||
|
|
||||||
|
set_fan_mode:
|
||||||
|
description: Turn fan on/off for a thermostat
|
||||||
|
|
||||||
|
fields:
|
||||||
|
entity_id:
|
||||||
|
description: Name(s) of entities to change
|
||||||
|
example: 'thermostat.nest'
|
||||||
|
|
||||||
|
fan:
|
||||||
|
description: New value of fan mode
|
||||||
|
example: true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user