From e8ce41874c8b637f666ab8809ff40be75c48221e Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 27 Jul 2017 15:57:30 -0700 Subject: [PATCH] Fix COMMAND_CLASS_BARRIER_OPERATOR for dev branch of OpenZwave (#8574) * Update zwave.py to work with updated OpenZwave library Update zwave.py to work with updated OpenZwave library * Update zwave.py * Update zwave.py * Update to fix garage door openers Update to fix garage door support for latest version of openzwavelib * Update to cover.zwave list of states Update to cover.zwave to provide list of states based on dev version of openzwave lib * Some values not saved * Formatting fix * Formatting fix * Variable typo * Formatting fix * Formatting * Variable Update Variable Update and properties added * Formatting fixes * Formatting Fix * Update test case for door states * Formatting / Testing process fix * Formatting * Formatting / Test Fixes * Variable rename * Added members to CoverDevice * Removed un-needed else * Formatting * Formatting * Variable name changes and const updates * Changed variable names to cover_state * Added constains into const.py * Updated to change the main state on the cover device * Fixes * Formatting fixes * Formatting/Variables * Formatting * Variable fixes * Import update * Formatting / Variables * Update test for new states * Revert state changes * Test fix * Variable Fix * Formatting * Variable typo * Missing constant * Variable fix * Requested changes * Added is_opening * Added is_closing * Updated test based on changes * Formatting * Changed cover_state back to _state * Formatting and variable fixes * Test fixes * Formatting and variable touchup * Formatting * Optimizations * Add new cover features to demo * Add tests for demo cover closing/opening * Remove unused STATE_STOPPED * Add tests for new zwave cover values --- homeassistant/components/cover/__init__.py | 17 +++++++++- homeassistant/components/cover/demo.py | 38 ++++++++++++++++------ homeassistant/components/cover/zwave.py | 18 ++++++++-- homeassistant/const.py | 2 ++ tests/components/cover/test_demo.py | 8 +++++ tests/components/cover/test_zwave.py | 27 +++++++++++---- 6 files changed, 90 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/cover/__init__.py b/homeassistant/components/cover/__init__.py index df096c9ba8087a..23c0be1a43e1ba 100644 --- a/homeassistant/components/cover/__init__.py +++ b/homeassistant/components/cover/__init__.py @@ -23,7 +23,7 @@ SERVICE_OPEN_COVER, SERVICE_CLOSE_COVER, SERVICE_SET_COVER_POSITION, SERVICE_STOP_COVER, SERVICE_OPEN_COVER_TILT, SERVICE_CLOSE_COVER_TILT, SERVICE_STOP_COVER_TILT, SERVICE_SET_COVER_TILT_POSITION, STATE_OPEN, - STATE_CLOSED, STATE_UNKNOWN, ATTR_ENTITY_ID) + STATE_CLOSED, STATE_UNKNOWN, STATE_OPENING, STATE_CLOSING, ATTR_ENTITY_ID) _LOGGER = logging.getLogger(__name__) @@ -225,6 +225,11 @@ def current_cover_tilt_position(self): @property def state(self): """Return the state of the cover.""" + if self.is_opening: + return STATE_OPENING + if self.is_closing: + return STATE_CLOSING + closed = self.is_closed if closed is None: @@ -262,6 +267,16 @@ def supported_features(self): return supported_features + @property + def is_opening(self): + """Return if the cover is opening or not.""" + pass + + @property + def is_closing(self): + """Return if the cover is closing or not.""" + pass + @property def is_closed(self): """Return if the cover is closed or not.""" diff --git a/homeassistant/components/cover/demo.py b/homeassistant/components/cover/demo.py index ed0606597467ad..827b50c8af9d1f 100644 --- a/homeassistant/components/cover/demo.py +++ b/homeassistant/components/cover/demo.py @@ -35,10 +35,12 @@ def __init__(self, hass, name, position=None, tilt_position=None, self._set_position = None self._set_tilt_position = None self._tilt_position = tilt_position - self._closing = True - self._closing_tilt = True + self._requested_closing = True + self._requested_closing_tilt = True self._unsub_listener_cover = None self._unsub_listener_cover_tilt = None + self._is_opening = False + self._is_closing = False if position is None: self._closed = True else: @@ -69,6 +71,16 @@ def is_closed(self): """Return if the cover is closed.""" return self._closed + @property + def is_closing(self): + """Return if the cover is closing.""" + return self._is_closing + + @property + def is_opening(self): + """Return if the cover is opening.""" + return self._is_opening + @property def device_class(self): """Return the class of this device, from component DEVICE_CLASSES.""" @@ -90,8 +102,10 @@ def close_cover(self, **kwargs): self.schedule_update_ha_state() return + self._is_closing = True self._listen_cover() - self._closing = True + self._requested_closing = True + self.schedule_update_ha_state() def close_cover_tilt(self, **kwargs): """Close the cover tilt.""" @@ -99,7 +113,7 @@ def close_cover_tilt(self, **kwargs): return self._listen_cover_tilt() - self._closing_tilt = True + self._requested_closing_tilt = True def open_cover(self, **kwargs): """Open the cover.""" @@ -110,8 +124,10 @@ def open_cover(self, **kwargs): self.schedule_update_ha_state() return + self._is_opening = True self._listen_cover() - self._closing = False + self._requested_closing = False + self.schedule_update_ha_state() def open_cover_tilt(self, **kwargs): """Open the cover tilt.""" @@ -119,7 +135,7 @@ def open_cover_tilt(self, **kwargs): return self._listen_cover_tilt() - self._closing_tilt = False + self._requested_closing_tilt = False def set_cover_position(self, position, **kwargs): """Move the cover to a specific position.""" @@ -128,7 +144,7 @@ def set_cover_position(self, position, **kwargs): return self._listen_cover() - self._closing = position < self._position + self._requested_closing = position < self._position def set_cover_tilt_position(self, tilt_position, **kwargs): """Move the cover til to a specific position.""" @@ -137,10 +153,12 @@ def set_cover_tilt_position(self, tilt_position, **kwargs): return self._listen_cover_tilt() - self._closing_tilt = tilt_position < self._tilt_position + self._requested_closing_tilt = tilt_position < self._tilt_position def stop_cover(self, **kwargs): """Stop the cover.""" + self._is_closing = False + self._is_opening = False if self._position is None: return if self._unsub_listener_cover is not None: @@ -166,7 +184,7 @@ def _listen_cover(self): def _time_changed_cover(self, now): """Track time changes.""" - if self._closing: + if self._requested_closing: self._position -= 10 else: self._position += 10 @@ -186,7 +204,7 @@ def _listen_cover_tilt(self): def _time_changed_cover_tilt(self, now): """Track time changes.""" - if self._closing_tilt: + if self._requested_closing_tilt: self._tilt_position -= 10 else: self._tilt_position += 10 diff --git a/homeassistant/components/cover/zwave.py b/homeassistant/components/cover/zwave.py index 6ec70d9a85a9dc..b8daab8150320f 100644 --- a/homeassistant/components/cover/zwave.py +++ b/homeassistant/components/cover/zwave.py @@ -110,24 +110,36 @@ class ZwaveGarageDoor(zwave.ZWaveDeviceEntity, CoverDevice): def __init__(self, values): """Initialize the zwave garage door.""" ZWaveDeviceEntity.__init__(self, values, DOMAIN) + self._state = None self.update_properties() def update_properties(self): """Handle data changes for node values.""" self._state = self.values.primary.data + _LOGGER.debug("self._state=%s", self._state) + + @property + def is_opening(self): + """Return true if cover is in an opening state.""" + return self._state == "Opening" + + @property + def is_closing(self): + """Return true if cover is in an closing state.""" + return self._state == "Closing" @property def is_closed(self): """Return the current position of Zwave garage door.""" - return not self._state + return self._state == "Closed" def close_cover(self): """Close the garage door.""" - self.values.primary.data = False + self.values.primary.data = "Closed" def open_cover(self): """Open the garage door.""" - self.values.primary.data = True + self.values.primary.data = "Opened" @property def device_class(self): diff --git a/homeassistant/const.py b/homeassistant/const.py index b4b2aac52e3008..ca8075b10abf32 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -188,7 +188,9 @@ STATE_NOT_HOME = 'not_home' STATE_UNKNOWN = 'unknown' STATE_OPEN = 'open' +STATE_OPENING = 'opening' STATE_CLOSED = 'closed' +STATE_CLOSING = 'closing' STATE_PLAYING = 'playing' STATE_PAUSED = 'paused' STATE_IDLE = 'idle' diff --git a/tests/components/cover/test_demo.py b/tests/components/cover/test_demo.py index 83907de7708bf7..9d26a6a4f4a354 100644 --- a/tests/components/cover/test_demo.py +++ b/tests/components/cover/test_demo.py @@ -38,29 +38,37 @@ def test_supported_features(self): def test_close_cover(self): """Test closing the cover.""" state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(state.state, 'open') self.assertEqual(70, state.attributes.get('current_position')) cover.close_cover(self.hass, ENTITY_COVER) self.hass.block_till_done() + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(state.state, 'closing') for _ in range(7): future = dt_util.utcnow() + timedelta(seconds=1) fire_time_changed(self.hass, future) self.hass.block_till_done() state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(state.state, 'closed') self.assertEqual(0, state.attributes.get('current_position')) def test_open_cover(self): """Test opening the cover.""" state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(state.state, 'open') self.assertEqual(70, state.attributes.get('current_position')) cover.open_cover(self.hass, ENTITY_COVER) self.hass.block_till_done() + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(state.state, 'opening') for _ in range(7): future = dt_util.utcnow() + timedelta(seconds=1) fire_time_changed(self.hass, future) self.hass.block_till_done() state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(state.state, 'open') self.assertEqual(100, state.attributes.get('current_position')) def test_set_cover_position(self): diff --git a/tests/components/cover/test_zwave.py b/tests/components/cover/test_zwave.py index e1ee6075cead75..fe9abe7172c685 100644 --- a/tests/components/cover/test_zwave.py +++ b/tests/components/cover/test_zwave.py @@ -161,31 +161,46 @@ def test_roller_reverse_open_close(hass, mock_openzwave): def test_garage_value_changed(hass, mock_openzwave): """Test position changed.""" node = MockNode() - value = MockValue(data=False, node=node, + value = MockValue(data="Closed", node=node, command_class=const.COMMAND_CLASS_BARRIER_OPERATOR) values = MockEntityValues(primary=value, node=node) device = zwave.get_device(hass=hass, node=node, values=values, node_config={}) assert device.is_closed + assert not device.is_opening + assert not device.is_closing - value.data = True + value.data = "Opening" value_changed(value) + assert not device.is_closed + assert device.is_opening + assert not device.is_closing + value.data = "Opened" + value_changed(value) + assert not device.is_closed + assert not device.is_opening + assert not device.is_closing + + value.data = "Closing" + value_changed(value) assert not device.is_closed + assert not device.is_opening + assert device.is_closing def test_garage_commands(hass, mock_openzwave): """Test position changed.""" node = MockNode() - value = MockValue(data=False, node=node, + value = MockValue(data="Closed", node=node, command_class=const.COMMAND_CLASS_BARRIER_OPERATOR) values = MockEntityValues(primary=value, node=node) device = zwave.get_device(hass=hass, node=node, values=values, node_config={}) - assert value.data is False + assert value.data == "Closed" device.open_cover() - assert value.data is True + assert value.data == "Opened" device.close_cover() - assert value.data is False + assert value.data == "Closed"