mirror of
https://github.com/home-assistant/core.git
synced 2025-07-08 22:07:10 +00:00
LimitlessLED assumed state (#12475)
* Use assumed state for LimitlessLED * Replace inheritance with feature tests * Clean up * Clean up conversion methods * Clamp temperature
This commit is contained in:
parent
da9c0a1fd7
commit
dc21c61a44
@ -4,17 +4,20 @@ Support for LimitlessLED bulbs.
|
|||||||
For more details about this platform, please refer to the documentation at
|
For more details about this platform, please refer to the documentation at
|
||||||
https://home-assistant.io/components/light.limitlessled/
|
https://home-assistant.io/components/light.limitlessled/
|
||||||
"""
|
"""
|
||||||
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import voluptuous as vol
|
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 (
|
from homeassistant.components.light import (
|
||||||
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_RGB_COLOR,
|
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_RGB_COLOR,
|
||||||
ATTR_TRANSITION, EFFECT_COLORLOOP, EFFECT_WHITE, FLASH_LONG,
|
ATTR_TRANSITION, EFFECT_COLORLOOP, EFFECT_WHITE, FLASH_LONG,
|
||||||
SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_FLASH,
|
SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_FLASH,
|
||||||
SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, Light, PLATFORM_SCHEMA)
|
SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, Light, PLATFORM_SCHEMA)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
from homeassistant.helpers.restore_state import async_get_last_state
|
||||||
|
|
||||||
REQUIREMENTS = ['limitlessled==1.0.8']
|
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_NUMBER),
|
||||||
group_conf.get(CONF_NAME),
|
group_conf.get(CONF_NAME),
|
||||||
group_conf.get(CONF_TYPE, DEFAULT_LED_TYPE))
|
group_conf.get(CONF_TYPE, DEFAULT_LED_TYPE))
|
||||||
lights.append(LimitlessLEDGroup.factory(group, {
|
lights.append(LimitlessLEDGroup(group, {
|
||||||
'fade': group_conf[CONF_FADE]
|
'fade': group_conf[CONF_FADE]
|
||||||
}))
|
}))
|
||||||
add_devices(lights)
|
add_devices(lights)
|
||||||
@ -138,9 +141,6 @@ def state(new_state):
|
|||||||
if self.repeating:
|
if self.repeating:
|
||||||
self.repeating = False
|
self.repeating = False
|
||||||
self.group.stop()
|
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.
|
# Set transition time.
|
||||||
if ATTR_TRANSITION in kwargs:
|
if ATTR_TRANSITION in kwargs:
|
||||||
transition_time = int(kwargs[ATTR_TRANSITION])
|
transition_time = int(kwargs[ATTR_TRANSITION])
|
||||||
@ -159,30 +159,44 @@ class LimitlessLEDGroup(Light):
|
|||||||
|
|
||||||
def __init__(self, group, config):
|
def __init__(self, group, config):
|
||||||
"""Initialize a group."""
|
"""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.rgbw import RgbwGroup
|
||||||
from limitlessled.group.white import WhiteGroup
|
from limitlessled.group.white import WhiteGroup
|
||||||
from limitlessled.group.rgbww import RgbwwGroup
|
from limitlessled.group.rgbww import RgbwwGroup
|
||||||
if isinstance(group, WhiteGroup):
|
if isinstance(group, WhiteGroup):
|
||||||
return LimitlessLEDWhiteGroup(group, config)
|
self._supported = SUPPORT_LIMITLESSLED_WHITE
|
||||||
elif isinstance(group, RgbwGroup):
|
elif isinstance(group, RgbwGroup):
|
||||||
return LimitlessLEDRGBWGroup(group, config)
|
self._supported = SUPPORT_LIMITLESSLED_RGB
|
||||||
elif isinstance(group, RgbwwGroup):
|
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
|
@property
|
||||||
def should_poll(self):
|
def should_poll(self):
|
||||||
"""No polling needed."""
|
"""No polling needed."""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def assumed_state(self):
|
||||||
|
"""Return True because unable to access real state of the entity."""
|
||||||
|
return True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the name of the group."""
|
"""Return the name of the group."""
|
||||||
@ -198,219 +212,92 @@ class LimitlessLEDGroup(Light):
|
|||||||
"""Return the brightness property."""
|
"""Return the brightness property."""
|
||||||
return self._brightness
|
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
|
# pylint: disable=arguments-differ
|
||||||
@state(False)
|
@state(False)
|
||||||
def turn_off(self, transition_time, pipeline, **kwargs):
|
def turn_off(self, transition_time, pipeline, **kwargs):
|
||||||
"""Turn off a group."""
|
"""Turn off a group."""
|
||||||
if self.is_on:
|
|
||||||
if self.config[CONF_FADE]:
|
if self.config[CONF_FADE]:
|
||||||
pipeline.transition(transition_time, brightness=0.0)
|
pipeline.transition(transition_time, brightness=0.0)
|
||||||
pipeline.off()
|
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
|
|
||||||
|
|
||||||
# pylint: disable=arguments-differ
|
# pylint: disable=arguments-differ
|
||||||
@state(True)
|
@state(True)
|
||||||
def turn_on(self, transition_time, pipeline, **kwargs):
|
def turn_on(self, transition_time, pipeline, **kwargs):
|
||||||
"""Turn on (or adjust property of) a group."""
|
"""Turn on (or adjust property of) a group."""
|
||||||
# Check arguments.
|
pipeline.on()
|
||||||
if ATTR_BRIGHTNESS in kwargs:
|
|
||||||
self._brightness = kwargs[ATTR_BRIGHTNESS]
|
|
||||||
if ATTR_COLOR_TEMP in kwargs:
|
|
||||||
self._temperature = kwargs[ATTR_COLOR_TEMP]
|
|
||||||
# Set up transition.
|
# Set up transition.
|
||||||
pipeline.transition(
|
args = {}
|
||||||
transition_time,
|
if self.config[CONF_FADE] and not self.is_on and self._brightness:
|
||||||
brightness=_from_hass_brightness(self._brightness),
|
args['brightness'] = self.limitlessled_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:
|
if ATTR_BRIGHTNESS in kwargs:
|
||||||
self._brightness = kwargs[ATTR_BRIGHTNESS]
|
self._brightness = kwargs[ATTR_BRIGHTNESS]
|
||||||
if ATTR_RGB_COLOR in kwargs:
|
args['brightness'] = self.limitlessled_brightness()
|
||||||
|
|
||||||
|
if ATTR_RGB_COLOR in kwargs and self._supported & SUPPORT_RGB_COLOR:
|
||||||
self._color = kwargs[ATTR_RGB_COLOR]
|
self._color = kwargs[ATTR_RGB_COLOR]
|
||||||
# White is a special case.
|
# White is a special case.
|
||||||
if min(self._color) > 256 - RGB_BOUNDARY:
|
if min(self._color) > 256 - RGB_BOUNDARY:
|
||||||
pipeline.white()
|
pipeline.white()
|
||||||
self._color = WHITE
|
self._color = WHITE
|
||||||
# Set up transition.
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
class LimitlessLEDRGBWWGroup(LimitlessLEDGroup):
|
|
||||||
"""Representation of a LimitlessLED RGBWW group."""
|
|
||||||
|
|
||||||
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:
|
else:
|
||||||
pipeline.transition(
|
args['color'] = self.limitlessled_color()
|
||||||
transition_time,
|
|
||||||
brightness=_from_hass_brightness(self._brightness),
|
if ATTR_COLOR_TEMP in kwargs:
|
||||||
color=_from_hass_color(self._color)
|
if self._supported & SUPPORT_RGB_COLOR:
|
||||||
)
|
pipeline.white()
|
||||||
|
self._color = WHITE
|
||||||
|
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.
|
# Flash.
|
||||||
if ATTR_FLASH in kwargs:
|
if ATTR_FLASH in kwargs and self._supported & SUPPORT_FLASH:
|
||||||
duration = 0
|
duration = 0
|
||||||
if kwargs[ATTR_FLASH] == FLASH_LONG:
|
if kwargs[ATTR_FLASH] == FLASH_LONG:
|
||||||
duration = 1
|
duration = 1
|
||||||
pipeline.flash(duration=duration)
|
pipeline.flash(duration=duration)
|
||||||
|
|
||||||
# Add effects.
|
# Add effects.
|
||||||
if ATTR_EFFECT in kwargs:
|
if ATTR_EFFECT in kwargs and self._supported & SUPPORT_EFFECT:
|
||||||
if kwargs[ATTR_EFFECT] == EFFECT_COLORLOOP:
|
if kwargs[ATTR_EFFECT] == EFFECT_COLORLOOP:
|
||||||
|
from limitlessled.presets import COLORLOOP
|
||||||
self.repeating = True
|
self.repeating = True
|
||||||
pipeline.append(COLORLOOP)
|
pipeline.append(COLORLOOP)
|
||||||
if kwargs[ATTR_EFFECT] == EFFECT_WHITE:
|
if kwargs[ATTR_EFFECT] == EFFECT_WHITE:
|
||||||
pipeline.white()
|
pipeline.white()
|
||||||
self._color = WHITE
|
self._color = WHITE
|
||||||
|
|
||||||
|
def limitlessled_temperature(self):
|
||||||
def _from_hass_temperature(temperature):
|
|
||||||
"""Convert Home Assistant color temperature units to percentage."""
|
"""Convert Home Assistant color temperature units to percentage."""
|
||||||
return 1 - (temperature - 154) / 346
|
width = self.max_mireds - self.min_mireds
|
||||||
|
temperature = 1 - (self._temperature - self.min_mireds) / width
|
||||||
|
return max(0, min(1, temperature))
|
||||||
|
|
||||||
|
def limitlessled_brightness(self):
|
||||||
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."""
|
"""Convert Home Assistant brightness units to percentage."""
|
||||||
return brightness / 255
|
return self._brightness / 255
|
||||||
|
|
||||||
|
def limitlessled_color(self):
|
||||||
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."""
|
"""Convert Home Assistant RGB list to Color tuple."""
|
||||||
from limitlessled import Color
|
from limitlessled import Color
|
||||||
return Color(*tuple(color))
|
return Color(*tuple(self._color))
|
||||||
|
|
||||||
|
|
||||||
def _to_hass_color(color):
|
|
||||||
"""Convert from Color tuple to Home Assistant RGB list."""
|
|
||||||
return list([int(c) for c in color])
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user