Advertisement
Guest User

Updated Hass limitlessled.py adding CCT for RGBWW bulbs

a guest
Feb 2nd, 2017
393
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 13.40 KB | None | 0 0
  1. """
  2. Support for LimitlessLED bulbs.
  3.  
  4. For more details about this platform, please refer to the documentation at
  5. https://home-assistant.io/components/light.limitlessled/
  6. """
  7.  
  8. import logging
  9.  
  10. import voluptuous as vol
  11.  
  12. from homeassistant.const import (CONF_NAME, CONF_HOST, CONF_PORT, CONF_TYPE)
  13. from homeassistant.components.light import (
  14.     ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_RGB_COLOR,
  15.     ATTR_TRANSITION, EFFECT_COLORLOOP, EFFECT_WHITE, FLASH_LONG,
  16.     SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_EFFECT, SUPPORT_FLASH,
  17.     SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, Light, PLATFORM_SCHEMA)
  18. import homeassistant.helpers.config_validation as cv
  19.  
  20. REQUIREMENTS = ['limitlessled==1.0.3']
  21.  
  22. _LOGGER = logging.getLogger(__name__)
  23.  
  24. CONF_BRIDGES = 'bridges'
  25. CONF_GROUPS = 'groups'
  26. CONF_NUMBER = 'number'
  27. CONF_VERSION = 'version'
  28.  
  29. DEFAULT_LED_TYPE = 'rgbw'
  30. DEFAULT_PORT = 5987
  31. DEFAULT_TRANSITION = 0
  32. DEFAULT_VERSION = 6
  33.  
  34. LED_TYPE = ['rgbw', 'white', 'rgbww', 'bridge-led']
  35.  
  36. RGB_BOUNDARY = 40
  37.  
  38. WHITE = [255, 255, 255]
  39.  
  40. SUPPORT_LIMITLESSLED_WHITE = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP |
  41.                               SUPPORT_TRANSITION)
  42. SUPPORT_LIMITLESSLED_RGB = (SUPPORT_BRIGHTNESS | SUPPORT_EFFECT |
  43.                             SUPPORT_FLASH | SUPPORT_RGB_COLOR |
  44.                             SUPPORT_TRANSITION)
  45. SUPPORT_LIMITLESSLED_RGBWW = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP |
  46.                             SUPPORT_EFFECT | SUPPORT_FLASH |
  47.                             SUPPORT_RGB_COLOR | SUPPORT_TRANSITION)
  48.  
  49. PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
  50.     vol.Required(CONF_BRIDGES): vol.All(cv.ensure_list, [
  51.         {
  52.             vol.Required(CONF_HOST): cv.string,
  53.             vol.Optional(CONF_VERSION,
  54.                          default=DEFAULT_VERSION): cv.positive_int,
  55.             vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
  56.             vol.Required(CONF_GROUPS):  vol.All(cv.ensure_list, [
  57.                 {
  58.                     vol.Required(CONF_NAME): cv.string,
  59.                     vol.Optional(CONF_TYPE, default=DEFAULT_LED_TYPE):
  60.                         vol.In(LED_TYPE),
  61.                     vol.Required(CONF_NUMBER): cv.positive_int,
  62.                 }
  63.             ]),
  64.         },
  65.     ]),
  66. })
  67.  
  68.  
  69. def rewrite_legacy(config):
  70.     """Rewrite legacy configuration to new format."""
  71.     bridges = config.get(CONF_BRIDGES, [config])
  72.     new_bridges = []
  73.     for bridge_conf in bridges:
  74.         groups = []
  75.         if 'groups' in bridge_conf:
  76.             groups = bridge_conf['groups']
  77.         else:
  78.             _LOGGER.warning("Legacy configuration format detected")
  79.             for i in range(1, 5):
  80.                 name_key = 'group_%d_name' % i
  81.                 if name_key in bridge_conf:
  82.                     groups.append({
  83.                         'number': i,
  84.                         'type':  bridge_conf.get('group_%d_type' % i,
  85.                                                  DEFAULT_LED_TYPE),
  86.                         'name': bridge_conf.get(name_key)
  87.                     })
  88.         new_bridges.append({
  89.             'host': bridge_conf.get(CONF_HOST),
  90.             'groups': groups
  91.         })
  92.     return {'bridges': new_bridges}
  93.  
  94.  
  95. def setup_platform(hass, config, add_devices, discovery_info=None):
  96.     """Setup the LimitlessLED lights."""
  97.     from limitlessled.bridge import Bridge
  98.  
  99.     # Two legacy configuration formats are supported to maintain backwards
  100.     # compatibility.
  101.     config = rewrite_legacy(config)
  102.  
  103.     # Use the expanded configuration format.
  104.     lights = []
  105.     for bridge_conf in config.get(CONF_BRIDGES):
  106.         bridge = Bridge(bridge_conf.get(CONF_HOST),
  107.                         port=bridge_conf.get(CONF_PORT, DEFAULT_PORT),
  108.                         version=bridge_conf.get(CONF_VERSION, DEFAULT_VERSION))
  109.         for group_conf in bridge_conf.get(CONF_GROUPS):
  110.             group = bridge.add_group(
  111.                 group_conf.get(CONF_NUMBER),
  112.                 group_conf.get(CONF_NAME),
  113.                 group_conf.get(CONF_TYPE, DEFAULT_LED_TYPE))
  114.             lights.append(LimitlessLEDGroup.factory(group))
  115.     add_devices(lights)
  116.  
  117.  
  118. def state(new_state):
  119.     """State decorator.
  120.  
  121.    Specify True (turn on) or False (turn off).
  122.    """
  123.     def decorator(function):
  124.         """Decorator function."""
  125.         # pylint: disable=no-member,protected-access
  126.         def wrapper(self, **kwargs):
  127.             """Wrap a group state change."""
  128.             from limitlessled.pipeline import Pipeline
  129.             pipeline = Pipeline()
  130.             transition_time = DEFAULT_TRANSITION
  131.             # Stop any repeating pipeline.
  132.             if self.repeating:
  133.                 self.repeating = False
  134.                 self.group.stop()
  135.             # Not on and should be? Turn on.
  136.             if not self.is_on and new_state is True:
  137.                 pipeline.on()
  138.             # Set transition time.
  139.             if ATTR_TRANSITION in kwargs:
  140.                 transition_time = kwargs[ATTR_TRANSITION]
  141.             # Do group type-specific work.
  142.             function(self, transition_time, pipeline, **kwargs)
  143.             # Update state.
  144.             self._is_on = new_state
  145.             self.group.enqueue(pipeline)
  146.             self.schedule_update_ha_state()
  147.         return wrapper
  148.     return decorator
  149.  
  150.  
  151. class LimitlessLEDGroup(Light):
  152.     """Representation of a LimitessLED group."""
  153.  
  154.     def __init__(self, group):
  155.         """Initialize a group."""
  156.         self.group = group
  157.         self.repeating = False
  158.         self._is_on = False
  159.         self._brightness = None
  160.  
  161.     @staticmethod
  162.     def factory(group):
  163.         """Produce LimitlessLEDGroup objects."""
  164.         from limitlessled.group.rgbw import RgbwGroup
  165.         from limitlessled.group.rgbww import RgbwwGroup
  166.         from limitlessled.group.white import WhiteGroup
  167.         if isinstance(group, WhiteGroup):
  168.             return LimitlessLEDWhiteGroup(group)
  169.         elif isinstance(group, RgbwwGroup):
  170.             return LimitlessLEDRGBWWGroup(group)
  171.         elif isinstance(group, RgbwGroup):
  172.             return LimitlessLEDRGBWGroup(group)
  173.  
  174.     @property
  175.     def should_poll(self):
  176.         """No polling needed."""
  177.         return False
  178.  
  179.     @property
  180.     def name(self):
  181.         """Return the name of the group."""
  182.         return self.group.name
  183.  
  184.     @property
  185.     def is_on(self):
  186.         """Return true if device is on."""
  187.         return self._is_on
  188.  
  189.     @property
  190.     def brightness(self):
  191.         """Return the brightness property."""
  192.         return self._brightness
  193.  
  194.     @state(False)
  195.     def turn_off(self, transition_time, pipeline, **kwargs):
  196.         """Turn off a group."""
  197.         if self.is_on:
  198.             pipeline.transition(transition_time, brightness=0.0).off()
  199.  
  200.  
  201. class LimitlessLEDWhiteGroup(LimitlessLEDGroup):
  202.     """Representation of a LimitlessLED White group."""
  203.  
  204.     def __init__(self, group):
  205.         """Initialize White group."""
  206.         super().__init__(group)
  207.         # Initialize group with known values.
  208.         self.group.on = True
  209.         self.group.temperature = 1.0
  210.         self.group.brightness = 0.0
  211.         self._brightness = _to_hass_brightness(1.0)
  212.         self._temperature = _to_hass_temperature(self.group.temperature)
  213.         self.group.on = False
  214.  
  215.     @property
  216.     def color_temp(self):
  217.         """Return the temperature property."""
  218.         return self._temperature
  219.  
  220.     @property
  221.     def supported_features(self):
  222.         """Flag supported features."""
  223.         return SUPPORT_LIMITLESSLED_WHITE
  224.  
  225.     @state(True)
  226.     def turn_on(self, transition_time, pipeline, **kwargs):
  227.         """Turn on (or adjust property of) a group."""
  228.         # Check arguments.
  229.         if ATTR_BRIGHTNESS in kwargs:
  230.             self._brightness = kwargs[ATTR_BRIGHTNESS]
  231.         if ATTR_COLOR_TEMP in kwargs:
  232.             self._temperature = kwargs[ATTR_COLOR_TEMP]
  233.         # Set up transition.
  234.         pipeline.transition(
  235.             transition_time,
  236.             brightness=_from_hass_brightness(self._brightness),
  237.             temperature=_from_hass_temperature(self._temperature)
  238.         )
  239.  
  240.  
  241. class LimitlessLEDRGBWGroup(LimitlessLEDGroup):
  242.     """Representation of a LimitlessLED RGBW group."""
  243.  
  244.     def __init__(self, group):
  245.         """Initialize RGBW group."""
  246.         super().__init__(group)
  247.         # Initialize group with known values.
  248.         self.group.on = True
  249.         self.group.white()
  250.         self._color = WHITE
  251.         self.group.brightness = 0.0
  252.         self._brightness = _to_hass_brightness(1.0)
  253.         self.group.on = False
  254.  
  255.     @property
  256.     def rgb_color(self):
  257.         """Return the color property."""
  258.         return self._color
  259.  
  260.     @property
  261.     def supported_features(self):
  262.         """Flag supported features."""
  263.         return SUPPORT_LIMITLESSLED_RGB
  264.  
  265.     @state(True)
  266.     def turn_on(self, transition_time, pipeline, **kwargs):
  267.         """Turn on (or adjust property of) a group."""
  268.         from limitlessled.presets import COLORLOOP
  269.         # Check arguments.
  270.         if ATTR_BRIGHTNESS in kwargs:
  271.             self._brightness = kwargs[ATTR_BRIGHTNESS]
  272.         if ATTR_RGB_COLOR in kwargs:
  273.             self._color = kwargs[ATTR_RGB_COLOR]
  274.         # White is a special case.
  275.         if min(self._color) > 256 - RGB_BOUNDARY:
  276.             pipeline.white()
  277.             self._color = WHITE
  278.         # Set up transition.
  279.         pipeline.transition(
  280.             transition_time,
  281.             brightness=_from_hass_brightness(self._brightness),
  282.             color=_from_hass_color(self._color)
  283.         )
  284.         # Flash.
  285.         if ATTR_FLASH in kwargs:
  286.             duration = 0
  287.             if kwargs[ATTR_FLASH] == FLASH_LONG:
  288.                 duration = 1
  289.             pipeline.flash(duration=duration)
  290.         # Add effects.
  291.         if ATTR_EFFECT in kwargs:
  292.             if kwargs[ATTR_EFFECT] == EFFECT_COLORLOOP:
  293.                 self.repeating = True
  294.                 pipeline.append(COLORLOOP)
  295.             if kwargs[ATTR_EFFECT] == EFFECT_WHITE:
  296.                 pipeline.white()
  297.                 self._color = WHITE
  298.  
  299. class LimitlessLEDRGBWWGroup(LimitlessLEDGroup):
  300.     """Representation of a LimitlessLED RGBWW group."""
  301.  
  302.     def __init__(self, group):
  303.         """Initialize RGBWW group."""
  304.         super().__init__(group)
  305.         # Initialize group with known values.
  306.         self.group.on = True
  307.         self.group.white()
  308.         self.group.temperature = 0.5
  309.         self._color = WHITE
  310.         self.group.brightness = 0.0
  311.         self._brightness = _to_hass_brightness(1.0)
  312.         self._temperature = _to_hass_temperature(self.group.temperature)
  313.         self.group.on = False
  314.  
  315.     @property
  316.     def rgb_color(self):
  317.         """Return the color property."""
  318.         return self._color
  319.  
  320.     @property
  321.     def color_temp(self):
  322.         """Return the temperature property."""
  323.         return self._temperature
  324.  
  325.     @property
  326.     def supported_features(self):
  327.         """Flag supported features."""
  328.         return SUPPORT_LIMITLESSLED_RGBWW
  329.  
  330.     @state(True)
  331.     def turn_on(self, transition_time, pipeline, **kwargs):
  332.         """Turn on (or adjust property of) a group."""
  333.         from limitlessled.presets import COLORLOOP
  334.         # Check arguments.
  335.         if ATTR_BRIGHTNESS in kwargs:
  336.             self._brightness = kwargs[ATTR_BRIGHTNESS]
  337.         if ATTR_RGB_COLOR in kwargs:
  338.             self._color = kwargs[ATTR_RGB_COLOR]
  339.         if ATTR_COLOR_TEMP in kwargs:
  340.             self._temperature = kwargs[ATTR_COLOR_TEMP]
  341.         # White is a special case.
  342.         if min(self._color) > 256 - RGB_BOUNDARY:
  343.             pipeline.white()
  344.             self._color = WHITE
  345.         # Set up transition.
  346.         pipeline.transition(
  347.             transition_time,
  348.             brightness=_from_hass_brightness(self._brightness),
  349.             color=_from_hass_color(self._color)
  350.         )
  351.         if self._color == WHITE:
  352.              pipeline.transition(
  353.                  transition_time,
  354.                  temperature=_from_hass_temperature(self._temperature)
  355.              )
  356.         # Flash.
  357.         if ATTR_FLASH in kwargs:
  358.             duration = 0
  359.             if kwargs[ATTR_FLASH] == FLASH_LONG:
  360.                 duration = 1
  361.             pipeline.flash(duration=duration)
  362.         # Add effects.
  363.         if ATTR_EFFECT in kwargs:
  364.             if kwargs[ATTR_EFFECT] == EFFECT_COLORLOOP:
  365.                 self.repeating = True
  366.                 pipeline.append(COLORLOOP)
  367.             if kwargs[ATTR_EFFECT] == EFFECT_WHITE:
  368.                 pipeline.white()
  369.                 self._color = WHITE
  370.  
  371.  
  372. def _from_hass_temperature(temperature):
  373.     """Convert Home Assistant color temperature units to percentage."""
  374.     return (temperature - 154) / 346
  375.  
  376.  
  377. def _to_hass_temperature(temperature):
  378.     """Convert percentage to Home Assistant color temperature units."""
  379.     return int(temperature * 346) + 154
  380.  
  381.  
  382. def _from_hass_brightness(brightness):
  383.     """Convert Home Assistant brightness units to percentage."""
  384.     return brightness / 255
  385.  
  386.  
  387. def _to_hass_brightness(brightness):
  388.     """Convert percentage to Home Assistant brightness units."""
  389.     return int(brightness * 255)
  390.  
  391.  
  392. def _from_hass_color(color):
  393.     """Convert Home Assistant RGB list to Color tuple."""
  394.     from limitlessled import Color
  395.     return Color(*tuple(color))
  396.  
  397.  
  398. def _to_hass_color(color):
  399.     """Convert from Color tuple to Home Assistant RGB list."""
  400.     return list([int(c) for c in color])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement