From ccedc5d38f147ea65e322c7684747f238c2e846e Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Fri, 26 Jul 2019 20:29:27 +0200 Subject: [PATCH 01/29] Initial commit --- homeassistant/components/climate/const.py | 3 ++ homeassistant/components/zwave/climate.py | 45 ++++++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/climate/const.py b/homeassistant/components/climate/const.py index 7b99442c2d7d3..c82d1410b3405 100644 --- a/homeassistant/components/climate/const.py +++ b/homeassistant/components/climate/const.py @@ -56,6 +56,9 @@ # Device is reacting to activity (e.g. movement sensors) PRESET_ACTIVITY = 'activity' +# Device is in manufacturer specific mode (e.g. setting the valve manually) +PRESET_MANUFACTURER_SPECIFIC = 'Manufacturer Specific' + # Possible fan state FAN_ON = "on" diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index f7d31bf764fa7..5470f9a3efbd8 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -7,7 +7,9 @@ CURRENT_HVAC_COOL, CURRENT_HVAC_FAN, CURRENT_HVAC_HEAT, CURRENT_HVAC_IDLE, CURRENT_HVAC_OFF, DOMAIN, HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_HEAT_COOL, HVAC_MODE_DRY, HVAC_MODE_FAN_ONLY, HVAC_MODE_OFF, - SUPPORT_FAN_MODE, SUPPORT_SWING_MODE, SUPPORT_TARGET_TEMPERATURE) + SUPPORT_FAN_MODE, SUPPORT_SWING_MODE, SUPPORT_TARGET_TEMPERATURE, + SUPPORT_PRESET_MODE, PRESET_BOOST, PRESET_ECO, PRESET_NONE, + PRESET_MANUFACTURER_SPECIFIC) from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT from homeassistant.core import callback from homeassistant.helpers.dispatcher import async_dispatcher_connect @@ -45,7 +47,6 @@ 'Auto': HVAC_MODE_HEAT_COOL, } - HVAC_CURRENT_MAPPINGS = { "Idle": CURRENT_HVAC_IDLE, "Heat": CURRENT_HVAC_HEAT, @@ -59,6 +60,11 @@ "Off": CURRENT_HVAC_OFF, } +PRESET_MAPPING = { + 'Full Power': PRESET_BOOST, + 'Heat Eco': PRESET_ECO, + 'Manufacturer Specific': PRESET_MANUFACTURER_SPECIFIC} + async def async_setup_platform( hass, config, async_add_entities, discovery_info=None): @@ -94,6 +100,7 @@ def __init__(self, values, temp_unit): self._hvac_list = None self._hvac_mapping = None self._hvac_mode = None + self._preset_mode = None self._current_fan_mode = None self._fan_modes = None self._fan_state = None @@ -131,6 +138,9 @@ def update_properties(self): if self.values.mode: self._hvac_list = [] self._hvac_mapping = {} + self._preset_list = [] + self._preset_mapping = {} + hvac_list = self.values.mode.data_items if hvac_list: for mode in hvac_list: @@ -139,11 +149,19 @@ def update_properties(self): self._hvac_mapping[ha_mode] = mode self._hvac_list.append(ha_mode) continue + ha_preset = PRESET_MAPPING.get(mode) + if ha_preset and ha_preset not in self._preset_mapping: + self._preset_mapping[ha_preset] = mode + self._preset_list.append(ha_preset) + continue + # If nothing matches self._hvac_list.append(mode) + current_mode = self.values.mode.data self._hvac_mode = next( (key for key, value in self._hvac_mapping.items() if value == current_mode), current_mode) + # TODO: Set self._preset_mode _LOGGER.debug("self._hvac_list=%s", self._hvac_list) _LOGGER.debug("self._hvac_action=%s", self._hvac_action) @@ -256,6 +274,26 @@ def hvac_action(self): """ return self._hvac_action + @property + def preset_mode(self): + """Return preset operation ie. eco, away. + + Need to be one of PRESET_*. + """ + if self.values.mode: + return self._preset_mode + return PRESET_NONE + + @property + def preset_modes(self): + """Return the list of available preset operation modes. + + Need to be a subset of PRESET_MODES. + """ + if self.values.mode: + return self._preset_list + return [] + @property def target_temperature(self): """Return the temperature we try to reach.""" @@ -279,6 +317,9 @@ def set_hvac_mode(self, hvac_mode): return self.values.mode.data = self._hvac_mapping.get(hvac_mode, hvac_mode) + def set_preset_mode(self, preset_mode): + raise NotImplementedError + def set_swing_mode(self, swing_mode): """Set new target swing mode.""" if self._zxt_120 == 1: From 1eec85323be0eeeaa32ec4c8846b59062b71bf87 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Sat, 27 Jul 2019 00:14:27 +0200 Subject: [PATCH 02/29] Add some more code --- homeassistant/components/zwave/climate.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index 5470f9a3efbd8..3b43c3a3ff355 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -130,6 +130,8 @@ def supported_features(self): support |= SUPPORT_FAN_MODE if self._zxt_120 == 1 and self.values.zxt_120_swing_mode: support |= SUPPORT_SWING_MODE + if self._preset_list: + support |= SUPPORT_PRESET_MODE return support def update_properties(self): @@ -161,7 +163,9 @@ def update_properties(self): self._hvac_mode = next( (key for key, value in self._hvac_mapping.items() if value == current_mode), current_mode) - # TODO: Set self._preset_mode + self._preset_mode = next( + (key for key, value in self._preset_mapping.items() + if value == current_mode), PRESET_NONE) _LOGGER.debug("self._hvac_list=%s", self._hvac_list) _LOGGER.debug("self._hvac_action=%s", self._hvac_action) @@ -318,7 +322,11 @@ def set_hvac_mode(self, hvac_mode): self.values.mode.data = self._hvac_mapping.get(hvac_mode, hvac_mode) def set_preset_mode(self, preset_mode): - raise NotImplementedError + """Set new target preset mode.""" + if not self.values.mode: + return + self.values.mode.data = self._preset_mapping.get( + preset_mode, preset_mode) def set_swing_mode(self, swing_mode): """Set new target swing mode.""" From 8b4ceb222ccf45ec3da0a0341052eed8e3071ddb Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Sun, 28 Jul 2019 13:04:56 +0200 Subject: [PATCH 03/29] Local tests passing --- homeassistant/components/zwave/climate.py | 23 ++++++++++++++++------- tests/components/zwave/test_climate.py | 18 ++++++++++++++++-- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index 3b43c3a3ff355..1c730073af43c 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -147,17 +147,17 @@ def update_properties(self): if hvac_list: for mode in hvac_list: ha_mode = HVAC_STATE_MAPPINGS.get(mode) + ha_preset = PRESET_MAPPING.get(mode) if ha_mode and ha_mode not in self._hvac_mapping: self._hvac_mapping[ha_mode] = mode self._hvac_list.append(ha_mode) - continue - ha_preset = PRESET_MAPPING.get(mode) - if ha_preset and ha_preset not in self._preset_mapping: + elif ha_preset and ha_preset not in self._preset_mapping: self._preset_mapping[ha_preset] = mode self._preset_list.append(ha_preset) - continue - # If nothing matches - self._hvac_list.append(mode) + else: + # If nothing matches + _LOGGER.debug("%s is nothing", mode) + self._hvac_list.append(mode) current_mode = self.values.mode.data self._hvac_mode = next( @@ -167,7 +167,10 @@ def update_properties(self): (key for key, value in self._preset_mapping.items() if value == current_mode), PRESET_NONE) _LOGGER.debug("self._hvac_list=%s", self._hvac_list) + _LOGGER.debug("self._hvac_mapping=%s", self._hvac_mapping) _LOGGER.debug("self._hvac_action=%s", self._hvac_action) + _LOGGER.debug("self._preset_list=%s", self._preset_list) + _LOGGER.debug("self._preset_mapping=%s", self._preset_mapping) # Current Temp if self.values.temperature: @@ -305,24 +308,29 @@ def target_temperature(self): def set_temperature(self, **kwargs): """Set new target temperature.""" + _LOGGER.debug("Set temperature to %s", kwargs.get(ATTR_TEMPERATURE)) if kwargs.get(ATTR_TEMPERATURE) is None: return self.values.primary.data = kwargs.get(ATTR_TEMPERATURE) def set_fan_mode(self, fan_mode): """Set new target fan mode.""" + _LOGGER.debug("Set fan mode to %s", fan_mode) if not self.values.fan_mode: return self.values.fan_mode.data = fan_mode def set_hvac_mode(self, hvac_mode): """Set new target hvac mode.""" + _LOGGER.debug("Set hvac_mode to %s", hvac_mode) if not self.values.mode: return - self.values.mode.data = self._hvac_mapping.get(hvac_mode, hvac_mode) + self.values.mode.data = self._hvac_mapping.get( + hvac_mode, hvac_mode) def set_preset_mode(self, preset_mode): """Set new target preset mode.""" + _LOGGER.debug("Set preset_mode to %s", preset_mode) if not self.values.mode: return self.values.mode.data = self._preset_mapping.get( @@ -330,6 +338,7 @@ def set_preset_mode(self, preset_mode): def set_swing_mode(self, swing_mode): """Set new target swing mode.""" + _LOGGER.debug("Set swing_mode to %s", swing_mode) if self._zxt_120 == 1: if self.values.zxt_120_swing_mode: self.values.zxt_120_swing_mode.data = swing_mode diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index 41269bf1c02a8..2b1f67d0cca70 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -2,7 +2,7 @@ import pytest from homeassistant.components.climate.const import ( - HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_OFF) + HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_OFF, PRESET_BOOST, PRESET_ECO) from homeassistant.components.zwave import climate from homeassistant.const import ( ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT) @@ -55,7 +55,8 @@ def device_mapping(hass, mock_openzwave): values = MockEntityValues( primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), - mode=MockValue(data='Off', data_items=['Off', 'Cool', 'Heat'], + mode=MockValue(data='Off', data_items=[ + 'Off', 'Cool', 'Heat', 'Heat Eco', 'Full Power'], node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), operating_state=MockValue(data=6, node=node), @@ -111,6 +112,13 @@ def test_data_lists(device): assert device.hvac_modes == [0, 1, 2] +def test_data_lists_mapping(device_mapping): + """Test data lists from zwave value items.""" + device = device_mapping + assert device.hvac_modes == ['off', 'cool', 'heat'] + assert device.preset_modes == ['eco', 'boost'] + + def test_target_value_set(device): """Test values changed for climate device.""" assert device.values.primary.data == 1 @@ -127,6 +135,8 @@ def test_operation_value_set(device): assert device.values.mode.data == 'test1' device.set_hvac_mode('test_set') assert device.values.mode.data == 'test_set' + device.set_preset_mode('another_test') + assert device.values.mode.data == 'another_test' def test_operation_value_set_mapping(device_mapping): @@ -139,6 +149,10 @@ def test_operation_value_set_mapping(device_mapping): assert device.values.mode.data == 'Cool' device.set_hvac_mode(HVAC_MODE_OFF) assert device.values.mode.data == 'Off' + device.set_preset_mode(PRESET_BOOST) + assert device.values.mode.data == 'Full Power' + device.set_preset_mode(PRESET_ECO) + assert device.values.mode.data == 'Heat Eco' def test_fan_mode_value_set(device): From 7aea241835ee4b9547de84451c0d54ecc4e9b195 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Sun, 28 Jul 2019 13:14:38 +0200 Subject: [PATCH 04/29] Remove unnecessary line --- homeassistant/components/zwave/climate.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index 1c730073af43c..566626506cd40 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -156,7 +156,6 @@ def update_properties(self): self._preset_list.append(ha_preset) else: # If nothing matches - _LOGGER.debug("%s is nothing", mode) self._hvac_list.append(mode) current_mode = self.values.mode.data From 0c48e3bc37a1eda7b874b757acd444f98a0a8ae0 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Sun, 28 Jul 2019 14:03:34 +0200 Subject: [PATCH 05/29] Add preset attributes to __init__ --- homeassistant/components/zwave/climate.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index 566626506cd40..1bf22ea3ca932 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -100,6 +100,8 @@ def __init__(self, values, temp_unit): self._hvac_list = None self._hvac_mapping = None self._hvac_mode = None + self._preset_mapping = None + self._preset_list = None self._preset_mode = None self._current_fan_mode = None self._fan_modes = None @@ -165,6 +167,7 @@ def update_properties(self): self._preset_mode = next( (key for key, value in self._preset_mapping.items() if value == current_mode), PRESET_NONE) + _LOGGER.debug("self._hvac_list=%s", self._hvac_list) _LOGGER.debug("self._hvac_mapping=%s", self._hvac_mapping) _LOGGER.debug("self._hvac_action=%s", self._hvac_action) From ae1c01a05bae88a7703af1cfd638aefd14a9e430 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Sun, 28 Jul 2019 16:10:03 +0200 Subject: [PATCH 06/29] Remove some more debugger lines --- homeassistant/components/zwave/climate.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index 1bf22ea3ca932..379783de2b211 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -169,10 +169,8 @@ def update_properties(self): if value == current_mode), PRESET_NONE) _LOGGER.debug("self._hvac_list=%s", self._hvac_list) - _LOGGER.debug("self._hvac_mapping=%s", self._hvac_mapping) _LOGGER.debug("self._hvac_action=%s", self._hvac_action) _LOGGER.debug("self._preset_list=%s", self._preset_list) - _LOGGER.debug("self._preset_mapping=%s", self._preset_mapping) # Current Temp if self.values.temperature: From ed41e39fa8fee66e7e2ff5626489f3af7dff8252 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Sun, 28 Jul 2019 20:06:19 +0200 Subject: [PATCH 07/29] Add some tests --- tests/components/zwave/test_climate.py | 56 +++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index 2b1f67d0cca70..bbe49157dc25b 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -2,7 +2,9 @@ import pytest from homeassistant.components.climate.const import ( - HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_OFF, PRESET_BOOST, PRESET_ECO) + HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_OFF, PRESET_BOOST, PRESET_ECO, + SUPPORT_FAN_MODE, SUPPORT_PRESET_MODE, SUPPORT_SWING_MODE, + SUPPORT_TARGET_TEMPERATURE) from homeassistant.components.zwave import climate from homeassistant.const import ( ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT) @@ -67,6 +69,26 @@ def device_mapping(hass, mock_openzwave): yield device +def test_supported_features(device): + """Test supported features flags""" + assert device.supported_features == SUPPORT_FAN_MODE + \ + SUPPORT_TARGET_TEMPERATURE + + +def test_supported_features_preset_mode(device_mapping): + """Test supported features flags with swing mode""" + device = device_mapping + assert device.supported_features == SUPPORT_FAN_MODE + \ + SUPPORT_TARGET_TEMPERATURE + SUPPORT_PRESET_MODE + + +def test_supported_features_swing_mode(device_zxt_120): + """Test supported features flags with swing mode""" + device = device_zxt_120 + assert device.supported_features == SUPPORT_FAN_MODE + \ + SUPPORT_TARGET_TEMPERATURE + SUPPORT_SWING_MODE + + def test_zxt_120_swing_mode(device_zxt_120): """Test operation of the zxt 120 swing mode.""" device = device_zxt_120 @@ -110,6 +132,7 @@ def test_data_lists(device): """Test data lists from zwave value items.""" assert device.fan_modes == [3, 4, 5] assert device.hvac_modes == [0, 1, 2] + assert device.preset_modes == [] def test_data_lists_mapping(device_mapping): @@ -137,6 +160,11 @@ def test_operation_value_set(device): assert device.values.mode.data == 'test_set' device.set_preset_mode('another_test') assert device.values.mode.data == 'another_test' + device.values.mode = None + device.set_hvac_mode('test_set_failes') + assert device.values.mode == None + device.set_preset_mode('test_set_failes') + assert device.values.mode == None def test_operation_value_set_mapping(device_mapping): @@ -160,6 +188,9 @@ def test_fan_mode_value_set(device): assert device.values.fan_mode.data == 'test2' device.set_fan_mode('test_fan_set') assert device.values.fan_mode.data == 'test_fan_set' + device.values.fan_mode = None + device.set_fan_mode('test_fan_set_failes') + assert device.values.fan_mode == None def test_target_value_changed(device): @@ -181,9 +212,20 @@ def test_temperature_value_changed(device): def test_operation_value_changed(device): """Test values changed for climate device.""" assert device.hvac_mode == 'test1' + assert device.preset_mode == 'none' device.values.mode.data = 'test_updated' value_changed(device.values.mode) assert device.hvac_mode == 'test_updated' + assert device.preset_mode == 'none' + + +def test_operation_value_changed_preset(device_mapping): + """Test preset changed for climate device.""" + device = device_mapping + assert device.preset_mode == 'none' + device.values.mode.data = 'Heat Eco' + value_changed(device.values.mode) + assert device.preset_mode == 'eco' def test_operation_value_changed_mapping(device_mapping): @@ -201,6 +243,18 @@ def test_operation_value_changed_mapping(device_mapping): assert device.hvac_mode == HVAC_MODE_OFF +def test_operation_value_changed_mapping_preset(device_mapping): + """Test values changed for climate device. Mapping with presets.""" + device = device_mapping + assert device.hvac_mode == 'off' + device.values.mode.data = 'eco' + value_changed(device.values.mode) + assert device.hvac_mode == PRESET_ECO + device.values.mode.data = 'boost' + value_changed(device.values.mode) + assert device.hvac_mode == PRESET_BOOST + + def test_fan_mode_value_changed(device): """Test values changed for climate device.""" assert device.fan_mode == 'test2' From 18365c2228dff99838c9786ec95f9a86e03cb313 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Sun, 28 Jul 2019 20:14:21 +0200 Subject: [PATCH 08/29] Fix comparision to None --- tests/components/zwave/test_climate.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index bbe49157dc25b..6d19806d41b56 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -162,9 +162,9 @@ def test_operation_value_set(device): assert device.values.mode.data == 'another_test' device.values.mode = None device.set_hvac_mode('test_set_failes') - assert device.values.mode == None + assert device.values.mode is None device.set_preset_mode('test_set_failes') - assert device.values.mode == None + assert device.values.mode is None def test_operation_value_set_mapping(device_mapping): @@ -190,7 +190,7 @@ def test_fan_mode_value_set(device): assert device.values.fan_mode.data == 'test_fan_set' device.values.fan_mode = None device.set_fan_mode('test_fan_set_failes') - assert device.values.fan_mode == None + assert device.values.fan_mode is None def test_target_value_changed(device): From 648118d636e36d1fa511b1ece08dce0ad6f64dfe Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Sun, 28 Jul 2019 23:30:27 +0200 Subject: [PATCH 09/29] Improve test coverage --- tests/components/zwave/test_climate.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index 6d19806d41b56..3dfe4a3ebd0fc 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -3,7 +3,7 @@ from homeassistant.components.climate.const import ( HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_OFF, PRESET_BOOST, PRESET_ECO, - SUPPORT_FAN_MODE, SUPPORT_PRESET_MODE, SUPPORT_SWING_MODE, + PRESET_NONE, SUPPORT_FAN_MODE, SUPPORT_PRESET_MODE, SUPPORT_SWING_MODE, SUPPORT_TARGET_TEMPERATURE) from homeassistant.components.zwave import climate from homeassistant.const import ( @@ -133,6 +133,8 @@ def test_data_lists(device): assert device.fan_modes == [3, 4, 5] assert device.hvac_modes == [0, 1, 2] assert device.preset_modes == [] + device.values.mode = None + assert device.preset_modes == [] def test_data_lists_mapping(device_mapping): @@ -140,6 +142,8 @@ def test_data_lists_mapping(device_mapping): device = device_mapping assert device.hvac_modes == ['off', 'cool', 'heat'] assert device.preset_modes == ['eco', 'boost'] + device.values.mode = None + assert device.preset_modes == [] def test_target_value_set(device): @@ -226,6 +230,8 @@ def test_operation_value_changed_preset(device_mapping): device.values.mode.data = 'Heat Eco' value_changed(device.values.mode) assert device.preset_mode == 'eco' + device.values.mode = None + assert device.preset_mode == 'none' def test_operation_value_changed_mapping(device_mapping): @@ -253,6 +259,8 @@ def test_operation_value_changed_mapping_preset(device_mapping): device.values.mode.data = 'boost' value_changed(device.values.mode) assert device.hvac_mode == PRESET_BOOST + device.values.mode = None + assert device.preset_mode == PRESET_NONE def test_fan_mode_value_changed(device): From 5afa232705e4bb9e6d9b6f925061b494e3edfa6a Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Sun, 28 Jul 2019 23:55:12 +0200 Subject: [PATCH 10/29] Use unknown modes as presets --- homeassistant/components/zwave/climate.py | 62 ++++++++++++----------- tests/components/zwave/test_climate.py | 10 ++-- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index 379783de2b211..bf5a874ba9ea6 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -34,36 +34,36 @@ } HVAC_STATE_MAPPINGS = { - 'Off': HVAC_MODE_OFF, - 'Heat': HVAC_MODE_HEAT, - 'Heat Mode': HVAC_MODE_HEAT, - 'Heat (Default)': HVAC_MODE_HEAT, - 'Aux Heat': HVAC_MODE_HEAT, - 'Furnace': HVAC_MODE_HEAT, - 'Fan Only': HVAC_MODE_FAN_ONLY, - 'Dry Air': HVAC_MODE_DRY, - 'Moist Air': HVAC_MODE_DRY, - 'Cool': HVAC_MODE_COOL, - 'Auto': HVAC_MODE_HEAT_COOL, + 'off': HVAC_MODE_OFF, + 'heat': HVAC_MODE_HEAT, + 'heat mode': HVAC_MODE_HEAT, + 'heat (default)': HVAC_MODE_HEAT, + 'aux heat': HVAC_MODE_HEAT, + 'furnace': HVAC_MODE_HEAT, + 'fan only': HVAC_MODE_FAN_ONLY, + 'dry air': HVAC_MODE_DRY, + 'moist air': HVAC_MODE_DRY, + 'cool': HVAC_MODE_COOL, + 'auto': HVAC_MODE_HEAT_COOL } HVAC_CURRENT_MAPPINGS = { - "Idle": CURRENT_HVAC_IDLE, - "Heat": CURRENT_HVAC_HEAT, - "Pending Heat": CURRENT_HVAC_IDLE, - "Heating": CURRENT_HVAC_HEAT, - "Cool": CURRENT_HVAC_COOL, - "Pending Cool": CURRENT_HVAC_IDLE, - "Cooling": CURRENT_HVAC_COOL, - "Fan Only": CURRENT_HVAC_FAN, - "Vent / Economiser": CURRENT_HVAC_FAN, - "Off": CURRENT_HVAC_OFF, + "idle": CURRENT_HVAC_IDLE, + "heat": CURRENT_HVAC_HEAT, + "pending heat": CURRENT_HVAC_IDLE, + "heating": CURRENT_HVAC_HEAT, + "cool": CURRENT_HVAC_COOL, + "pending cool": CURRENT_HVAC_IDLE, + "cooling": CURRENT_HVAC_COOL, + "fan only": CURRENT_HVAC_FAN, + "vent / economiser": CURRENT_HVAC_FAN, + "off": CURRENT_HVAC_OFF, } PRESET_MAPPING = { - 'Full Power': PRESET_BOOST, - 'Heat Eco': PRESET_ECO, - 'Manufacturer Specific': PRESET_MANUFACTURER_SPECIFIC} + 'full power': PRESET_BOOST, + 'heat eco': PRESET_ECO, + 'manufacturer specific': PRESET_MANUFACTURER_SPECIFIC} async def async_setup_platform( @@ -145,11 +145,13 @@ def update_properties(self): self._preset_list = [] self._preset_mapping = {} - hvac_list = self.values.mode.data_items - if hvac_list: - for mode in hvac_list: - ha_mode = HVAC_STATE_MAPPINGS.get(mode) - ha_preset = PRESET_MAPPING.get(mode) + mode_list = self.values.mode.data_items + if mode_list: + for mode in mode_list: + ha_mode = HVAC_STATE_MAPPINGS.get( + mode.lower() if type(mode) == str else mode) + ha_preset = PRESET_MAPPING.get( + mode.lower() if type(mode) == str else mode) if ha_mode and ha_mode not in self._hvac_mapping: self._hvac_mapping[ha_mode] = mode self._hvac_list.append(ha_mode) @@ -158,7 +160,7 @@ def update_properties(self): self._preset_list.append(ha_preset) else: # If nothing matches - self._hvac_list.append(mode) + self._preset_list.append(mode) current_mode = self.values.mode.data self._hvac_mode = next( diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index 3dfe4a3ebd0fc..dde8840de30c0 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -20,7 +20,9 @@ def device(hass, mock_openzwave): values = MockEntityValues( primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), - mode=MockValue(data='test1', data_items=[0, 1, 2], node=node), + mode=MockValue(data='test1', data_items=[ + HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_COOL], + node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), operating_state=MockValue(data=6, node=node), fan_state=MockValue(data=7, node=node), @@ -38,7 +40,9 @@ def device_zxt_120(hass, mock_openzwave): values = MockEntityValues( primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), - mode=MockValue(data='test1', data_items=[0, 1, 2], node=node), + mode=MockValue(data='test1', data_items=[ + HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_COOL], + node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), operating_state=MockValue(data=6, node=node), fan_state=MockValue(data=7, node=node), @@ -131,7 +135,7 @@ def test_default_target_temperature(device): def test_data_lists(device): """Test data lists from zwave value items.""" assert device.fan_modes == [3, 4, 5] - assert device.hvac_modes == [0, 1, 2] + assert device.hvac_modes == [HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_COOL] assert device.preset_modes == [] device.values.mode = None assert device.preset_modes == [] From ad8d4c577fa6edb217bda42cbf470305a4933f30 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Mon, 29 Jul 2019 00:32:28 +0200 Subject: [PATCH 11/29] Bugfixes and test improvements --- homeassistant/components/zwave/climate.py | 5 +- tests/components/zwave/test_climate.py | 67 +++++++++++++---------- 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index bf5a874ba9ea6..92a3550592874 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -165,10 +165,11 @@ def update_properties(self): current_mode = self.values.mode.data self._hvac_mode = next( (key for key, value in self._hvac_mapping.items() - if value == current_mode), current_mode) + if value == current_mode), None) self._preset_mode = next( (key for key, value in self._preset_mapping.items() - if value == current_mode), PRESET_NONE) + if value == current_mode), + current_mode if self._hvac_mode is None else PRESET_NONE) _LOGGER.debug("self._hvac_list=%s", self._hvac_list) _LOGGER.debug("self._hvac_action=%s", self._hvac_action) diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index dde8840de30c0..6e538dbe94ff4 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -20,7 +20,7 @@ def device(hass, mock_openzwave): values = MockEntityValues( primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), - mode=MockValue(data='test1', data_items=[ + mode=MockValue(data=HVAC_MODE_HEAT, data_items=[ HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_COOL], node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), @@ -40,7 +40,7 @@ def device_zxt_120(hass, mock_openzwave): values = MockEntityValues( primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), - mode=MockValue(data='test1', data_items=[ + mode=MockValue(data=HVAC_MODE_HEAT, data_items=[ HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_COOL], node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), @@ -61,7 +61,7 @@ def device_mapping(hass, mock_openzwave): values = MockEntityValues( primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), - mode=MockValue(data='Off', data_items=[ + mode=MockValue(data='Heat', data_items=[ 'Off', 'Cool', 'Heat', 'Heat Eco', 'Full Power'], node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), @@ -163,11 +163,11 @@ def test_target_value_set(device): def test_operation_value_set(device): """Test values changed for climate device.""" - assert device.values.mode.data == 'test1' - device.set_hvac_mode('test_set') - assert device.values.mode.data == 'test_set' - device.set_preset_mode('another_test') - assert device.values.mode.data == 'another_test' + assert device.values.mode.data == HVAC_MODE_HEAT + device.set_hvac_mode(HVAC_MODE_COOL) + assert device.values.mode.data == HVAC_MODE_COOL + device.set_preset_mode(PRESET_ECO) + assert device.values.mode.data == PRESET_ECO device.values.mode = None device.set_hvac_mode('test_set_failes') assert device.values.mode is None @@ -178,8 +178,6 @@ def test_operation_value_set(device): def test_operation_value_set_mapping(device_mapping): """Test values changed for climate device. Mapping.""" device = device_mapping - assert device.values.mode.data == 'Off' - device.set_hvac_mode(HVAC_MODE_HEAT) assert device.values.mode.data == 'Heat' device.set_hvac_mode(HVAC_MODE_COOL) assert device.values.mode.data == 'Cool' @@ -219,50 +217,59 @@ def test_temperature_value_changed(device): def test_operation_value_changed(device): """Test values changed for climate device.""" - assert device.hvac_mode == 'test1' - assert device.preset_mode == 'none' - device.values.mode.data = 'test_updated' + assert device.hvac_mode == HVAC_MODE_HEAT + assert device.preset_mode == PRESET_NONE + device.values.mode.data = HVAC_MODE_COOL + value_changed(device.values.mode) + assert device.hvac_mode == HVAC_MODE_COOL + assert device.preset_mode == PRESET_NONE + device.values.mode.data = HVAC_MODE_OFF value_changed(device.values.mode) - assert device.hvac_mode == 'test_updated' - assert device.preset_mode == 'none' + assert device.hvac_mode == HVAC_MODE_OFF + assert device.preset_mode == PRESET_NONE def test_operation_value_changed_preset(device_mapping): """Test preset changed for climate device.""" device = device_mapping - assert device.preset_mode == 'none' - device.values.mode.data = 'Heat Eco' + assert device.hvac_mode == HVAC_MODE_HEAT + assert device.preset_mode == PRESET_NONE + device.values.mode.data = PRESET_ECO value_changed(device.values.mode) - assert device.preset_mode == 'eco' + assert device.hvac_mode == None + assert device.preset_mode == PRESET_ECO device.values.mode = None - assert device.preset_mode == 'none' + assert device.preset_mode == PRESET_NONE def test_operation_value_changed_mapping(device_mapping): """Test values changed for climate device. Mapping.""" device = device_mapping - assert device.hvac_mode == 'off' - device.values.mode.data = 'Heat' - value_changed(device.values.mode) assert device.hvac_mode == HVAC_MODE_HEAT - device.values.mode.data = 'Cool' - value_changed(device.values.mode) - assert device.hvac_mode == HVAC_MODE_COOL + assert device.preset_mode == PRESET_NONE device.values.mode.data = 'Off' value_changed(device.values.mode) assert device.hvac_mode == HVAC_MODE_OFF + assert device.preset_mode == PRESET_NONE + device.values.mode.data = 'Cool' + value_changed(device.values.mode) + assert device.hvac_mode == HVAC_MODE_COOL + assert device.preset_mode == PRESET_NONE def test_operation_value_changed_mapping_preset(device_mapping): """Test values changed for climate device. Mapping with presets.""" device = device_mapping - assert device.hvac_mode == 'off' - device.values.mode.data = 'eco' + assert device.hvac_mode == HVAC_MODE_HEAT + assert device.preset_mode == PRESET_NONE + device.values.mode.data = 'Heat Eco' value_changed(device.values.mode) - assert device.hvac_mode == PRESET_ECO - device.values.mode.data = 'boost' + assert device.hvac_mode == None + assert device.preset_mode == PRESET_ECO + device.values.mode.data = 'Full Power' value_changed(device.values.mode) - assert device.hvac_mode == PRESET_BOOST + assert device.hvac_mode == None + assert device.preset_mode == PRESET_BOOST device.values.mode = None assert device.preset_mode == PRESET_NONE From 19011245bff1df7e68c7fb4f2a23da6da4596fca Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Mon, 29 Jul 2019 00:35:28 +0200 Subject: [PATCH 12/29] Add tests for unknown preset modes --- tests/components/zwave/test_climate.py | 39 ++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index 6e538dbe94ff4..1c69ef57d9830 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -73,6 +73,25 @@ def device_mapping(hass, mock_openzwave): yield device +@pytest.fixture +def device_unknown(hass, mock_openzwave): + """Fixture to provide a precreated climate device. Test state unknown.""" + node = MockNode() + values = MockEntityValues( + primary=MockValue(data=1, node=node), + temperature=MockValue(data=5, node=node, units=None), + mode=MockValue(data='Heat', data_items=[ + 'Off', 'Cool', 'Heat', 'Heat Eco', 'Abcdefg'], + node=node), + fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), + operating_state=MockValue(data=6, node=node), + fan_state=MockValue(data=7, node=node), + ) + device = climate.get_device(hass, node=node, values=values, node_config={}) + + yield device + + def test_supported_features(device): """Test supported features flags""" assert device.supported_features == SUPPORT_FAN_MODE + \ @@ -189,6 +208,16 @@ def test_operation_value_set_mapping(device_mapping): assert device.values.mode.data == 'Heat Eco' +def test_operation_value_set_unknown(device_unknown): + """Test values changed for climate device. Unknown.""" + device = device_unknown + assert device.values.mode.data == 'Heat' + device.set_preset_mode(PRESET_ECO) + assert device.values.mode.data == 'Heat Eco' + device.set_preset_mode('Abcdefg') + assert device.values.mode.data == 'Abcdefg' + + def test_fan_mode_value_set(device): """Test values changed for climate device.""" assert device.values.fan_mode.data == 'test2' @@ -273,6 +302,16 @@ def test_operation_value_changed_mapping_preset(device_mapping): device.values.mode = None assert device.preset_mode == PRESET_NONE +def test_operation_value_changed_unknown(device_unknown): + """Test preset changed for climate device. Unknown""" + device = device_unknown + assert device.hvac_mode == HVAC_MODE_HEAT + assert device.preset_mode == PRESET_NONE + device.values.mode.data = 'Abcdefg' + value_changed(device.values.mode) + assert device.hvac_mode == None + assert device.preset_mode == 'Abcdefg' + def test_fan_mode_value_changed(device): """Test values changed for climate device.""" From 99bff0ae9469f424c01425aa2d854f9e8811f4e7 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Mon, 29 Jul 2019 00:42:10 +0200 Subject: [PATCH 13/29] linting --- tests/components/zwave/test_climate.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index 1c69ef57d9830..fd29072fcce1a 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -265,7 +265,7 @@ def test_operation_value_changed_preset(device_mapping): assert device.preset_mode == PRESET_NONE device.values.mode.data = PRESET_ECO value_changed(device.values.mode) - assert device.hvac_mode == None + assert device.hvac_mode is None assert device.preset_mode == PRESET_ECO device.values.mode = None assert device.preset_mode == PRESET_NONE @@ -293,15 +293,16 @@ def test_operation_value_changed_mapping_preset(device_mapping): assert device.preset_mode == PRESET_NONE device.values.mode.data = 'Heat Eco' value_changed(device.values.mode) - assert device.hvac_mode == None + assert device.hvac_mode is None assert device.preset_mode == PRESET_ECO device.values.mode.data = 'Full Power' value_changed(device.values.mode) - assert device.hvac_mode == None + assert device.hvac_mode is None assert device.preset_mode == PRESET_BOOST device.values.mode = None assert device.preset_mode == PRESET_NONE + def test_operation_value_changed_unknown(device_unknown): """Test preset changed for climate device. Unknown""" device = device_unknown @@ -309,7 +310,7 @@ def test_operation_value_changed_unknown(device_unknown): assert device.preset_mode == PRESET_NONE device.values.mode.data = 'Abcdefg' value_changed(device.values.mode) - assert device.hvac_mode == None + assert device.hvac_mode is None assert device.preset_mode == 'Abcdefg' From 5674978e52568aba2f54cf2d2193cce84fcd6c97 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Mon, 29 Jul 2019 06:23:28 +0200 Subject: [PATCH 14/29] Improve mappings --- homeassistant/components/zwave/climate.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index 92a3550592874..1cdc660be0985 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -60,7 +60,7 @@ "off": CURRENT_HVAC_OFF, } -PRESET_MAPPING = { +PRESET_MAPPINGS = { 'full power': PRESET_BOOST, 'heat eco': PRESET_ECO, 'manufacturer specific': PRESET_MANUFACTURER_SPECIFIC} @@ -149,9 +149,9 @@ def update_properties(self): if mode_list: for mode in mode_list: ha_mode = HVAC_STATE_MAPPINGS.get( - mode.lower() if type(mode) == str else mode) - ha_preset = PRESET_MAPPING.get( - mode.lower() if type(mode) == str else mode) + mode.lower() if isinstance(mode, str) else mode) + ha_preset = PRESET_MAPPINGS.get( + mode.lower() if isinstance(mode, str) else mode) if ha_mode and ha_mode not in self._hvac_mapping: self._hvac_mapping[ha_mode] = mode self._hvac_list.append(ha_mode) @@ -216,7 +216,8 @@ def update_properties(self): # Operating state if self.values.operating_state: mode = self.values.operating_state.data - self._hvac_action = HVAC_CURRENT_MAPPINGS.get(mode) + self._hvac_action = HVAC_CURRENT_MAPPINGS.get( + mode.lower() if isinstance(mode, str) else mode) # Fan operating state if self.values.fan_state: From 4e93f4d4262c4e58c414fdf0007ac562cfc94940 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Mon, 29 Jul 2019 16:07:58 +0200 Subject: [PATCH 15/29] Move PRESET_MANUFACTURER_SPECIFIC to zwave --- homeassistant/components/climate/const.py | 3 --- homeassistant/components/zwave/climate.py | 7 +++++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/climate/const.py b/homeassistant/components/climate/const.py index c82d1410b3405..7b99442c2d7d3 100644 --- a/homeassistant/components/climate/const.py +++ b/homeassistant/components/climate/const.py @@ -56,9 +56,6 @@ # Device is reacting to activity (e.g. movement sensors) PRESET_ACTIVITY = 'activity' -# Device is in manufacturer specific mode (e.g. setting the valve manually) -PRESET_MANUFACTURER_SPECIFIC = 'Manufacturer Specific' - # Possible fan state FAN_ON = "on" diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index 1cdc660be0985..1f3a7abb27bec 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -8,8 +8,7 @@ CURRENT_HVAC_OFF, DOMAIN, HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_HEAT_COOL, HVAC_MODE_DRY, HVAC_MODE_FAN_ONLY, HVAC_MODE_OFF, SUPPORT_FAN_MODE, SUPPORT_SWING_MODE, SUPPORT_TARGET_TEMPERATURE, - SUPPORT_PRESET_MODE, PRESET_BOOST, PRESET_ECO, PRESET_NONE, - PRESET_MANUFACTURER_SPECIFIC) + SUPPORT_PRESET_MODE, PRESET_BOOST, PRESET_ECO, PRESET_NONE) from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT from homeassistant.core import callback from homeassistant.helpers.dispatcher import async_dispatcher_connect @@ -27,6 +26,10 @@ ATTR_OPERATING_STATE = 'operating_state' ATTR_FAN_STATE = 'fan_state' + +# Device is in manufacturer specific mode (e.g. setting the valve manually) +PRESET_MANUFACTURER_SPECIFIC = 'Manufacturer Specific' + WORKAROUND_ZXT_120 = 'zxt_120' DEVICE_MAPPINGS = { From d097ba60e91f98d5db67e3493f39b1c62b2dc53b Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Mon, 29 Jul 2019 16:08:23 +0200 Subject: [PATCH 16/29] Replace isinstance with cast --- homeassistant/components/zwave/climate.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index 1f3a7abb27bec..73f0af8b086a5 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -151,10 +151,8 @@ def update_properties(self): mode_list = self.values.mode.data_items if mode_list: for mode in mode_list: - ha_mode = HVAC_STATE_MAPPINGS.get( - mode.lower() if isinstance(mode, str) else mode) - ha_preset = PRESET_MAPPINGS.get( - mode.lower() if isinstance(mode, str) else mode) + ha_mode = HVAC_STATE_MAPPINGS.get(str(mode).lower()) + ha_preset = PRESET_MAPPINGS.get(str(mode).lower()) if ha_mode and ha_mode not in self._hvac_mapping: self._hvac_mapping[ha_mode] = mode self._hvac_list.append(ha_mode) @@ -219,8 +217,7 @@ def update_properties(self): # Operating state if self.values.operating_state: mode = self.values.operating_state.data - self._hvac_action = HVAC_CURRENT_MAPPINGS.get( - mode.lower() if isinstance(mode, str) else mode) + self._hvac_action = HVAC_CURRENT_MAPPINGS.get(str(mode).lower()) # Fan operating state if self.values.fan_state: From 8b7e24de5b8170eca510baf562638695a0f3af32 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Mon, 29 Jul 2019 16:28:16 +0200 Subject: [PATCH 17/29] Add test for hvac_action --- homeassistant/components/zwave/climate.py | 3 +- tests/components/zwave/test_climate.py | 36 +++++++++++++++++++---- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index 73f0af8b086a5..a7e517267dc17 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -217,7 +217,8 @@ def update_properties(self): # Operating state if self.values.operating_state: mode = self.values.operating_state.data - self._hvac_action = HVAC_CURRENT_MAPPINGS.get(str(mode).lower()) + self._hvac_action = HVAC_CURRENT_MAPPINGS.get( + str(mode).lower(), mode) # Fan operating state if self.values.fan_state: diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index fd29072fcce1a..bb94c02109294 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -4,7 +4,7 @@ from homeassistant.components.climate.const import ( HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_OFF, PRESET_BOOST, PRESET_ECO, PRESET_NONE, SUPPORT_FAN_MODE, SUPPORT_PRESET_MODE, SUPPORT_SWING_MODE, - SUPPORT_TARGET_TEMPERATURE) + SUPPORT_TARGET_TEMPERATURE, CURRENT_HVAC_HEAT, CURRENT_HVAC_COOL) from homeassistant.components.zwave import climate from homeassistant.const import ( ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT) @@ -24,7 +24,7 @@ def device(hass, mock_openzwave): HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_COOL], node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), - operating_state=MockValue(data=6, node=node), + operating_state=MockValue(data=CURRENT_HVAC_HEAT, node=node), fan_state=MockValue(data=7, node=node), ) device = climate.get_device(hass, node=node, values=values, node_config={}) @@ -44,7 +44,7 @@ def device_zxt_120(hass, mock_openzwave): HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_COOL], node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), - operating_state=MockValue(data=6, node=node), + operating_state=MockValue(data=CURRENT_HVAC_HEAT, node=node), fan_state=MockValue(data=7, node=node), zxt_120_swing_mode=MockValue( data='test3', data_items=[6, 7, 8], node=node), @@ -65,7 +65,7 @@ def device_mapping(hass, mock_openzwave): 'Off', 'Cool', 'Heat', 'Heat Eco', 'Full Power'], node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), - operating_state=MockValue(data=6, node=node), + operating_state=MockValue(data='heating', node=node), fan_state=MockValue(data=7, node=node), ) device = climate.get_device(hass, node=node, values=values, node_config={}) @@ -84,7 +84,7 @@ def device_unknown(hass, mock_openzwave): 'Off', 'Cool', 'Heat', 'Heat Eco', 'Abcdefg'], node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), - operating_state=MockValue(data=6, node=node), + operating_state=MockValue(data='test4', node=node), fan_state=MockValue(data=7, node=node), ) device = climate.get_device(hass, node=node, values=values, node_config={}) @@ -320,3 +320,29 @@ def test_fan_mode_value_changed(device): device.values.fan_mode.data = 'test_updated_fan' value_changed(device.values.fan_mode) assert device.fan_mode == 'test_updated_fan' + + +def test_hvac_action_value_changed(device): + """Test values changed for climate device.""" + assert device.hvac_action == CURRENT_HVAC_HEAT + device.values.operating_state.data = CURRENT_HVAC_COOL + value_changed(device.values.operating_state) + assert device.hvac_action == CURRENT_HVAC_COOL + + +def test_hvac_action_value_changed_mapping(device_mapping): + """Test values changed for climate device.""" + device = device_mapping + assert device.hvac_action == CURRENT_HVAC_HEAT + device.values.operating_state.data = 'cooling' + value_changed(device.values.operating_state) + assert device.hvac_action == CURRENT_HVAC_COOL + + +def test_hvac_action_value_changed_unknown(device_unknown): + """Test values changed for climate device.""" + device = device_unknown + assert device.hvac_action == 'test4' + device.values.operating_state.data = 'another_hvac_action' + value_changed(device.values.operating_state) + assert device.hvac_action == 'another_hvac_action' From 5735392cb234aeb13edfec1d3200f58bdf62cf2c Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Tue, 30 Jul 2019 13:40:19 +0200 Subject: [PATCH 18/29] hvac_mode is never None --- homeassistant/components/zwave/climate.py | 23 +++++++++++++++++------ tests/components/zwave/test_climate.py | 21 ++++++++++++--------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index a7e517267dc17..2bdcb164fb2d3 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -47,7 +47,7 @@ 'dry air': HVAC_MODE_DRY, 'moist air': HVAC_MODE_DRY, 'cool': HVAC_MODE_COOL, - 'auto': HVAC_MODE_HEAT_COOL + 'auto': HVAC_MODE_HEAT_COOL, } HVAC_CURRENT_MAPPINGS = { @@ -66,7 +66,8 @@ PRESET_MAPPINGS = { 'full power': PRESET_BOOST, 'heat eco': PRESET_ECO, - 'manufacturer specific': PRESET_MANUFACTURER_SPECIFIC} + 'manufacturer specific': PRESET_MANUFACTURER_SPECIFIC, +} async def async_setup_platform( @@ -169,8 +170,18 @@ def update_properties(self): if value == current_mode), None) self._preset_mode = next( (key for key, value in self._preset_mapping.items() - if value == current_mode), - current_mode if self._hvac_mode is None else PRESET_NONE) + if value == current_mode), None) + + if self._hvac_mode is not None and self._preset_mode is None: + # The current mode is a hvac mode + self._preset_mode = PRESET_NONE + elif self._hvac_mode is None and self._preset_mode is not None: + # The current mode is a preset mode + self._hvac_mode = HVAC_MODE_HEAT_COOL + elif self._hvac_mode is None and self._preset_mode is None: + # The current mode couldn't be found in any mapping + self._hvac_mode = HVAC_MODE_HEAT_COOL + self._preset_mode = current_mode _LOGGER.debug("self._hvac_list=%s", self._hvac_list) _LOGGER.debug("self._hvac_action=%s", self._hvac_action) @@ -190,8 +201,8 @@ def update_properties(self): if fan_modes: self._fan_modes = list(fan_modes) _LOGGER.debug("self._fan_modes=%s", self._fan_modes) - _LOGGER.debug("self._current_fan_mode=%s", - self._current_fan_mode) + _LOGGER.debug("self._current_fan_mode=%s", self._current_fan_mode) + # Swing mode if self._zxt_120 == 1: if self.values.zxt_120_swing_mode: diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index bb94c02109294..7c079a604561c 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -2,9 +2,10 @@ import pytest from homeassistant.components.climate.const import ( - HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_OFF, PRESET_BOOST, PRESET_ECO, - PRESET_NONE, SUPPORT_FAN_MODE, SUPPORT_PRESET_MODE, SUPPORT_SWING_MODE, - SUPPORT_TARGET_TEMPERATURE, CURRENT_HVAC_HEAT, CURRENT_HVAC_COOL) + HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_HEAT_COOL, HVAC_MODE_OFF, + PRESET_BOOST, PRESET_ECO, PRESET_NONE, SUPPORT_FAN_MODE, + SUPPORT_PRESET_MODE, SUPPORT_SWING_MODE, SUPPORT_TARGET_TEMPERATURE, + CURRENT_HVAC_HEAT, CURRENT_HVAC_COOL) from homeassistant.components.zwave import climate from homeassistant.const import ( ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT) @@ -80,8 +81,8 @@ def device_unknown(hass, mock_openzwave): values = MockEntityValues( primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), - mode=MockValue(data='Heat', data_items=[ - 'Off', 'Cool', 'Heat', 'Heat Eco', 'Abcdefg'], + mode=MockValue(data='Heat', data_items=['Off', 'Cool', 'Heat', + 'Heat Eco', 'Abcdefg'], node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), operating_state=MockValue(data='test4', node=node), @@ -265,9 +266,10 @@ def test_operation_value_changed_preset(device_mapping): assert device.preset_mode == PRESET_NONE device.values.mode.data = PRESET_ECO value_changed(device.values.mode) - assert device.hvac_mode is None + assert device.hvac_mode == HVAC_MODE_HEAT_COOL assert device.preset_mode == PRESET_ECO device.values.mode = None + assert device.hvac_mode == HVAC_MODE_HEAT assert device.preset_mode == PRESET_NONE @@ -293,13 +295,14 @@ def test_operation_value_changed_mapping_preset(device_mapping): assert device.preset_mode == PRESET_NONE device.values.mode.data = 'Heat Eco' value_changed(device.values.mode) - assert device.hvac_mode is None + assert device.hvac_mode == HVAC_MODE_HEAT_COOL assert device.preset_mode == PRESET_ECO device.values.mode.data = 'Full Power' value_changed(device.values.mode) - assert device.hvac_mode is None + assert device.hvac_mode == HVAC_MODE_HEAT_COOL assert device.preset_mode == PRESET_BOOST device.values.mode = None + assert device.hvac_mode == HVAC_MODE_HEAT assert device.preset_mode == PRESET_NONE @@ -310,7 +313,7 @@ def test_operation_value_changed_unknown(device_unknown): assert device.preset_mode == PRESET_NONE device.values.mode.data = 'Abcdefg' value_changed(device.values.mode) - assert device.hvac_mode is None + assert device.hvac_mode == HVAC_MODE_HEAT_COOL assert device.preset_mode == 'Abcdefg' From 81f14f063080f612decac0af8206d6a8bd23c3f9 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Tue, 30 Jul 2019 13:59:17 +0200 Subject: [PATCH 19/29] Improved mapping of current mode to hvac/preset modes --- homeassistant/components/zwave/climate.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index 2bdcb164fb2d3..bcd43efbc1667 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -168,20 +168,16 @@ def update_properties(self): self._hvac_mode = next( (key for key, value in self._hvac_mapping.items() if value == current_mode), None) - self._preset_mode = next( - (key for key, value in self._preset_mapping.items() - if value == current_mode), None) - if self._hvac_mode is not None and self._preset_mode is None: + if self._hvac_mode is None: + # The current mode is not a hvac mode + self._hvac_mode = HVAC_MODE_HEAT_COOL + self._preset_mode = next( + (key for key, value in self._preset_mapping.items() + if value == current_mode), current_mode) + else: # The current mode is a hvac mode self._preset_mode = PRESET_NONE - elif self._hvac_mode is None and self._preset_mode is not None: - # The current mode is a preset mode - self._hvac_mode = HVAC_MODE_HEAT_COOL - elif self._hvac_mode is None and self._preset_mode is None: - # The current mode couldn't be found in any mapping - self._hvac_mode = HVAC_MODE_HEAT_COOL - self._preset_mode = current_mode _LOGGER.debug("self._hvac_list=%s", self._hvac_list) _LOGGER.debug("self._hvac_action=%s", self._hvac_action) From c5300b66c8ebc02ed9db47b27329806ee91428ea Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Wed, 31 Jul 2019 18:44:08 +0200 Subject: [PATCH 20/29] Fix bugs where hvac_mode is None --- homeassistant/components/zwave/climate.py | 20 +++++++++++++------- tests/components/zwave/test_climate.py | 18 ++++++++---------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index bcd43efbc1667..e99bc46245eb3 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -65,7 +65,6 @@ PRESET_MAPPINGS = { 'full power': PRESET_BOOST, - 'heat eco': PRESET_ECO, 'manufacturer specific': PRESET_MANUFACTURER_SPECIFIC, } @@ -164,12 +163,15 @@ def update_properties(self): # If nothing matches self._preset_list.append(mode) + if self._preset_list: + self._preset_list.append(PRESET_NONE) + current_mode = self.values.mode.data - self._hvac_mode = next( + _hvac_temp = next( (key for key, value in self._hvac_mapping.items() if value == current_mode), None) - if self._hvac_mode is None: + if _hvac_temp is None: # The current mode is not a hvac mode self._hvac_mode = HVAC_MODE_HEAT_COOL self._preset_mode = next( @@ -177,6 +179,7 @@ def update_properties(self): if value == current_mode), current_mode) else: # The current mode is a hvac mode + self._hvac_mode = _hvac_temp self._preset_mode = PRESET_NONE _LOGGER.debug("self._hvac_list=%s", self._hvac_list) @@ -337,16 +340,19 @@ def set_hvac_mode(self, hvac_mode): _LOGGER.debug("Set hvac_mode to %s", hvac_mode) if not self.values.mode: return - self.values.mode.data = self._hvac_mapping.get( - hvac_mode, hvac_mode) + self.values.mode.data = self._hvac_mapping.get(hvac_mode, hvac_mode) def set_preset_mode(self, preset_mode): """Set new target preset mode.""" _LOGGER.debug("Set preset_mode to %s", preset_mode) if not self.values.mode: return - self.values.mode.data = self._preset_mapping.get( - preset_mode, preset_mode) + if preset_mode == PRESET_NONE: + # Activate the currently active hvac mode (HVAC_MODE_HEAT_COOL) + self.values.mode.data = HVAC_MODE_HEAT_COOL + else: + self.values.mode.data = self._preset_mapping.get( + preset_mode, preset_mode) def set_swing_mode(self, swing_mode): """Set new target swing mode.""" diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index 7c079a604561c..dc31cfed2a5b8 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -63,7 +63,7 @@ def device_mapping(hass, mock_openzwave): primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), mode=MockValue(data='Heat', data_items=[ - 'Off', 'Cool', 'Heat', 'Heat Eco', 'Full Power'], + 'Off', 'Cool', 'Heat', 'Full Power'], node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), operating_state=MockValue(data='heating', node=node), @@ -82,7 +82,7 @@ def device_unknown(hass, mock_openzwave): primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), mode=MockValue(data='Heat', data_items=['Off', 'Cool', 'Heat', - 'Heat Eco', 'Abcdefg'], + 'Abcdefg'], node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), operating_state=MockValue(data='test4', node=node), @@ -165,7 +165,7 @@ def test_data_lists_mapping(device_mapping): """Test data lists from zwave value items.""" device = device_mapping assert device.hvac_modes == ['off', 'cool', 'heat'] - assert device.preset_modes == ['eco', 'boost'] + assert device.preset_modes == ['boost', 'none'] device.values.mode = None assert device.preset_modes == [] @@ -188,6 +188,8 @@ def test_operation_value_set(device): assert device.values.mode.data == HVAC_MODE_COOL device.set_preset_mode(PRESET_ECO) assert device.values.mode.data == PRESET_ECO + device.set_preset_mode(PRESET_NONE) + assert device.values.mode.data == HVAC_MODE_HEAT_COOL device.values.mode = None device.set_hvac_mode('test_set_failes') assert device.values.mode is None @@ -206,17 +208,17 @@ def test_operation_value_set_mapping(device_mapping): device.set_preset_mode(PRESET_BOOST) assert device.values.mode.data == 'Full Power' device.set_preset_mode(PRESET_ECO) - assert device.values.mode.data == 'Heat Eco' + assert device.values.mode.data == 'eco' def test_operation_value_set_unknown(device_unknown): """Test values changed for climate device. Unknown.""" device = device_unknown assert device.values.mode.data == 'Heat' - device.set_preset_mode(PRESET_ECO) - assert device.values.mode.data == 'Heat Eco' device.set_preset_mode('Abcdefg') assert device.values.mode.data == 'Abcdefg' + device.set_preset_mode(PRESET_NONE) + assert device.values.mode.data == HVAC_MODE_HEAT_COOL def test_fan_mode_value_set(device): @@ -293,10 +295,6 @@ def test_operation_value_changed_mapping_preset(device_mapping): device = device_mapping assert device.hvac_mode == HVAC_MODE_HEAT assert device.preset_mode == PRESET_NONE - device.values.mode.data = 'Heat Eco' - value_changed(device.values.mode) - assert device.hvac_mode == HVAC_MODE_HEAT_COOL - assert device.preset_mode == PRESET_ECO device.values.mode.data = 'Full Power' value_changed(device.values.mode) assert device.hvac_mode == HVAC_MODE_HEAT_COOL From 7edf8d970eb2316a70efb341c80d54b6cb2e97fd Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Wed, 31 Jul 2019 19:22:03 +0200 Subject: [PATCH 21/29] Add default hvac mode --- homeassistant/components/zwave/climate.py | 28 +++++++++-- tests/components/zwave/test_climate.py | 60 ++++++++++++++++++----- 2 files changed, 70 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index e99bc46245eb3..430cb12f132ed 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -8,7 +8,7 @@ CURRENT_HVAC_OFF, DOMAIN, HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_HEAT_COOL, HVAC_MODE_DRY, HVAC_MODE_FAN_ONLY, HVAC_MODE_OFF, SUPPORT_FAN_MODE, SUPPORT_SWING_MODE, SUPPORT_TARGET_TEMPERATURE, - SUPPORT_PRESET_MODE, PRESET_BOOST, PRESET_ECO, PRESET_NONE) + SUPPORT_PRESET_MODE, PRESET_BOOST, PRESET_NONE) from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT from homeassistant.core import callback from homeassistant.helpers.dispatcher import async_dispatcher_connect @@ -47,6 +47,7 @@ 'dry air': HVAC_MODE_DRY, 'moist air': HVAC_MODE_DRY, 'cool': HVAC_MODE_COOL, + 'heat_cool': HVAC_MODE_HEAT_COOL, 'auto': HVAC_MODE_HEAT_COOL, } @@ -68,6 +69,15 @@ 'manufacturer specific': PRESET_MANUFACTURER_SPECIFIC, } +DEFAULT_HVAC_MODES = [ + HVAC_MODE_HEAT_COOL, + HVAC_MODE_HEAT, + HVAC_MODE_COOL, + HVAC_MODE_FAN_ONLY, + HVAC_MODE_DRY, + HVAC_MODE_OFF, +] + async def async_setup_platform( hass, config, async_add_entities, discovery_info=None): @@ -103,6 +113,7 @@ def __init__(self, values, temp_unit): self._hvac_list = None self._hvac_mapping = None self._hvac_mode = None + self._default_hvac_mode = None self._preset_mapping = None self._preset_list = None self._preset_mode = None @@ -163,7 +174,14 @@ def update_properties(self): # If nothing matches self._preset_list.append(mode) + # Default operation mode + for mode in DEFAULT_HVAC_MODES: + if mode in self._hvac_list: + self._default_hvac_mode = mode + break + if self._preset_list: + # Presets are supported self._preset_list.append(PRESET_NONE) current_mode = self.values.mode.data @@ -173,7 +191,7 @@ def update_properties(self): if _hvac_temp is None: # The current mode is not a hvac mode - self._hvac_mode = HVAC_MODE_HEAT_COOL + self._hvac_mode = self._default_hvac_mode self._preset_mode = next( (key for key, value in self._preset_mapping.items() if value == current_mode), current_mode) @@ -276,7 +294,7 @@ def hvac_mode(self): """ if self.values.mode: return self._hvac_mode - return HVAC_MODE_HEAT + return self._default_hvac_mode @property def hvac_modes(self): @@ -348,8 +366,8 @@ def set_preset_mode(self, preset_mode): if not self.values.mode: return if preset_mode == PRESET_NONE: - # Activate the currently active hvac mode (HVAC_MODE_HEAT_COOL) - self.values.mode.data = HVAC_MODE_HEAT_COOL + # Activate the default hvac mode + self.values.mode.data = self._default_hvac_mode else: self.values.mode.data = self._preset_mapping.get( preset_mode, preset_mode) diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index dc31cfed2a5b8..8ee0a149da0b9 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -21,8 +21,10 @@ def device(hass, mock_openzwave): values = MockEntityValues( primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), - mode=MockValue(data=HVAC_MODE_HEAT, data_items=[ - HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_COOL], + mode=MockValue(data=HVAC_MODE_HEAT, data_items=[HVAC_MODE_OFF, + HVAC_MODE_HEAT, + HVAC_MODE_COOL, + HVAC_MODE_HEAT_COOL], node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), operating_state=MockValue(data=CURRENT_HVAC_HEAT, node=node), @@ -41,8 +43,10 @@ def device_zxt_120(hass, mock_openzwave): values = MockEntityValues( primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), - mode=MockValue(data=HVAC_MODE_HEAT, data_items=[ - HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_COOL], + mode=MockValue(data=HVAC_MODE_HEAT, data_items=[HVAC_MODE_OFF, + HVAC_MODE_HEAT, + HVAC_MODE_COOL, + HVAC_MODE_HEAT_COOL], node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), operating_state=MockValue(data=CURRENT_HVAC_HEAT, node=node), @@ -63,7 +67,7 @@ def device_mapping(hass, mock_openzwave): primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), mode=MockValue(data='Heat', data_items=[ - 'Off', 'Cool', 'Heat', 'Full Power'], + 'Off', 'Cool', 'Heat', 'Full Power', 'auto'], node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), operating_state=MockValue(data='heating', node=node), @@ -81,8 +85,27 @@ def device_unknown(hass, mock_openzwave): values = MockEntityValues( primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), - mode=MockValue(data='Heat', data_items=['Off', 'Cool', 'Heat', - 'Abcdefg'], + mode=MockValue(data='Heat', data_items=[ + 'Off', 'Cool', 'Heat', 'heat_cool', 'Abcdefg'], + node=node), + fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), + operating_state=MockValue(data='test4', node=node), + fan_state=MockValue(data=7, node=node), + ) + device = climate.get_device(hass, node=node, values=values, node_config={}) + + yield device + + +@pytest.fixture +def device_heat(hass, mock_openzwave): + """Fixture to provide a precreated climate device. Test state heat only.""" + node = MockNode() + values = MockEntityValues( + primary=MockValue(data=1, node=node), + temperature=MockValue(data=5, node=node, units=None), + mode=MockValue(data=HVAC_MODE_HEAT, data_items=[ + HVAC_MODE_OFF, HVAC_MODE_HEAT, 'Heat Eco'], node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), operating_state=MockValue(data='test4', node=node), @@ -155,7 +178,8 @@ def test_default_target_temperature(device): def test_data_lists(device): """Test data lists from zwave value items.""" assert device.fan_modes == [3, 4, 5] - assert device.hvac_modes == [HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_COOL] + assert device.hvac_modes == [ + HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_COOL, HVAC_MODE_HEAT_COOL] assert device.preset_modes == [] device.values.mode = None assert device.preset_modes == [] @@ -164,7 +188,7 @@ def test_data_lists(device): def test_data_lists_mapping(device_mapping): """Test data lists from zwave value items.""" device = device_mapping - assert device.hvac_modes == ['off', 'cool', 'heat'] + assert device.hvac_modes == ['off', 'cool', 'heat', 'heat_cool'] assert device.preset_modes == ['boost', 'none'] device.values.mode = None assert device.preset_modes == [] @@ -221,6 +245,16 @@ def test_operation_value_set_unknown(device_unknown): assert device.values.mode.data == HVAC_MODE_HEAT_COOL +def test_operation_value_set_heat(device_heat): + """Test values changed for climate device. Heat only.""" + device = device_heat + assert device.values.mode.data == HVAC_MODE_HEAT + device.set_preset_mode('Heat Eco') + assert device.values.mode.data == 'Heat Eco' + device.set_preset_mode(PRESET_NONE) + assert device.values.mode.data == HVAC_MODE_HEAT + + def test_fan_mode_value_set(device): """Test values changed for climate device.""" assert device.values.fan_mode.data == 'test2' @@ -259,6 +293,9 @@ def test_operation_value_changed(device): value_changed(device.values.mode) assert device.hvac_mode == HVAC_MODE_OFF assert device.preset_mode == PRESET_NONE + device.values.mode = None + assert device.hvac_mode == HVAC_MODE_HEAT_COOL + assert device.preset_mode == PRESET_NONE def test_operation_value_changed_preset(device_mapping): @@ -270,9 +307,6 @@ def test_operation_value_changed_preset(device_mapping): value_changed(device.values.mode) assert device.hvac_mode == HVAC_MODE_HEAT_COOL assert device.preset_mode == PRESET_ECO - device.values.mode = None - assert device.hvac_mode == HVAC_MODE_HEAT - assert device.preset_mode == PRESET_NONE def test_operation_value_changed_mapping(device_mapping): @@ -300,7 +334,7 @@ def test_operation_value_changed_mapping_preset(device_mapping): assert device.hvac_mode == HVAC_MODE_HEAT_COOL assert device.preset_mode == PRESET_BOOST device.values.mode = None - assert device.hvac_mode == HVAC_MODE_HEAT + assert device.hvac_mode == HVAC_MODE_HEAT_COOL assert device.preset_mode == PRESET_NONE From a7e0ec3a22ba08e0d72356fe9d7e670bcd1d3b9e Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Thu, 1 Aug 2019 07:12:53 +0200 Subject: [PATCH 22/29] Fixed default hvac mode --- homeassistant/components/zwave/climate.py | 11 ++++++++--- tests/components/zwave/test_climate.py | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index 430cb12f132ed..7c64a0b98ca6d 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -176,8 +176,8 @@ def update_properties(self): # Default operation mode for mode in DEFAULT_HVAC_MODES: - if mode in self._hvac_list: - self._default_hvac_mode = mode + if mode in self._hvac_mapping.keys(): + self._default_hvac_mode = self._hvac_mapping.get(mode) break if self._preset_list: @@ -191,7 +191,9 @@ def update_properties(self): if _hvac_temp is None: # The current mode is not a hvac mode - self._hvac_mode = self._default_hvac_mode + self._hvac_mode = next( + (key for key, value in self._hvac_mapping.items() + if value == self._default_hvac_mode)) self._preset_mode = next( (key for key, value in self._preset_mapping.items() if value == current_mode), current_mode) @@ -201,8 +203,11 @@ def update_properties(self): self._preset_mode = PRESET_NONE _LOGGER.debug("self._hvac_list=%s", self._hvac_list) + _LOGGER.debug("self._hvac_mode=%s", self._hvac_mode) + _LOGGER.debug("self._default_hvac_mode=%s", self._default_hvac_mode) _LOGGER.debug("self._hvac_action=%s", self._hvac_action) _LOGGER.debug("self._preset_list=%s", self._preset_list) + _LOGGER.debug("self._preset_mode=%s", self._preset_mode) # Current Temp if self.values.temperature: diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index 8ee0a149da0b9..440f78451c584 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -67,7 +67,7 @@ def device_mapping(hass, mock_openzwave): primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), mode=MockValue(data='Heat', data_items=[ - 'Off', 'Cool', 'Heat', 'Full Power', 'auto'], + 'Off', 'Cool', 'Heat', 'Full Power', 'heat_cool'], node=node), fan_mode=MockValue(data='test2', data_items=[3, 4, 5], node=node), operating_state=MockValue(data='heating', node=node), From 8fe32371bba12157bf1e81a82fdcffcd2466163b Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Thu, 1 Aug 2019 07:39:29 +0200 Subject: [PATCH 23/29] Fix linting --- homeassistant/components/zwave/climate.py | 46 +++++++++++++++++------ tests/components/zwave/test_climate.py | 17 +++++++-- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index ba375a462ee5e..7f2f969238070 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -4,11 +4,24 @@ from homeassistant.components.climate import ClimateDevice from homeassistant.components.climate.const import ( - CURRENT_HVAC_COOL, CURRENT_HVAC_FAN, CURRENT_HVAC_HEAT, CURRENT_HVAC_IDLE, - CURRENT_HVAC_OFF, DOMAIN, HVAC_MODE_COOL, HVAC_MODE_HEAT, - HVAC_MODE_HEAT_COOL, HVAC_MODE_DRY, HVAC_MODE_FAN_ONLY, HVAC_MODE_OFF, - SUPPORT_FAN_MODE, SUPPORT_SWING_MODE, SUPPORT_TARGET_TEMPERATURE, - SUPPORT_PRESET_MODE, PRESET_BOOST, PRESET_NONE) + CURRENT_HVAC_COOL, + CURRENT_HVAC_FAN, + CURRENT_HVAC_HEAT, + CURRENT_HVAC_IDLE, + CURRENT_HVAC_OFF, + DOMAIN, + HVAC_MODE_COOL, + HVAC_MODE_HEAT, + HVAC_MODE_HEAT_COOL, + HVAC_MODE_DRY, + HVAC_MODE_FAN_ONLY, + HVAC_MODE_OFF, + SUPPORT_FAN_MODE, + SUPPORT_SWING_MODE, + SUPPORT_TARGET_TEMPERATURE, + SUPPORT_PRESET_MODE, + PRESET_BOOST, + PRESET_NONE) from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT from homeassistant.core import callback from homeassistant.helpers.dispatcher import async_dispatcher_connect @@ -183,17 +196,28 @@ def update_properties(self): current_mode = self.values.mode.data _hvac_temp = next( - (key for key, value in self._hvac_mapping.items() - if value == current_mode), None) + ( + key + for key, value in self._hvac_mapping.items() + if value == current_mode), + None + ) if _hvac_temp is None: # The current mode is not a hvac mode self._hvac_mode = next( - (key for key, value in self._hvac_mapping.items() - if value == self._default_hvac_mode)) + ( + key + for key, value in self._hvac_mapping.items() + if value == self._default_hvac_mode) + ) self._preset_mode = next( - (key for key, value in self._preset_mapping.items() - if value == current_mode), current_mode) + ( + key + for key, value in self._preset_mapping.items() + if value == current_mode), + current_mode + ) else: # The current mode is a hvac mode self._hvac_mode = _hvac_temp diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index a979524371f04..80c0910264bcd 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -2,10 +2,19 @@ import pytest from homeassistant.components.climate.const import ( - HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_HEAT_COOL, HVAC_MODE_OFF, - PRESET_BOOST, PRESET_ECO, PRESET_NONE, SUPPORT_FAN_MODE, - SUPPORT_PRESET_MODE, SUPPORT_SWING_MODE, SUPPORT_TARGET_TEMPERATURE, - CURRENT_HVAC_HEAT, CURRENT_HVAC_COOL) + HVAC_MODE_COOL, + HVAC_MODE_HEAT, + HVAC_MODE_HEAT_COOL, + HVAC_MODE_OFF, + PRESET_BOOST, + PRESET_ECO, + PRESET_NONE, + SUPPORT_FAN_MODE, + SUPPORT_PRESET_MODE, + SUPPORT_SWING_MODE, + SUPPORT_TARGET_TEMPERATURE, + CURRENT_HVAC_HEAT, + CURRENT_HVAC_COOL) from homeassistant.components.zwave import climate from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT From 1f6b23c8d33012d3fb62fc8ee8495cd04a44fc11 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Thu, 1 Aug 2019 07:47:33 +0200 Subject: [PATCH 24/29] Make flake happy --- tests/components/zwave/test_climate.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index 80c0910264bcd..d8552cc30ce60 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -123,20 +123,20 @@ def device_heat(hass, mock_openzwave): def test_supported_features(device): - """Test supported features flags""" + """Test supported features flags.""" assert device.supported_features == SUPPORT_FAN_MODE + \ SUPPORT_TARGET_TEMPERATURE def test_supported_features_preset_mode(device_mapping): - """Test supported features flags with swing mode""" + """Test supported features flags with swing mode.""" device = device_mapping assert device.supported_features == SUPPORT_FAN_MODE + \ SUPPORT_TARGET_TEMPERATURE + SUPPORT_PRESET_MODE def test_supported_features_swing_mode(device_zxt_120): - """Test supported features flags with swing mode""" + """Test supported features flags with swing mode.""" device = device_zxt_120 assert device.supported_features == SUPPORT_FAN_MODE + \ SUPPORT_TARGET_TEMPERATURE + SUPPORT_SWING_MODE @@ -343,7 +343,7 @@ def test_operation_value_changed_mapping_preset(device_mapping): def test_operation_value_changed_unknown(device_unknown): - """Test preset changed for climate device. Unknown""" + """Test preset changed for climate device. Unknown.""" device = device_unknown assert device.hvac_mode == HVAC_MODE_HEAT assert device.preset_mode == PRESET_NONE From 7da932e374a671db696ac38ebe628236989d4fa2 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Thu, 1 Aug 2019 07:57:59 +0200 Subject: [PATCH 25/29] Another linting --- homeassistant/components/zwave/climate.py | 12 ++++++++---- tests/components/zwave/test_climate.py | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index 7f2f969238070..ce29049bf3f3b 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -21,7 +21,8 @@ SUPPORT_TARGET_TEMPERATURE, SUPPORT_PRESET_MODE, PRESET_BOOST, - PRESET_NONE) + PRESET_NONE, +) from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT from homeassistant.core import callback from homeassistant.helpers.dispatcher import async_dispatcher_connect @@ -199,7 +200,8 @@ def update_properties(self): ( key for key, value in self._hvac_mapping.items() - if value == current_mode), + if value == current_mode + ), None ) @@ -209,13 +211,15 @@ def update_properties(self): ( key for key, value in self._hvac_mapping.items() - if value == self._default_hvac_mode) + if value == self._default_hvac_mode + ) ) self._preset_mode = next( ( key for key, value in self._preset_mapping.items() - if value == current_mode), + if value == current_mode + ), current_mode ) else: diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index d8552cc30ce60..735638c7bc462 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -14,7 +14,8 @@ SUPPORT_SWING_MODE, SUPPORT_TARGET_TEMPERATURE, CURRENT_HVAC_HEAT, - CURRENT_HVAC_COOL) + CURRENT_HVAC_COOL, +) from homeassistant.components.zwave import climate from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT From 067f2d004a3b90770d85354a1506fb9a5c2f7918 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Thu, 1 Aug 2019 16:28:42 +0200 Subject: [PATCH 26/29] Make black happy --- homeassistant/components/zwave/climate.py | 10 ++- tests/components/zwave/test_climate.py | 75 +++++++++++++++-------- 2 files changed, 53 insertions(+), 32 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index ce29049bf3f3b..1cc2eb942ead2 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -202,7 +202,7 @@ def update_properties(self): for key, value in self._hvac_mapping.items() if value == current_mode ), - None + None, ) if _hvac_temp is None: @@ -220,7 +220,7 @@ def update_properties(self): for key, value in self._preset_mapping.items() if value == current_mode ), - current_mode + current_mode, ) else: # The current mode is a hvac mode @@ -272,8 +272,7 @@ def update_properties(self): # Operating state if self.values.operating_state: mode = self.values.operating_state.data - self._hvac_action = HVAC_CURRENT_MAPPINGS.get( - str(mode).lower(), mode) + self._hvac_action = HVAC_CURRENT_MAPPINGS.get(str(mode).lower(), mode) # Fan operating state if self.values.fan_state: @@ -396,8 +395,7 @@ def set_preset_mode(self, preset_mode): # Activate the default hvac mode self.values.mode.data = self._default_hvac_mode else: - self.values.mode.data = self._preset_mapping.get( - preset_mode, preset_mode) + self.values.mode.data = self._preset_mapping.get(preset_mode, preset_mode) def set_swing_mode(self, swing_mode): """Set new target swing mode.""" diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index 735638c7bc462..e9e75a7834e7e 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -29,11 +29,16 @@ def device(hass, mock_openzwave): values = MockEntityValues( primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), - mode=MockValue(data=HVAC_MODE_HEAT, data_items=[HVAC_MODE_OFF, - HVAC_MODE_HEAT, - HVAC_MODE_COOL, - HVAC_MODE_HEAT_COOL], - node=node), + mode=MockValue( + data=HVAC_MODE_HEAT, + data_items=[ + HVAC_MODE_OFF, + HVAC_MODE_HEAT, + HVAC_MODE_COOL, + HVAC_MODE_HEAT_COOL, + ], + node=node, + ), fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), operating_state=MockValue(data=CURRENT_HVAC_HEAT, node=node), fan_state=MockValue(data=7, node=node), @@ -51,11 +56,16 @@ def device_zxt_120(hass, mock_openzwave): values = MockEntityValues( primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), - mode=MockValue(data=HVAC_MODE_HEAT, data_items=[HVAC_MODE_OFF, - HVAC_MODE_HEAT, - HVAC_MODE_COOL, - HVAC_MODE_HEAT_COOL], - node=node), + mode=MockValue( + data=HVAC_MODE_HEAT, + data_items=[ + HVAC_MODE_OFF, + HVAC_MODE_HEAT, + HVAC_MODE_COOL, + HVAC_MODE_HEAT_COOL, + ], + node=node, + ), fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), operating_state=MockValue(data=CURRENT_HVAC_HEAT, node=node), fan_state=MockValue(data=7, node=node), @@ -73,9 +83,11 @@ def device_mapping(hass, mock_openzwave): values = MockEntityValues( primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), - mode=MockValue(data="Heat", data_items=[ - "Off", "Cool", "Heat", "Full Power", "heat_cool"], - node=node), + mode=MockValue( + data="Heat", + data_items=["Off", "Cool", "Heat", "Full Power", "heat_cool"], + node=node, + ), fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), operating_state=MockValue(data="heating", node=node), fan_state=MockValue(data=7, node=node), @@ -92,9 +104,11 @@ def device_unknown(hass, mock_openzwave): values = MockEntityValues( primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), - mode=MockValue(data="Heat", data_items=[ - "Off", "Cool", "Heat", "heat_cool", "Abcdefg"], - node=node), + mode=MockValue( + data="Heat", + data_items=["Off", "Cool", "Heat", "heat_cool", "Abcdefg"], + node=node, + ), fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), operating_state=MockValue(data="test4", node=node), fan_state=MockValue(data=7, node=node), @@ -111,9 +125,11 @@ def device_heat(hass, mock_openzwave): values = MockEntityValues( primary=MockValue(data=1, node=node), temperature=MockValue(data=5, node=node, units=None), - mode=MockValue(data=HVAC_MODE_HEAT, data_items=[ - HVAC_MODE_OFF, HVAC_MODE_HEAT, "Heat Eco"], - node=node), + mode=MockValue( + data=HVAC_MODE_HEAT, + data_items=[HVAC_MODE_OFF, HVAC_MODE_HEAT, "Heat Eco"], + node=node, + ), fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), operating_state=MockValue(data="test4", node=node), fan_state=MockValue(data=7, node=node), @@ -125,22 +141,25 @@ def device_heat(hass, mock_openzwave): def test_supported_features(device): """Test supported features flags.""" - assert device.supported_features == SUPPORT_FAN_MODE + \ - SUPPORT_TARGET_TEMPERATURE + assert device.supported_features == SUPPORT_FAN_MODE + SUPPORT_TARGET_TEMPERATURE def test_supported_features_preset_mode(device_mapping): """Test supported features flags with swing mode.""" device = device_mapping - assert device.supported_features == SUPPORT_FAN_MODE + \ - SUPPORT_TARGET_TEMPERATURE + SUPPORT_PRESET_MODE + assert ( + device.supported_features + == SUPPORT_FAN_MODE + SUPPORT_TARGET_TEMPERATURE + SUPPORT_PRESET_MODE + ) def test_supported_features_swing_mode(device_zxt_120): """Test supported features flags with swing mode.""" device = device_zxt_120 - assert device.supported_features == SUPPORT_FAN_MODE + \ - SUPPORT_TARGET_TEMPERATURE + SUPPORT_SWING_MODE + assert ( + device.supported_features + == SUPPORT_FAN_MODE + SUPPORT_TARGET_TEMPERATURE + SUPPORT_SWING_MODE + ) def test_zxt_120_swing_mode(device_zxt_120): @@ -186,7 +205,11 @@ def test_data_lists(device): """Test data lists from zwave value items.""" assert device.fan_modes == [3, 4, 5] assert device.hvac_modes == [ - HVAC_MODE_OFF, HVAC_MODE_HEAT, HVAC_MODE_COOL, HVAC_MODE_HEAT_COOL] + HVAC_MODE_OFF, + HVAC_MODE_HEAT, + HVAC_MODE_COOL, + HVAC_MODE_HEAT_COOL, + ] assert device.preset_modes == [] device.values.mode = None assert device.preset_modes == [] From 428e5f519efa5f9393fb4f7021d260481eca44b9 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Thu, 1 Aug 2019 16:35:26 +0200 Subject: [PATCH 27/29] Complete list of default hvac modes --- homeassistant/components/zwave/climate.py | 6 ++++-- tests/components/zwave/test_climate.py | 12 ++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index 1cc2eb942ead2..681b7e5a1ebad 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -10,18 +10,19 @@ CURRENT_HVAC_IDLE, CURRENT_HVAC_OFF, DOMAIN, + HVAC_MODE_AUTO, HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_HEAT_COOL, HVAC_MODE_DRY, HVAC_MODE_FAN_ONLY, HVAC_MODE_OFF, + PRESET_BOOST, + PRESET_NONE, SUPPORT_FAN_MODE, SUPPORT_SWING_MODE, SUPPORT_TARGET_TEMPERATURE, SUPPORT_PRESET_MODE, - PRESET_BOOST, - PRESET_NONE, ) from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT from homeassistant.core import callback @@ -88,6 +89,7 @@ HVAC_MODE_FAN_ONLY, HVAC_MODE_DRY, HVAC_MODE_OFF, + HVAC_MODE_AUTO, ] diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index e9e75a7834e7e..fcd66ca48bb0a 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -2,6 +2,9 @@ import pytest from homeassistant.components.climate.const import ( + CURRENT_HVAC_HEAT, + CURRENT_HVAC_COOL, + HVAC_MODES, HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_HEAT_COOL, @@ -13,10 +16,9 @@ SUPPORT_PRESET_MODE, SUPPORT_SWING_MODE, SUPPORT_TARGET_TEMPERATURE, - CURRENT_HVAC_HEAT, - CURRENT_HVAC_COOL, ) from homeassistant.components.zwave import climate +from homeassistant.components.zwave.climate import DEFAULT_HVAC_MODES from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT from tests.mock.zwave import MockEntityValues, MockNode, MockValue, value_changed @@ -139,6 +141,12 @@ def device_heat(hass, mock_openzwave): yield device +def test_default_hvac_modes(): + """Test wether all hvac modes are included in default_hvac_modes.""" + for hvac_mode in HVAC_MODES: + assert hvac_mode in DEFAULT_HVAC_MODES + + def test_supported_features(device): """Test supported features flags.""" assert device.supported_features == SUPPORT_FAN_MODE + SUPPORT_TARGET_TEMPERATURE From ccbd34df41315d426e87a39c55dbdc145b323788 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Thu, 1 Aug 2019 17:03:59 +0200 Subject: [PATCH 28/29] Add mapping to heat/cool eco --- homeassistant/components/zwave/climate.py | 43 ++++++++++++++++++----- tests/components/zwave/test_climate.py | 35 +++++++++++++++--- 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index 681b7e5a1ebad..ea964f907095b 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -209,13 +209,39 @@ def update_properties(self): if _hvac_temp is None: # The current mode is not a hvac mode - self._hvac_mode = next( - ( - key - for key, value in self._hvac_mapping.items() - if value == self._default_hvac_mode + if ( + "heat" in current_mode.lower() + and HVAC_MODE_HEAT in self._hvac_mapping.values() + ): + # The current preset modes maps to HVAC_MODE_HEAT + self._hvac_mode = next( + ( + key + for key, value in self._hvac_mapping.items() + if value == HVAC_MODE_HEAT + ) + ) + elif ( + "cool" in current_mode.lower() + and HVAC_MODE_COOL in self._hvac_mapping.values() + ): + # The current preset modes maps to HVAC_MODE_COOL + self._hvac_mode = next( + ( + key + for key, value in self._hvac_mapping.items() + if value == HVAC_MODE_COOL + ) + ) + else: + # The current preset modes maps to self._default_hvac_mode + self._hvac_mode = next( + ( + key + for key, value in self._hvac_mapping.items() + if value == self._default_hvac_mode + ) ) - ) self._preset_mode = next( ( key @@ -394,8 +420,9 @@ def set_preset_mode(self, preset_mode): if not self.values.mode: return if preset_mode == PRESET_NONE: - # Activate the default hvac mode - self.values.mode.data = self._default_hvac_mode + # Activate the current hvac mode + self.update_properties() + self.values.mode.data = self._hvac_mapping.get(self.hvac_mode) else: self.values.mode.data = self._preset_mapping.get(preset_mode, preset_mode) diff --git a/tests/components/zwave/test_climate.py b/tests/components/zwave/test_climate.py index fcd66ca48bb0a..60a9dcd0dabca 100644 --- a/tests/components/zwave/test_climate.py +++ b/tests/components/zwave/test_climate.py @@ -121,7 +121,7 @@ def device_unknown(hass, mock_openzwave): @pytest.fixture -def device_heat(hass, mock_openzwave): +def device_heat_cool(hass, mock_openzwave): """Fixture to provide a precreated climate device. Test state heat only.""" node = MockNode() values = MockEntityValues( @@ -129,7 +129,13 @@ def device_heat(hass, mock_openzwave): temperature=MockValue(data=5, node=node, units=None), mode=MockValue( data=HVAC_MODE_HEAT, - data_items=[HVAC_MODE_OFF, HVAC_MODE_HEAT, "Heat Eco"], + data_items=[ + HVAC_MODE_OFF, + HVAC_MODE_HEAT, + HVAC_MODE_COOL, + "Heat Eco", + "Cool Eco", + ], node=node, ), fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), @@ -281,14 +287,18 @@ def test_operation_value_set_unknown(device_unknown): assert device.values.mode.data == HVAC_MODE_HEAT_COOL -def test_operation_value_set_heat(device_heat): - """Test values changed for climate device. Heat only.""" - device = device_heat +def test_operation_value_set_heat_cool(device_heat_cool): + """Test values changed for climate device. Heat/Cool only.""" + device = device_heat_cool assert device.values.mode.data == HVAC_MODE_HEAT device.set_preset_mode("Heat Eco") assert device.values.mode.data == "Heat Eco" device.set_preset_mode(PRESET_NONE) assert device.values.mode.data == HVAC_MODE_HEAT + device.set_preset_mode("Cool Eco") + assert device.values.mode.data == "Cool Eco" + device.set_preset_mode(PRESET_NONE) + assert device.values.mode.data == HVAC_MODE_COOL def test_fan_mode_value_set(device): @@ -385,6 +395,21 @@ def test_operation_value_changed_unknown(device_unknown): assert device.preset_mode == "Abcdefg" +def test_operation_value_changed_heat_cool(device_heat_cool): + """Test preset changed for climate device. Heat/Cool only.""" + device = device_heat_cool + assert device.hvac_mode == HVAC_MODE_HEAT + assert device.preset_mode == PRESET_NONE + device.values.mode.data = "Cool Eco" + value_changed(device.values.mode) + assert device.hvac_mode == HVAC_MODE_COOL + assert device.preset_mode == "Cool Eco" + device.values.mode.data = "Heat Eco" + value_changed(device.values.mode) + assert device.hvac_mode == HVAC_MODE_HEAT + assert device.preset_mode == "Heat Eco" + + def test_fan_mode_value_changed(device): """Test values changed for climate device.""" assert device.fan_mode == "test2" From 8137b2bd9ec2a3c6417e4c32ca6f801dc5b48a02 Mon Sep 17 00:00:00 2001 From: Tobias Haase Date: Fri, 2 Aug 2019 09:09:33 +0200 Subject: [PATCH 29/29] Fixed another bug where mapping goes wrong --- homeassistant/components/zwave/climate.py | 62 ++++++++++------------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/homeassistant/components/zwave/climate.py b/homeassistant/components/zwave/climate.py index ea964f907095b..6f66c6f36c460 100644 --- a/homeassistant/components/zwave/climate.py +++ b/homeassistant/components/zwave/climate.py @@ -124,13 +124,13 @@ def __init__(self, values, temp_unit): self._target_temperature = None self._current_temperature = None self._hvac_action = None - self._hvac_list = None - self._hvac_mapping = None - self._hvac_mode = None - self._default_hvac_mode = None - self._preset_mapping = None - self._preset_list = None - self._preset_mode = None + self._hvac_list = None # [zwave_mode] + self._hvac_mapping = None # {ha_mode:zwave_mode} + self._hvac_mode = None # ha_mode + self._default_hvac_mode = None # ha_mode + self._preset_mapping = None # {ha_mode:zwave_mode} + self._preset_list = None # [zwave_mode] + self._preset_mode = None # ha_mode if exists, else zwave_mode self._current_fan_mode = None self._fan_modes = None self._fan_state = None @@ -190,7 +190,7 @@ def update_properties(self): # Default operation mode for mode in DEFAULT_HVAC_MODES: if mode in self._hvac_mapping.keys(): - self._default_hvac_mode = self._hvac_mapping.get(mode) + self._default_hvac_mode = mode break if self._preset_list: @@ -198,6 +198,7 @@ def update_properties(self): self._preset_list.append(PRESET_NONE) current_mode = self.values.mode.data + _LOGGER.debug("current_mode=%s", current_mode) _hvac_temp = next( ( key @@ -211,37 +212,22 @@ def update_properties(self): # The current mode is not a hvac mode if ( "heat" in current_mode.lower() - and HVAC_MODE_HEAT in self._hvac_mapping.values() + and HVAC_MODE_HEAT in self._hvac_mapping.keys() ): # The current preset modes maps to HVAC_MODE_HEAT - self._hvac_mode = next( - ( - key - for key, value in self._hvac_mapping.items() - if value == HVAC_MODE_HEAT - ) - ) + _LOGGER.debug("Mapped to HEAT") + self._hvac_mode = HVAC_MODE_HEAT elif ( "cool" in current_mode.lower() - and HVAC_MODE_COOL in self._hvac_mapping.values() + and HVAC_MODE_COOL in self._hvac_mapping.keys() ): # The current preset modes maps to HVAC_MODE_COOL - self._hvac_mode = next( - ( - key - for key, value in self._hvac_mapping.items() - if value == HVAC_MODE_COOL - ) - ) + _LOGGER.debug("Mapped to COOL") + self._hvac_mode = HVAC_MODE_COOL else: # The current preset modes maps to self._default_hvac_mode - self._hvac_mode = next( - ( - key - for key, value in self._hvac_mapping.items() - if value == self._default_hvac_mode - ) - ) + _LOGGER.debug("Mapped to DEFAULT") + self._hvac_mode = self._default_hvac_mode self._preset_mode = next( ( key @@ -255,10 +241,12 @@ def update_properties(self): self._hvac_mode = _hvac_temp self._preset_mode = PRESET_NONE + _LOGGER.debug("self._hvac_mapping=%s", self._hvac_mapping) _LOGGER.debug("self._hvac_list=%s", self._hvac_list) _LOGGER.debug("self._hvac_mode=%s", self._hvac_mode) _LOGGER.debug("self._default_hvac_mode=%s", self._default_hvac_mode) _LOGGER.debug("self._hvac_action=%s", self._hvac_action) + _LOGGER.debug("self._preset_mapping=%s", self._preset_mapping) _LOGGER.debug("self._preset_list=%s", self._preset_list) _LOGGER.debug("self._preset_mode=%s", self._preset_mode) @@ -412,7 +400,9 @@ def set_hvac_mode(self, hvac_mode): _LOGGER.debug("Set hvac_mode to %s", hvac_mode) if not self.values.mode: return - self.values.mode.data = self._hvac_mapping.get(hvac_mode, hvac_mode) + operation_mode = self._hvac_mapping.get(hvac_mode) + _LOGGER.debug("Set operation_mode to %s", operation_mode) + self.values.mode.data = operation_mode def set_preset_mode(self, preset_mode): """Set new target preset mode.""" @@ -422,9 +412,13 @@ def set_preset_mode(self, preset_mode): if preset_mode == PRESET_NONE: # Activate the current hvac mode self.update_properties() - self.values.mode.data = self._hvac_mapping.get(self.hvac_mode) + operation_mode = self._hvac_mapping.get(self.hvac_mode) + _LOGGER.debug("Set operation_mode to %s", operation_mode) + self.values.mode.data = operation_mode else: - self.values.mode.data = self._preset_mapping.get(preset_mode, preset_mode) + operation_mode = self._preset_mapping.get(preset_mode, preset_mode) + _LOGGER.debug("Set operation_mode to %s", operation_mode) + self.values.mode.data = operation_mode def set_swing_mode(self, swing_mode): """Set new target swing mode."""