Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 35 additions & 13 deletions homeassistant/components/climate/generic_thermostat.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
SUPPORT_AWAY_MODE, SUPPORT_TARGET_TEMPERATURE, PLATFORM_SCHEMA)
from homeassistant.const import (
ATTR_UNIT_OF_MEASUREMENT, STATE_ON, STATE_OFF, ATTR_TEMPERATURE,
CONF_NAME, ATTR_ENTITY_ID, SERVICE_TURN_ON, SERVICE_TURN_OFF)
CONF_NAME, ATTR_ENTITY_ID, SERVICE_TURN_ON, SERVICE_TURN_OFF,
STATE_UNKNOWN)
from homeassistant.helpers import condition
from homeassistant.helpers.event import (
async_track_state_change, async_track_time_interval)
Expand All @@ -30,7 +31,6 @@

DEFAULT_TOLERANCE = 0.3
DEFAULT_NAME = 'Generic Thermostat'
DEFAULT_AWAY_TEMP = 16

CONF_HEATER = 'heater'
CONF_SENSOR = 'target_sensor'
Expand All @@ -44,7 +44,7 @@
CONF_KEEP_ALIVE = 'keep_alive'
CONF_INITIAL_OPERATION_MODE = 'initial_operation_mode'
CONF_AWAY_TEMP = 'away_temp'
SUPPORT_FLAGS = (SUPPORT_TARGET_TEMPERATURE | SUPPORT_AWAY_MODE |
SUPPORT_FLAGS = (SUPPORT_TARGET_TEMPERATURE |
SUPPORT_OPERATION_MODE)

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
Expand All @@ -64,8 +64,7 @@
cv.time_period, cv.positive_timedelta),
vol.Optional(CONF_INITIAL_OPERATION_MODE):
vol.In([STATE_AUTO, STATE_OFF]),
vol.Optional(CONF_AWAY_TEMP,
default=DEFAULT_AWAY_TEMP): vol.Coerce(float)
vol.Optional(CONF_AWAY_TEMP): vol.Coerce(float)
})


Expand Down Expand Up @@ -119,6 +118,7 @@ def __init__(self, hass, name, heater_entity_id, sensor_entity_id,
self._operation_list = [STATE_HEAT, STATE_OFF]
if initial_operation_mode == STATE_OFF:
self._enabled = False
self._current_operation = STATE_OFF
else:
self._enabled = True
self._active = False
Expand All @@ -127,6 +127,9 @@ def __init__(self, hass, name, heater_entity_id, sensor_entity_id,
self._max_temp = max_temp
self._target_temp = target_temp
self._unit = hass.config.units.temperature_unit
self._support_flags = SUPPORT_FLAGS
if away_temp is not None:
self._support_flags = SUPPORT_FLAGS | SUPPORT_AWAY_MODE
self._away_temp = away_temp
self._is_away = False

Expand All @@ -139,6 +142,10 @@ def __init__(self, hass, name, heater_entity_id, sensor_entity_id,
async_track_time_interval(
hass, self._async_keep_alive, self._keep_alive)

sensor_state = hass.states.get(sensor_entity_id)
if sensor_state and sensor_state.state != STATE_UNKNOWN:
self._async_update_temp(sensor_state)

@asyncio.coroutine
def async_added_to_hass(self):
"""Run when entity about to be added."""
Expand All @@ -154,19 +161,33 @@ def async_added_to_hass(self):
self._target_temp = self.max_temp
else:
self._target_temp = self.min_temp
_LOGGER.warning('Undefined target temperature, \
falling back to %s', self._target_temp)
_LOGGER.warning('Undefined target temperature,'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use double quotes for log messages.

'falling back to %s', self._target_temp)
else:
self._target_temp = float(
old_state.attributes[ATTR_TEMPERATURE])
self._is_away = True if str(
old_state.attributes[ATTR_AWAY_MODE]) == STATE_ON else False
if old_state.attributes[ATTR_AWAY_MODE] is not None:
self._is_away = True if str(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self._is_away = str(
    old_state.attributes[ATTR_AWAY_MODE]) == STATE_ON

old_state.attributes[ATTR_AWAY_MODE]) == STATE_ON \
else False
if old_state.attributes[ATTR_OPERATION_MODE] == STATE_OFF:
self._current_operation = STATE_OFF
self._enabled = False
if self._initial_operation_mode is None:
if old_state.attributes[ATTR_OPERATION_MODE] == STATE_OFF:
self._enabled = False
if old_state.attributes[ATTR_OPERATION_MODE] is not None:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Join this with the statement on the previous line using AND.

self._current_operation = \
old_state.attributes[ATTR_OPERATION_MODE]
if self._current_operation != STATE_OFF:
self._enabled = True
else:
# No previous state, try and restore defaults
if self._target_temp is None:
if self.ac_mode:
self._target_temp = self.max_temp
else:
self._target_temp = self.min_temp
_LOGGER.warning("No previously saved temperature, setting to %s",
self._target_temp)

@property
def state(self):
Expand Down Expand Up @@ -308,7 +329,8 @@ def _async_control_heating(self):
self._target_temp):
self._active = True
_LOGGER.info('Obtained current and target temperature. '
'Generic thermostat active.')
'Generic thermostat active. %s, %s',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use double quotes.

self._cur_temp, self._target_temp)

if not self._active:
return
Expand Down Expand Up @@ -365,7 +387,7 @@ def _is_device_active(self):
@property
def supported_features(self):
"""Return the list of supported features."""
return SUPPORT_FLAGS
return self._support_flags

@callback
def _heater_turn_on(self):
Expand Down
11 changes: 7 additions & 4 deletions tests/components/climate/test_generic_thermostat.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ def setUp(self): # pylint: disable=invalid-name
'cold_tolerance': 2,
'hot_tolerance': 4,
'heater': ENT_SWITCH,
'target_sensor': ENT_SENSOR
'target_sensor': ENT_SENSOR,
'away_temp': 16
}})

def tearDown(self): # pylint: disable=invalid-name
Expand All @@ -176,7 +177,7 @@ def test_default_setup_params(self):
state = self.hass.states.get(ENTITY)
self.assertEqual(7, state.attributes.get('min_temp'))
self.assertEqual(35, state.attributes.get('max_temp'))
self.assertEqual(None, state.attributes.get('temperature'))
self.assertEqual(7, state.attributes.get('temperature'))

def test_get_operation_modes(self):
"""Test that the operation list returns the correct modes."""
Expand Down Expand Up @@ -266,7 +267,7 @@ def test_set_target_temp_heater_off(self):
self.hass.block_till_done()
climate.set_temperature(self.hass, 25)
self.hass.block_till_done()
self.assertEqual(1, len(self.calls))
self.assertEqual(2, len(self.calls))
call = self.calls[0]
self.assertEqual('homeassistant', call.domain)
self.assertEqual(SERVICE_TURN_OFF, call.service)
Expand Down Expand Up @@ -414,7 +415,7 @@ def test_set_target_temp_ac_off(self):
self.hass.block_till_done()
climate.set_temperature(self.hass, 30)
self.hass.block_till_done()
self.assertEqual(1, len(self.calls))
self.assertEqual(2, len(self.calls))
call = self.calls[0]
self.assertEqual('homeassistant', call.domain)
self.assertEqual(SERVICE_TURN_OFF, call.service)
Expand Down Expand Up @@ -750,6 +751,7 @@ def setUp(self): # pylint: disable=invalid-name
'cold_tolerance': 0.3,
'hot_tolerance': 0.3,
'heater': ENT_SWITCH,
'target_temp': 25,
'target_sensor': ENT_SENSOR,
'ac_mode': True,
'keep_alive': datetime.timedelta(minutes=10)
Expand Down Expand Up @@ -841,6 +843,7 @@ def setUp(self): # pylint: disable=invalid-name
'name': 'test',
'cold_tolerance': 0.3,
'hot_tolerance': 0.3,
'target_temp': 25,
'heater': ENT_SWITCH,
'target_sensor': ENT_SENSOR,
'keep_alive': datetime.timedelta(minutes=10)
Expand Down