From 599542394a2942242cc6fc2731af8cf2902afff5 Mon Sep 17 00:00:00 2001 From: Nick Touran Date: Thu, 8 Nov 2018 00:39:35 -0800 Subject: [PATCH] Added optional precision configuration option to generic_thermostat. (#18317) * Added optional precision configuration option to generic_thermostat. * Added optional precision configuration option to generic_thermostat. * Style update. --- .../components/climate/generic_thermostat.py | 22 ++++++++++--- .../climate/test_generic_thermostat.py | 32 +++++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/climate/generic_thermostat.py b/homeassistant/components/climate/generic_thermostat.py index d421157c2ec..212c4265d8a 100644 --- a/homeassistant/components/climate/generic_thermostat.py +++ b/homeassistant/components/climate/generic_thermostat.py @@ -17,7 +17,8 @@ from homeassistant.components.climate import ( SUPPORT_AWAY_MODE, SUPPORT_TARGET_TEMPERATURE, PLATFORM_SCHEMA) from homeassistant.const import ( STATE_ON, STATE_OFF, ATTR_TEMPERATURE, CONF_NAME, ATTR_ENTITY_ID, - SERVICE_TURN_ON, SERVICE_TURN_OFF, STATE_UNKNOWN) + SERVICE_TURN_ON, SERVICE_TURN_OFF, STATE_UNKNOWN, PRECISION_HALVES, + PRECISION_TENTHS, PRECISION_WHOLE) from homeassistant.helpers import condition from homeassistant.helpers.event import ( async_track_state_change, async_track_time_interval) @@ -43,6 +44,7 @@ CONF_HOT_TOLERANCE = 'hot_tolerance' CONF_KEEP_ALIVE = 'keep_alive' CONF_INITIAL_OPERATION_MODE = 'initial_operation_mode' CONF_AWAY_TEMP = 'away_temp' +CONF_PRECISION = 'precision' SUPPORT_FLAGS = (SUPPORT_TARGET_TEMPERATURE | SUPPORT_OPERATION_MODE) @@ -63,7 +65,9 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ cv.time_period, cv.positive_timedelta), vol.Optional(CONF_INITIAL_OPERATION_MODE): vol.In([STATE_AUTO, STATE_OFF]), - vol.Optional(CONF_AWAY_TEMP): vol.Coerce(float) + vol.Optional(CONF_AWAY_TEMP): vol.Coerce(float), + vol.Optional(CONF_PRECISION): vol.In( + [PRECISION_TENTHS, PRECISION_HALVES, PRECISION_WHOLE]), }) @@ -83,11 +87,13 @@ async def async_setup_platform(hass, config, async_add_entities, keep_alive = config.get(CONF_KEEP_ALIVE) initial_operation_mode = config.get(CONF_INITIAL_OPERATION_MODE) away_temp = config.get(CONF_AWAY_TEMP) + precision = config.get(CONF_PRECISION) async_add_entities([GenericThermostat( hass, name, heater_entity_id, sensor_entity_id, min_temp, max_temp, target_temp, ac_mode, min_cycle_duration, cold_tolerance, - hot_tolerance, keep_alive, initial_operation_mode, away_temp)]) + hot_tolerance, keep_alive, initial_operation_mode, away_temp, + precision)]) class GenericThermostat(ClimateDevice): @@ -96,7 +102,7 @@ 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, cold_tolerance, hot_tolerance, keep_alive, - initial_operation_mode, away_temp): + initial_operation_mode, away_temp, precision): """Initialize the thermostat.""" self.hass = hass self._name = name @@ -109,6 +115,7 @@ class GenericThermostat(ClimateDevice): self._initial_operation_mode = initial_operation_mode self._saved_target_temp = target_temp if target_temp is not None \ else away_temp + self._temp_precision = precision if self.ac_mode: self._current_operation = STATE_COOL self._operation_list = [STATE_COOL, STATE_OFF] @@ -202,6 +209,13 @@ class GenericThermostat(ClimateDevice): """Return the name of the thermostat.""" return self._name + @property + def precision(self): + """Return the precision of the system.""" + if self._temp_precision is not None: + return self._temp_precision + return super().precision + @property def temperature_unit(self): """Return the unit of measurement.""" diff --git a/tests/components/climate/test_generic_thermostat.py b/tests/components/climate/test_generic_thermostat.py index 3d30a21504a..8d2346260d9 100644 --- a/tests/components/climate/test_generic_thermostat.py +++ b/tests/components/climate/test_generic_thermostat.py @@ -15,6 +15,7 @@ from homeassistant.const import ( STATE_OFF, STATE_IDLE, TEMP_CELSIUS, + TEMP_FAHRENHEIT, ATTR_TEMPERATURE ) from homeassistant import loader @@ -1074,6 +1075,37 @@ async def test_turn_off_when_off(hass, setup_comp_9): state_cool.attributes.get('operation_mode') +@pytest.fixture +def setup_comp_10(hass): + """Initialize components.""" + hass.config.temperature_unit = TEMP_FAHRENHEIT + assert hass.loop.run_until_complete(async_setup_component( + hass, climate.DOMAIN, {'climate': { + 'platform': 'generic_thermostat', + 'name': 'test', + 'cold_tolerance': 0.3, + 'hot_tolerance': 0.3, + 'target_temp': 25, + 'heater': ENT_SWITCH, + 'target_sensor': ENT_SENSOR, + 'min_cycle_duration': datetime.timedelta(minutes=15), + 'keep_alive': datetime.timedelta(minutes=10), + 'precision': 0.1 + }})) + + +async def test_precision(hass, setup_comp_10): + """Test that setting precision to tenths works as intended.""" + common.async_set_operation_mode(hass, STATE_OFF) + await hass.async_block_till_done() + await hass.services.async_call('climate', SERVICE_TURN_OFF) + await hass.async_block_till_done() + common.async_set_temperature(hass, 23.27) + await hass.async_block_till_done() + state = hass.states.get(ENTITY) + assert 23.3 == state.attributes.get('temperature') + + async def test_custom_setup_params(hass): """Test the setup with custom parameters.""" result = await async_setup_component(