"""Support for lights from FHEM""" import voluptuous as vol import logging from homeassistant.components.light import ATTR_BRIGHTNESS, PLATFORM_SCHEMA, SUPPORT_BRIGHTNESS, Light from homeassistant.const import CONF_NAME import homeassistant.helpers.config_validation as cv from . import DATA_FHEM _LOGGER = logging.getLogger(__name__) CONF_FHEM_IDS = 'fhem_ids' CONF_DIMMER = 'dimmer' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_FHEM_IDS): vol.All(cv.ensure_list, [cv.string]), vol.Optional(CONF_DIMMER, default=False): cv.boolean, vol.Required(CONF_NAME): cv.string, }) async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up lights for KNX platform.""" connection = hass.data[DATA_FHEM] light = FhemLight(connection, config[CONF_NAME], config[CONF_FHEM_IDS], dimmer=config[CONF_DIMMER]) for dev_id in config[CONF_FHEM_IDS]: connection.devices[dev_id] = light async_add_entities([light]) class FhemLight(Light): def __init__(self, connection, name, ids, dimmer=False): self._brightness = None self.connection = connection self._dimmer = dimmer self._ids = ids self._name = name self._available = True @property def should_poll(self): """No polling needed.""" return False @property def brightness(self): return self._brightness @property def is_on(self): """Return true if light is on.""" if self._brightness is not None: return self._brightness > 0 else: return None @property def name(self): """Return the name of the KNX device.""" return self._name @property def available(self) -> bool: return self._available and self.connection.connected @property def supported_features(self): """Flag supported features.""" flags = 0 if self._dimmer: flags |= SUPPORT_BRIGHTNESS return flags async def async_turn_on(self, **kwargs): brightness = kwargs.get(ATTR_BRIGHTNESS, self.brightness) if brightness is None: brightness = 255 if self._dimmer: self.connection.fhem_set(self._ids[0], brightness / 255 * 100) else: self.connection.fhem_set(self._ids[0], 'on') async def async_turn_off(self, **kwargs): self.connection.fhem_set(self._ids[0], 'off') async def line_received(self, line): _LOGGER.debug("FHEM line received (device): " + self.name + ": " + line) if line.startswith('dim:'): self._available = True _, new_dim_state, new_level = line.split(':') new_level = new_level.strip().lower() new_dim_state = new_dim_state.strip().lower() assert new_dim_state == 'stop' or new_dim_state == 'up' or new_dim_state == 'down' if new_dim_state == 'stop': if new_level == 'on': self._brightness = 255 elif new_level == 'off': self._brightness = 0 else: new_level = int(float(new_level)) # first convert from string to floating point then truncate assert 0 <= new_level <= 100 self._brightness = int(new_level / 100 * 255) await self.async_update_ha_state() elif line.startswith('level:') and not self._dimmer: self._available = True _, new_level = line.split(':') new_level = new_level.strip().lower() if new_level == 'on': self._brightness = 255 elif new_level == 'off': self._brightness = 0 else: try: new_level = int(float(new_level)) # first convert from string to floating point then truncate assert 0 <= new_level <= 100 self._brightness = int(new_level / 100 * 255) except ValueError: pass await self.async_update_ha_state() elif line.startswith('overheat'): overheat = line.split(':')[1] overheat = overheat.strip().lower() assert overheat == 'on' or overheat == 'off' if overheat == 'on': self.hass.components.persistent_notification.async_create( "FHEM: Light overheated:
" "{0}".format(self.entity_id), title="Light overheat") elif line.startswith('overload'): overload = line.split(':')[1] overload = overload.strip().lower() assert overload == 'on' or overload == 'off' if overload == 'on': self.hass.components.persistent_notification.async_create( "FHEM: Light overloaded:
" "{0}".format(self.entity_id), title="Light overloaded") elif line.startswith('ResndFail') or line.startswith('MISSING ACK'): self._available = False await self.async_update_ha_state()