Guest User

switch

a guest
Oct 23rd, 2018
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 14.95 KB | None | 0 0
  1. """
  2. Circadian Lighting Switch for Home-Assistant.
  3. """
  4.  
  5. DEPENDENCIES = ['circadian_lighting', 'light']
  6.  
  7. import logging
  8.  
  9. from custom_components.circadian_lighting import DOMAIN, CIRCADIAN_LIGHTING_UPDATE_TOPIC, DATA_CIRCADIAN_LIGHTING
  10.  
  11. import voluptuous as vol
  12.  
  13. import homeassistant.helpers.config_validation as cv
  14. from homeassistant.helpers.dispatcher import dispatcher_connect
  15. from homeassistant.helpers.event import track_state_change
  16. from homeassistant.helpers.restore_state import async_get_last_state
  17. from homeassistant.components.light import (
  18.     is_on, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, ATTR_TRANSITION,
  19.     ATTR_WHITE_VALUE, ATTR_XY_COLOR, DOMAIN as LIGHT_DOMAIN)
  20. from homeassistant.components.switch import SwitchDevice
  21. from homeassistant.const import (
  22.     ATTR_ENTITY_ID, CONF_NAME, CONF_PLATFORM, STATE_ON,
  23.     SERVICE_TURN_ON)
  24. from homeassistant.util import slugify
  25. from homeassistant.util.color import (
  26.     color_RGB_to_xy, color_temperature_kelvin_to_mired, color_temperature_to_rgb)
  27.  
  28. _LOGGER = logging.getLogger(__name__)
  29.  
  30. ICON = 'mdi:theme-light-dark'
  31.  
  32. CONF_LIGHTS_CT = 'lights_ct'
  33. CONF_LIGHTS_RGB = 'lights_rgb'
  34. CONF_LIGHTS_XY = 'lights_xy'
  35. CONF_LIGHTS_BRIGHT = 'lights_brightness'
  36. CONF_DISABLE_BRIGHTNESS_ADJUST = 'disable_brightness_adjust'
  37. CONF_MIN_BRIGHT = 'min_brightness'
  38. DEFAULT_MIN_BRIGHT = 1
  39. CONF_MAX_BRIGHT = 'max_brightness'
  40. DEFAULT_MAX_BRIGHT = 100
  41. CONF_SLEEP_ENTITY = 'sleep_entity'
  42. CONF_SLEEP_STATE = 'sleep_state'
  43. CONF_SLEEP_CT = 'sleep_colortemp'
  44. CONF_SLEEP_BRIGHT = 'sleep_brightness'
  45. CONF_DISABLE_ENTITY = 'disable_entity'
  46. CONF_DISABLE_STATE = 'disable_state'
  47.  
  48. PLATFORM_SCHEMA = vol.Schema({
  49.     vol.Required(CONF_PLATFORM): 'circadian_lighting',
  50.     vol.Optional(CONF_NAME, default="Circadian Lighting"): cv.string,
  51.     vol.Optional(CONF_LIGHTS_CT): cv.entity_ids,
  52.     vol.Optional(CONF_LIGHTS_RGB): cv.entity_ids,
  53.     vol.Optional(CONF_LIGHTS_XY): cv.entity_ids,
  54.     vol.Optional(CONF_LIGHTS_BRIGHT): cv.entity_ids,
  55.     vol.Optional(CONF_DISABLE_BRIGHTNESS_ADJUST, default=False): cv.boolean,
  56.     vol.Optional(CONF_MIN_BRIGHT, default=DEFAULT_MIN_BRIGHT):
  57.         vol.All(vol.Coerce(int), vol.Range(min=1, max=100)),
  58.     vol.Optional(CONF_MAX_BRIGHT, default=DEFAULT_MAX_BRIGHT):
  59.         vol.All(vol.Coerce(int), vol.Range(min=1, max=100)),
  60.     vol.Optional(CONF_SLEEP_ENTITY): cv.entity_id,
  61.     vol.Optional(CONF_SLEEP_STATE): cv.string,
  62.     vol.Optional(CONF_SLEEP_CT):
  63.         vol.All(vol.Coerce(int), vol.Range(min=1000, max=10000)),
  64.     vol.Optional(CONF_SLEEP_BRIGHT):
  65.         vol.All(vol.Coerce(int), vol.Range(min=1, max=100)),
  66.     vol.Optional(CONF_DISABLE_ENTITY): cv.entity_id,
  67.     vol.Optional(CONF_DISABLE_STATE): cv.string
  68. })
  69.  
  70. def setup_platform(hass, config, add_devices, discovery_info=None):
  71.     """Set up the Circadian Lighting switches."""
  72.     cl = hass.data.get(DATA_CIRCADIAN_LIGHTING)
  73.     if cl:
  74.         lights_ct = config.get(CONF_LIGHTS_CT)
  75.         lights_rgb = config.get(CONF_LIGHTS_RGB)
  76.         lights_xy = config.get(CONF_LIGHTS_XY)
  77.         lights_brightness = config.get(CONF_LIGHTS_BRIGHT)
  78.         disable_brightness_adjust = config.get(CONF_DISABLE_BRIGHTNESS_ADJUST)
  79.         name = config.get(CONF_NAME)
  80.         min_brightness = config.get(CONF_MIN_BRIGHT)
  81.         max_brightness = config.get(CONF_MAX_BRIGHT)
  82.         sleep_entity = config.get(CONF_SLEEP_ENTITY)
  83.         sleep_state = config.get(CONF_SLEEP_STATE)
  84.         sleep_colortemp = config.get(CONF_SLEEP_CT)
  85.         sleep_brightness = config.get(CONF_SLEEP_BRIGHT)
  86.         disable_entity = config.get(CONF_DISABLE_ENTITY)
  87.         disable_state = config.get(CONF_DISABLE_STATE)
  88.         cs = CircadianSwitch(hass, cl, name, lights_ct, lights_rgb, lights_xy, lights_brightness,
  89.                                 disable_brightness_adjust, min_brightness, max_brightness,
  90.                                 sleep_entity, sleep_state, sleep_colortemp, sleep_brightness,
  91.                                 disable_entity, disable_state)
  92.         add_devices([cs])
  93.  
  94.         def update(call=None):
  95.             """Update lights."""
  96.             cs.update_switch()
  97.         return True
  98.     else:
  99.         return False
  100.  
  101.  
  102. class CircadianSwitch(SwitchDevice):
  103.     """Representation of a Circadian Lighting switch."""
  104.  
  105.     def __init__(self, hass, cl, name, lights_ct, lights_rgb, lights_xy, lights_brightness,
  106.                     disable_brightness_adjust, min_brightness, max_brightness,
  107.                     sleep_entity, sleep_state, sleep_colortemp, sleep_brightness,
  108.                     disable_entity, disable_state):
  109.         """Initialize the Circadian Lighting switch."""
  110.         self.hass = hass
  111.         self._cl = cl
  112.         self._name = name
  113.         self._entity_id = "switch." + slugify("{} {}".format('circadian_lighting', name))
  114.         self._state = None
  115.         self._icon = ICON
  116.         self._hs_color = self._cl.data['hs_color']
  117.         self._attributes = {}
  118.         self._attributes['lights_ct'] = lights_ct
  119.         self._attributes['lights_rgb'] = lights_rgb
  120.         self._attributes['lights_xy'] = lights_xy
  121.         self._attributes['lights_brightness'] = lights_brightness
  122.         self._attributes['disable_brightness_adjust'] = disable_brightness_adjust
  123.         self._attributes['min_brightness'] = min_brightness
  124.         self._attributes['max_brightness'] = max_brightness
  125.         self._attributes['sleep_entity'] = sleep_entity
  126.         self._attributes['sleep_state'] = sleep_state
  127.         self._attributes['sleep_colortemp'] = sleep_colortemp
  128.         self._attributes['sleep_brightness'] = sleep_brightness
  129.         self._attributes['disable_entity'] = disable_entity
  130.         self._attributes['disable_state'] = disable_state
  131.         self._attributes['hs_color'] = self._hs_color
  132.         self._attributes['brightness'] = self.calc_brightness()
  133.  
  134.         self._lights = []
  135.         if lights_ct != None:
  136.             self._lights += lights_ct
  137.         if lights_rgb != None:
  138.             self._lights += lights_rgb
  139.         if lights_xy != None:
  140.             self._lights += lights_xy
  141.         if lights_brightness != None:
  142.             self._lights += lights_brightness
  143.  
  144.         """Register callbacks."""
  145.         dispatcher_connect(hass, CIRCADIAN_LIGHTING_UPDATE_TOPIC, self.update_switch)
  146.         track_state_change(hass, self._lights, self.light_state_changed)
  147.         if self._attributes['sleep_entity'] is not None:
  148.             track_state_change(hass, self._attributes['sleep_entity'], self.sleep_state_changed)
  149.  
  150.     @property
  151.     def entity_id(self):
  152.         """Return the entity ID of the switch."""
  153.         return self._entity_id
  154.  
  155.     @property
  156.     def name(self):
  157.         """Return the name of the device if any."""
  158.         return self._name
  159.  
  160.     @property
  161.     def is_on(self):
  162.         """Return true if circadian lighting is on."""
  163.         return self._state
  164.  
  165.     async def async_added_to_hass(self):
  166.         """Call when entity about to be added to hass."""
  167.         # If not None, we got an initial value.
  168.         if self._state is not None:
  169.             return
  170.  
  171.         state = await async_get_last_state(self.hass, self._entity_id)
  172.         self._state = state and state.state == STATE_ON
  173.  
  174.     @property
  175.     def icon(self):
  176.         """Icon to use in the frontend, if any."""
  177.         return self._icon
  178.  
  179.     @property
  180.     def hs_color(self):
  181.         return self._hs_color
  182.  
  183.     @property
  184.     def device_state_attributes(self):
  185.         """Return the attributes of the switch."""
  186.         return self._attributes
  187.  
  188.     def turn_on(self, **kwargs):
  189.         """Turn on circadian lighting."""
  190.         self._state = True
  191.  
  192.         # Make initial update
  193.         self.update_switch()
  194.  
  195.         self.schedule_update_ha_state()
  196.  
  197.     def turn_off(self, **kwargs):
  198.         """Turn off circadian lighting."""
  199.         self._state = False
  200.         self.schedule_update_ha_state()
  201.         self._hs_color = None
  202.         self._attributes['hs_color'] = self._hs_color
  203.  
  204.     def calc_ct(self):
  205.         if self._attributes['sleep_entity'] is not None and self.hass.states.get(self._attributes['sleep_entity']).state == self._attributes['sleep_state']:
  206.             _LOGGER.debug(self._name + " in Sleep mode")
  207.             return color_temperature_kelvin_to_mired(self._attributes['sleep_colortemp'])
  208.         else:
  209.             return color_temperature_kelvin_to_mired(self._cl.data['colortemp'])
  210.  
  211.     def calc_rgb(self):
  212.         if self._attributes['sleep_entity'] is not None and self.hass.states.get(self._attributes['sleep_entity']).state == self._attributes['sleep_state']:
  213.             _LOGGER.debug(self._name + " in Sleep mode")
  214.             return color_temperature_to_rgb(self._attributes['sleep_colortemp'])
  215.         else:
  216.             return color_temperature_to_rgb(self._cl.data['colortemp'])
  217.  
  218.     def calc_xy(self):
  219.         return color_RGB_to_xy(*self.calc_rgb())
  220.  
  221.     def calc_brightness(self):
  222.         if self._attributes['disable_brightness_adjust'] is True:
  223.             return None
  224.         else:
  225.             if self._attributes['sleep_entity'] is not None and self.hass.states.get(self._attributes['sleep_entity']).state == self._attributes['sleep_state']:
  226.                 _LOGGER.debug(self._name + " in Sleep mode")
  227.                 return self._attributes['sleep_brightness']
  228.             else:
  229.                 if self._cl.data['percent'] > 0:
  230.                     return self._attributes['max_brightness']
  231.                 else:
  232.                     return ((self._attributes['max_brightness'] - self._attributes['min_brightness']) * ((100+self._cl.data['percent']) / 100)) + self._attributes['min_brightness']
  233.  
  234.     def update_switch(self):
  235.         if self._cl.data is not None:
  236.             self._hs_color = self._cl.data['hs_color']
  237.             self._attributes['hs_color'] = self._hs_color
  238.             self._attributes['brightness'] = self.calc_brightness()
  239.             _LOGGER.debug(self._name + " Switch Updated")
  240.  
  241.         self.adjust_lights(self._lights)
  242.  
  243.     def should_adjust(self):
  244.         if self._state is not True:
  245.             _LOGGER.debug(self._name + " off - not adjusting")
  246.             return False
  247.         elif self._cl.data is None:
  248.             _LOGGER.debug(self._name + " could not retrieve Circadian Lighting data")
  249.             return False
  250.         elif self._attributes['disable_entity'] is not None and self.hass.states.get(self._attributes['disable_entity']).state == self._attributes['disable_state']:
  251.             _LOGGER.debug(self._name + " disabled by " + str(self._attributes['disable_entity']))
  252.             return False
  253.         else:
  254.             return True
  255.  
  256.     def adjust_lights(self, lights, transition=None):
  257.         if self.should_adjust():
  258.             if transition == None:
  259.                 transition = self._cl.data['transition']
  260.  
  261.             brightness = (self._attributes['brightness'] / 100) * 255 if self._attributes['brightness'] is not None else None
  262.  
  263.             for light in lights:
  264.                 """Set color of array of ct light."""
  265.                 if self._attributes['lights_ct'] is not None and light in self._attributes['lights_ct']:
  266.                     mired = int(self.calc_ct())
  267.                     if is_on(self.hass, light):
  268.                         service_data = {ATTR_ENTITY_ID: light}
  269.                         if mired is not None:
  270.                             service_data[ATTR_COLOR_TEMP] = int(mired)
  271.                         if brightness is not None:
  272.                             service_data[ATTR_BRIGHTNESS] = brightness
  273.                         if transition is not None:
  274.                             service_data[ATTR_TRANSITION] = transition
  275.                         self.hass.services.call(
  276.                             LIGHT_DOMAIN, SERVICE_TURN_ON, service_data)
  277.                         _LOGGER.debug(light + " CT Adjusted - color_temp: " + str(mired) + ", brightness: " + str(brightness) + ", transition: " + str(transition))
  278.  
  279.                 """Set color of array of rgb light."""
  280.                 if self._attributes['lights_rgb'] is not None and light in self._attributes['lights_rgb']:
  281.                     rgb = self.calc_rgb()
  282.                     if is_on(self.hass, light):
  283.                         service_data = {ATTR_ENTITY_ID: light}
  284.                         if rgb is not None:
  285.                             service_data[ATTR_RGB_COLOR] = rgb
  286.                         if transition is not None:
  287.                             service_data[ATTR_TRANSITION] = transition
  288.                         if brightness is not None:
  289.                             service_data[ATTR_BRIGHTNESS] = brightness
  290.                         self.hass.services.call(
  291.                             LIGHT_DOMAIN, SERVICE_TURN_ON, service_data)
  292.                         _LOGGER.debug(light + " RGB Adjusted - rgb_color: " + str(rgb) + ", brightness: " + str(brightness) + ", transition: " + str(transition))
  293.  
  294.                 """Set color of array of xy light."""
  295.                 if self._attributes['lights_xy'] is not None and light in self._attributes['lights_xy']:
  296.                     x_val, y_val = self.calc_xy()
  297.                     if is_on(self.hass, light):
  298.                         service_data = {ATTR_ENTITY_ID: light}
  299.                         if x_val is not None and y_val is not None:
  300.                             service_data[ATTR_XY_COLOR] = [x_val, y_val]
  301.                         if brightness is not None:
  302.                             service_data[ATTR_BRIGHTNESS] = brightness
  303.                             service_data[ATTR_WHITE_VALUE] = brightness
  304.                         if transition is not None:
  305.                             service_data[ATTR_TRANSITION] = transition
  306.                         self.hass.services.call(
  307.                             LIGHT_DOMAIN, SERVICE_TURN_ON, service_data)
  308.                         _LOGGER.debug(light + " XY Adjusted - xy_color: [" + str(x_val) + ", " + str(y_val) + "], brightness: " + str(brightness) + ", transition: " + str(transition) + ", white_value: " + str(brightness))
  309.  
  310.                 """Set color of array of brightness light."""
  311.                 if self._attributes['lights_brightness'] is not None and light in self._attributes['lights_brightness']:
  312.                     if is_on(self.hass, light):
  313.                         service_data = {ATTR_ENTITY_ID: light}
  314.                         if brightness is not None:
  315.                             service_data[ATTR_BRIGHTNESS] = brightness
  316.                         if transition is not None:
  317.                             service_data[ATTR_TRANSITION] = transition
  318.                         self.hass.services.call(
  319.                             LIGHT_DOMAIN, SERVICE_TURN_ON, service_data)
  320.                         _LOGGER.debug(light + " Brightness Adjusted - brightness: " + str(brightness) + ", transition: " + str(transition))
  321.  
  322.     def light_state_changed(self, entity_id, from_state, to_state):
  323.         self.adjust_lights([entity_id], 1)
  324.  
  325.     def sleep_state_changed(self, entity_id, from_state, to_state):
  326.         if to_state.state == self._attributes['sleep_state']:
  327.             self.adjust_lights(self._lights, 1)
Add Comment
Please, Sign In to add comment