From ba2820810623a4bf9d822661b15ce6611cda5f7b Mon Sep 17 00:00:00 2001 From: John Arild Berentsen Date: Fri, 9 Sep 2016 19:06:53 +0200 Subject: [PATCH] Added stuff for support range setting (#3189) --- homeassistant/components/climate/__init__.py | 61 +++++++++++------- homeassistant/components/climate/demo.py | 38 ++++++++--- homeassistant/components/climate/ecobee.py | 25 ++++++-- .../components/climate/eq3btsmart.py | 7 +- .../components/climate/generic_thermostat.py | 8 ++- homeassistant/components/climate/heatmiser.py | 10 +-- homeassistant/components/climate/homematic.py | 7 +- homeassistant/components/climate/honeywell.py | 13 +++- homeassistant/components/climate/knx.py | 7 +- homeassistant/components/climate/nest.py | 8 ++- homeassistant/components/climate/proliphix.py | 7 +- .../components/climate/radiotherm.py | 7 +- homeassistant/components/climate/zwave.py | 57 ++++++++++------- tests/components/climate/test_demo.py | 64 ++++++++++++++++--- tests/components/climate/test_honeywell.py | 8 +-- 15 files changed, 231 insertions(+), 96 deletions(-) diff --git a/homeassistant/components/climate/__init__.py b/homeassistant/components/climate/__init__.py index e4215bcea859b4..726ed4f674cf07 100644 --- a/homeassistant/components/climate/__init__.py +++ b/homeassistant/components/climate/__init__.py @@ -12,7 +12,6 @@ from homeassistant.helpers.entity_component import EntityComponent from homeassistant.config import load_yaml_config_file -import homeassistant.util as util from homeassistant.util.temperature import convert as convert_temperature from homeassistant.helpers.entity import Entity from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa @@ -44,6 +43,8 @@ ATTR_CURRENT_TEMPERATURE = "current_temperature" ATTR_MAX_TEMP = "max_temp" ATTR_MIN_TEMP = "min_temp" +ATTR_TARGET_TEMP_HIGH = "target_temp_high" +ATTR_TARGET_TEMP_LOW = "target_temp_low" ATTR_AWAY_MODE = "away_mode" ATTR_AUX_HEAT = "aux_heat" ATTR_FAN_MODE = "fan_mode" @@ -68,8 +69,10 @@ vol.Required(ATTR_AUX_HEAT): cv.boolean, }) SET_TEMPERATURE_SCHEMA = vol.Schema({ + vol.Exclusive(ATTR_TEMPERATURE, 'temperature'): vol.Coerce(float), + vol.Inclusive(ATTR_TARGET_TEMP_HIGH, 'temperature'): vol.Coerce(float), + vol.Inclusive(ATTR_TARGET_TEMP_LOW, 'temperature'): vol.Coerce(float), vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, - vol.Required(ATTR_TEMPERATURE): vol.Coerce(float), }) SET_FAN_MODE_SCHEMA = vol.Schema({ vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, @@ -113,14 +116,19 @@ def set_aux_heat(hass, aux_heat, entity_id=None): hass.services.call(DOMAIN, SERVICE_SET_AUX_HEAT, data) -def set_temperature(hass, temperature, entity_id=None): +def set_temperature(hass, temperature=None, entity_id=None, + target_temp_high=None, target_temp_low=None): """Set new target temperature.""" - data = {ATTR_TEMPERATURE: temperature} - - if entity_id is not None: - data[ATTR_ENTITY_ID] = entity_id - - hass.services.call(DOMAIN, SERVICE_SET_TEMPERATURE, data) + kwargs = { + key: value for key, value in [ + (ATTR_TEMPERATURE, temperature), + (ATTR_TARGET_TEMP_HIGH, target_temp_high), + (ATTR_TARGET_TEMP_LOW, target_temp_low), + (ATTR_ENTITY_ID, entity_id), + ] if value is not None + } + _LOGGER.debug("set_temperature start data=%s", kwargs) + hass.services.call(DOMAIN, SERVICE_SET_TEMPERATURE, kwargs) def set_humidity(hass, humidity, entity_id=None): @@ -227,20 +235,9 @@ def aux_heat_set_service(service): def temperature_set_service(service): """Set temperature on the target climate devices.""" target_climate = component.extract_from_service(service) - - temperature = util.convert( - service.data.get(ATTR_TEMPERATURE), float) - - if temperature is None: - _LOGGER.error( - "Received call to %s without attribute %s", - SERVICE_SET_TEMPERATURE, ATTR_TEMPERATURE) - return - + kwargs = service.data for climate in target_climate: - climate.set_temperature(convert_temperature( - temperature, hass.config.units.temperature_unit, - climate.unit_of_measurement)) + climate.set_temperature(**kwargs) if climate.should_poll: climate.update_ha_state(True) @@ -351,7 +348,7 @@ class ClimateDevice(Entity): @property def state(self): """Return the current state.""" - return self.target_temperature or STATE_UNKNOWN + return self.current_operation or STATE_UNKNOWN @property def state_attributes(self): @@ -364,6 +361,12 @@ def state_attributes(self): ATTR_TEMPERATURE: self._convert_for_display(self.target_temperature), } + target_temp_high = self.target_temperature_high + if target_temp_high is not None: + data[ATTR_TARGET_TEMP_HIGH] = self._convert_for_display( + self.target_temperature_high) + data[ATTR_TARGET_TEMP_LOW] = self._convert_for_display( + self.target_temperature_low) humidity = self.target_humidity if humidity is not None: @@ -432,6 +435,16 @@ def target_temperature(self): """Return the temperature we try to reach.""" return None + @property + def target_temperature_high(self): + """Return the highbound target temperature we try to reach.""" + return None + + @property + def target_temperature_low(self): + """Return the lowbound target temperature we try to reach.""" + return None + @property def is_away_mode_on(self): """Return true if away mode is on.""" @@ -462,7 +475,7 @@ def swing_list(self): """List of available swing modes.""" return None - def set_temperature(self, temperature): + def set_temperature(self, **kwargs): """Set new target temperature.""" raise NotImplementedError() diff --git a/homeassistant/components/climate/demo.py b/homeassistant/components/climate/demo.py index 340cc29f582787..cb85a153cc8036 100644 --- a/homeassistant/components/climate/demo.py +++ b/homeassistant/components/climate/demo.py @@ -4,17 +4,20 @@ For more details about this platform, please refer to the documentation https://home-assistant.io/components/demo/ """ -from homeassistant.components.climate import ClimateDevice -from homeassistant.const import TEMP_CELSIUS, TEMP_FAHRENHEIT +from homeassistant.components.climate import ( + ClimateDevice, ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW) +from homeassistant.const import TEMP_CELSIUS, TEMP_FAHRENHEIT, ATTR_TEMPERATURE def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Demo climate devices.""" add_devices([ DemoClimate("HeatPump", 68, TEMP_FAHRENHEIT, None, 77, "Auto Low", - None, None, "Auto", "Heat", None), + None, None, "Auto", "heat", None, None, None), DemoClimate("Hvac", 21, TEMP_CELSIUS, True, 22, "On High", - 67, 54, "Off", "Cool", False), + 67, 54, "Off", "cool", False, None, None), + DemoClimate("Ecobee", 23, TEMP_CELSIUS, None, 23, "Auto Low", + None, None, "Auto", "auto", None, 24, 21) ]) @@ -26,7 +29,7 @@ class DemoClimate(ClimateDevice): def __init__(self, name, target_temperature, unit_of_measurement, away, current_temperature, current_fan_mode, target_humidity, current_humidity, current_swing_mode, - current_operation, aux): + current_operation, aux, target_temp_high, target_temp_low): """Initialize the climate device.""" self._name = name self._target_temperature = target_temperature @@ -40,8 +43,10 @@ def __init__(self, name, target_temperature, unit_of_measurement, self._aux = aux self._current_swing_mode = current_swing_mode self._fan_list = ["On Low", "On High", "Auto Low", "Auto High", "Off"] - self._operation_list = ["Heat", "Cool", "Auto Changeover", "Off"] + self._operation_list = ["heat", "cool", "auto", "off"] self._swing_list = ["Auto", "1", "2", "3", "Off"] + self._target_temperature_high = target_temp_high + self._target_temperature_low = target_temp_low @property def should_poll(self): @@ -68,6 +73,16 @@ def target_temperature(self): """Return the temperature we try to reach.""" return self._target_temperature + @property + def target_temperature_high(self): + """Return the highbound target temperature we try to reach.""" + return self._target_temperature_high + + @property + def target_temperature_low(self): + """Return the lowbound target temperature we try to reach.""" + return self._target_temperature_low + @property def current_humidity(self): """Return the current humidity.""" @@ -108,9 +123,14 @@ def fan_list(self): """List of available fan modes.""" return self._fan_list - def set_temperature(self, temperature): - """Set new target temperature.""" - self._target_temperature = temperature + def set_temperature(self, **kwargs): + """Set new target temperatures.""" + if kwargs.get(ATTR_TEMPERATURE) is not None: + self._target_temperature = kwargs.get(ATTR_TEMPERATURE) + if kwargs.get(ATTR_TARGET_TEMP_HIGH) is not None and \ + kwargs.get(ATTR_TARGET_TEMP_LOW) is not None: + self._target_temperature_high = kwargs.get(ATTR_TARGET_TEMP_HIGH) + self._target_temperature_low = kwargs.get(ATTR_TARGET_TEMP_LOW) self.update_ha_state() def set_humidity(self, humidity): diff --git a/homeassistant/components/climate/ecobee.py b/homeassistant/components/climate/ecobee.py index 08bb93d5458593..5d78aeb8597deb 100644 --- a/homeassistant/components/climate/ecobee.py +++ b/homeassistant/components/climate/ecobee.py @@ -11,9 +11,10 @@ from homeassistant.components import ecobee from homeassistant.components.climate import ( - DOMAIN, STATE_COOL, STATE_HEAT, STATE_IDLE, ClimateDevice) + DOMAIN, STATE_COOL, STATE_HEAT, STATE_IDLE, ClimateDevice, + ATTR_TARGET_TEMP_LOW, ATTR_TARGET_TEMP_HIGH) from homeassistant.const import ( - ATTR_ENTITY_ID, STATE_OFF, STATE_ON, TEMP_FAHRENHEIT) + ATTR_ENTITY_ID, STATE_OFF, STATE_ON, TEMP_FAHRENHEIT, ATTR_TEMPERATURE) from homeassistant.config import load_yaml_config_file import homeassistant.helpers.config_validation as cv @@ -145,7 +146,11 @@ def fan(self): @property def current_operation(self): """Return current operation.""" - return self.operation_mode + if self.operation_mode == 'auxHeatOnly' or \ + self.operation_mode == 'heatPump': + return STATE_HEAT + else: + return self.operation_mode @property def operation_list(self): @@ -214,11 +219,17 @@ def turn_away_mode_off(self): """Turn away off.""" self.data.ecobee.resume_program(self.thermostat_index) - def set_temperature(self, temperature): + def set_temperature(self, **kwargs): """Set new target temperature.""" - temperature = int(temperature) - low_temp = temperature - 1 - high_temp = temperature + 1 + if kwargs.get(ATTR_TEMPERATURE) is not None: + temperature = kwargs.get(ATTR_TEMPERATURE) + low_temp = temperature - 1 + high_temp = temperature + 1 + if kwargs.get(ATTR_TARGET_TEMP_LOW) is not None and \ + kwargs.get(ATTR_TARGET_TEMP_HIGH) is not None: + low_temp = kwargs.get(ATTR_TARGET_TEMP_LOW) + high_temp = kwargs.get(ATTR_TARGET_TEMP_HIGH) + if self.hold_temp: self.data.ecobee.set_hold_temp(self.thermostat_index, low_temp, high_temp, "indefinite") diff --git a/homeassistant/components/climate/eq3btsmart.py b/homeassistant/components/climate/eq3btsmart.py index ee7fb7050f57e3..646bf7f2aa851e 100644 --- a/homeassistant/components/climate/eq3btsmart.py +++ b/homeassistant/components/climate/eq3btsmart.py @@ -7,7 +7,7 @@ import logging from homeassistant.components.climate import ClimateDevice -from homeassistant.const import TEMP_CELSIUS, CONF_DEVICES +from homeassistant.const import TEMP_CELSIUS, CONF_DEVICES, ATTR_TEMPERATURE from homeassistant.util.temperature import convert REQUIREMENTS = ['bluepy_devices==0.2.0'] @@ -60,8 +60,11 @@ def target_temperature(self): """Return the temperature we try to reach.""" return self._thermostat.target_temperature - def set_temperature(self, temperature): + def set_temperature(self, **kwargs): """Set new target temperature.""" + temperature = kwargs.get(ATTR_TEMPERATURE) + if temperature is None: + return self._thermostat.target_temperature = temperature @property diff --git a/homeassistant/components/climate/generic_thermostat.py b/homeassistant/components/climate/generic_thermostat.py index 11e6707ad47d70..fd85d7fd46b490 100644 --- a/homeassistant/components/climate/generic_thermostat.py +++ b/homeassistant/components/climate/generic_thermostat.py @@ -11,7 +11,8 @@ from homeassistant.components import switch from homeassistant.components.climate import ( STATE_HEAT, STATE_COOL, STATE_IDLE, ClimateDevice) -from homeassistant.const import ATTR_UNIT_OF_MEASUREMENT, STATE_ON, STATE_OFF +from homeassistant.const import ( + ATTR_UNIT_OF_MEASUREMENT, STATE_ON, STATE_OFF, ATTR_TEMPERATURE) from homeassistant.helpers import condition from homeassistant.helpers.event import track_state_change @@ -123,8 +124,11 @@ def target_temperature(self): """Return the temperature we try to reach.""" return self._target_temp - def set_temperature(self, temperature): + def set_temperature(self, **kwargs): """Set new target temperature.""" + temperature = kwargs.get(ATTR_TEMPERATURE) + if temperature is None: + return self._target_temp = temperature self._control_heating() self.update_ha_state() diff --git a/homeassistant/components/climate/heatmiser.py b/homeassistant/components/climate/heatmiser.py index c7dd5534f57fa8..941f211c411690 100644 --- a/homeassistant/components/climate/heatmiser.py +++ b/homeassistant/components/climate/heatmiser.py @@ -10,7 +10,7 @@ import logging from homeassistant.components.climate import ClimateDevice -from homeassistant.const import TEMP_CELSIUS +from homeassistant.const import TEMP_CELSIUS, ATTR_TEMPERATURE CONF_IPADDRESS = 'ipaddress' CONF_PORT = 'port' @@ -98,16 +98,18 @@ def target_temperature(self): """Return the temperature we try to reach.""" return self._target_temperature - def set_temperature(self, temperature): + def set_temperature(self, **kwargs): """Set new target temperature.""" - temperature = int(temperature) + temperature = kwargs.get(ATTR_TEMPERATURE) + if temperature is None: + return self.heatmiser.hmSendAddress( self._id, 18, temperature, 1, self.serport) - self._target_temperature = int(temperature) + self._target_temperature = temperature def update(self): """Get the latest data.""" diff --git a/homeassistant/components/climate/homematic.py b/homeassistant/components/climate/homematic.py index e51ad5e67a5f6f..a8fa47999d23b4 100644 --- a/homeassistant/components/climate/homematic.py +++ b/homeassistant/components/climate/homematic.py @@ -8,7 +8,7 @@ import homeassistant.components.homematic as homematic from homeassistant.components.climate import ClimateDevice, STATE_AUTO from homeassistant.util.temperature import convert -from homeassistant.const import TEMP_CELSIUS, STATE_UNKNOWN +from homeassistant.const import TEMP_CELSIUS, STATE_UNKNOWN, ATTR_TEMPERATURE DEPENDENCIES = ['homematic'] @@ -90,10 +90,13 @@ def target_temperature(self): return None return self._data.get('SET_TEMPERATURE', None) - def set_temperature(self, temperature): + def set_temperature(self, **kwargs): """Set new target temperature.""" + temperature = kwargs.get(ATTR_TEMPERATURE) if not self.available: return None + if temperature is None: + return self._hmdevice.set_temperature(temperature) def set_operation_mode(self, operation_mode): diff --git a/homeassistant/components/climate/honeywell.py b/homeassistant/components/climate/honeywell.py index 1efce2b95de5bd..001bf8806acf7f 100644 --- a/homeassistant/components/climate/honeywell.py +++ b/homeassistant/components/climate/honeywell.py @@ -9,7 +9,8 @@ from homeassistant.components.climate import ClimateDevice from homeassistant.const import ( - CONF_PASSWORD, CONF_USERNAME, TEMP_CELSIUS, TEMP_FAHRENHEIT) + CONF_PASSWORD, CONF_USERNAME, TEMP_CELSIUS, TEMP_FAHRENHEIT, + ATTR_TEMPERATURE) REQUIREMENTS = ['evohomeclient==0.2.5', 'somecomfort==0.2.1'] @@ -132,8 +133,11 @@ def target_temperature(self): return None return self._target_temperature - def set_temperature(self, temperature): + def set_temperature(self, **kwargs): """Set new target temperature.""" + temperature = kwargs.get(ATTR_TEMPERATURE) + if temperature is None: + return self.device.set_temperature(self._name, temperature) @property @@ -234,8 +238,11 @@ def current_operation(self: ClimateDevice) -> str: """Return current operation ie. heat, cool, idle.""" return getattr(self._device, 'system_mode', None) - def set_temperature(self, temperature): + def set_temperature(self, **kwargs): """Set target temperature.""" + temperature = kwargs.get(ATTR_TEMPERATURE) + if temperature is None: + return import somecomfort try: if self._device.system_mode == 'cool': diff --git a/homeassistant/components/climate/knx.py b/homeassistant/components/climate/knx.py index 10f02d80cc7758..a9d4358a059966 100644 --- a/homeassistant/components/climate/knx.py +++ b/homeassistant/components/climate/knx.py @@ -7,7 +7,7 @@ import logging from homeassistant.components.climate import ClimateDevice -from homeassistant.const import TEMP_CELSIUS +from homeassistant.const import TEMP_CELSIUS, ATTR_TEMPERATURE from homeassistant.components.knx import ( KNXConfig, KNXMultiAddressDevice) @@ -71,8 +71,11 @@ def target_temperature(self): return knx2_to_float(self.value("setpoint")) - def set_temperature(self, temperature): + def set_temperature(self, **kwargs): """Set new target temperature.""" + temperature = kwargs.get(ATTR_TEMPERATURE) + if temperature is None: + return from knxip.conversion import float_to_knx2 self.set_value("setpoint", float_to_knx2(temperature)) diff --git a/homeassistant/components/climate/nest.py b/homeassistant/components/climate/nest.py index 585ff804526d8f..f55d1d856eb9b8 100644 --- a/homeassistant/components/climate/nest.py +++ b/homeassistant/components/climate/nest.py @@ -9,7 +9,8 @@ import homeassistant.components.nest as nest from homeassistant.components.climate import ( STATE_COOL, STATE_HEAT, STATE_IDLE, ClimateDevice, PLATFORM_SCHEMA) -from homeassistant.const import TEMP_CELSIUS, CONF_SCAN_INTERVAL +from homeassistant.const import ( + TEMP_CELSIUS, CONF_SCAN_INTERVAL, ATTR_TEMPERATURE) DEPENDENCIES = ['nest'] @@ -131,8 +132,11 @@ def is_away_mode_on(self): """Return if away mode is on.""" return self.structure.away - def set_temperature(self, temperature): + def set_temperature(self, **kwargs): """Set new target temperature.""" + temperature = kwargs.get(ATTR_TEMPERATURE) + if temperature is None: + return if self.device.mode == 'range': if self.target_temperature == self.target_temperature_low: temperature = (temperature, self.target_temperature_high) diff --git a/homeassistant/components/climate/proliphix.py b/homeassistant/components/climate/proliphix.py index c6e8ed6961704b..fa2230fba55d64 100644 --- a/homeassistant/components/climate/proliphix.py +++ b/homeassistant/components/climate/proliphix.py @@ -7,7 +7,7 @@ from homeassistant.components.climate import ( STATE_COOL, STATE_HEAT, STATE_IDLE, ClimateDevice) from homeassistant.const import ( - CONF_HOST, CONF_PASSWORD, CONF_USERNAME, TEMP_FAHRENHEIT) + CONF_HOST, CONF_PASSWORD, CONF_USERNAME, TEMP_FAHRENHEIT, ATTR_TEMPERATURE) REQUIREMENTS = ['proliphix==0.3.1'] @@ -85,6 +85,9 @@ def current_operation(self): elif state == 6: return STATE_COOL - def set_temperature(self, temperature): + def set_temperature(self, **kwargs): """Set new target temperature.""" + temperature = kwargs.get(ATTR_TEMPERATURE) + if temperature is None: + return self._pdp.setback = temperature diff --git a/homeassistant/components/climate/radiotherm.py b/homeassistant/components/climate/radiotherm.py index deee3d53f3fab7..90611ce20b2c4a 100644 --- a/homeassistant/components/climate/radiotherm.py +++ b/homeassistant/components/climate/radiotherm.py @@ -11,7 +11,7 @@ from homeassistant.components.climate import ( STATE_AUTO, STATE_COOL, STATE_HEAT, STATE_IDLE, STATE_OFF, ClimateDevice) -from homeassistant.const import CONF_HOST, TEMP_FAHRENHEIT +from homeassistant.const import CONF_HOST, TEMP_FAHRENHEIT, ATTR_TEMPERATURE REQUIREMENTS = ['radiotherm==1.2'] HOLD_TEMP = 'hold_temp' @@ -107,8 +107,11 @@ def update(self): else: self._current_operation = STATE_IDLE - def set_temperature(self, temperature): + def set_temperature(self, **kwargs): """Set new target temperature.""" + temperature = kwargs.get(ATTR_TEMPERATURE) + if temperature is None: + return if self._current_operation == STATE_COOL: self.device.t_cool = temperature elif self._current_operation == STATE_HEAT: diff --git a/homeassistant/components/climate/zwave.py b/homeassistant/components/climate/zwave.py index 3a1152c7a96c89..0ba85105c1883e 100755 --- a/homeassistant/components/climate/zwave.py +++ b/homeassistant/components/climate/zwave.py @@ -12,7 +12,8 @@ from homeassistant.components.zwave import ( ATTR_NODE_ID, ATTR_VALUE_ID, ZWaveDeviceEntity) from homeassistant.components import zwave -from homeassistant.const import TEMP_CELSIUS, TEMP_FAHRENHEIT +from homeassistant.const import ( + TEMP_CELSIUS, TEMP_FAHRENHEIT, ATTR_TEMPERATURE) _LOGGER = logging.getLogger(__name__) @@ -96,6 +97,7 @@ def __init__(self, value, temp_unit): self._current_swing_mode = None self._swing_list = None self._unit = temp_unit + self._index_operation = None _LOGGER.debug("temp_unit is %s", self._unit) self._zxt_120 = None self._hrt4_zw = None @@ -132,6 +134,8 @@ def update_properties(self): for value in self._node.get_values( class_id=COMMAND_CLASS_THERMOSTAT_MODE).values(): self._current_operation = value.data + self._index_operation = SET_TEMP_TO_INDEX.get( + self._current_operation) self._operation_list = list(value.data_items) _LOGGER.debug("self._operation_list=%s", self._operation_list) _LOGGER.debug("self._current_operation=%s", @@ -165,22 +169,14 @@ def update_properties(self): class_id=COMMAND_CLASS_THERMOSTAT_SETPOINT).values(): if self.current_operation is not None and \ self.current_operation != 'Off': - if SET_TEMP_TO_INDEX.get(self._current_operation) \ - != value.index: + if self._index_operation != value.index: continue if self._zxt_120: - continue + break self._target_temperature = int(value.data) - _LOGGER.debug("Get setpoint value: SET_TEMP_TO_INDEX=%s and" - " self._current_operation=%s", - SET_TEMP_TO_INDEX.get(self._current_operation), - self._current_operation) break - _LOGGER.debug("Get setpoint value not matching any " - "SET_TEMP_TO_INDEX=%s and " - "self._current_operation=%s. Using value.data=%s", - SET_TEMP_TO_INDEX.get(self._current_operation), - self._current_operation, int(value.data)) + _LOGGER.debug("Device can't set setpoint based on operation mode." + " Defaulting to index=1") self._target_temperature = int(value.data) @property @@ -238,31 +234,48 @@ def target_temperature(self): """Return the temperature we try to reach.""" return self._target_temperature - def set_temperature(self, temperature): +# pylint: disable=too-many-branches, too-many-statements + def set_temperature(self, **kwargs): """Set new target temperature.""" + if kwargs.get(ATTR_TEMPERATURE) is not None: + temperature = kwargs.get(ATTR_TEMPERATURE) + else: + return + for value in self._node.get_values( class_id=COMMAND_CLASS_THERMOSTAT_SETPOINT).values(): if self.current_operation is not None: if self._hrt4_zw and self.current_operation == 'Off': # HRT4-ZW can change setpoint when off. value.data = int(temperature) - if SET_TEMP_TO_INDEX.get(self._current_operation) \ - != value.index: + if self._index_operation != value.index: continue - _LOGGER.debug("SET_TEMP_TO_INDEX=%s and" + _LOGGER.debug("self._index_operation=%s and" " self._current_operation=%s", - SET_TEMP_TO_INDEX.get(self._current_operation), + self._index_operation, self._current_operation) if self._zxt_120: + _LOGGER.debug("zxt_120: Setting new setpoint for %s, " + " operation=%s, temp=%s", + self._index_operation, + self._current_operation, temperature) # ZXT-120 does not support get setpoint self._target_temperature = temperature # ZXT-120 responds only to whole int - value.data = int(round(temperature, 0)) + value.data = round(temperature, 0) + break else: - value.data = int(temperature) - break + _LOGGER.debug("Setting new setpoint for %s, " + "operation=%s, temp=%s", + self._index_operation, + self._current_operation, temperature) + value.data = temperature + break else: - value.data = int(temperature) + _LOGGER.debug("Setting new setpoint for no known " + "operation mode. Index=1 and " + "temperature=%s", temperature) + value.data = temperature break def set_fan_mode(self, fan): diff --git a/tests/components/climate/test_demo.py b/tests/components/climate/test_demo.py index 4b3d4fcc64aed4..dbb9f8a192eff7 100644 --- a/tests/components/climate/test_demo.py +++ b/tests/components/climate/test_demo.py @@ -10,6 +10,7 @@ ENTITY_CLIMATE = 'climate.hvac' +ENTITY_ECOBEE = 'climate.ecobee' class TestDemoClimate(unittest.TestCase): @@ -37,7 +38,7 @@ def test_setup_params(self): self.assertEqual(67, state.attributes.get('humidity')) self.assertEqual(54, state.attributes.get('current_humidity')) self.assertEqual("Off", state.attributes.get('swing_mode')) - self.assertEqual("Cool", state.attributes.get('operation_mode')) + self.assertEqual("cool", state.attributes.get('operation_mode')) self.assertEqual('off', state.attributes.get('aux_heat')) def test_default_setup_params(self): @@ -48,7 +49,7 @@ def test_default_setup_params(self): self.assertEqual(30, state.attributes.get('min_humidity')) self.assertEqual(99, state.attributes.get('max_humidity')) - def test_set_target_temp_bad_attr(self): + def test_set_only_target_temp_bad_attr(self): """Test setting the target temperature without required attribute.""" state = self.hass.states.get(ENTITY_CLIMATE) self.assertEqual(21, state.attributes.get('temperature')) @@ -56,23 +57,55 @@ def test_set_target_temp_bad_attr(self): self.hass.pool.block_till_done() self.assertEqual(21, state.attributes.get('temperature')) - def test_set_target_temp(self): + def test_set_only_target_temp(self): """Test the setting of the target temperature.""" + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual(21, state.attributes.get('temperature')) climate.set_temperature(self.hass, 30, ENTITY_CLIMATE) self.hass.pool.block_till_done() state = self.hass.states.get(ENTITY_CLIMATE) self.assertEqual(30.0, state.attributes.get('temperature')) + def test_set_target_temp_range(self): + """Test the setting of the target temperature with range.""" + state = self.hass.states.get(ENTITY_ECOBEE) + self.assertEqual(23.0, state.attributes.get('temperature')) + self.assertEqual(21.0, state.attributes.get('target_temp_low')) + self.assertEqual(24.0, state.attributes.get('target_temp_high')) + climate.set_temperature(self.hass, 30, ENTITY_ECOBEE, 25, 20) + self.hass.pool.block_till_done() + state = self.hass.states.get(ENTITY_ECOBEE) + self.assertEqual(30.0, state.attributes.get('temperature')) + self.assertEqual(20.0, state.attributes.get('target_temp_low')) + self.assertEqual(25.0, state.attributes.get('target_temp_high')) + + def test_set_target_temp_range_bad_attr(self): + """Test setting the target temperature range without required + attribute.""" + state = self.hass.states.get(ENTITY_ECOBEE) + self.assertEqual(23, state.attributes.get('temperature')) + self.assertEqual(21.0, state.attributes.get('target_temp_low')) + self.assertEqual(24.0, state.attributes.get('target_temp_high')) + climate.set_temperature(self.hass, None, ENTITY_ECOBEE, None, None) + self.hass.pool.block_till_done() + state = self.hass.states.get(ENTITY_ECOBEE) + self.assertEqual(23, state.attributes.get('temperature')) + self.assertEqual(21.0, state.attributes.get('target_temp_low')) + self.assertEqual(24.0, state.attributes.get('target_temp_high')) + def test_set_target_humidity_bad_attr(self): """Test setting the target humidity without required attribute.""" state = self.hass.states.get(ENTITY_CLIMATE) self.assertEqual(67, state.attributes.get('humidity')) climate.set_humidity(self.hass, None, ENTITY_CLIMATE) self.hass.pool.block_till_done() + state = self.hass.states.get(ENTITY_CLIMATE) self.assertEqual(67, state.attributes.get('humidity')) def test_set_target_humidity(self): """Test the setting of the target humidity.""" + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual(67, state.attributes.get('humidity')) climate.set_humidity(self.hass, 64, ENTITY_CLIMATE) self.hass.pool.block_till_done() state = self.hass.states.get(ENTITY_CLIMATE) @@ -84,10 +117,13 @@ def test_set_fan_mode_bad_attr(self): self.assertEqual("On High", state.attributes.get('fan_mode')) climate.set_fan_mode(self.hass, None, ENTITY_CLIMATE) self.hass.pool.block_till_done() + state = self.hass.states.get(ENTITY_CLIMATE) self.assertEqual("On High", state.attributes.get('fan_mode')) def test_set_fan_mode(self): """Test setting of new fan mode.""" + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual("On High", state.attributes.get('fan_mode')) climate.set_fan_mode(self.hass, "On Low", ENTITY_CLIMATE) self.hass.pool.block_till_done() state = self.hass.states.get(ENTITY_CLIMATE) @@ -99,30 +135,40 @@ def test_set_swing_mode_bad_attr(self): self.assertEqual("Off", state.attributes.get('swing_mode')) climate.set_swing_mode(self.hass, None, ENTITY_CLIMATE) self.hass.pool.block_till_done() + state = self.hass.states.get(ENTITY_CLIMATE) self.assertEqual("Off", state.attributes.get('swing_mode')) def test_set_swing(self): """Test setting of new swing mode.""" + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual("Off", state.attributes.get('swing_mode')) climate.set_swing_mode(self.hass, "Auto", ENTITY_CLIMATE) self.hass.pool.block_till_done() state = self.hass.states.get(ENTITY_CLIMATE) self.assertEqual("Auto", state.attributes.get('swing_mode')) - def test_set_operation_bad_attr(self): - """Test setting operation mode without required attribute.""" + def test_set_operation_bad_attr_and_state(self): + """Test setting operation mode without required attribute, and + check the state.""" state = self.hass.states.get(ENTITY_CLIMATE) - self.assertEqual("Cool", state.attributes.get('operation_mode')) + self.assertEqual("cool", state.attributes.get('operation_mode')) + self.assertEqual("cool", state.state) climate.set_operation_mode(self.hass, None, ENTITY_CLIMATE) self.hass.pool.block_till_done() state = self.hass.states.get(ENTITY_CLIMATE) - self.assertEqual("Cool", state.attributes.get('operation_mode')) + self.assertEqual("cool", state.attributes.get('operation_mode')) + self.assertEqual("cool", state.state) def test_set_operation(self): """Test setting of new operation mode.""" - climate.set_operation_mode(self.hass, "Heat", ENTITY_CLIMATE) + state = self.hass.states.get(ENTITY_CLIMATE) + self.assertEqual("cool", state.attributes.get('operation_mode')) + self.assertEqual("cool", state.state) + climate.set_operation_mode(self.hass, "heat", ENTITY_CLIMATE) self.hass.pool.block_till_done() state = self.hass.states.get(ENTITY_CLIMATE) - self.assertEqual("Heat", state.attributes.get('operation_mode')) + self.assertEqual("heat", state.attributes.get('operation_mode')) + self.assertEqual("heat", state.state) def test_set_away_mode_bad_attr(self): """Test setting the away mode without required attribute.""" diff --git a/tests/components/climate/test_honeywell.py b/tests/components/climate/test_honeywell.py index 6c97b65dea78de..75a4d1081f3c6c 100644 --- a/tests/components/climate/test_honeywell.py +++ b/tests/components/climate/test_honeywell.py @@ -274,7 +274,7 @@ def test_away_mode(self): def test_set_temperature(self): """Test setting the temperature.""" - self.round1.set_temperature(25) + self.round1.set_temperature(temperature=25) self.device.set_temperature.assert_called_once_with('House', 25) def test_set_operation_mode(self: unittest.TestCase) -> None: @@ -327,13 +327,13 @@ def test_target_temp(self): def test_set_temp(self): """Test setting the temperature.""" - self.honeywell.set_temperature(70) + self.honeywell.set_temperature(temperature=70) self.assertEqual(70, self.device.setpoint_heat) self.assertEqual(70, self.honeywell.target_temperature) self.device.system_mode = 'cool' self.assertEqual(78, self.honeywell.target_temperature) - self.honeywell.set_temperature(74) + self.honeywell.set_temperature(temperature=74) self.assertEqual(74, self.device.setpoint_cool) self.assertEqual(74, self.honeywell.target_temperature) @@ -351,7 +351,7 @@ def test_set_temp_fail(self): """Test if setting the temperature fails.""" self.device.setpoint_heat = mock.MagicMock( side_effect=somecomfort.SomeComfortError) - self.honeywell.set_temperature(123) + self.honeywell.set_temperature(temperature=123) def test_attributes(self): """Test the attributes."""