From 2d54fdd979823128e3921cf19f39e25dad354f07 Mon Sep 17 00:00:00 2001 From: zyell Date: Thu, 10 Sep 2015 15:11:59 -0700 Subject: [PATCH 1/4] Initial code for generic thermostat range support and nest compliance --- .../components/thermostat/__init__.py | 35 +++++++++++++- homeassistant/components/thermostat/nest.py | 48 ++++++++++++++++--- 2 files changed, 75 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/thermostat/__init__.py b/homeassistant/components/thermostat/__init__.py index bbc0979e38c..93e264091b9 100644 --- a/homeassistant/components/thermostat/__init__.py +++ b/homeassistant/components/thermostat/__init__.py @@ -27,6 +27,9 @@ ATTR_CURRENT_TEMPERATURE = "current_temperature" ATTR_AWAY_MODE = "away_mode" ATTR_MAX_TEMP = "max_temp" ATTR_MIN_TEMP = "min_temp" +ATTR_TEMPERATURE_LOW = "target_temp_low" +ATTR_TEMPERATURE_HIGH = "target_temp_high" +ATTR_OPERATION = "current_operation" _LOGGER = logging.getLogger(__name__) @@ -111,7 +114,7 @@ class ThermostatDevice(Entity): @property def state(self): """ Returns the current state. """ - return self.target_temperature + return self.operation @property def device_state_attributes(self): @@ -134,7 +137,20 @@ class ThermostatDevice(Entity): user_unit), 0), ATTR_MAX_TEMP: round(convert(self.max_temp, thermostat_unit, - user_unit), 0) + user_unit), 0), + ATTR_TEMPERATURE: round(convert(self.target_temperature, + thermostat_unit, + user_unit), 0), + ATTR_TEMPERATURE_LOW: round(convert(self.target_temperature_low, + thermostat_unit, + user_unit), 0), + ATTR_TEMPERATURE_HIGH: round(convert(self.target_temperature_high, + thermostat_unit, + user_unit), 0), + ATTR_OPERATION: round(convert(self.operation, + thermostat_unit, + user_unit), 0) + } is_away = self.is_away_mode_on @@ -159,11 +175,26 @@ class ThermostatDevice(Entity): """ Returns the current temperature. """ raise NotImplementedError + @property + def operation(self): + """ Returns current operation ie. heat, cool, idle """ + return NotImplementedError + @property def target_temperature(self): """ Returns the temperature we try to reach. """ raise NotImplementedError + @property + def target_temperature_low(self): + """ Returns the lower bound temperature we try to reach. """ + return self.target_temperature + + @property + def target_temperature_high(self): + """ Returns the upper bound temperature we try to reach. """ + return self.target_temperature + @property def is_away_mode_on(self): """ diff --git a/homeassistant/components/thermostat/nest.py b/homeassistant/components/thermostat/nest.py index 72f10033a91..39480daa731 100644 --- a/homeassistant/components/thermostat/nest.py +++ b/homeassistant/components/thermostat/nest.py @@ -8,6 +8,10 @@ import logging from homeassistant.components.thermostat import ThermostatDevice from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD, TEMP_CELCIUS) +STATE_HEAT = "heat" +STATE_COOL = "cool" +STATE_IDLE = "idle" + REQUIREMENTS = ['python-nest==2.6.0'] @@ -83,25 +87,52 @@ class NestThermostat(ThermostatDevice): """ Returns the current temperature. """ return round(self.device.temperature, 1) + @property + def operation(self): + """ Returns current operation ie. heat, cool, idle """ + if self.device.hvac_ac_state is True: + return STATE_COOL + elif self.device.hvac_heater_state is True: + return STATE_HEAT + else: + return STATE_IDLE + @property def target_temperature(self): """ Returns the temperature we try to reach. """ target = self.device.target - if isinstance(target, tuple): + if self.device.mode == 'range': low, high = target - - if self.current_temperature < low: - temp = low - elif self.current_temperature > high: + if self.operation == STATE_COOL: temp = high + elif self.operation == STATE_HEAT: + temp = low else: - temp = (low + high)/2 + range_average = (low + high)/2 + if self.current_temperature < range_average: + temp = low + elif self.current_temperature > range_average: + temp = high else: temp = target return round(temp, 1) + @property + def target_temperature_low(self): + """ Returns the lower bound temperature we try to reach. """ + if self.device.mode == 'range': + return self.device.target["low"] + return round(self.target_temperature, 1) + + @property + def target_temperature_high(self): + """ Returns the upper bound temperature we try to reach. """ + if self.device.mode == 'range': + return self.device.target["high"] + return round(self.target_temperature, 1) + @property def is_away_mode_on(self): """ Returns if away mode is on. """ @@ -109,6 +140,11 @@ class NestThermostat(ThermostatDevice): def set_temperature(self, temperature): """ Set new target temperature """ + if self.device.mode == 'range': + if self.target_temperature == self.target_temperature_low: + temperature = (temperature, self.target_temperature_high) + elif self.target_temperature == self.target_temperature_high: + temperature = (self.target_temperature_low, temperature) self.device.target = temperature def turn_away_mode_on(self): From 21812ba71729a3b90ecefeffef1828d3bd71c6ef Mon Sep 17 00:00:00 2001 From: zyell Date: Thu, 10 Sep 2015 15:42:34 -0700 Subject: [PATCH 2/4] Bug fixes and state adjustment for initial thermostat range support --- homeassistant/components/thermostat/__init__.py | 7 ++----- homeassistant/components/thermostat/nest.py | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/thermostat/__init__.py b/homeassistant/components/thermostat/__init__.py index 93e264091b9..bb981d25572 100644 --- a/homeassistant/components/thermostat/__init__.py +++ b/homeassistant/components/thermostat/__init__.py @@ -114,7 +114,7 @@ class ThermostatDevice(Entity): @property def state(self): """ Returns the current state. """ - return self.operation + return self.target_temperature @property def device_state_attributes(self): @@ -147,10 +147,7 @@ class ThermostatDevice(Entity): ATTR_TEMPERATURE_HIGH: round(convert(self.target_temperature_high, thermostat_unit, user_unit), 0), - ATTR_OPERATION: round(convert(self.operation, - thermostat_unit, - user_unit), 0) - + ATTR_OPERATION: self.operation } is_away = self.is_away_mode_on diff --git a/homeassistant/components/thermostat/nest.py b/homeassistant/components/thermostat/nest.py index 39480daa731..428f32694f4 100644 --- a/homeassistant/components/thermostat/nest.py +++ b/homeassistant/components/thermostat/nest.py @@ -123,14 +123,14 @@ class NestThermostat(ThermostatDevice): def target_temperature_low(self): """ Returns the lower bound temperature we try to reach. """ if self.device.mode == 'range': - return self.device.target["low"] + return round(self.device.target[0], 1) return round(self.target_temperature, 1) @property def target_temperature_high(self): """ Returns the upper bound temperature we try to reach. """ if self.device.mode == 'range': - return self.device.target["high"] + return round(self.device.target[1], 1) return round(self.target_temperature, 1) @property From 775d3198ae378bd6a39460bff49a089eaf6c4726 Mon Sep 17 00:00:00 2001 From: zyell Date: Thu, 10 Sep 2015 17:46:59 -0700 Subject: [PATCH 3/4] Fix logic coverage in target_temperature --- homeassistant/components/thermostat/nest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/thermostat/nest.py b/homeassistant/components/thermostat/nest.py index 428f32694f4..9c4dbfaf937 100644 --- a/homeassistant/components/thermostat/nest.py +++ b/homeassistant/components/thermostat/nest.py @@ -112,7 +112,7 @@ class NestThermostat(ThermostatDevice): range_average = (low + high)/2 if self.current_temperature < range_average: temp = low - elif self.current_temperature > range_average: + elif self.current_temperature >= range_average: temp = high else: temp = target From de89de890fd33e31e01760c8004ec2bdc6a9bae0 Mon Sep 17 00:00:00 2001 From: zyell Date: Sat, 12 Sep 2015 07:27:05 -0700 Subject: [PATCH 4/4] Move state constants to __init__ for all thermostats --- homeassistant/components/thermostat/__init__.py | 4 ++++ homeassistant/components/thermostat/nest.py | 7 ++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/thermostat/__init__.py b/homeassistant/components/thermostat/__init__.py index bb981d25572..940c656ad94 100644 --- a/homeassistant/components/thermostat/__init__.py +++ b/homeassistant/components/thermostat/__init__.py @@ -23,6 +23,10 @@ SCAN_INTERVAL = 60 SERVICE_SET_AWAY_MODE = "set_away_mode" SERVICE_SET_TEMPERATURE = "set_temperature" +STATE_HEAT = "heat" +STATE_COOL = "cool" +STATE_IDLE = "idle" + ATTR_CURRENT_TEMPERATURE = "current_temperature" ATTR_AWAY_MODE = "away_mode" ATTR_MAX_TEMP = "max_temp" diff --git a/homeassistant/components/thermostat/nest.py b/homeassistant/components/thermostat/nest.py index 9c4dbfaf937..c724a4f6dea 100644 --- a/homeassistant/components/thermostat/nest.py +++ b/homeassistant/components/thermostat/nest.py @@ -5,13 +5,10 @@ Adds support for Nest thermostats. """ import logging -from homeassistant.components.thermostat import ThermostatDevice +from homeassistant.components.thermostat import (ThermostatDevice, STATE_COOL, + STATE_IDLE, STATE_HEAT) from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD, TEMP_CELCIUS) -STATE_HEAT = "heat" -STATE_COOL = "cool" -STATE_IDLE = "idle" - REQUIREMENTS = ['python-nest==2.6.0']