diff --git a/homeassistant/components/light/limitlessled.py b/homeassistant/components/light/limitlessled.py index ad3aa4e92e8..5619e54f123 100644 --- a/homeassistant/components/light/limitlessled.py +++ b/homeassistant/components/light/limitlessled.py @@ -4,17 +4,20 @@ Support for LimitlessLED bulbs. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/light.limitlessled/ """ +import asyncio import logging import voluptuous as vol -from homeassistant.const import (CONF_NAME, CONF_HOST, CONF_PORT, CONF_TYPE) +from homeassistant.const import ( + CONF_NAME, CONF_HOST, CONF_PORT, CONF_TYPE, STATE_ON) from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_RGB_COLOR, ATTR_TRANSITION, EFFECT_COLORLOOP, EFFECT_WHITE, FLASH_LONG, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_FLASH, SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, Light, PLATFORM_SCHEMA) import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.restore_state import async_get_last_state REQUIREMENTS = ['limitlessled==1.0.8'] @@ -115,7 +118,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): group_conf.get(CONF_NUMBER), group_conf.get(CONF_NAME), group_conf.get(CONF_TYPE, DEFAULT_LED_TYPE)) - lights.append(LimitlessLEDGroup.factory(group, { + lights.append(LimitlessLEDGroup(group, { 'fade': group_conf[CONF_FADE] })) add_devices(lights) @@ -138,9 +141,6 @@ def state(new_state): if self.repeating: self.repeating = False self.group.stop() - # Not on and should be? Turn on. - if not self.is_on and new_state is True: - pipeline.on() # Set transition time. if ATTR_TRANSITION in kwargs: transition_time = int(kwargs[ATTR_TRANSITION]) @@ -159,30 +159,44 @@ class LimitlessLEDGroup(Light): def __init__(self, group, config): """Initialize a group.""" - self.group = group - self.repeating = False - self._is_on = False - self._brightness = None - self.config = config - - @staticmethod - def factory(group, config): - """Produce LimitlessLEDGroup objects.""" from limitlessled.group.rgbw import RgbwGroup from limitlessled.group.white import WhiteGroup from limitlessled.group.rgbww import RgbwwGroup if isinstance(group, WhiteGroup): - return LimitlessLEDWhiteGroup(group, config) + self._supported = SUPPORT_LIMITLESSLED_WHITE elif isinstance(group, RgbwGroup): - return LimitlessLEDRGBWGroup(group, config) + self._supported = SUPPORT_LIMITLESSLED_RGB elif isinstance(group, RgbwwGroup): - return LimitlessLEDRGBWWGroup(group, config) + self._supported = SUPPORT_LIMITLESSLED_RGBWW + + self.group = group + self.config = config + self.repeating = False + self._is_on = False + self._brightness = None + self._temperature = None + self._color = None + + @asyncio.coroutine + def async_added_to_hass(self): + """Called when entity is about to be added to hass.""" + last_state = yield from async_get_last_state(self.hass, self.entity_id) + if last_state: + self._is_on = (last_state.state == STATE_ON) + self._brightness = last_state.attributes.get('brightness') + self._temperature = last_state.attributes.get('color_temp') + self._color = last_state.attributes.get('rgb_color') @property def should_poll(self): """No polling needed.""" return False + @property + def assumed_state(self): + """Return True because unable to access real state of the entity.""" + return True + @property def name(self): """Return the name of the group.""" @@ -198,219 +212,92 @@ class LimitlessLEDGroup(Light): """Return the brightness property.""" return self._brightness + @property + def color_temp(self): + """Return the temperature property.""" + return self._temperature + + @property + def rgb_color(self): + """Return the color property.""" + return self._color + + @property + def supported_features(self): + """Flag supported features.""" + return self._supported + # pylint: disable=arguments-differ @state(False) def turn_off(self, transition_time, pipeline, **kwargs): """Turn off a group.""" - if self.is_on: - if self.config[CONF_FADE]: - pipeline.transition(transition_time, brightness=0.0) - pipeline.off() - - -class LimitlessLEDWhiteGroup(LimitlessLEDGroup): - """Representation of a LimitlessLED White group.""" - - def __init__(self, group, config): - """Initialize White group.""" - super().__init__(group, config) - # Initialize group with known values. - self.group.on = True - self.group.temperature = 1.0 - self.group.brightness = 0.0 - self._brightness = _to_hass_brightness(1.0) - self._temperature = _to_hass_temperature(self.group.temperature) - self.group.on = False - - @property - def color_temp(self): - """Return the temperature property.""" - return self._temperature - - @property - def supported_features(self): - """Flag supported features.""" - return SUPPORT_LIMITLESSLED_WHITE + if self.config[CONF_FADE]: + pipeline.transition(transition_time, brightness=0.0) + pipeline.off() # pylint: disable=arguments-differ @state(True) def turn_on(self, transition_time, pipeline, **kwargs): """Turn on (or adjust property of) a group.""" - # Check arguments. + pipeline.on() + + # Set up transition. + args = {} + if self.config[CONF_FADE] and not self.is_on and self._brightness: + args['brightness'] = self.limitlessled_brightness() + if ATTR_BRIGHTNESS in kwargs: self._brightness = kwargs[ATTR_BRIGHTNESS] + args['brightness'] = self.limitlessled_brightness() + + if ATTR_RGB_COLOR in kwargs and self._supported & SUPPORT_RGB_COLOR: + self._color = kwargs[ATTR_RGB_COLOR] + # White is a special case. + if min(self._color) > 256 - RGB_BOUNDARY: + pipeline.white() + self._color = WHITE + else: + args['color'] = self.limitlessled_color() + if ATTR_COLOR_TEMP in kwargs: - self._temperature = kwargs[ATTR_COLOR_TEMP] - # Set up transition. - pipeline.transition( - transition_time, - brightness=_from_hass_brightness(self._brightness), - temperature=_from_hass_temperature(self._temperature) - ) - - -class LimitlessLEDRGBWGroup(LimitlessLEDGroup): - """Representation of a LimitlessLED RGBW group.""" - - def __init__(self, group, config): - """Initialize RGBW group.""" - super().__init__(group, config) - # Initialize group with known values. - self.group.on = True - self.group.white() - self._color = WHITE - self.group.brightness = 0.0 - self._brightness = _to_hass_brightness(1.0) - self.group.on = False - - @property - def rgb_color(self): - """Return the color property.""" - return self._color - - @property - def supported_features(self): - """Flag supported features.""" - return SUPPORT_LIMITLESSLED_RGB - - # pylint: disable=arguments-differ - @state(True) - def turn_on(self, transition_time, pipeline, **kwargs): - """Turn on (or adjust property of) a group.""" - from limitlessled.presets import COLORLOOP - # Check arguments. - if ATTR_BRIGHTNESS in kwargs: - self._brightness = kwargs[ATTR_BRIGHTNESS] - if ATTR_RGB_COLOR in kwargs: - self._color = kwargs[ATTR_RGB_COLOR] - # White is a special case. - if min(self._color) > 256 - RGB_BOUNDARY: - pipeline.white() + if self._supported & SUPPORT_RGB_COLOR: + pipeline.white() self._color = WHITE - # Set up transition. - pipeline.transition( - transition_time, - brightness=_from_hass_brightness(self._brightness), - color=_from_hass_color(self._color) - ) + if self._supported & SUPPORT_COLOR_TEMP: + self._temperature = kwargs[ATTR_COLOR_TEMP] + args['temperature'] = self.limitlessled_temperature() + + if args: + pipeline.transition(transition_time, **args) + # Flash. - if ATTR_FLASH in kwargs: + if ATTR_FLASH in kwargs and self._supported & SUPPORT_FLASH: duration = 0 if kwargs[ATTR_FLASH] == FLASH_LONG: duration = 1 pipeline.flash(duration=duration) + # Add effects. - if ATTR_EFFECT in kwargs: + if ATTR_EFFECT in kwargs and self._supported & SUPPORT_EFFECT: if kwargs[ATTR_EFFECT] == EFFECT_COLORLOOP: + from limitlessled.presets import COLORLOOP self.repeating = True pipeline.append(COLORLOOP) if kwargs[ATTR_EFFECT] == EFFECT_WHITE: pipeline.white() self._color = WHITE + def limitlessled_temperature(self): + """Convert Home Assistant color temperature units to percentage.""" + width = self.max_mireds - self.min_mireds + temperature = 1 - (self._temperature - self.min_mireds) / width + return max(0, min(1, temperature)) -class LimitlessLEDRGBWWGroup(LimitlessLEDGroup): - """Representation of a LimitlessLED RGBWW group.""" + def limitlessled_brightness(self): + """Convert Home Assistant brightness units to percentage.""" + return self._brightness / 255 - def __init__(self, group, config): - """Initialize RGBWW group.""" - super().__init__(group, config) - # Initialize group with known values. - self.group.on = True - self.group.white() - self.group.temperature = 0.0 - self._color = WHITE - self.group.brightness = 0.0 - self._brightness = _to_hass_brightness(1.0) - self._temperature = _to_hass_temperature(self.group.temperature) - self.group.on = False - - @property - def rgb_color(self): - """Return the color property.""" - return self._color - - @property - def color_temp(self): - """Return the temperature property.""" - return self._temperature - - @property - def supported_features(self): - """Flag supported features.""" - return SUPPORT_LIMITLESSLED_RGBWW - - # pylint: disable=arguments-differ - @state(True) - def turn_on(self, transition_time, pipeline, **kwargs): - """Turn on (or adjust property of) a group.""" - from limitlessled.presets import COLORLOOP - # Check arguments. - if ATTR_BRIGHTNESS in kwargs: - self._brightness = kwargs[ATTR_BRIGHTNESS] - if ATTR_RGB_COLOR in kwargs: - self._color = kwargs[ATTR_RGB_COLOR] - elif ATTR_COLOR_TEMP in kwargs: - self._temperature = kwargs[ATTR_COLOR_TEMP] - # White is a special case. - if min(self._color) > 256 - RGB_BOUNDARY: - pipeline.white() - self._color = WHITE - # Set up transition. - if self._color == WHITE: - pipeline.transition( - transition_time, - brightness=_from_hass_brightness(self._brightness), - temperature=_from_hass_temperature(self._temperature) - ) - else: - pipeline.transition( - transition_time, - brightness=_from_hass_brightness(self._brightness), - color=_from_hass_color(self._color) - ) - # Flash. - if ATTR_FLASH in kwargs: - duration = 0 - if kwargs[ATTR_FLASH] == FLASH_LONG: - duration = 1 - pipeline.flash(duration=duration) - # Add effects. - if ATTR_EFFECT in kwargs: - if kwargs[ATTR_EFFECT] == EFFECT_COLORLOOP: - self.repeating = True - pipeline.append(COLORLOOP) - if kwargs[ATTR_EFFECT] == EFFECT_WHITE: - pipeline.white() - self._color = WHITE - - -def _from_hass_temperature(temperature): - """Convert Home Assistant color temperature units to percentage.""" - return 1 - (temperature - 154) / 346 - - -def _to_hass_temperature(temperature): - """Convert percentage to Home Assistant color temperature units.""" - return 500 - int(temperature * 346) - - -def _from_hass_brightness(brightness): - """Convert Home Assistant brightness units to percentage.""" - return brightness / 255 - - -def _to_hass_brightness(brightness): - """Convert percentage to Home Assistant brightness units.""" - return int(brightness * 255) - - -def _from_hass_color(color): - """Convert Home Assistant RGB list to Color tuple.""" - from limitlessled import Color - return Color(*tuple(color)) - - -def _to_hass_color(color): - """Convert from Color tuple to Home Assistant RGB list.""" - return list([int(c) for c in color]) + def limitlessled_color(self): + """Convert Home Assistant RGB list to Color tuple.""" + from limitlessled import Color + return Color(*tuple(self._color))