From cb5426c1fa223fb408e9d3a54ee473043b9c5d9f Mon Sep 17 00:00:00 2001 From: Tommaso Marchionni Date: Mon, 17 Jun 2019 23:44:47 +0200 Subject: [PATCH] Added invert_percent configuration for zwave rollershutter (#23101) * Added invert_percent configuration for zwave rollershutter * Added invert_percent configuration for zwave rollershutter * Fix typo in zwave default configuration --- homeassistant/components/zwave/__init__.py | 4 +++ homeassistant/components/zwave/cover.py | 21 ++++++++++----- tests/components/zwave/test_cover.py | 30 +++++++++++++++++++++- 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/zwave/__init__.py b/homeassistant/components/zwave/__init__.py index fdc00903f09..a5a460d129e 100644 --- a/homeassistant/components/zwave/__init__.py +++ b/homeassistant/components/zwave/__init__.py @@ -47,6 +47,7 @@ ATTR_POWER = 'power_consumption' CONF_POLLING_INTENSITY = 'polling_intensity' CONF_IGNORED = 'ignored' CONF_INVERT_OPENCLOSE_BUTTONS = 'invert_openclose_buttons' +CONF_INVERT_PERCENT = 'invert_percent' CONF_REFRESH_VALUE = 'refresh_value' CONF_REFRESH_DELAY = 'delay' CONF_DEVICE_CONFIG = 'device_config' @@ -57,6 +58,7 @@ DATA_ZWAVE_CONFIG = 'zwave_config' DEFAULT_CONF_IGNORED = False DEFAULT_CONF_INVERT_OPENCLOSE_BUTTONS = False +DEFAULT_CONF_INVERT_PERCENT = False DEFAULT_CONF_REFRESH_VALUE = False DEFAULT_CONF_REFRESH_DELAY = 5 @@ -146,6 +148,8 @@ DEVICE_CONFIG_SCHEMA_ENTRY = vol.Schema({ vol.Optional(CONF_IGNORED, default=DEFAULT_CONF_IGNORED): cv.boolean, vol.Optional(CONF_INVERT_OPENCLOSE_BUTTONS, default=DEFAULT_CONF_INVERT_OPENCLOSE_BUTTONS): cv.boolean, + vol.Optional(CONF_INVERT_PERCENT, + default=DEFAULT_CONF_INVERT_PERCENT): cv.boolean, vol.Optional(CONF_REFRESH_VALUE, default=DEFAULT_CONF_REFRESH_VALUE): cv.boolean, vol.Optional(CONF_REFRESH_DELAY, default=DEFAULT_CONF_REFRESH_DELAY): diff --git a/homeassistant/components/zwave/cover.py b/homeassistant/components/zwave/cover.py index a3cd7269b99..1ab643bde11 100644 --- a/homeassistant/components/zwave/cover.py +++ b/homeassistant/components/zwave/cover.py @@ -6,7 +6,8 @@ from homeassistant.components.cover import ( from homeassistant.components.cover import CoverDevice from homeassistant.helpers.dispatcher import async_dispatcher_connect from . import ( - ZWaveDeviceEntity, CONF_INVERT_OPENCLOSE_BUTTONS, workaround) + ZWaveDeviceEntity, CONF_INVERT_OPENCLOSE_BUTTONS, CONF_INVERT_PERCENT, + workaround) from .const import ( COMMAND_CLASS_SWITCH_MULTILEVEL, COMMAND_CLASS_SWITCH_BINARY, COMMAND_CLASS_BARRIER_OPERATOR, DATA_NETWORK) @@ -35,10 +36,11 @@ async def async_setup_entry(hass, config_entry, async_add_entities): def get_device(hass, values, node_config, **kwargs): """Create Z-Wave entity device.""" invert_buttons = node_config.get(CONF_INVERT_OPENCLOSE_BUTTONS) + invert_percent = node_config.get(CONF_INVERT_PERCENT) if (values.primary.command_class == COMMAND_CLASS_SWITCH_MULTILEVEL and values.primary.index == 0): - return ZwaveRollershutter(hass, values, invert_buttons) + return ZwaveRollershutter(hass, values, invert_buttons, invert_percent) if values.primary.command_class == COMMAND_CLASS_SWITCH_BINARY: return ZwaveGarageDoorSwitch(values) if values.primary.command_class == \ @@ -50,7 +52,7 @@ def get_device(hass, values, node_config, **kwargs): class ZwaveRollershutter(ZWaveDeviceEntity, CoverDevice): """Representation of an Z-Wave cover.""" - def __init__(self, hass, values, invert_buttons): + def __init__(self, hass, values, invert_buttons, invert_percent): """Initialize the Z-Wave rollershutter.""" ZWaveDeviceEntity.__init__(self, values, DOMAIN) self._network = hass.data[DATA_NETWORK] @@ -58,6 +60,7 @@ class ZwaveRollershutter(ZWaveDeviceEntity, CoverDevice): self._close_id = None self._current_position = None self._invert_buttons = invert_buttons + self._invert_percent = invert_percent self._workaround = workaround.get_device_mapping(values.primary) if self._workaround: @@ -92,12 +95,14 @@ class ZwaveRollershutter(ZWaveDeviceEntity, CoverDevice): """Return the current position of Zwave roller shutter.""" if self._workaround == workaround.WORKAROUND_NO_POSITION: return None + if self._current_position is not None: if self._current_position <= 5: - return 0 + return 100 if self._invert_percent else 0 if self._current_position >= 95: - return 100 - return self._current_position + return 0 if self._invert_percent else 100 + return 100 - self._current_position if self._invert_percent \ + else self._current_position def open_cover(self, **kwargs): """Move the roller shutter up.""" @@ -110,7 +115,9 @@ class ZwaveRollershutter(ZWaveDeviceEntity, CoverDevice): def set_cover_position(self, **kwargs): """Move the roller shutter to a specific position.""" self.node.set_dimmer(self.values.primary.value_id, - kwargs.get(ATTR_POSITION)) + (100 - kwargs.get(ATTR_POSITION)) + if self._invert_percent + else kwargs.get(ATTR_POSITION)) def stop_cover(self, **kwargs): """Stop the roller shutter.""" diff --git a/tests/components/zwave/test_cover.py b/tests/components/zwave/test_cover.py index ce34111c612..4d4d537e4b4 100644 --- a/tests/components/zwave/test_cover.py +++ b/tests/components/zwave/test_cover.py @@ -3,7 +3,7 @@ from unittest.mock import MagicMock from homeassistant.components.cover import SUPPORT_OPEN, SUPPORT_CLOSE from homeassistant.components.zwave import ( - const, cover, CONF_INVERT_OPENCLOSE_BUTTONS) + const, cover, CONF_INVERT_OPENCLOSE_BUTTONS, CONF_INVERT_PERCENT) from tests.mock.zwave import ( MockNode, MockValue, MockEntityValues, value_changed) @@ -141,6 +141,34 @@ def test_roller_commands(hass, mock_openzwave): assert value_id == open_value.value_id +def test_roller_invert_percent(hass, mock_openzwave): + """Test position changed.""" + mock_network = hass.data[const.DATA_NETWORK] = MagicMock() + node = MockNode() + value = MockValue(data=50, node=node, + command_class=const.COMMAND_CLASS_SWITCH_MULTILEVEL) + open_value = MockValue(data=False, node=node) + close_value = MockValue(data=False, node=node) + values = MockEntityValues(primary=value, open=open_value, + close=close_value, node=node) + device = cover.get_device( + hass=hass, + node=node, + values=values, + node_config={CONF_INVERT_PERCENT: True}) + + device.set_cover_position(position=25) + assert node.set_dimmer.called + value_id, brightness = node.set_dimmer.mock_calls[0][1] + assert value_id == value.value_id + assert brightness == 75 + + device.open_cover() + assert mock_network.manager.pressButton.called + value_id, = mock_network.manager.pressButton.mock_calls.pop(0)[1] + assert value_id == open_value.value_id + + def test_roller_reverse_open_close(hass, mock_openzwave): """Test position changed.""" mock_network = hass.data[const.DATA_NETWORK] = MagicMock()