Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ccedc5d
Initial commit
Santobert Jul 26, 2019
1eec853
Add some more code
Santobert Jul 26, 2019
8b4ceb2
Local tests passing
Santobert Jul 28, 2019
7aea241
Remove unnecessary line
Santobert Jul 28, 2019
0c48e3b
Add preset attributes to __init__
Santobert Jul 28, 2019
ae1c01a
Remove some more debugger lines
Santobert Jul 28, 2019
ed41e39
Add some tests
Santobert Jul 28, 2019
18365c2
Fix comparision to None
Santobert Jul 28, 2019
648118d
Improve test coverage
Santobert Jul 28, 2019
5afa232
Use unknown modes as presets
Santobert Jul 28, 2019
ad8d4c5
Bugfixes and test improvements
Santobert Jul 28, 2019
1901124
Add tests for unknown preset modes
Santobert Jul 28, 2019
99bff0a
linting
Santobert Jul 28, 2019
5674978
Improve mappings
Santobert Jul 29, 2019
4e93f4d
Move PRESET_MANUFACTURER_SPECIFIC to zwave
Santobert Jul 29, 2019
d097ba6
Replace isinstance with cast
Santobert Jul 29, 2019
8b7e24d
Add test for hvac_action
Santobert Jul 29, 2019
5735392
hvac_mode is never None
Santobert Jul 30, 2019
81f14f0
Improved mapping of current mode to hvac/preset modes
Santobert Jul 30, 2019
c5300b6
Fix bugs where hvac_mode is None
Santobert Jul 31, 2019
7edf8d9
Add default hvac mode
Santobert Jul 31, 2019
a7e0ec3
Fixed default hvac mode
Santobert Aug 1, 2019
a0188f1
Merge branch 'dev' into feature_zwave_preset_modes
Santobert Aug 1, 2019
8fe3237
Fix linting
Santobert Aug 1, 2019
1f6b23c
Make flake happy
Santobert Aug 1, 2019
7da932e
Another linting
Santobert Aug 1, 2019
067f2d0
Make black happy
Santobert Aug 1, 2019
428e5f5
Complete list of default hvac modes
Santobert Aug 1, 2019
ccbd34d
Add mapping to heat/cool eco
Santobert Aug 1, 2019
8137b2b
Fixed another bug where mapping goes wrong
Santobert Aug 2, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions homeassistant/components/climate/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Comment thread
Santobert marked this conversation as resolved.
Outdated


# Possible fan state
FAN_ON = "on"
Expand Down
68 changes: 63 additions & 5 deletions homeassistant/components/zwave/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -45,7 +47,6 @@
'Auto': HVAC_MODE_HEAT_COOL,
}


HVAC_CURRENT_MAPPINGS = {
"Idle": CURRENT_HVAC_IDLE,
"Heat": CURRENT_HVAC_HEAT,
Expand All @@ -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):
Expand Down Expand Up @@ -94,6 +100,9 @@ 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
self._fan_state = None
Expand Down Expand Up @@ -123,6 +132,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):
Expand All @@ -131,21 +142,35 @@ 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:
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
self._hvac_list.append(mode)
elif ha_preset and ha_preset not in self._preset_mapping:
self._preset_mapping[ha_preset] = mode
self._preset_list.append(ha_preset)
else:
# If nothing matches
self._hvac_list.append(mode)
Comment thread
Santobert marked this conversation as resolved.
Outdated

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)
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)
_LOGGER.debug("self._preset_list=%s", self._preset_list)

# Current Temp
if self.values.temperature:
Expand Down Expand Up @@ -256,31 +281,64 @@ 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."""
return self._target_temperature

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)

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._hvac_mapping.get(hvac_mode, hvac_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."""
_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
72 changes: 70 additions & 2 deletions tests/components/zwave/test_climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
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,
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)
Expand Down Expand Up @@ -55,7 +57,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),
Expand All @@ -66,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
Expand Down Expand Up @@ -109,6 +132,14 @@ 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):
"""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):
Expand All @@ -127,6 +158,13 @@ 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'
device.values.mode = None
device.set_hvac_mode('test_set_failes')
assert device.values.mode is None
device.set_preset_mode('test_set_failes')
assert device.values.mode is None


def test_operation_value_set_mapping(device_mapping):
Expand All @@ -139,13 +177,20 @@ 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):
"""Test values changed for climate 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 is None


def test_target_value_changed(device):
Expand All @@ -167,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):
Expand All @@ -187,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'
Expand Down