From afa4fc4ef59cccc75b40173b811c0f0ebe51111e Mon Sep 17 00:00:00 2001
From: Michael Auchter
Date: Sun, 24 Jan 2016 12:02:23 -0600
Subject: [PATCH 1/4] thermostat: split up services
---
.../components/thermostat/__init__.py | 83 ++++++++++---------
1 file changed, 43 insertions(+), 40 deletions(-)
diff --git a/homeassistant/components/thermostat/__init__.py b/homeassistant/components/thermostat/__init__.py
index 7610070b1f0..dce742b71a8 100644
--- a/homeassistant/components/thermostat/__init__.py
+++ b/homeassistant/components/thermostat/__init__.py
@@ -75,51 +75,54 @@ def setup(hass, config):
SCAN_INTERVAL, DISCOVERY_PLATFORMS)
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(
os.path.join(os.path.dirname(__file__), 'services.yaml'))
- hass.services.register(
- DOMAIN, SERVICE_SET_AWAY_MODE, thermostat_service,
- descriptions.get(SERVICE_SET_AWAY_MODE))
+ def away_mode_set_service(service):
+ """ Set away mode on target thermostats """
+
+ 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(
- 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))
return True
From a0ed469aa204aecc60bc61165d78588d82effc3f Mon Sep 17 00:00:00 2001
From: Michael Auchter
Date: Mon, 11 Jan 2016 19:08:41 -0600
Subject: [PATCH 2/4] thermostat: move fan attribute up to thermostat
---
homeassistant/components/thermostat/__init__.py | 13 +++++++++++++
homeassistant/components/thermostat/nest.py | 6 +++++-
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/homeassistant/components/thermostat/__init__.py b/homeassistant/components/thermostat/__init__.py
index dce742b71a8..17b9a2daca6 100644
--- a/homeassistant/components/thermostat/__init__.py
+++ b/homeassistant/components/thermostat/__init__.py
@@ -34,6 +34,7 @@ STATE_IDLE = "idle"
ATTR_CURRENT_TEMPERATURE = "current_temperature"
ATTR_AWAY_MODE = "away_mode"
+ATTR_FAN = "fan"
ATTR_MAX_TEMP = "max_temp"
ATTR_MIN_TEMP = "min_temp"
ATTR_TEMPERATURE_LOW = "target_temp_low"
@@ -167,6 +168,10 @@ class ThermostatDevice(Entity):
if is_away is not None:
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
if device_attr is not None:
@@ -212,6 +217,14 @@ class ThermostatDevice(Entity):
"""
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):
""" Set new target temperature. """
pass
diff --git a/homeassistant/components/thermostat/nest.py b/homeassistant/components/thermostat/nest.py
index 423a3195976..88a7761cb28 100644
--- a/homeassistant/components/thermostat/nest.py
+++ b/homeassistant/components/thermostat/nest.py
@@ -66,7 +66,6 @@ class NestThermostat(ThermostatDevice):
return {
"humidity": self.device.humidity,
"target_humidity": self.device.target_humidity,
- "fan": self.device.fan,
"mode": self.device.mode
}
@@ -143,6 +142,11 @@ class NestThermostat(ThermostatDevice):
""" Turns away off. """
self.structure.away = False
+ @property
+ def is_fan_on(self):
+ """ Returns whether the fan is on """
+ return self.device.fan
+
@property
def min_temp(self):
""" Identifies min_temp in Nest API or defaults if not available. """
From df94c909f7db9c7948dc097ad0ee52169cb41bbb Mon Sep 17 00:00:00 2001
From: Michael Auchter
Date: Mon, 11 Jan 2016 19:23:24 -0600
Subject: [PATCH 3/4] thermostat: add service to control fan mode
---
.../components/thermostat/__init__.py | 47 +++++++++++++++++++
.../components/thermostat/services.yaml | 12 +++++
2 files changed, 59 insertions(+)
diff --git a/homeassistant/components/thermostat/__init__.py b/homeassistant/components/thermostat/__init__.py
index 17b9a2daca6..d92a71ba1f6 100644
--- a/homeassistant/components/thermostat/__init__.py
+++ b/homeassistant/components/thermostat/__init__.py
@@ -27,6 +27,7 @@ SCAN_INTERVAL = 60
SERVICE_SET_AWAY_MODE = "set_away_mode"
SERVICE_SET_TEMPERATURE = "set_temperature"
+SERVICE_SET_FAN_MODE = "set_fan_mode"
STATE_HEAT = "heat"
STATE_COOL = "cool"
@@ -70,6 +71,19 @@ def set_temperature(hass, temperature, entity_id=None):
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):
""" Setup thermostats. """
component = EntityComponent(_LOGGER, DOMAIN, hass,
@@ -126,6 +140,31 @@ def setup(hass, config):
DOMAIN, SERVICE_SET_TEMPERATURE, temperature_set_service,
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
@@ -237,6 +276,14 @@ class ThermostatDevice(Entity):
""" Turns away mode off. """
pass
+ def turn_fan_on(self):
+ """ Turns fan on. """
+ pass
+
+ def turn_fan_off(self):
+ """ Turns fan off. """
+ pass
+
@property
def min_temp(self):
""" Return minimum temperature. """
diff --git a/homeassistant/components/thermostat/services.yaml b/homeassistant/components/thermostat/services.yaml
index 0d4f4726204..3592dfce75d 100644
--- a/homeassistant/components/thermostat/services.yaml
+++ b/homeassistant/components/thermostat/services.yaml
@@ -22,3 +22,15 @@ set_temperature:
temperature:
description: New target temperature for thermostat
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
From 881c82c2df42628413c7a55825e5d79d726fe879 Mon Sep 17 00:00:00 2001
From: Michael Auchter
Date: Mon, 11 Jan 2016 19:24:27 -0600
Subject: [PATCH 4/4] nest: implement fan control
---
homeassistant/components/thermostat/nest.py | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/homeassistant/components/thermostat/nest.py b/homeassistant/components/thermostat/nest.py
index 88a7761cb28..e0e1f74cdbc 100644
--- a/homeassistant/components/thermostat/nest.py
+++ b/homeassistant/components/thermostat/nest.py
@@ -147,6 +147,14 @@ class NestThermostat(ThermostatDevice):
""" 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
def min_temp(self):
""" Identifies min_temp in Nest API or defaults if not available. """