Advertisement
Guest User

Untitled

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