diff --git a/homeassistant/components/climate/generic_thermostat.py b/homeassistant/components/climate/generic_thermostat.py index 6af06323fd0..191960d2848 100644 --- a/homeassistant/components/climate/generic_thermostat.py +++ b/homeassistant/components/climate/generic_thermostat.py @@ -36,7 +36,8 @@ CONF_MAX_TEMP = 'max_temp' CONF_TARGET_TEMP = 'target_temp' CONF_AC_MODE = 'ac_mode' CONF_MIN_DUR = 'min_cycle_duration' -CONF_TOLERANCE = 'tolerance' +CONF_COLD_TOLERANCE = 'cold_tolerance' +CONF_HOT_TOLERANCE = 'hot_tolerance' CONF_KEEP_ALIVE = 'keep_alive' @@ -48,7 +49,10 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_MIN_DUR): vol.All(cv.time_period, cv.positive_timedelta), vol.Optional(CONF_MIN_TEMP): vol.Coerce(float), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_TOLERANCE, default=DEFAULT_TOLERANCE): vol.Coerce(float), + vol.Optional(CONF_COLD_TOLERANCE, default=DEFAULT_TOLERANCE): vol.Coerce( + float), + vol.Optional(CONF_HOT_TOLERANCE, default=DEFAULT_TOLERANCE): vol.Coerce( + float), vol.Optional(CONF_TARGET_TEMP): vol.Coerce(float), vol.Optional(CONF_KEEP_ALIVE): vol.All( cv.time_period, cv.positive_timedelta), @@ -66,12 +70,14 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): target_temp = config.get(CONF_TARGET_TEMP) ac_mode = config.get(CONF_AC_MODE) min_cycle_duration = config.get(CONF_MIN_DUR) - tolerance = config.get(CONF_TOLERANCE) + cold_tolerance = config.get(CONF_COLD_TOLERANCE) + hot_tolerance = config.get(CONF_HOT_TOLERANCE) keep_alive = config.get(CONF_KEEP_ALIVE) async_add_devices([GenericThermostat( hass, name, heater_entity_id, sensor_entity_id, min_temp, max_temp, - target_temp, ac_mode, min_cycle_duration, tolerance, keep_alive)]) + target_temp, ac_mode, min_cycle_duration, cold_tolerance, + hot_tolerance, keep_alive)]) class GenericThermostat(ClimateDevice): @@ -79,14 +85,15 @@ class GenericThermostat(ClimateDevice): def __init__(self, hass, name, heater_entity_id, sensor_entity_id, min_temp, max_temp, target_temp, ac_mode, min_cycle_duration, - tolerance, keep_alive): + cold_tolerance, hot_tolerance, keep_alive): """Initialize the thermostat.""" self.hass = hass self._name = name self.heater_entity_id = heater_entity_id self.ac_mode = ac_mode self.min_cycle_duration = min_cycle_duration - self._tolerance = tolerance + self._cold_tolerance = cold_tolerance + self._hot_tolerance = hot_tolerance self._keep_alive = keep_alive self._enabled = True @@ -261,25 +268,29 @@ class GenericThermostat(ClimateDevice): if self.ac_mode: is_cooling = self._is_device_active if is_cooling: - too_cold = self._target_temp - self._cur_temp > self._tolerance + too_cold = self._target_temp - self._cur_temp >= \ + self._cold_tolerance if too_cold: _LOGGER.info('Turning off AC %s', self.heater_entity_id) switch.async_turn_off(self.hass, self.heater_entity_id) else: - too_hot = self._cur_temp - self._target_temp > self._tolerance + too_hot = self._cur_temp - self._target_temp >= \ + self._hot_tolerance if too_hot: _LOGGER.info('Turning on AC %s', self.heater_entity_id) switch.async_turn_on(self.hass, self.heater_entity_id) else: is_heating = self._is_device_active if is_heating: - too_hot = self._cur_temp - self._target_temp > self._tolerance + too_hot = self._cur_temp - self._target_temp >= \ + self._hot_tolerance if too_hot: _LOGGER.info('Turning off heater %s', self.heater_entity_id) switch.async_turn_off(self.hass, self.heater_entity_id) else: - too_cold = self._target_temp - self._cur_temp > self._tolerance + too_cold = self._target_temp - self._cur_temp >= \ + self._cold_tolerance if too_cold: _LOGGER.info('Turning on heater %s', self.heater_entity_id) switch.async_turn_on(self.hass, self.heater_entity_id) diff --git a/tests/components/climate/test_generic_thermostat.py b/tests/components/climate/test_generic_thermostat.py index 15fc3f6a982..74b2186b8d7 100644 --- a/tests/components/climate/test_generic_thermostat.py +++ b/tests/components/climate/test_generic_thermostat.py @@ -28,7 +28,8 @@ ENT_SWITCH = 'switch.test' MIN_TEMP = 3.0 MAX_TEMP = 65.0 TARGET_TEMP = 42.0 -TOLERANCE = 0.5 +COLD_TOLERANCE = 0.5 +HOT_TOLERANCE = 0.5 class TestSetupClimateGenericThermostat(unittest.TestCase): @@ -88,7 +89,8 @@ class TestClimateGenericThermostat(unittest.TestCase): assert setup_component(self.hass, climate.DOMAIN, {'climate': { 'platform': 'generic_thermostat', 'name': 'test', - 'tolerance': 2, + 'cold_tolerance': 2, + 'hot_tolerance': 4, 'heater': ENT_SWITCH, 'target_sensor': ENT_SENSOR }}) @@ -183,11 +185,11 @@ class TestClimateGenericThermostat(unittest.TestCase): self.assertEqual(0, len(self.calls)) def test_temp_change_heater_on_outside_tolerance(self): - """Test if temperature change turn heater on outside tolerance.""" + """Test if temperature change turn heater on outside cold tolerance.""" self._setup_switch(False) climate.set_temperature(self.hass, 30) self.hass.block_till_done() - self._setup_sensor(25) + self._setup_sensor(27) self.hass.block_till_done() self.assertEqual(1, len(self.calls)) call = self.calls[0] @@ -200,12 +202,12 @@ class TestClimateGenericThermostat(unittest.TestCase): self._setup_switch(True) climate.set_temperature(self.hass, 30) self.hass.block_till_done() - self._setup_sensor(31) + self._setup_sensor(33) self.hass.block_till_done() self.assertEqual(0, len(self.calls)) def test_temp_change_heater_off_outside_tolerance(self): - """Test if temperature change turn heater off outside tolerance.""" + """Test if temperature change turn heater off outside hot tolerance.""" self._setup_switch(True) climate.set_temperature(self.hass, 30) self.hass.block_till_done() @@ -271,7 +273,8 @@ class TestClimateGenericThermostatACMode(unittest.TestCase): assert setup_component(self.hass, climate.DOMAIN, {'climate': { 'platform': 'generic_thermostat', 'name': 'test', - 'tolerance': 0.3, + 'cold_tolerance': 2, + 'hot_tolerance': 4, 'heater': ENT_SWITCH, 'target_sensor': ENT_SENSOR, 'ac_mode': True @@ -321,7 +324,7 @@ class TestClimateGenericThermostatACMode(unittest.TestCase): self._setup_switch(True) climate.set_temperature(self.hass, 30) self.hass.block_till_done() - self._setup_sensor(25) + self._setup_sensor(27) self.hass.block_till_done() self.assertEqual(1, len(self.calls)) call = self.calls[0] @@ -405,7 +408,8 @@ class TestClimateGenericThermostatACModeMinCycle(unittest.TestCase): assert setup_component(self.hass, climate.DOMAIN, {'climate': { 'platform': 'generic_thermostat', 'name': 'test', - 'tolerance': 0.3, + 'cold_tolerance': 0.3, + 'hot_tolerance': 0.3, 'heater': ENT_SWITCH, 'target_sensor': ENT_SENSOR, 'ac_mode': True, @@ -498,7 +502,8 @@ class TestClimateGenericThermostatMinCycle(unittest.TestCase): assert setup_component(self.hass, climate.DOMAIN, {'climate': { 'platform': 'generic_thermostat', 'name': 'test', - 'tolerance': 0.3, + 'cold_tolerance': 0.3, + 'hot_tolerance': 0.3, 'heater': ENT_SWITCH, 'target_sensor': ENT_SENSOR, 'min_cycle_duration': datetime.timedelta(minutes=10) @@ -590,7 +595,8 @@ class TestClimateGenericThermostatACKeepAlive(unittest.TestCase): assert setup_component(self.hass, climate.DOMAIN, {'climate': { 'platform': 'generic_thermostat', 'name': 'test', - 'tolerance': 0.3, + 'cold_tolerance': 0.3, + 'hot_tolerance': 0.3, 'heater': ENT_SWITCH, 'target_sensor': ENT_SENSOR, 'ac_mode': True, @@ -681,7 +687,8 @@ class TestClimateGenericThermostatKeepAlive(unittest.TestCase): assert setup_component(self.hass, climate.DOMAIN, {'climate': { 'platform': 'generic_thermostat', 'name': 'test', - 'tolerance': 0.3, + 'cold_tolerance': 0.3, + 'hot_tolerance': 0.3, 'heater': ENT_SWITCH, 'target_sensor': ENT_SENSOR, 'keep_alive': datetime.timedelta(minutes=10)