Improve z-wave thermostat support (#27040)

* Improve z-wave thermostat support

Discover thermostat using COMMAND_CLASS_THERMOSTAT_MODE
so that it is a single entitiy in case there are multiple
setpoints. z-wave docs mention it is always present.
Add support for single/range target temperature depending
on the current thermostat mode.

* Remove debug print

* Refactor Z-Wave dynamic setpoint(s) selection

- use explicit mapping between modes and setpoints as defined in
Z-Wave specs
- add tests for away (2 setpoints) and heat eco (1 setpoint) modes

* Add non-standard thermostat mode aliases
This commit is contained in:
Andrew Onyshchuk 2019-11-25 18:32:37 -06:00 committed by Paulus Schoutsen
parent 807de1aeb3
commit f5c01cc30d
4 changed files with 479 additions and 115 deletions

View File

@ -2,6 +2,8 @@
# Because we do not compile openzwave on CI # Because we do not compile openzwave on CI
import logging import logging
from typing import Optional
from homeassistant.components.climate import ClimateDevice from homeassistant.components.climate import ClimateDevice
from homeassistant.components.climate.const import ( from homeassistant.components.climate.const import (
CURRENT_HVAC_COOL, CURRENT_HVAC_COOL,
@ -17,18 +19,23 @@ from homeassistant.components.climate.const import (
HVAC_MODE_DRY, HVAC_MODE_DRY,
HVAC_MODE_FAN_ONLY, HVAC_MODE_FAN_ONLY,
HVAC_MODE_OFF, HVAC_MODE_OFF,
PRESET_AWAY,
PRESET_BOOST, PRESET_BOOST,
PRESET_NONE, PRESET_NONE,
SUPPORT_AUX_HEAT, SUPPORT_AUX_HEAT,
SUPPORT_FAN_MODE, SUPPORT_FAN_MODE,
SUPPORT_SWING_MODE, SUPPORT_SWING_MODE,
SUPPORT_TARGET_TEMPERATURE, SUPPORT_TARGET_TEMPERATURE,
SUPPORT_TARGET_TEMPERATURE_RANGE,
SUPPORT_PRESET_MODE, SUPPORT_PRESET_MODE,
ATTR_TARGET_TEMP_LOW,
ATTR_TARGET_TEMP_HIGH,
) )
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from . import ZWaveDeviceEntity from . import ZWaveDeviceEntity
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -66,6 +73,33 @@ HVAC_STATE_MAPPINGS = {
"auto changeover": HVAC_MODE_HEAT_COOL, "auto changeover": HVAC_MODE_HEAT_COOL,
} }
MODE_SETPOINT_MAPPINGS = {
"off": (),
"heat": ("setpoint_heating",),
"cool": ("setpoint_cooling",),
"auto": ("setpoint_heating", "setpoint_cooling"),
"aux heat": ("setpoint_heating",),
"furnace": ("setpoint_furnace",),
"dry air": ("setpoint_dry_air",),
"moist air": ("setpoint_moist_air",),
"auto changeover": ("setpoint_auto_changeover",),
"heat econ": ("setpoint_eco_heating",),
"cool econ": ("setpoint_eco_cooling",),
"away": ("setpoint_away_heating", "setpoint_away_cooling"),
"full power": ("setpoint_full_power",),
# aliases found in xml configs
"comfort": ("setpoint_heating",),
"heat mode": ("setpoint_heating",),
"heat (default)": ("setpoint_heating",),
"dry floor": ("setpoint_dry_air",),
"heat eco": ("setpoint_eco_heating",),
"energy saving": ("setpoint_eco_heating",),
"energy heat": ("setpoint_eco_heating",),
"vacation": ("setpoint_away_heating", "setpoint_away_cooling"),
# for tests
"heat_cool": ("setpoint_heating", "setpoint_cooling"),
}
HVAC_CURRENT_MAPPINGS = { HVAC_CURRENT_MAPPINGS = {
"idle": CURRENT_HVAC_IDLE, "idle": CURRENT_HVAC_IDLE,
"heat": CURRENT_HVAC_HEAT, "heat": CURRENT_HVAC_HEAT,
@ -80,6 +114,7 @@ HVAC_CURRENT_MAPPINGS = {
} }
PRESET_MAPPINGS = { PRESET_MAPPINGS = {
"away": PRESET_AWAY,
"full power": PRESET_BOOST, "full power": PRESET_BOOST,
"manufacturer specific": PRESET_MANUFACTURER_SPECIFIC, "manufacturer specific": PRESET_MANUFACTURER_SPECIFIC,
} }
@ -124,6 +159,7 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice):
"""Initialize the Z-Wave climate device.""" """Initialize the Z-Wave climate device."""
ZWaveDeviceEntity.__init__(self, values, DOMAIN) ZWaveDeviceEntity.__init__(self, values, DOMAIN)
self._target_temperature = None self._target_temperature = None
self._target_temperature_range = (None, None)
self._current_temperature = None self._current_temperature = None
self._hvac_action = None self._hvac_action = None
self._hvac_list = None # [zwave_mode] self._hvac_list = None # [zwave_mode]
@ -154,10 +190,20 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice):
self._zxt_120 = 1 self._zxt_120 = 1
self.update_properties() self.update_properties()
def _current_mode_setpoints(self):
current_mode = str(self.values.primary.data).lower()
setpoints_names = MODE_SETPOINT_MAPPINGS.get(current_mode, ())
return tuple(getattr(self.values, name, None) for name in setpoints_names)
@property @property
def supported_features(self): def supported_features(self):
"""Return the list of supported features.""" """Return the list of supported features."""
support = SUPPORT_TARGET_TEMPERATURE support = SUPPORT_TARGET_TEMPERATURE
if HVAC_MODE_HEAT_COOL in self._hvac_list:
support |= SUPPORT_TARGET_TEMPERATURE_RANGE
if PRESET_AWAY in self._preset_list:
support |= SUPPORT_TARGET_TEMPERATURE_RANGE
if self.values.fan_mode: if self.values.fan_mode:
support |= SUPPORT_FAN_MODE support |= SUPPORT_FAN_MODE
if self._zxt_120 == 1 and self.values.zxt_120_swing_mode: if self._zxt_120 == 1 and self.values.zxt_120_swing_mode:
@ -193,13 +239,13 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice):
def _update_operation_mode(self): def _update_operation_mode(self):
"""Update hvac and preset modes.""" """Update hvac and preset modes."""
if self.values.mode: if self.values.primary:
self._hvac_list = [] self._hvac_list = []
self._hvac_mapping = {} self._hvac_mapping = {}
self._preset_list = [] self._preset_list = []
self._preset_mapping = {} self._preset_mapping = {}
mode_list = self.values.mode.data_items mode_list = self.values.primary.data_items
if mode_list: if mode_list:
for mode in mode_list: for mode in mode_list:
ha_mode = HVAC_STATE_MAPPINGS.get(str(mode).lower()) ha_mode = HVAC_STATE_MAPPINGS.get(str(mode).lower())
@ -227,7 +273,7 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice):
# Presets are supported # Presets are supported
self._preset_list.append(PRESET_NONE) self._preset_list.append(PRESET_NONE)
current_mode = self.values.mode.data current_mode = self.values.primary.data
_LOGGER.debug("current_mode=%s", current_mode) _LOGGER.debug("current_mode=%s", current_mode)
_hvac_temp = next( _hvac_temp = next(
( (
@ -313,15 +359,21 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice):
def _update_target_temp(self): def _update_target_temp(self):
"""Update target temperature.""" """Update target temperature."""
if self.values.primary.data == 0: current_setpoints = self._current_mode_setpoints()
_LOGGER.debug( self._target_temperature = None
"Setpoint is 0, setting default to " "current_temperature=%s", self._target_temperature_range = (None, None)
self._current_temperature, if len(current_setpoints) == 1:
) (setpoint,) = current_setpoints
if self._current_temperature is not None: if setpoint is not None:
self._target_temperature = round((float(self._current_temperature)), 1) self._target_temperature = round((float(setpoint.data)), 1)
else: elif len(current_setpoints) == 2:
self._target_temperature = round((float(self.values.primary.data)), 1) (setpoint_low, setpoint_high) = current_setpoints
target_low, target_high = None, None
if setpoint_low is not None:
target_low = round((float(setpoint_low.data)), 1)
if setpoint_high is not None:
target_high = round((float(setpoint_high.data)), 1)
self._target_temperature_range = (target_low, target_high)
def _update_operating_state(self): def _update_operating_state(self):
"""Update operating state.""" """Update operating state."""
@ -374,7 +426,7 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice):
Need to be one of HVAC_MODE_*. Need to be one of HVAC_MODE_*.
""" """
if self.values.mode: if self.values.primary:
return self._hvac_mode return self._hvac_mode
return self._default_hvac_mode return self._default_hvac_mode
@ -384,7 +436,7 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice):
Need to be a subset of HVAC_MODES. Need to be a subset of HVAC_MODES.
""" """
if self.values.mode: if self.values.primary:
return self._hvac_list return self._hvac_list
return [] return []
@ -401,7 +453,7 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice):
"""Return true if aux heater.""" """Return true if aux heater."""
if not self._aux_heat: if not self._aux_heat:
return None return None
if self.values.mode.data == AUX_HEAT_ZWAVE_MODE: if self.values.primary.data == AUX_HEAT_ZWAVE_MODE:
return True return True
return False return False
@ -411,7 +463,7 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice):
Need to be one of PRESET_*. Need to be one of PRESET_*.
""" """
if self.values.mode: if self.values.primary:
return self._preset_mode return self._preset_mode
return PRESET_NONE return PRESET_NONE
@ -421,7 +473,7 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice):
Need to be a subset of PRESET_MODES. Need to be a subset of PRESET_MODES.
""" """
if self.values.mode: if self.values.primary:
return self._preset_list return self._preset_list
return [] return []
@ -430,12 +482,35 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice):
"""Return the temperature we try to reach.""" """Return the temperature we try to reach."""
return self._target_temperature return self._target_temperature
@property
def target_temperature_low(self) -> Optional[float]:
"""Return the lowbound target temperature we try to reach."""
return self._target_temperature_range[0]
@property
def target_temperature_high(self) -> Optional[float]:
"""Return the highbound target temperature we try to reach."""
return self._target_temperature_range[1]
def set_temperature(self, **kwargs): def set_temperature(self, **kwargs):
"""Set new target temperature.""" """Set new target temperature."""
_LOGGER.debug("Set temperature to %s", kwargs.get(ATTR_TEMPERATURE)) current_setpoints = self._current_mode_setpoints()
if kwargs.get(ATTR_TEMPERATURE) is None: if len(current_setpoints) == 1:
return (setpoint,) = current_setpoints
self.values.primary.data = kwargs.get(ATTR_TEMPERATURE) target_temp = kwargs.get(ATTR_TEMPERATURE)
if setpoint is not None and target_temp is not None:
_LOGGER.debug("Set temperature to %s", target_temp)
setpoint.data = target_temp
elif len(current_setpoints) == 2:
(setpoint_low, setpoint_high) = current_setpoints
target_temp_low = kwargs.get(ATTR_TARGET_TEMP_LOW)
target_temp_high = kwargs.get(ATTR_TARGET_TEMP_HIGH)
if setpoint_low is not None and target_temp_low is not None:
_LOGGER.debug("Set low temperature to %s", target_temp_low)
setpoint_low.data = target_temp_low
if setpoint_high is not None and target_temp_high is not None:
_LOGGER.debug("Set high temperature to %s", target_temp_high)
setpoint_high.data = target_temp_high
def set_fan_mode(self, fan_mode): def set_fan_mode(self, fan_mode):
"""Set new target fan mode.""" """Set new target fan mode."""
@ -447,11 +522,11 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice):
def set_hvac_mode(self, hvac_mode): def set_hvac_mode(self, hvac_mode):
"""Set new target hvac mode.""" """Set new target hvac mode."""
_LOGGER.debug("Set hvac_mode to %s", hvac_mode) _LOGGER.debug("Set hvac_mode to %s", hvac_mode)
if not self.values.mode: if not self.values.primary:
return return
operation_mode = self._hvac_mapping.get(hvac_mode) operation_mode = self._hvac_mapping.get(hvac_mode)
_LOGGER.debug("Set operation_mode to %s", operation_mode) _LOGGER.debug("Set operation_mode to %s", operation_mode)
self.values.mode.data = operation_mode self.values.primary.data = operation_mode
def turn_aux_heat_on(self): def turn_aux_heat_on(self):
"""Turn auxillary heater on.""" """Turn auxillary heater on."""
@ -459,7 +534,7 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice):
return return
operation_mode = AUX_HEAT_ZWAVE_MODE operation_mode = AUX_HEAT_ZWAVE_MODE
_LOGGER.debug("Aux heat on. Set operation mode to %s", operation_mode) _LOGGER.debug("Aux heat on. Set operation mode to %s", operation_mode)
self.values.mode.data = operation_mode self.values.primary.data = operation_mode
def turn_aux_heat_off(self): def turn_aux_heat_off(self):
"""Turn auxillary heater off.""" """Turn auxillary heater off."""
@ -470,23 +545,23 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice):
else: else:
operation_mode = self._hvac_mapping.get(HVAC_MODE_OFF) operation_mode = self._hvac_mapping.get(HVAC_MODE_OFF)
_LOGGER.debug("Aux heat off. Set operation mode to %s", operation_mode) _LOGGER.debug("Aux heat off. Set operation mode to %s", operation_mode)
self.values.mode.data = operation_mode self.values.primary.data = operation_mode
def set_preset_mode(self, preset_mode): def set_preset_mode(self, preset_mode):
"""Set new target preset mode.""" """Set new target preset mode."""
_LOGGER.debug("Set preset_mode to %s", preset_mode) _LOGGER.debug("Set preset_mode to %s", preset_mode)
if not self.values.mode: if not self.values.primary:
return return
if preset_mode == PRESET_NONE: if preset_mode == PRESET_NONE:
# Activate the current hvac mode # Activate the current hvac mode
self._update_operation_mode() self._update_operation_mode()
operation_mode = 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) _LOGGER.debug("Set operation_mode to %s", operation_mode)
self.values.mode.data = operation_mode self.values.primary.data = operation_mode
else: else:
operation_mode = 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) _LOGGER.debug("Set operation_mode to %s", operation_mode)
self.values.mode.data = operation_mode self.values.primary.data = operation_mode
def set_swing_mode(self, swing_mode): def set_swing_mode(self, swing_mode):
"""Set new target swing mode.""" """Set new target swing mode."""

View File

@ -57,17 +57,68 @@ DISCOVERY_SCHEMAS = [
DEFAULT_VALUES_SCHEMA, DEFAULT_VALUES_SCHEMA,
**{ **{
const.DISC_PRIMARY: { const.DISC_PRIMARY: {
const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT] const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_MODE]
},
"setpoint_heating": {
const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT],
const.DISC_INDEX: [1],
const.DISC_OPTIONAL: True,
},
"setpoint_cooling": {
const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT],
const.DISC_INDEX: [2],
const.DISC_OPTIONAL: True,
},
"setpoint_furnace": {
const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT],
const.DISC_INDEX: [7],
const.DISC_OPTIONAL: True,
},
"setpoint_dry_air": {
const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT],
const.DISC_INDEX: [8],
const.DISC_OPTIONAL: True,
},
"setpoint_moist_air": {
const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT],
const.DISC_INDEX: [9],
const.DISC_OPTIONAL: True,
},
"setpoint_auto_changeover": {
const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT],
const.DISC_INDEX: [10],
const.DISC_OPTIONAL: True,
},
"setpoint_eco_heating": {
const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT],
const.DISC_INDEX: [11],
const.DISC_OPTIONAL: True,
},
"setpoint_eco_cooling": {
const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT],
const.DISC_INDEX: [12],
const.DISC_OPTIONAL: True,
},
"setpoint_away_heating": {
const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT],
const.DISC_INDEX: [13],
const.DISC_OPTIONAL: True,
},
"setpoint_away_cooling": {
const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT],
const.DISC_INDEX: [14],
const.DISC_OPTIONAL: True,
},
"setpoint_full_power": {
const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_SETPOINT],
const.DISC_INDEX: [15],
const.DISC_OPTIONAL: True,
}, },
"temperature": { "temperature": {
const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SENSOR_MULTILEVEL], const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_SENSOR_MULTILEVEL],
const.DISC_INDEX: [const.INDEX_SENSOR_MULTILEVEL_TEMPERATURE], const.DISC_INDEX: [const.INDEX_SENSOR_MULTILEVEL_TEMPERATURE],
const.DISC_OPTIONAL: True, const.DISC_OPTIONAL: True,
}, },
"mode": {
const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_MODE],
const.DISC_OPTIONAL: True,
},
"fan_mode": { "fan_mode": {
const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_FAN_MODE], const.DISC_COMMAND_CLASS: [const.COMMAND_CLASS_THERMOSTAT_FAN_MODE],
const.DISC_OPTIONAL: True, const.DISC_OPTIONAL: True,

View File

@ -9,6 +9,7 @@ from homeassistant.components.climate.const import (
HVAC_MODE_HEAT, HVAC_MODE_HEAT,
HVAC_MODE_HEAT_COOL, HVAC_MODE_HEAT_COOL,
HVAC_MODE_OFF, HVAC_MODE_OFF,
PRESET_AWAY,
PRESET_BOOST, PRESET_BOOST,
PRESET_ECO, PRESET_ECO,
PRESET_NONE, PRESET_NONE,
@ -16,6 +17,9 @@ from homeassistant.components.climate.const import (
SUPPORT_PRESET_MODE, SUPPORT_PRESET_MODE,
SUPPORT_SWING_MODE, SUPPORT_SWING_MODE,
SUPPORT_TARGET_TEMPERATURE, SUPPORT_TARGET_TEMPERATURE,
SUPPORT_TARGET_TEMPERATURE_RANGE,
ATTR_TARGET_TEMP_LOW,
ATTR_TARGET_TEMP_HIGH,
) )
from homeassistant.components.zwave import climate from homeassistant.components.zwave import climate
from homeassistant.components.zwave.climate import DEFAULT_HVAC_MODES from homeassistant.components.zwave.climate import DEFAULT_HVAC_MODES
@ -29,9 +33,7 @@ def device(hass, mock_openzwave):
"""Fixture to provide a precreated climate device.""" """Fixture to provide a precreated climate device."""
node = MockNode() node = MockNode()
values = MockEntityValues( values = MockEntityValues(
primary=MockValue(data=1, node=node), primary=MockValue(
temperature=MockValue(data=5, node=node, units=None),
mode=MockValue(
data=HVAC_MODE_HEAT, data=HVAC_MODE_HEAT,
data_items=[ data_items=[
HVAC_MODE_OFF, HVAC_MODE_OFF,
@ -41,6 +43,9 @@ def device(hass, mock_openzwave):
], ],
node=node, node=node,
), ),
setpoint_heating=MockValue(data=1, node=node),
setpoint_cooling=MockValue(data=10, node=node),
temperature=MockValue(data=5, node=node, units=None),
fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node),
operating_state=MockValue(data=CURRENT_HVAC_HEAT, node=node), operating_state=MockValue(data=CURRENT_HVAC_HEAT, node=node),
fan_action=MockValue(data=7, node=node), fan_action=MockValue(data=7, node=node),
@ -56,9 +61,7 @@ def device_zxt_120(hass, mock_openzwave):
node = MockNode(manufacturer_id="5254", product_id="8377") node = MockNode(manufacturer_id="5254", product_id="8377")
values = MockEntityValues( values = MockEntityValues(
primary=MockValue(data=1, node=node), primary=MockValue(
temperature=MockValue(data=5, node=node, units=None),
mode=MockValue(
data=HVAC_MODE_HEAT, data=HVAC_MODE_HEAT,
data_items=[ data_items=[
HVAC_MODE_OFF, HVAC_MODE_OFF,
@ -68,6 +71,9 @@ def device_zxt_120(hass, mock_openzwave):
], ],
node=node, node=node,
), ),
setpoint_heating=MockValue(data=1, node=node),
setpoint_cooling=MockValue(data=10, node=node),
temperature=MockValue(data=5, node=node, units=None),
fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node),
operating_state=MockValue(data=CURRENT_HVAC_HEAT, node=node), operating_state=MockValue(data=CURRENT_HVAC_HEAT, node=node),
fan_action=MockValue(data=7, node=node), fan_action=MockValue(data=7, node=node),
@ -83,13 +89,14 @@ def device_mapping(hass, mock_openzwave):
"""Fixture to provide a precreated climate device. Test state mapping.""" """Fixture to provide a precreated climate device. Test state mapping."""
node = MockNode() node = MockNode()
values = MockEntityValues( values = MockEntityValues(
primary=MockValue(data=1, node=node), primary=MockValue(
temperature=MockValue(data=5, node=node, units=None),
mode=MockValue(
data="Heat", data="Heat",
data_items=["Off", "Cool", "Heat", "Full Power", "heat_cool"], data_items=["Off", "Cool", "Heat", "Full Power", "Auto"],
node=node, node=node,
), ),
setpoint_heating=MockValue(data=1, node=node),
setpoint_cooling=MockValue(data=10, node=node),
temperature=MockValue(data=5, node=node, units=None),
fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node),
operating_state=MockValue(data="heating", node=node), operating_state=MockValue(data="heating", node=node),
fan_action=MockValue(data=7, node=node), fan_action=MockValue(data=7, node=node),
@ -104,13 +111,14 @@ def device_unknown(hass, mock_openzwave):
"""Fixture to provide a precreated climate device. Test state unknown.""" """Fixture to provide a precreated climate device. Test state unknown."""
node = MockNode() node = MockNode()
values = MockEntityValues( values = MockEntityValues(
primary=MockValue(data=1, node=node), primary=MockValue(
temperature=MockValue(data=5, node=node, units=None),
mode=MockValue(
data="Heat", data="Heat",
data_items=["Off", "Cool", "Heat", "heat_cool", "Abcdefg"], data_items=["Off", "Cool", "Heat", "heat_cool", "Abcdefg"],
node=node, node=node,
), ),
setpoint_heating=MockValue(data=1, node=node),
setpoint_cooling=MockValue(data=10, node=node),
temperature=MockValue(data=5, node=node, units=None),
fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node),
operating_state=MockValue(data="test4", node=node), operating_state=MockValue(data="test4", node=node),
fan_action=MockValue(data=7, node=node), fan_action=MockValue(data=7, node=node),
@ -125,9 +133,7 @@ def device_heat_cool(hass, mock_openzwave):
"""Fixture to provide a precreated climate device. Test state heat only.""" """Fixture to provide a precreated climate device. Test state heat only."""
node = MockNode() node = MockNode()
values = MockEntityValues( values = MockEntityValues(
primary=MockValue(data=1, node=node), primary=MockValue(
temperature=MockValue(data=5, node=node, units=None),
mode=MockValue(
data=HVAC_MODE_HEAT, data=HVAC_MODE_HEAT,
data_items=[ data_items=[
HVAC_MODE_OFF, HVAC_MODE_OFF,
@ -138,6 +144,88 @@ def device_heat_cool(hass, mock_openzwave):
], ],
node=node, node=node,
), ),
setpoint_heating=MockValue(data=1, node=node),
setpoint_cooling=MockValue(data=10, node=node),
temperature=MockValue(data=5, node=node, units=None),
fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node),
operating_state=MockValue(data="test4", node=node),
fan_action=MockValue(data=7, node=node),
)
device = climate.get_device(hass, node=node, values=values, node_config={})
yield device
@pytest.fixture
def device_heat_cool_range(hass, mock_openzwave):
"""Fixture to provide a precreated climate device. Target range mode."""
node = MockNode()
values = MockEntityValues(
primary=MockValue(
data=HVAC_MODE_HEAT_COOL,
data_items=[
HVAC_MODE_OFF,
HVAC_MODE_HEAT,
HVAC_MODE_COOL,
HVAC_MODE_HEAT_COOL,
],
node=node,
),
setpoint_heating=MockValue(data=1, node=node),
setpoint_cooling=MockValue(data=10, node=node),
temperature=MockValue(data=5, node=node, units=None),
fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node),
operating_state=MockValue(data="test4", node=node),
fan_action=MockValue(data=7, node=node),
)
device = climate.get_device(hass, node=node, values=values, node_config={})
yield device
@pytest.fixture
def device_heat_cool_away(hass, mock_openzwave):
"""Fixture to provide a precreated climate device. Target range mode."""
node = MockNode()
values = MockEntityValues(
primary=MockValue(
data=HVAC_MODE_HEAT_COOL,
data_items=[
HVAC_MODE_OFF,
HVAC_MODE_HEAT,
HVAC_MODE_COOL,
HVAC_MODE_HEAT_COOL,
PRESET_AWAY,
],
node=node,
),
setpoint_heating=MockValue(data=2, node=node),
setpoint_cooling=MockValue(data=9, node=node),
setpoint_away_heating=MockValue(data=1, node=node),
setpoint_away_cooling=MockValue(data=10, node=node),
temperature=MockValue(data=5, node=node, units=None),
fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node),
operating_state=MockValue(data="test4", node=node),
fan_action=MockValue(data=7, node=node),
)
device = climate.get_device(hass, node=node, values=values, node_config={})
yield device
@pytest.fixture
def device_heat_eco(hass, mock_openzwave):
"""Fixture to provide a precreated climate device. heat/heat eco."""
node = MockNode()
values = MockEntityValues(
primary=MockValue(
data=HVAC_MODE_HEAT,
data_items=[HVAC_MODE_OFF, HVAC_MODE_HEAT, "heat econ"],
node=node,
),
setpoint_heating=MockValue(data=2, node=node),
setpoint_eco_heating=MockValue(data=1, node=node),
temperature=MockValue(data=5, node=node, units=None),
fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node), fan_mode=MockValue(data="test2", data_items=[3, 4, 5], node=node),
operating_state=MockValue(data="test4", node=node), operating_state=MockValue(data="test4", node=node),
fan_action=MockValue(data=7, node=node), fan_action=MockValue(data=7, node=node),
@ -155,7 +243,23 @@ def test_default_hvac_modes():
def test_supported_features(device): def test_supported_features(device):
"""Test supported features flags.""" """Test supported features flags."""
assert device.supported_features == SUPPORT_FAN_MODE + SUPPORT_TARGET_TEMPERATURE assert (
device.supported_features
== SUPPORT_FAN_MODE
+ SUPPORT_TARGET_TEMPERATURE
+ SUPPORT_TARGET_TEMPERATURE_RANGE
)
def test_supported_features_temp_range(device_heat_cool_range):
"""Test supported features flags with target temp range."""
device = device_heat_cool_range
assert (
device.supported_features
== SUPPORT_FAN_MODE
+ SUPPORT_TARGET_TEMPERATURE
+ SUPPORT_TARGET_TEMPERATURE_RANGE
)
def test_supported_features_preset_mode(device_mapping): def test_supported_features_preset_mode(device_mapping):
@ -163,7 +267,10 @@ def test_supported_features_preset_mode(device_mapping):
device = device_mapping device = device_mapping
assert ( assert (
device.supported_features device.supported_features
== SUPPORT_FAN_MODE + SUPPORT_TARGET_TEMPERATURE + SUPPORT_PRESET_MODE == SUPPORT_FAN_MODE
+ SUPPORT_TARGET_TEMPERATURE
+ SUPPORT_TARGET_TEMPERATURE_RANGE
+ SUPPORT_PRESET_MODE
) )
@ -172,7 +279,10 @@ def test_supported_features_swing_mode(device_zxt_120):
device = device_zxt_120 device = device_zxt_120
assert ( assert (
device.supported_features device.supported_features
== SUPPORT_FAN_MODE + SUPPORT_TARGET_TEMPERATURE + SUPPORT_SWING_MODE == SUPPORT_FAN_MODE
+ SUPPORT_TARGET_TEMPERATURE
+ SUPPORT_TARGET_TEMPERATURE_RANGE
+ SUPPORT_SWING_MODE
) )
@ -207,14 +317,6 @@ def test_temperature_unit(device):
assert device.temperature_unit == TEMP_CELSIUS assert device.temperature_unit == TEMP_CELSIUS
def test_default_target_temperature(device):
"""Test default setting of target temperature."""
assert device.target_temperature == 1
device.values.primary.data = 0
value_changed(device.values.primary)
assert device.target_temperature == 5 # Current Temperature
def test_data_lists(device): def test_data_lists(device):
"""Test data lists from zwave value items.""" """Test data lists from zwave value items."""
assert device.fan_modes == [3, 4, 5] assert device.fan_modes == [3, 4, 5]
@ -225,7 +327,7 @@ def test_data_lists(device):
HVAC_MODE_HEAT_COOL, HVAC_MODE_HEAT_COOL,
] ]
assert device.preset_modes == [] assert device.preset_modes == []
device.values.mode = None device.values.primary = None
assert device.preset_modes == [] assert device.preset_modes == []
@ -234,71 +336,126 @@ def test_data_lists_mapping(device_mapping):
device = device_mapping device = device_mapping
assert device.hvac_modes == ["off", "cool", "heat", "heat_cool"] assert device.hvac_modes == ["off", "cool", "heat", "heat_cool"]
assert device.preset_modes == ["boost", "none"] assert device.preset_modes == ["boost", "none"]
device.values.mode = None device.values.primary = None
assert device.preset_modes == [] assert device.preset_modes == []
def test_target_value_set(device): def test_target_value_set(device):
"""Test values changed for climate device.""" """Test values changed for climate device."""
assert device.values.primary.data == 1 assert device.values.setpoint_heating.data == 1
assert device.values.setpoint_cooling.data == 10
device.set_temperature() device.set_temperature()
assert device.values.primary.data == 1 assert device.values.setpoint_heating.data == 1
assert device.values.setpoint_cooling.data == 10
device.set_temperature(**{ATTR_TEMPERATURE: 2}) device.set_temperature(**{ATTR_TEMPERATURE: 2})
assert device.values.primary.data == 2 assert device.values.setpoint_heating.data == 2
assert device.values.setpoint_cooling.data == 10
device.set_hvac_mode(HVAC_MODE_COOL)
value_changed(device.values.primary)
assert device.values.setpoint_heating.data == 2
assert device.values.setpoint_cooling.data == 10
device.set_temperature(**{ATTR_TEMPERATURE: 9})
assert device.values.setpoint_heating.data == 2
assert device.values.setpoint_cooling.data == 9
def test_target_value_set_range(device_heat_cool_range):
"""Test values changed for climate device."""
device = device_heat_cool_range
assert device.values.setpoint_heating.data == 1
assert device.values.setpoint_cooling.data == 10
device.set_temperature()
assert device.values.setpoint_heating.data == 1
assert device.values.setpoint_cooling.data == 10
device.set_temperature(**{ATTR_TARGET_TEMP_LOW: 2})
assert device.values.setpoint_heating.data == 2
assert device.values.setpoint_cooling.data == 10
device.set_temperature(**{ATTR_TARGET_TEMP_HIGH: 9})
assert device.values.setpoint_heating.data == 2
assert device.values.setpoint_cooling.data == 9
device.set_temperature(**{ATTR_TARGET_TEMP_LOW: 3, ATTR_TARGET_TEMP_HIGH: 8})
assert device.values.setpoint_heating.data == 3
assert device.values.setpoint_cooling.data == 8
def test_target_value_set_range_away(device_heat_cool_away):
"""Test values changed for climate device."""
device = device_heat_cool_away
assert device.values.setpoint_heating.data == 2
assert device.values.setpoint_cooling.data == 9
assert device.values.setpoint_away_heating.data == 1
assert device.values.setpoint_away_cooling.data == 10
device.set_preset_mode(PRESET_AWAY)
device.set_temperature(**{ATTR_TARGET_TEMP_LOW: 0, ATTR_TARGET_TEMP_HIGH: 11})
assert device.values.setpoint_heating.data == 2
assert device.values.setpoint_cooling.data == 9
assert device.values.setpoint_away_heating.data == 0
assert device.values.setpoint_away_cooling.data == 11
def test_target_value_set_eco(device_heat_eco):
"""Test values changed for climate device."""
device = device_heat_eco
assert device.values.setpoint_heating.data == 2
assert device.values.setpoint_eco_heating.data == 1
device.set_preset_mode("heat econ")
device.set_temperature(**{ATTR_TEMPERATURE: 0})
assert device.values.setpoint_heating.data == 2
assert device.values.setpoint_eco_heating.data == 0
def test_operation_value_set(device): def test_operation_value_set(device):
"""Test values changed for climate device.""" """Test values changed for climate device."""
assert device.values.mode.data == HVAC_MODE_HEAT assert device.values.primary.data == HVAC_MODE_HEAT
device.set_hvac_mode(HVAC_MODE_COOL) device.set_hvac_mode(HVAC_MODE_COOL)
assert device.values.mode.data == HVAC_MODE_COOL assert device.values.primary.data == HVAC_MODE_COOL
device.set_preset_mode(PRESET_ECO) device.set_preset_mode(PRESET_ECO)
assert device.values.mode.data == PRESET_ECO assert device.values.primary.data == PRESET_ECO
device.set_preset_mode(PRESET_NONE) device.set_preset_mode(PRESET_NONE)
assert device.values.mode.data == HVAC_MODE_HEAT_COOL assert device.values.primary.data == HVAC_MODE_HEAT_COOL
device.values.mode = None device.values.primary = None
device.set_hvac_mode("test_set_failes") device.set_hvac_mode("test_set_failes")
assert device.values.mode is None assert device.values.primary is None
device.set_preset_mode("test_set_failes") device.set_preset_mode("test_set_failes")
assert device.values.mode is None assert device.values.primary is None
def test_operation_value_set_mapping(device_mapping): def test_operation_value_set_mapping(device_mapping):
"""Test values changed for climate device. Mapping.""" """Test values changed for climate device. Mapping."""
device = device_mapping device = device_mapping
assert device.values.mode.data == "Heat" assert device.values.primary.data == "Heat"
device.set_hvac_mode(HVAC_MODE_COOL) device.set_hvac_mode(HVAC_MODE_COOL)
assert device.values.mode.data == "Cool" assert device.values.primary.data == "Cool"
device.set_hvac_mode(HVAC_MODE_OFF) device.set_hvac_mode(HVAC_MODE_OFF)
assert device.values.mode.data == "Off" assert device.values.primary.data == "Off"
device.set_preset_mode(PRESET_BOOST) device.set_preset_mode(PRESET_BOOST)
assert device.values.mode.data == "Full Power" assert device.values.primary.data == "Full Power"
device.set_preset_mode(PRESET_ECO) device.set_preset_mode(PRESET_ECO)
assert device.values.mode.data == "eco" assert device.values.primary.data == "eco"
def test_operation_value_set_unknown(device_unknown): def test_operation_value_set_unknown(device_unknown):
"""Test values changed for climate device. Unknown.""" """Test values changed for climate device. Unknown."""
device = device_unknown device = device_unknown
assert device.values.mode.data == "Heat" assert device.values.primary.data == "Heat"
device.set_preset_mode("Abcdefg") device.set_preset_mode("Abcdefg")
assert device.values.mode.data == "Abcdefg" assert device.values.primary.data == "Abcdefg"
device.set_preset_mode(PRESET_NONE) device.set_preset_mode(PRESET_NONE)
assert device.values.mode.data == HVAC_MODE_HEAT_COOL assert device.values.primary.data == HVAC_MODE_HEAT_COOL
def test_operation_value_set_heat_cool(device_heat_cool): def test_operation_value_set_heat_cool(device_heat_cool):
"""Test values changed for climate device. Heat/Cool only.""" """Test values changed for climate device. Heat/Cool only."""
device = device_heat_cool device = device_heat_cool
assert device.values.mode.data == HVAC_MODE_HEAT assert device.values.primary.data == HVAC_MODE_HEAT
device.set_preset_mode("Heat Eco") device.set_preset_mode("Heat Eco")
assert device.values.mode.data == "Heat Eco" assert device.values.primary.data == "Heat Eco"
device.set_preset_mode(PRESET_NONE) device.set_preset_mode(PRESET_NONE)
assert device.values.mode.data == HVAC_MODE_HEAT assert device.values.primary.data == HVAC_MODE_HEAT
device.set_preset_mode("Cool Eco") device.set_preset_mode("Cool Eco")
assert device.values.mode.data == "Cool Eco" assert device.values.primary.data == "Cool Eco"
device.set_preset_mode(PRESET_NONE) device.set_preset_mode(PRESET_NONE)
assert device.values.mode.data == HVAC_MODE_COOL assert device.values.primary.data == HVAC_MODE_COOL
def test_fan_mode_value_set(device): def test_fan_mode_value_set(device):
@ -314,11 +471,81 @@ def test_fan_mode_value_set(device):
def test_target_value_changed(device): def test_target_value_changed(device):
"""Test values changed for climate device.""" """Test values changed for climate device."""
assert device.target_temperature == 1 assert device.target_temperature == 1
device.values.primary.data = 2 device.values.setpoint_heating.data = 2
value_changed(device.values.setpoint_heating)
assert device.target_temperature == 2
device.values.primary.data = HVAC_MODE_COOL
value_changed(device.values.primary)
assert device.target_temperature == 10
device.values.setpoint_cooling.data = 9
value_changed(device.values.setpoint_cooling)
assert device.target_temperature == 9
def test_target_range_changed(device_heat_cool_range):
"""Test values changed for climate device."""
device = device_heat_cool_range
assert device.target_temperature_low == 1
assert device.target_temperature_high == 10
device.values.setpoint_heating.data = 2
value_changed(device.values.setpoint_heating)
assert device.target_temperature_low == 2
assert device.target_temperature_high == 10
device.values.setpoint_cooling.data = 9
value_changed(device.values.setpoint_cooling)
assert device.target_temperature_low == 2
assert device.target_temperature_high == 9
def test_target_changed_preset_range(device_heat_cool_away):
"""Test values changed for climate device."""
device = device_heat_cool_away
assert device.target_temperature_low == 2
assert device.target_temperature_high == 9
device.values.primary.data = PRESET_AWAY
value_changed(device.values.primary)
assert device.target_temperature_low == 1
assert device.target_temperature_high == 10
device.values.setpoint_away_heating.data = 0
value_changed(device.values.setpoint_away_heating)
device.values.setpoint_away_cooling.data = 11
value_changed(device.values.setpoint_away_cooling)
assert device.target_temperature_low == 0
assert device.target_temperature_high == 11
device.values.primary.data = HVAC_MODE_HEAT_COOL
value_changed(device.values.primary)
assert device.target_temperature_low == 2
assert device.target_temperature_high == 9
def test_target_changed_eco(device_heat_eco):
"""Test values changed for climate device."""
device = device_heat_eco
assert device.target_temperature == 2
device.values.primary.data = "heat econ"
value_changed(device.values.primary)
assert device.target_temperature == 1
device.values.setpoint_eco_heating.data = 0
value_changed(device.values.setpoint_eco_heating)
assert device.target_temperature == 0
device.values.primary.data = HVAC_MODE_HEAT
value_changed(device.values.primary) value_changed(device.values.primary)
assert device.target_temperature == 2 assert device.target_temperature == 2
def test_target_changed_with_mode(device):
"""Test values changed for climate device."""
assert device.hvac_mode == HVAC_MODE_HEAT
assert device.target_temperature == 1
device.values.primary.data = HVAC_MODE_COOL
value_changed(device.values.primary)
assert device.target_temperature == 10
device.values.primary.data = HVAC_MODE_HEAT_COOL
value_changed(device.values.primary)
assert device.target_temperature_low == 1
assert device.target_temperature_high == 10
def test_temperature_value_changed(device): def test_temperature_value_changed(device):
"""Test values changed for climate device.""" """Test values changed for climate device."""
assert device.current_temperature == 5 assert device.current_temperature == 5
@ -331,15 +558,15 @@ def test_operation_value_changed(device):
"""Test values changed for climate device.""" """Test values changed for climate device."""
assert device.hvac_mode == HVAC_MODE_HEAT assert device.hvac_mode == HVAC_MODE_HEAT
assert device.preset_mode == PRESET_NONE assert device.preset_mode == PRESET_NONE
device.values.mode.data = HVAC_MODE_COOL device.values.primary.data = HVAC_MODE_COOL
value_changed(device.values.mode) value_changed(device.values.primary)
assert device.hvac_mode == HVAC_MODE_COOL assert device.hvac_mode == HVAC_MODE_COOL
assert device.preset_mode == PRESET_NONE assert device.preset_mode == PRESET_NONE
device.values.mode.data = HVAC_MODE_OFF device.values.primary.data = HVAC_MODE_OFF
value_changed(device.values.mode) value_changed(device.values.primary)
assert device.hvac_mode == HVAC_MODE_OFF assert device.hvac_mode == HVAC_MODE_OFF
assert device.preset_mode == PRESET_NONE assert device.preset_mode == PRESET_NONE
device.values.mode = None device.values.primary = None
assert device.hvac_mode == HVAC_MODE_HEAT_COOL assert device.hvac_mode == HVAC_MODE_HEAT_COOL
assert device.preset_mode == PRESET_NONE assert device.preset_mode == PRESET_NONE
@ -349,8 +576,8 @@ def test_operation_value_changed_preset(device_mapping):
device = device_mapping device = device_mapping
assert device.hvac_mode == HVAC_MODE_HEAT assert device.hvac_mode == HVAC_MODE_HEAT
assert device.preset_mode == PRESET_NONE assert device.preset_mode == PRESET_NONE
device.values.mode.data = PRESET_ECO device.values.primary.data = PRESET_ECO
value_changed(device.values.mode) value_changed(device.values.primary)
assert device.hvac_mode == HVAC_MODE_HEAT_COOL assert device.hvac_mode == HVAC_MODE_HEAT_COOL
assert device.preset_mode == PRESET_ECO assert device.preset_mode == PRESET_ECO
@ -360,12 +587,12 @@ def test_operation_value_changed_mapping(device_mapping):
device = device_mapping device = device_mapping
assert device.hvac_mode == HVAC_MODE_HEAT assert device.hvac_mode == HVAC_MODE_HEAT
assert device.preset_mode == PRESET_NONE assert device.preset_mode == PRESET_NONE
device.values.mode.data = "Off" device.values.primary.data = "Off"
value_changed(device.values.mode) value_changed(device.values.primary)
assert device.hvac_mode == HVAC_MODE_OFF assert device.hvac_mode == HVAC_MODE_OFF
assert device.preset_mode == PRESET_NONE assert device.preset_mode == PRESET_NONE
device.values.mode.data = "Cool" device.values.primary.data = "Cool"
value_changed(device.values.mode) value_changed(device.values.primary)
assert device.hvac_mode == HVAC_MODE_COOL assert device.hvac_mode == HVAC_MODE_COOL
assert device.preset_mode == PRESET_NONE assert device.preset_mode == PRESET_NONE
@ -375,11 +602,11 @@ def test_operation_value_changed_mapping_preset(device_mapping):
device = device_mapping device = device_mapping
assert device.hvac_mode == HVAC_MODE_HEAT assert device.hvac_mode == HVAC_MODE_HEAT
assert device.preset_mode == PRESET_NONE assert device.preset_mode == PRESET_NONE
device.values.mode.data = "Full Power" device.values.primary.data = "Full Power"
value_changed(device.values.mode) value_changed(device.values.primary)
assert device.hvac_mode == HVAC_MODE_HEAT_COOL assert device.hvac_mode == HVAC_MODE_HEAT_COOL
assert device.preset_mode == PRESET_BOOST assert device.preset_mode == PRESET_BOOST
device.values.mode = None device.values.primary = None
assert device.hvac_mode == HVAC_MODE_HEAT_COOL assert device.hvac_mode == HVAC_MODE_HEAT_COOL
assert device.preset_mode == PRESET_NONE assert device.preset_mode == PRESET_NONE
@ -389,8 +616,8 @@ def test_operation_value_changed_unknown(device_unknown):
device = device_unknown device = device_unknown
assert device.hvac_mode == HVAC_MODE_HEAT assert device.hvac_mode == HVAC_MODE_HEAT
assert device.preset_mode == PRESET_NONE assert device.preset_mode == PRESET_NONE
device.values.mode.data = "Abcdefg" device.values.primary.data = "Abcdefg"
value_changed(device.values.mode) value_changed(device.values.primary)
assert device.hvac_mode == HVAC_MODE_HEAT_COOL assert device.hvac_mode == HVAC_MODE_HEAT_COOL
assert device.preset_mode == "Abcdefg" assert device.preset_mode == "Abcdefg"
@ -400,12 +627,12 @@ def test_operation_value_changed_heat_cool(device_heat_cool):
device = device_heat_cool device = device_heat_cool
assert device.hvac_mode == HVAC_MODE_HEAT assert device.hvac_mode == HVAC_MODE_HEAT
assert device.preset_mode == PRESET_NONE assert device.preset_mode == PRESET_NONE
device.values.mode.data = "Cool Eco" device.values.primary.data = "Cool Eco"
value_changed(device.values.mode) value_changed(device.values.primary)
assert device.hvac_mode == HVAC_MODE_COOL assert device.hvac_mode == HVAC_MODE_COOL
assert device.preset_mode == "Cool Eco" assert device.preset_mode == "Cool Eco"
device.values.mode.data = "Heat Eco" device.values.primary.data = "Heat Eco"
value_changed(device.values.mode) value_changed(device.values.primary)
assert device.hvac_mode == HVAC_MODE_HEAT assert device.hvac_mode == HVAC_MODE_HEAT
assert device.preset_mode == "Heat Eco" assert device.preset_mode == "Heat Eco"

View File

@ -574,18 +574,33 @@ async def test_value_discovery_existing_entity(hass, mock_openzwave):
assert len(mock_receivers) == 1 assert len(mock_receivers) == 1
node = MockNode(node_id=11, generic=const.GENERIC_TYPE_THERMOSTAT) node = MockNode(node_id=11, generic=const.GENERIC_TYPE_THERMOSTAT)
setpoint = MockValue( thermostat_mode = MockValue(
data="Heat",
data_items=["Off", "Heat"],
node=node,
command_class=const.COMMAND_CLASS_THERMOSTAT_MODE,
genre=const.GENRE_USER,
)
setpoint_heating = MockValue(
data=22.0, data=22.0,
node=node, node=node,
index=12,
instance=13,
command_class=const.COMMAND_CLASS_THERMOSTAT_SETPOINT, command_class=const.COMMAND_CLASS_THERMOSTAT_SETPOINT,
index=1,
genre=const.GENRE_USER, genre=const.GENRE_USER,
units="C",
) )
hass.async_add_job(mock_receivers[0], node, setpoint)
hass.async_add_job(mock_receivers[0], node, thermostat_mode)
await hass.async_block_till_done() await hass.async_block_till_done()
def mock_update(self):
self.hass.add_job(self.async_update_ha_state)
with patch.object(
zwave.node_entity.ZWaveBaseEntity, "maybe_schedule_update", new=mock_update
):
hass.async_add_job(mock_receivers[0], node, setpoint_heating)
await hass.async_block_till_done()
assert ( assert (
hass.states.get("climate.mock_node_mock_value").attributes["temperature"] hass.states.get("climate.mock_node_mock_value").attributes["temperature"]
== 22.0 == 22.0
@ -597,9 +612,6 @@ async def test_value_discovery_existing_entity(hass, mock_openzwave):
is None is None
) )
def mock_update(self):
self.hass.add_job(self.async_update_ha_state)
with patch.object( with patch.object(
zwave.node_entity.ZWaveBaseEntity, "maybe_schedule_update", new=mock_update zwave.node_entity.ZWaveBaseEntity, "maybe_schedule_update", new=mock_update
): ):
@ -607,7 +619,6 @@ async def test_value_discovery_existing_entity(hass, mock_openzwave):
data=23.5, data=23.5,
node=node, node=node,
index=1, index=1,
instance=13,
command_class=const.COMMAND_CLASS_SENSOR_MULTILEVEL, command_class=const.COMMAND_CLASS_SENSOR_MULTILEVEL,
genre=const.GENRE_USER, genre=const.GENRE_USER,
units="C", units="C",