""" Support for deCONZ covers. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/cover.deconz/ """ from homeassistant.components.cover import ( ATTR_POSITION, CoverDevice, SUPPORT_CLOSE, SUPPORT_OPEN, SUPPORT_STOP, SUPPORT_SET_POSITION) from homeassistant.core import callback from homeassistant.helpers.dispatcher import async_dispatcher_connect from .const import COVER_TYPES, DAMPERS, DOMAIN as DECONZ_DOMAIN, WINDOW_COVERS from .deconz_device import DeconzDevice DEPENDENCIES = ['deconz'] ZIGBEE_SPEC = ['lumi.curtain'] async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Unsupported way of setting up deCONZ covers.""" pass async def async_setup_entry(hass, config_entry, async_add_entities): """Set up covers for deCONZ component. Covers are based on same device class as lights in deCONZ. """ gateway = hass.data[DECONZ_DOMAIN] @callback def async_add_cover(lights): """Add cover from deCONZ.""" entities = [] for light in lights: if light.type in COVER_TYPES: if light.modelid in ZIGBEE_SPEC: entities.append(DeconzCoverZigbeeSpec(light, gateway)) else: entities.append(DeconzCover(light, gateway)) async_add_entities(entities, True) gateway.listeners.append( async_dispatcher_connect(hass, 'deconz_new_light', async_add_cover)) async_add_cover(gateway.api.lights.values()) class DeconzCover(DeconzDevice, CoverDevice): """Representation of a deCONZ cover.""" def __init__(self, device, gateway): """Set up cover and add update callback to get data from websocket.""" super().__init__(device, gateway) self._features = SUPPORT_OPEN self._features |= SUPPORT_CLOSE self._features |= SUPPORT_STOP self._features |= SUPPORT_SET_POSITION @property def current_cover_position(self): """Return the current position of the cover.""" if self.is_closed: return 0 return int(self._device.brightness / 255 * 100) @property def is_closed(self): """Return if the cover is closed.""" return not self._device.state @property def device_class(self): """Return the class of the cover.""" if self._device.type in DAMPERS: return 'damper' if self._device.type in WINDOW_COVERS: return 'window' @property def supported_features(self): """Flag supported features.""" return self._features async def async_set_cover_position(self, **kwargs): """Move the cover to a specific position.""" position = kwargs[ATTR_POSITION] data = {'on': False} if position > 0: data['on'] = True data['bri'] = int(position / 100 * 255) await self._device.async_set_state(data) async def async_open_cover(self, **kwargs): """Open cover.""" data = {ATTR_POSITION: 100} await self.async_set_cover_position(**data) async def async_close_cover(self, **kwargs): """Close cover.""" data = {ATTR_POSITION: 0} await self.async_set_cover_position(**data) async def async_stop_cover(self, **kwargs): """Stop cover.""" data = {'bri_inc': 0} await self._device.async_set_state(data) class DeconzCoverZigbeeSpec(DeconzCover): """Zigbee spec is the inverse of how deCONZ normally reports attributes.""" @property def current_cover_position(self): """Return the current position of the cover.""" return 100 - int(self._device.brightness / 255 * 100) @property def is_closed(self): """Return if the cover is closed.""" return self._device.state async def async_set_cover_position(self, **kwargs): """Move the cover to a specific position.""" position = kwargs[ATTR_POSITION] data = {'on': False} if position < 100: data['on'] = True data['bri'] = 255 - int(position / 100 * 255) await self._device.async_set_state(data)