diff --git a/homeassistant/components/light/osramlightify.py b/homeassistant/components/light/osramlightify.py index 3faeb1a9d71..143dc52cbee 100644 --- a/homeassistant/components/light/osramlightify.py +++ b/homeassistant/components/light/osramlightify.py @@ -15,26 +15,32 @@ from homeassistant import util from homeassistant.const import CONF_HOST from homeassistant.components.light import ( Light, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_RGB_COLOR, - ATTR_TRANSITION, EFFECT_RANDOM, SUPPORT_BRIGHTNESS, SUPPORT_EFFECT, - SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, SUPPORT_TRANSITION, PLATFORM_SCHEMA) + ATTR_XY_COLOR, ATTR_TRANSITION, EFFECT_RANDOM, SUPPORT_BRIGHTNESS, + SUPPORT_EFFECT, SUPPORT_XY_COLOR, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, + SUPPORT_TRANSITION, PLATFORM_SCHEMA) from homeassistant.util.color import ( - color_temperature_mired_to_kelvin, color_temperature_kelvin_to_mired) + color_temperature_mired_to_kelvin, color_temperature_kelvin_to_mired, + color_xy_brightness_to_RGB) import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['https://github.com/tfriedel/python-lightify/archive/' - 'd6eadcf311e6e21746182d1480e97b350dda2b3e.zip#lightify==1.0.4'] + '1bb1db0e7bd5b14304d7bb267e2398cd5160df46.zip#lightify==1.0.5'] _LOGGER = logging.getLogger(__name__) MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10) MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(milliseconds=100) +CONF_ALLOW_LIGHTIFY_GROUPS = "allow_lightify_groups" +DEFAULT_ALLOW_LIGHTIFY_GROUPS = True SUPPORT_OSRAMLIGHTIFY = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_EFFECT | SUPPORT_RGB_COLOR | - SUPPORT_TRANSITION) + SUPPORT_TRANSITION | SUPPORT_XY_COLOR) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_ALLOW_LIGHTIFY_GROUPS, + default=DEFAULT_ALLOW_LIGHTIFY_GROUPS): cv.boolean, }) @@ -42,6 +48,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the Osram Lightify lights.""" import lightify host = config.get(CONF_HOST) + add_groups = config.get(CONF_ALLOW_LIGHTIFY_GROUPS) if host: try: bridge = lightify.Lightify(host) @@ -50,20 +57,26 @@ def setup_platform(hass, config, add_devices, discovery_info=None): host, str(err)) _LOGGER.exception(msg) return False - setup_bridge(bridge, add_devices) + setup_bridge(bridge, add_devices, add_groups) else: _LOGGER.error("No host found in configuration") return False -def setup_bridge(bridge, add_devices_callback): +def setup_bridge(bridge, add_devices_callback, add_groups): """Set up the Lightify bridge.""" lights = {} @util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS) def update_lights(): """Update the lights objects with latest info from bridge.""" - bridge.update_all_light_status() + try: + bridge.update_all_light_status() + bridge.update_group_list() + except TimeoutError: + _LOGGER.error('Timeout during updating of lights.') + except OSError: + _LOGGER.error('OSError during updating of lights.') new_lights = [] @@ -77,22 +90,31 @@ def setup_bridge(bridge, add_devices_callback): else: lights[light_id].light = light + if add_groups: + for (group_name, group) in bridge.groups().items(): + if group_name not in lights: + osram_group = OsramLightifyGroup(group, bridge, + update_lights) + lights[group_name] = osram_group + new_lights.append(osram_group) + else: + lights[group_name].group = group + if new_lights: add_devices_callback(new_lights) update_lights() -class OsramLightifyLight(Light): - """Representation of an Osram Lightify Light.""" +class Luminary(Light): + """ABS for Lightify Lights and Groups.""" - def __init__(self, light_id, light, update_lights): - """Initialize the light.""" - self._light = light - self._light_id = light_id + def __init__(self, luminary, update_lights): + """Init Luminary object.""" self.update_lights = update_lights + self._luminary = luminary self._brightness = None - self._rgb = None + self._rgb = [None] self._name = None self._temperature = None self._state = False @@ -105,9 +127,7 @@ class OsramLightifyLight(Light): @property def rgb_color(self): - """Return the last RGB color value set.""" - _LOGGER.debug("rgb_color light state for light: %s is: %s %s %s", - self._name, self._rgb[0], self._rgb[1], self._rgb[2]) + """Last RGB color value set.""" return self._rgb @property @@ -117,16 +137,12 @@ class OsramLightifyLight(Light): @property def brightness(self): - """Return the brightness of this light between 0..255.""" - _LOGGER.debug( - "Brightness for light %s is: %s", self._name, self._brightness) + """Brightness of this light between 0..255.""" return self._brightness @property def is_on(self): """Update Status to True if device is on.""" - _LOGGER.debug( - "is_on light state for light: %s is: %s", self._name, self._state) return self._state @property @@ -134,12 +150,14 @@ class OsramLightifyLight(Light): """Flag supported features.""" return SUPPORT_OSRAMLIGHTIFY + @property + def effect_list(self): + """List of supported effects.""" + return [EFFECT_RANDOM] + def turn_on(self, **kwargs): """Turn the device on.""" - _LOGGER.debug("turn_on Attempting to turn on light: %s ", self._name) - - self._light.set_onoff(1) - self._state = self._light.on() + self._luminary.set_onoff(1) if ATTR_TRANSITION in kwargs: transition = int(kwargs[ATTR_TRANSITION] * 10) @@ -152,32 +170,42 @@ class OsramLightifyLight(Light): if ATTR_RGB_COLOR in kwargs: red, green, blue = kwargs[ATTR_RGB_COLOR] - _LOGGER.debug("turn_on requested ATTR_RGB_COLOR for light: " - "%s is: %s %s %s", self._name, red, green, blue) - self._light.set_rgb(red, green, blue, transition) + _LOGGER.debug("turn_on requested ATTR_RGB_COLOR for light:" + " %s is: %s %s %s ", + self._name, red, green, blue) + self._luminary.set_rgb(red, green, blue, transition) + + if ATTR_XY_COLOR in kwargs: + x_mired, y_mired = kwargs[ATTR_XY_COLOR] + _LOGGER.debug("turn_on requested ATTR_XY_COLOR for light:" + " %s is: %s,%s", self._name, x_mired, y_mired) + red, green, blue = color_xy_brightness_to_RGB( + x_mired, y_mired, self._brightness + ) + self._luminary.set_rgb(red, green, blue, transition) if ATTR_COLOR_TEMP in kwargs: color_t = kwargs[ATTR_COLOR_TEMP] kelvin = int(color_temperature_mired_to_kelvin(color_t)) _LOGGER.debug("turn_on requested set_temperature for light: " "%s: %s", self._name, kelvin) - self._light.set_temperature(kelvin, transition) + self._luminary.set_temperature(kelvin, transition) if ATTR_BRIGHTNESS in kwargs: self._brightness = kwargs[ATTR_BRIGHTNESS] _LOGGER.debug("turn_on requested brightness for light: %s is: %s ", self._name, self._brightness) - self._brightness = self._light.set_luminance( + self._brightness = self._luminary.set_luminance( int(self._brightness / 2.55), transition) if ATTR_EFFECT in kwargs: effect = kwargs.get(ATTR_EFFECT) if effect == EFFECT_RANDOM: - self._light.set_rgb(random.randrange(0, 255), - random.randrange(0, 255), - random.randrange(0, 255), - transition) + self._luminary.set_rgb(random.randrange(0, 255), + random.randrange(0, 255), + random.randrange(0, 255), + transition) _LOGGER.debug("turn_on requested random effect for light: " "%s with transition %s", self._name, transition) @@ -189,27 +217,74 @@ class OsramLightifyLight(Light): self._name) if ATTR_TRANSITION in kwargs: transition = int(kwargs[ATTR_TRANSITION] * 10) - _LOGGER.debug("turn_off requested transition time for light: " - "%s is: %s", self._name, transition) - self._light.set_luminance(0, transition) + _LOGGER.debug("turn_off requested transition time for light:" + " %s is: %s ", + self._name, transition) + self._luminary.set_luminance(0, transition) else: transition = 0 - _LOGGER.debug("turn_off requested transition time for light: " - "%s is: %s ", self._name, transition) - self._light.set_onoff(0) - self._state = self._light.on() - + _LOGGER.debug("turn_off requested transition time for light:" + " %s is: %s ", + self._name, transition) + self._luminary.set_onoff(0) self.schedule_update_ha_state() def update(self): """Synchronize state with bridge.""" self.update_lights(no_throttle=True) - self._brightness = int(self._light.lum() * 2.55) - self._name = self._light.name() - self._rgb = self._light.rgb() - o_temp = self._light.temp() + self._name = self._luminary.name() + + +class OsramLightifyLight(Luminary): + """Representation of an Osram Lightify Light.""" + + def __init__(self, light_id, light, update_lights): + """Initialize the light.""" + self._light_id = light_id + super().__init__(light, update_lights) + + def update(self): + """Update status of a Light.""" + super().update() + self._state = self._luminary.on() + self._rgb = self._luminary.rgb() + o_temp = self._luminary.temp() + if o_temp == 0: + self._temperature = None + else: + self._temperature = color_temperature_kelvin_to_mired( + self._luminary.temp() + ) + self._brightness = int(self._luminary.lum() * 2.55) + + +class OsramLightifyGroup(Luminary): + """Representation of an Osram Lightify Group.""" + + def __init__(self, group, bridge, update_lights): + """Init light group.""" + self._bridge = bridge + self._light_ids = [] + super().__init__(group, update_lights) + + def _get_state(self): + """Get state of group. + + The group is on, if any of the lights in on. + """ + lights = self._bridge.lights() + return any(lights[light_id].on() for light_id in self._light_ids) + + def update(self): + """Update group status.""" + super().update() + self._light_ids = self._luminary.lights() + light = self._bridge.lights()[self._light_ids[0]] + self._brightness = int(light.lum() * 2.55) + self._rgb = light.rgb() + o_temp = light.temp() if o_temp == 0: self._temperature = None else: self._temperature = color_temperature_kelvin_to_mired(o_temp) - self._state = self._light.on() + self._state = light.on() diff --git a/requirements_all.txt b/requirements_all.txt index 9d3be36d135..762c9c77f56 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -312,7 +312,7 @@ https://github.com/sander76/powerviewApi/archive/246e782d60d5c0addcc98d7899a0186 https://github.com/soldag/pyflic/archive/0.4.zip#pyflic==0.4 # homeassistant.components.light.osramlightify -https://github.com/tfriedel/python-lightify/archive/d6eadcf311e6e21746182d1480e97b350dda2b3e.zip#lightify==1.0.4 +https://github.com/tfriedel/python-lightify/archive/1bb1db0e7bd5b14304d7bb267e2398cd5160df46.zip#lightify==1.0.5 # homeassistant.components.lutron https://github.com/thecynic/pylutron/archive/v0.1.0.zip#pylutron==0.1.0