"""Support for covers from FHEM""" import voluptuous as vol import logging from homeassistant.components.cover import PLATFORM_SCHEMA, CoverDevice, SUPPORT_OPEN, SUPPORT_CLOSE, \ SUPPORT_SET_POSITION, SUPPORT_STOP, ATTR_POSITION from homeassistant.const import CONF_NAME import homeassistant.helpers.config_validation as cv from . import DATA_FHEM, device_error_reporting, CONF_FHEM_IDS PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_FHEM_IDS): vol.All(cv.ensure_list, [cv.string]), vol.Required(CONF_NAME): cv.string, }) _LOGGER = logging.getLogger(__name__) async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): connection = hass.data[DATA_FHEM] cover = FhemCover(connection, config[CONF_NAME], config[CONF_FHEM_IDS]) for dev_id in config[CONF_FHEM_IDS]: connection.register_device(dev_id, cover) async_add_entities([cover]) class FhemCover(CoverDevice): def __init__(self, connection, name, ids): self._position = None self.connection = connection self._ids = ids self._name = name self._available = True @property def name(self): return self._name @property def should_poll(self): """No polling needed.""" return False @property def available(self) -> bool: return self._available and self.connection.connected @property def supported_features(self): """Flag supported features.""" return SUPPORT_OPEN | SUPPORT_CLOSE | SUPPORT_SET_POSITION | SUPPORT_STOP @property def current_cover_position(self): return self._position @property def is_closed(self): """Return if the cover is closed.""" if self._position is None: return None return self._position <= 25 async def async_close_cover(self, **kwargs): await self.async_set_cover_position(**{ATTR_POSITION: 0}) async def async_open_cover(self, **kwargs): await self.async_set_cover_position(**{ATTR_POSITION: 100}) async def async_set_cover_position(self, **kwargs): """Move the cover to a specific position.""" if ATTR_POSITION in kwargs: position = kwargs[ATTR_POSITION] self._position = position self.connection.fhem_set(self._ids[0], int(position)) async def async_stop_cover(self, **kwargs): """Stop the cover.""" self.connection.fhem_set(self._ids[0], 'stop') async def line_received(self, line): if line.startswith('motor:'): self._available = True _, new_motor_state, new_position = line.split(':') new_position = new_position.strip().lower() new_motor_state = new_motor_state.strip().lower() assert new_motor_state == 'stop' or new_motor_state == 'up' or new_motor_state == 'down', \ 'Unknown motor state ' + new_motor_state if new_motor_state == 'stop': if new_position == 'on': self._position = 100 elif new_position == 'off': self._position = 0 else: new_position = int(float(new_position)) # first convert from string to floating point then truncate assert 0 <= new_position <= 100 self._position = new_position await self.async_update_ha_state() elif line.startswith('ResndFail') or line.startswith('MISSING ACK'): self._available = False await self.async_update_ha_state() else: device_error_reporting(self.hass, line, component_type="Cover", component_name=self.entity_id)