From 6846a76c46cae8bc1565b3a74ea688b62e522cea Mon Sep 17 00:00:00 2001 From: Open Home Automation Date: Wed, 28 Jun 2017 14:08:07 +0200 Subject: [PATCH] KNX Cover tilt control (#8159) * Added invert flag for position for actuators that uses 100% for fully closed position * Implementation of tilt functionality * Bugfix check tilt * Formatting * Formatting fixes * Formatting * Bugfix set_tilt * Minor modifications in configuration section * Formatting * Update knx.py --- homeassistant/components/cover/knx.py | 60 ++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/cover/knx.py b/homeassistant/components/cover/knx.py index a28da2e4c4d..4883cfe3648 100644 --- a/homeassistant/components/cover/knx.py +++ b/homeassistant/components/cover/knx.py @@ -9,7 +9,9 @@ import logging import voluptuous as vol from homeassistant.components.cover import ( - CoverDevice, PLATFORM_SCHEMA, ATTR_POSITION, DEVICE_CLASSES_SCHEMA + CoverDevice, PLATFORM_SCHEMA, ATTR_POSITION, DEVICE_CLASSES_SCHEMA, + SUPPORT_OPEN, SUPPORT_CLOSE, SUPPORT_SET_POSITION, SUPPORT_STOP, + SUPPORT_SET_TILT_POSITION ) from homeassistant.components.knx import (KNXConfig, KNXMultiAddressDevice) from homeassistant.const import (CONF_NAME, CONF_DEVICE_CLASS) @@ -19,9 +21,12 @@ _LOGGER = logging.getLogger(__name__) CONF_GETPOSITION_ADDRESS = 'getposition_address' CONF_SETPOSITION_ADDRESS = 'setposition_address' +CONF_GETANGLE_ADDRESS = 'getangle_address' +CONF_SETANGLE_ADDRESS = 'setangle_address' CONF_STOP = 'stop_address' CONF_UPDOWN = 'updown_address' CONF_INVERT_POSITION = 'invert_position' +CONF_INVERT_ANGLE = 'invert_angle' DEFAULT_NAME = 'KNX Cover' DEPENDENCIES = ['knx'] @@ -34,6 +39,9 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_SETPOSITION_ADDRESS): cv.string, vol.Optional(CONF_INVERT_POSITION, default=False): cv.boolean, + vol.Inclusive(CONF_GETANGLE_ADDRESS, 'angle'): cv.string, + vol.Inclusive(CONF_SETANGLE_ADDRESS, 'angle'): cv.string, + vol.Optional(CONF_INVERT_ANGLE, default=False): cv.boolean, }) @@ -50,19 +58,38 @@ class KNXCover(KNXMultiAddressDevice, CoverDevice): KNXMultiAddressDevice.__init__( self, hass, config, ['updown', 'stop'], # required - optional=['setposition', 'getposition'] + optional=['setposition', 'getposition', + 'getangle', 'setangle'] ) self._device_class = config.config.get(CONF_DEVICE_CLASS) self._invert_position = config.config.get(CONF_INVERT_POSITION) + self._invert_angle = config.config.get(CONF_INVERT_ANGLE) self._hass = hass self._current_pos = None self._target_pos = None + self._current_tilt = None + self._target_tilt = None + self._supported_features = SUPPORT_OPEN | SUPPORT_CLOSE | \ + SUPPORT_SET_POSITION | SUPPORT_STOP + + # Tilt is only supported, if there is a angle get and set address + if CONF_SETANGLE_ADDRESS in config.config: + _LOGGER.debug("%s: Tilt supported at addresses %s, %s", + self.name, config.config.get(CONF_SETANGLE_ADDRESS), + config.config.get(CONF_GETANGLE_ADDRESS)) + self._supported_features = self._supported_features | \ + SUPPORT_SET_TILT_POSITION @property def should_poll(self): """Polling is needed for the KNX cover.""" return True + @property + def supported_features(self): + """Flag supported features.""" + return self._supported_features + @property def is_closed(self): """Return if the cover is closed.""" @@ -85,6 +112,19 @@ class KNXCover(KNXMultiAddressDevice, CoverDevice): """Return the position we are trying to reach: 0 - 100.""" return self._target_pos + @property + def current_cover_tilt_position(self): + """Return current position of cover. + + None is unknown, 0 is closed, 100 is fully open. + """ + return self._current_tilt + + @property + def target_tilt(self): + """Return the tilt angle (in %) we are trying to reach: 0 - 100.""" + return self._target_tilt + def set_cover_position(self, **kwargs): """Set new target position.""" position = kwargs.get(ATTR_POSITION) @@ -108,6 +148,14 @@ class KNXCover(KNXMultiAddressDevice, CoverDevice): self._current_pos = 100-value _LOGGER.debug("%s: position = %d", self.name, value) + if self._supported_features & SUPPORT_SET_TILT_POSITION: + value = self.get_percentage('getangle') + if value is not None: + self._current_tilt = value + if self._invert_angle: + self._current_tilt = 100-value + _LOGGER.debug("%s: tilt = %d", self.name, value) + def open_cover(self, **kwargs): """Open the cover.""" _LOGGER.debug("%s: open: updown = 0", self.name) @@ -123,6 +171,14 @@ class KNXCover(KNXMultiAddressDevice, CoverDevice): _LOGGER.debug("%s: stop: stop = 1", self.name) self.set_int_value('stop', 1) + def set_cover_tilt_position(self, tilt_position, **kwargs): + """Move the cover til to a specific position.""" + if self._invert_angle: + tilt_position = 100-tilt_position + + self._target_tilt = round(tilt_position, -1) + self.set_percentage('setangle', tilt_position) + @property def device_class(self): """Return the class of this device, from component DEVICE_CLASSES."""