def __init__(self, pool, controller_id, group, name): super().__init__(pool, controller_id, group, name, 'rgbw') self._brightness = 100 self._xy_color = color_RGB_to_xy(255, 255, 255) # Build a color table that maps an RGB color to a color string # recognized by LedController's set_color method self._color_table = [(color_RGB_to_xy(*x[0]), x[1]) for x in [ ((0xFF, 0xFF, 0xFF), 'white'), ((0xEE, 0x82, 0xEE), 'violet'), ((0x41, 0x69, 0xE1), 'royal_blue'), ((0x87, 0xCE, 0xFA), 'baby_blue'), ((0x00, 0xFF, 0xFF), 'aqua'), ((0x7F, 0xFF, 0xD4), 'royal_mint'), ((0x2E, 0x8B, 0x57), 'seafoam_green'), ((0x00, 0x80, 0x00), 'green'), ((0x32, 0xCD, 0x32), 'lime_green'), ((0xFF, 0xFF, 0x00), 'yellow'), ((0xDA, 0xA5, 0x20), 'yellow_orange'), ((0xFF, 0xA5, 0x00), 'orange'), ((0xFF, 0x00, 0x00), 'red'), ((0xFF, 0xC0, 0xCB), 'pink'), ((0xFF, 0x00, 0xFF), 'fusia'), ((0xDA, 0x70, 0xD6), 'lilac'), ((0xE6, 0xE6, 0xFA), 'lavendar'), ]]
def _light_internal_convert_color(self, color_mode: str) -> dict: data: dict[str, tuple] = {} if color_mode == COLOR_MODE_HS and self.hs_color: hs_color = self.hs_color data[ATTR_HS_COLOR] = (round(hs_color[0], 3), round(hs_color[1], 3)) data[ATTR_RGB_COLOR] = color_util.color_hs_to_RGB(*hs_color) data[ATTR_XY_COLOR] = color_util.color_hs_to_xy(*hs_color) elif color_mode == COLOR_MODE_XY and self.xy_color: xy_color = self.xy_color data[ATTR_HS_COLOR] = color_util.color_xy_to_hs(*xy_color) data[ATTR_RGB_COLOR] = color_util.color_xy_to_RGB(*xy_color) data[ATTR_XY_COLOR] = (round(xy_color[0], 6), round(xy_color[1], 6)) elif color_mode == COLOR_MODE_RGB and self.rgb_color: rgb_color = self.rgb_color data[ATTR_HS_COLOR] = color_util.color_RGB_to_hs(*rgb_color) data[ATTR_RGB_COLOR] = tuple(int(x) for x in rgb_color[0:3]) data[ATTR_XY_COLOR] = color_util.color_RGB_to_xy(*rgb_color) elif color_mode == COLOR_MODE_RGBW and self._light_internal_rgbw_color: rgbw_color = self._light_internal_rgbw_color rgb_color = color_util.color_rgbw_to_rgb(*rgbw_color) data[ATTR_HS_COLOR] = color_util.color_RGB_to_hs(*rgb_color) data[ATTR_RGB_COLOR] = tuple(int(x) for x in rgb_color[0:3]) data[ATTR_RGBW_COLOR] = tuple(int(x) for x in rgbw_color[0:4]) data[ATTR_XY_COLOR] = color_util.color_RGB_to_xy(*rgb_color) elif color_mode == COLOR_MODE_RGBWW and self.rgbww_color: rgbww_color = self.rgbww_color rgb_color = color_util.color_rgbww_to_rgb( *rgbww_color, self.min_mireds, self.max_mireds ) data[ATTR_HS_COLOR] = color_util.color_RGB_to_hs(*rgb_color) data[ATTR_RGB_COLOR] = tuple(int(x) for x in rgb_color[0:3]) data[ATTR_RGBWW_COLOR] = tuple(int(x) for x in rgbww_color[0:5]) data[ATTR_XY_COLOR] = color_util.color_RGB_to_xy(*rgb_color) return data
def __init__(self, pool, controller_id, group, name): super().__init__(pool, controller_id, group, name, "rgbw") self._brightness = 100 self._xy_color = color_RGB_to_xy(255, 255, 255) # Build a color table that maps an RGB color to a color string # recognized by LedController's set_color method self._color_table = [ (color_RGB_to_xy(*x[0]), x[1]) for x in [ ((0xFF, 0xFF, 0xFF), "white"), ((0xEE, 0x82, 0xEE), "violet"), ((0x41, 0x69, 0xE1), "royal_blue"), ((0x87, 0xCE, 0xFA), "baby_blue"), ((0x00, 0xFF, 0xFF), "aqua"), ((0x7F, 0xFF, 0xD4), "royal_mint"), ((0x2E, 0x8B, 0x57), "seafoam_green"), ((0x00, 0x80, 0x00), "green"), ((0x32, 0xCD, 0x32), "lime_green"), ((0xFF, 0xFF, 0x00), "yellow"), ((0xDA, 0xA5, 0x20), "yellow_orange"), ((0xFF, 0xA5, 0x00), "orange"), ((0xFF, 0x00, 0x00), "red"), ((0xFF, 0xC0, 0xCB), "pink"), ((0xFF, 0x00, 0xFF), "fusia"), ((0xDA, 0x70, 0xD6), "lilac"), ((0xE6, 0xE6, 0xFA), "lavendar"), ] ]
def __init__(self, led, group, name): self.led = led self.group = group # LimitlessLEDs don't report state, we have track it ourselves. self.led.off(self.group) self._name = name or DEVICE_DEFAULT_NAME self._state = False self._brightness = 100 self._xy_color = color_RGB_to_xy(255, 255, 255) # Build a color table that maps an RGB color to a color string # recognized by LedController's set_color method self._color_table = [(color_RGB_to_xy(*x[0]), x[1]) for x in [ ((0xFF, 0xFF, 0xFF), 'white'), ((0xEE, 0x82, 0xEE), 'violet'), ((0x41, 0x69, 0xE1), 'royal_blue'), ((0x87, 0xCE, 0xFA), 'baby_blue'), ((0x00, 0xFF, 0xFF), 'aqua'), ((0x7F, 0xFF, 0xD4), 'royal_mint'), ((0x2E, 0x8B, 0x57), 'seafoam_green'), ((0x00, 0x80, 0x00), 'green'), ((0x32, 0xCD, 0x32), 'lime_green'), ((0xFF, 0xFF, 0x00), 'yellow'), ((0xDA, 0xA5, 0x20), 'yellow_orange'), ((0xFF, 0xA5, 0x00), 'orange'), ((0xFF, 0x00, 0x00), 'red'), ((0xFF, 0xC0, 0xCB), 'pink'), ((0xFF, 0x00, 0xFF), 'fusia'), ((0xDA, 0x70, 0xD6), 'lilac'), ((0xE6, 0xE6, 0xFA), 'lavendar'), ]]
def test_color_RGB_to_xy(self): """Test color_RGB_to_xy.""" assert (0, 0) == \ color_util.color_RGB_to_xy(0, 0, 0) assert (0.323, 0.329) == \ color_util.color_RGB_to_xy(255, 255, 255) assert (0.136, 0.04) == \ color_util.color_RGB_to_xy(0, 0, 255) assert (0.172, 0.747) == \ color_util.color_RGB_to_xy(0, 255, 0) assert (0.701, 0.299) == \ color_util.color_RGB_to_xy(255, 0, 0) assert (0.701, 0.299) == \ color_util.color_RGB_to_xy(128, 0, 0) assert (0.138, 0.08) == \ color_util.color_RGB_to_xy(0, 0, 255, GAMUT) assert (0.215, 0.711) == \ color_util.color_RGB_to_xy(0, 255, 0, GAMUT) assert (0.7, 0.299) == \ color_util.color_RGB_to_xy(255, 0, 0, GAMUT)
def flux_update(self, now=dt_now()): """Update all the lights using flux.""" sunset = next_setting(self.hass, SUN).replace(day=now.day, month=now.month, year=now.year) start_time = self.find_start_time(now) stop_time = now.replace(hour=self._stop_time.hour, minute=self._stop_time.minute, second=0) if start_time < now < sunset: # Daytime temp_range = abs(self._start_colortemp - self._sunset_colortemp) day_length = int(sunset.timestamp() - start_time.timestamp()) seconds_from_start = int(now.timestamp() - start_time.timestamp()) percentage_of_day_complete = seconds_from_start / day_length temp_offset = temp_range * percentage_of_day_complete if self._start_colortemp > self._sunset_colortemp: temp = self._start_colortemp - temp_offset else: temp = self._start_colortemp + temp_offset x_val, y_val, b_val = color_RGB_to_xy(*temp_to_rgb(temp)) brightness = self._brightness if self._brightness else b_val set_lights_xy(self.hass, self._lights, x_val, y_val, brightness) _LOGGER.info("Lights updated to x:%s y:%s brightness:%s, %s%%" " of day cycle complete at %s", x_val, y_val, brightness, round(percentage_of_day_complete*100), as_local(now)) else: # Nightime if now < stop_time and now > start_time: now_time = now else: now_time = stop_time temp_range = abs(self._sunset_colortemp - self._stop_colortemp) night_length = int(stop_time.timestamp() - sunset.timestamp()) seconds_from_sunset = int(now_time.timestamp() - sunset.timestamp()) percentage_of_night_complete = seconds_from_sunset / night_length temp_offset = temp_range * percentage_of_night_complete if self._sunset_colortemp > self._stop_colortemp: temp = self._sunset_colortemp - temp_offset else: temp = self._sunset_colortemp + temp_offset x_val, y_val, b_val = color_RGB_to_xy(*temp_to_rgb(temp)) brightness = self._brightness if self._brightness else b_val set_lights_xy(self.hass, self._lights, x_val, y_val, brightness) _LOGGER.info("Lights updated to x:%s y:%s brightness:%s, %s%%" " of night cycle complete at %s", x_val, y_val, brightness, round(percentage_of_night_complete*100), as_local(now))
def test_color_RGB_to_xy(self): """ Test color_RGB_to_xy. """ self.assertEqual((0, 0), color_util.color_RGB_to_xy(0, 0, 0)) self.assertEqual((0.3127159072215825, 0.3290014805066623), color_util.color_RGB_to_xy(255, 255, 255)) self.assertEqual((0.15001662234042554, 0.060006648936170214), color_util.color_RGB_to_xy(0, 0, 255)) self.assertEqual((0.3, 0.6), color_util.color_RGB_to_xy(0, 255, 0)) self.assertEqual((0.6400744994567747, 0.3299705106316933), color_util.color_RGB_to_xy(255, 0, 0))
def test_color_RGB_to_xy(self): """Test color_RGB_to_xy.""" self.assertEqual((0, 0, 0), color_util.color_RGB_to_xy(0, 0, 0)) self.assertEqual((0.32, 0.336, 255), color_util.color_RGB_to_xy(255, 255, 255)) self.assertEqual((0.136, 0.04, 12), color_util.color_RGB_to_xy(0, 0, 255)) self.assertEqual((0.172, 0.747, 170), color_util.color_RGB_to_xy(0, 255, 0)) self.assertEqual((0.679, 0.321, 80), color_util.color_RGB_to_xy(255, 0, 0))
def async_turn_on(self, **kwargs): """Turn the entity on.""" duration = 5 # tenths of s if light.ATTR_COLOR_TEMP in kwargs: temperature = kwargs[light.ATTR_COLOR_TEMP] yield from self._endpoint.light_color.move_to_color_temp( temperature, duration) self._color_temp = temperature if light.ATTR_XY_COLOR in kwargs: self._xy_color = kwargs[light.ATTR_XY_COLOR] elif light.ATTR_RGB_COLOR in kwargs: xyb = color_RGB_to_xy(*(int(val) for val in kwargs[light.ATTR_RGB_COLOR])) self._xy_color = (xyb[0], xyb[1]) self._brightness = xyb[2] if light.ATTR_XY_COLOR in kwargs or light.ATTR_RGB_COLOR in kwargs: yield from self._endpoint.light_color.move_to_color( int(self._xy_color[0] * 65535), int(self._xy_color[1] * 65535), duration, ) if self._brightness is not None: brightness = kwargs.get('brightness', self._brightness or 255) self._brightness = brightness # Move to level with on/off: yield from self._endpoint.level.move_to_level_with_on_off( brightness, duration) self._state = 1 return yield from self._endpoint.on_off.on() self._state = 1
def flux_update(self, now=None): """Update all the lights using flux.""" if now is None: now = dt_now() sunset = next_setting(self.hass, SUN).replace(day=now.day, month=now.month, year=now.year) start_time = self.find_start_time(now) stop_time = now.replace(hour=self._stop_time.hour, minute=self._stop_time.minute, second=0) if start_time < now < sunset: # Daytime time_state = 'day' temp_range = abs(self._start_colortemp - self._sunset_colortemp) day_length = int(sunset.timestamp() - start_time.timestamp()) seconds_from_start = int(now.timestamp() - start_time.timestamp()) percentage_complete = seconds_from_start / day_length temp_offset = temp_range * percentage_complete if self._start_colortemp > self._sunset_colortemp: temp = self._start_colortemp - temp_offset else: temp = self._start_colortemp + temp_offset else: # Nightime time_state = 'night' if now < stop_time and now > start_time: now_time = now else: now_time = stop_time temp_range = abs(self._sunset_colortemp - self._stop_colortemp) night_length = int(stop_time.timestamp() - sunset.timestamp()) seconds_from_sunset = int(now_time.timestamp() - sunset.timestamp()) percentage_complete = seconds_from_sunset / night_length temp_offset = temp_range * percentage_complete if self._sunset_colortemp > self._stop_colortemp: temp = self._sunset_colortemp - temp_offset else: temp = self._sunset_colortemp + temp_offset x_val, y_val, b_val = color_RGB_to_xy(*color_temperature_to_rgb(temp)) brightness = self._brightness if self._brightness else b_val if self._disable_brightness_adjust: brightness = None if self._mode == MODE_XY: set_lights_xy(self.hass, self._lights, x_val, y_val, brightness) _LOGGER.info("Lights updated to x:%s y:%s brightness:%s, %s%%" " of %s cycle complete at %s", x_val, y_val, brightness, round( percentage_complete * 100), time_state, now) else: # Convert to mired and clamp to allowed values mired = color_temperature_kelvin_to_mired(temp) mired = max(HASS_COLOR_MIN, min(mired, HASS_COLOR_MAX)) set_lights_temp(self.hass, self._lights, mired, brightness) _LOGGER.info("Lights updated to mired:%s brightness:%s, %s%%" " of %s cycle complete at %s", mired, brightness, round(percentage_complete * 100), time_state, now)
def async_turn_on(self, **kwargs): """Turn on light.""" data = {'on': True} if ATTR_COLOR_TEMP in kwargs: data['ct'] = kwargs[ATTR_COLOR_TEMP] if ATTR_RGB_COLOR in kwargs: xyb = color_RGB_to_xy(*(int(val) for val in kwargs[ATTR_RGB_COLOR])) data['xy'] = xyb[0], xyb[1] data['bri'] = xyb[2] if ATTR_BRIGHTNESS in kwargs: data['bri'] = kwargs[ATTR_BRIGHTNESS] if ATTR_TRANSITION in kwargs: data['transitiontime'] = int(kwargs[ATTR_TRANSITION]) * 10 if ATTR_FLASH in kwargs: if kwargs[ATTR_FLASH] == FLASH_SHORT: data['alert'] = 'select' del data['on'] elif kwargs[ATTR_FLASH] == FLASH_LONG: data['alert'] = 'lselect' del data['on'] if ATTR_EFFECT in kwargs: if kwargs[ATTR_EFFECT] == EFFECT_COLORLOOP: data['effect'] = 'colorloop' else: data['effect'] = 'none' yield from self._light.async_set_state(data)
def get_settings( self, is_sleep ) -> Dict[str, Union[float, Tuple[float, float], Tuple[float, float, float]]]: """Get all light settings. Calculating all values takes <0.5ms. """ percent = self.calc_percent() brightness_pct = self.calc_brightness_pct(percent, is_sleep) color_temp_kelvin = self.calc_color_temp_kelvin(percent, is_sleep) color_temp_mired: float = color_temperature_kelvin_to_mired( color_temp_kelvin) rgb_color: Tuple[float, float, float] = color_temperature_to_rgb(color_temp_kelvin) xy_color: Tuple[float, float] = color_RGB_to_xy(*rgb_color) hs_color: Tuple[float, float] = color_xy_to_hs(*xy_color) return { "brightness_pct": brightness_pct, "color_temp_kelvin": color_temp_kelvin, "color_temp_mired": color_temp_mired, "rgb_color": rgb_color, "xy_color": xy_color, "hs_color": hs_color, }
def update_sensor(self): if self._cl.data is not None: self._state = self._cl.data['percent'] self._hs_color = self._cl.data['hs_color'] self._attributes = self._cl.data min_brightness = 30 max_brightness = 100 brightness = int(((max_brightness - min_brightness) * ((100 + self._cl.data['percent']) / 100)) + (min_brightness / 100) * 254) ct = color_temperature_kelvin_to_mired(self._cl.data['colortemp']) rgb = color_temperature_to_rgb(self._cl.data['colortemp']) _LOGGER.debug("RGB values: " + str(rgb)) xy = color_RGB_to_xy(rgb[0], rgb[1], rgb[2]) url = "http://" + hue_gateway + "/api/" + key + "/scenes/" r = requests.get(url).json() scenes = [] for val in r: name = r[val]['name'] if re.match(r"Circadian", name): scenes.append(val) for val in scenes: update_scene_lights(val, brightness, xy[0], xy[1], ct)
def turn_on(self, **kwargs): """Turn the light on.""" transitiontime = int(kwargs.get(ATTR_TRANSITION, 0)) if ATTR_XY_COLOR in kwargs: xycolor = kwargs[ATTR_XY_COLOR] elif ATTR_RGB_COLOR in kwargs: xycolor = color_util.color_RGB_to_xy( *(int(val) for val in kwargs[ATTR_RGB_COLOR])) kwargs.setdefault(ATTR_BRIGHTNESS, xycolor[2]) else: xycolor = None if xycolor is not None: self.device.set_color(xycolor, transition=transitiontime) if ATTR_COLOR_TEMP in kwargs: colortemp = kwargs[ATTR_COLOR_TEMP] self.device.set_temperature(mireds=colortemp, transition=transitiontime) if ATTR_BRIGHTNESS in kwargs: brightness = kwargs.get(ATTR_BRIGHTNESS, self.brightness or 255) self.device.turn_on(level=brightness, transition=transitiontime) else: self.device.turn_on(transition=transitiontime)
def async_api_set_color(hass, config, request, entity): """Process a set color request.""" supported = entity.attributes.get(ATTR_SUPPORTED_FEATURES) rgb = color_util.color_hsb_to_RGB( float(request[API_PAYLOAD]['color']['hue']), float(request[API_PAYLOAD]['color']['saturation']), float(request[API_PAYLOAD]['color']['brightness'])) if supported & light.SUPPORT_RGB_COLOR > 0: yield from hass.services.async_call( entity.domain, SERVICE_TURN_ON, { ATTR_ENTITY_ID: entity.entity_id, light.ATTR_RGB_COLOR: rgb, }, blocking=False) else: xyz = color_util.color_RGB_to_xy(*rgb) yield from hass.services.async_call( entity.domain, SERVICE_TURN_ON, { ATTR_ENTITY_ID: entity.entity_id, light.ATTR_XY_COLOR: (xyz[0], xyz[1]), light.ATTR_BRIGHTNESS: xyz[2], }, blocking=False) return api_message(request)
def rgb_received(topic, payload, qos): """ A new MQTT message has been received. """ self._rgb = [int(val) for val in payload.split(',')] self._xy = color_util.color_RGB_to_xy(int(self._rgb[0]), int(self._rgb[1]), int(self._rgb[2])) self.update_ha_state()
def update(self) -> None: """Update properties from the bulb.""" import yeelight try: self._bulb.get_properties() if self._bulb_device.bulb_type == yeelight.BulbType.Color: self._supported_features = SUPPORT_YEELIGHT_RGB self._is_on = self._properties.get('power') == 'on' bright = self._properties.get('bright', None) if bright: self._brightness = 255 * (int(bright) / 100) temp_in_k = self._properties.get('ct', None) if temp_in_k: self._color_temp = kelvin_to_mired(int(temp_in_k)) self._rgb = self._get_rgb_from_properties() if self._rgb: xyb = color_RGB_to_xy(*self._rgb) self._xy = (xyb[0], xyb[1]) else: self._xy = None self._available = True except yeelight.BulbException as ex: if self._available: # just inform once _LOGGER.error("Unable to update bulb status: %s", ex) self._available = False
def turn_on(self, **kwargs): """Turn the switch on.""" brightness = kwargs.get(ATTR_BRIGHTNESS) rgb_color = kwargs.get(ATTR_RGB_COLOR) color_temp_mired = kwargs.get(ATTR_COLOR_TEMP) state_kwargs = { } if rgb_color: if self.wink.supports_xy_color(): xyb = color_util.color_RGB_to_xy(*rgb_color) state_kwargs['color_xy'] = xyb[0], xyb[1] state_kwargs['brightness'] = xyb[2] if self.wink.supports_hue_saturation(): hsv = colorsys.rgb_to_hsv( rgb_color[0], rgb_color[1], rgb_color[2]) state_kwargs['color_hue_saturation'] = hsv[0], hsv[1] if color_temp_mired: state_kwargs['color_kelvin'] = mired_to_kelvin(color_temp_mired) if brightness: state_kwargs['brightness'] = brightness / 255.0 self.wink.set_state(True, **state_kwargs)
def calc_xy(self): rgb = self.calc_rgb() iR = rgb[0] iG = rgb[1] iB = rgb[2] return color_RGB_to_xy(iR, iG, iB)
def flux_update(self, now=None): """Update all the lights using flux.""" if now is None: now = dt_now() sunset = next_setting(self.hass, SUN).replace(day=now.day, month=now.month, year=now.year) start_time = self.find_start_time(now) stop_time = now.replace(hour=self._stop_time.hour, minute=self._stop_time.minute, second=0) if start_time < now < sunset: # Daytime time_state = 'day' temp_range = abs(self._start_colortemp - self._sunset_colortemp) day_length = int(sunset.timestamp() - start_time.timestamp()) seconds_from_start = int(now.timestamp() - start_time.timestamp()) percentage_complete = seconds_from_start / day_length temp_offset = temp_range * percentage_complete if self._start_colortemp > self._sunset_colortemp: temp = self._start_colortemp - temp_offset else: temp = self._start_colortemp + temp_offset else: # Nightime time_state = 'night' if now < stop_time and now > start_time: now_time = now else: now_time = stop_time temp_range = abs(self._sunset_colortemp - self._stop_colortemp) night_length = int(stop_time.timestamp() - sunset.timestamp()) seconds_from_sunset = int(now_time.timestamp() - sunset.timestamp()) percentage_complete = seconds_from_sunset / night_length temp_offset = temp_range * percentage_complete if self._sunset_colortemp > self._stop_colortemp: temp = self._sunset_colortemp - temp_offset else: temp = self._sunset_colortemp + temp_offset x_val, y_val, b_val = color_RGB_to_xy(*color_temperature_to_rgb(temp)) brightness = self._brightness if self._brightness else b_val if self._mode == MODE_XY: set_lights_xy(self.hass, self._lights, x_val, y_val, brightness) _LOGGER.info("Lights updated to x:%s y:%s brightness:%s, %s%%" " of %s cycle complete at %s", x_val, y_val, brightness, round( percentage_complete * 100), time_state, as_local(now)) else: # Convert to mired and clamp to allowed values mired = color_temperature_kelvin_to_mired(temp) mired = max(HASS_COLOR_MIN, min(mired, HASS_COLOR_MAX)) set_lights_temp(self.hass, self._lights, mired, brightness) _LOGGER.info("Lights updated to mired:%s brightness:%s, %s%%" " of %s cycle complete at %s", mired, brightness, round(percentage_complete * 100), time_state, as_local(now))
def turn_on(self, **kwargs): """Turn the specified or all lights on.""" command = {'on': True} if ATTR_TRANSITION in kwargs: command['transitiontime'] = int(kwargs[ATTR_TRANSITION] * 10) if ATTR_XY_COLOR in kwargs: if self.info.get('manufacturername') == "OSRAM": hsv = color_util.color_xy_brightness_to_hsv( *kwargs[ATTR_XY_COLOR], ibrightness=self.info['bri']) command['hue'] = hsv[0] command['sat'] = hsv[1] command['bri'] = hsv[2] else: command['xy'] = kwargs[ATTR_XY_COLOR] elif ATTR_RGB_COLOR in kwargs: if self.info.get('manufacturername') == "OSRAM": hsv = color_util.color_RGB_to_hsv( *(int(val) for val in kwargs[ATTR_RGB_COLOR])) command['hue'] = hsv[0] command['sat'] = hsv[1] command['bri'] = hsv[2] else: xyb = color_util.color_RGB_to_xy( *(int(val) for val in kwargs[ATTR_RGB_COLOR])) command['xy'] = xyb[0], xyb[1] command['bri'] = xyb[2] if ATTR_BRIGHTNESS in kwargs: command['bri'] = kwargs[ATTR_BRIGHTNESS] if ATTR_COLOR_TEMP in kwargs: command['ct'] = kwargs[ATTR_COLOR_TEMP] flash = kwargs.get(ATTR_FLASH) if flash == FLASH_LONG: command['alert'] = 'lselect' del command['on'] elif flash == FLASH_SHORT: command['alert'] = 'select' del command['on'] elif self.bridge_type == 'hue': command['alert'] = 'none' effect = kwargs.get(ATTR_EFFECT) if effect == EFFECT_COLORLOOP: command['effect'] = 'colorloop' elif effect == EFFECT_RANDOM: command['hue'] = random.randrange(0, 65535) command['sat'] = random.randrange(150, 254) elif self.bridge_type == 'hue': if self.info.get('manufacturername') != "OSRAM": command['effect'] = 'none' self._command_func(self.light_id, command)
def color_xy(self): """ XY color value. """ self._rgb_color = self._light.rgb() r = self._rgb_color[0] g = self._rgb_color[1] b = self._rgb_color[2] self._xy = color_RGB_to_xy(r,g,b) return self._xy
def turn_on(self, **kwargs): """Turn the specified or all lights on.""" command = {'on': True} if ATTR_TRANSITION in kwargs: command['transitiontime'] = int(kwargs[ATTR_TRANSITION] * 10) if ATTR_XY_COLOR in kwargs: if self.info.get('manufacturername') == 'OSRAM': color_hue, sat = color_util.color_xy_to_hs( *kwargs[ATTR_XY_COLOR]) command['hue'] = color_hue / 360 * 65535 command['sat'] = sat / 100 * 255 else: command['xy'] = kwargs[ATTR_XY_COLOR] elif ATTR_RGB_COLOR in kwargs: if self.info.get('manufacturername') == 'OSRAM': hsv = color_util.color_RGB_to_hsv( *(int(val) for val in kwargs[ATTR_RGB_COLOR])) command['hue'] = hsv[0] / 360 * 65535 command['sat'] = hsv[1] / 100 * 255 command['bri'] = hsv[2] / 100 * 255 else: xyb = color_util.color_RGB_to_xy( *(int(val) for val in kwargs[ATTR_RGB_COLOR])) command['xy'] = xyb[0], xyb[1] elif ATTR_COLOR_TEMP in kwargs: temp = kwargs[ATTR_COLOR_TEMP] command['ct'] = max(self.min_mireds, min(temp, self.max_mireds)) if ATTR_BRIGHTNESS in kwargs: command['bri'] = kwargs[ATTR_BRIGHTNESS] flash = kwargs.get(ATTR_FLASH) if flash == FLASH_LONG: command['alert'] = 'lselect' del command['on'] elif flash == FLASH_SHORT: command['alert'] = 'select' del command['on'] else: command['alert'] = 'none' effect = kwargs.get(ATTR_EFFECT) if effect == EFFECT_COLORLOOP: command['effect'] = 'colorloop' elif effect == EFFECT_RANDOM: command['hue'] = random.randrange(0, 65535) command['sat'] = random.randrange(150, 254) elif self.info.get('manufacturername') == 'Philips': command['effect'] = 'none' self._command_func(self.light_id, command)
def __init__(self, addr, light, name, state, rgb_color, brightness, xy=None): self._light = light self._addr = addr self._name = name self._state = state self._rgb_color = rgb_color r = self._rgb_color[0] g = self._rgb_color[1] b = self._rgb_color[2] self._xy = color_RGB_to_xy(r,g,b) self._brightness = brightness
async def _update_attrs(self): """Update Adaptive Values.""" # Setting all values because this method takes <0.5ms to execute. self._percent = self._calc_percent() self._brightness = self._calc_brightness() self._color_temp_kelvin = self._calc_color_temp_kelvin() self._color_temp_mired = color_temperature_kelvin_to_mired( self._color_temp_kelvin) self._rgb_color = color_temperature_to_rgb(self._color_temp_kelvin) self._xy_color = color_RGB_to_xy(*self._rgb_color) self._hs_color = color_xy_to_hs(*self._xy_color) self.async_write_ha_state() _LOGGER.debug("'_update_attrs' called for %s", self._name)
def turn_on(self, **kwargs): """Turn the switch on.""" brightness = kwargs.get(ATTR_BRIGHTNESS) rgb_color = kwargs.get(ATTR_RGB_COLOR) color_temp_mired = kwargs.get(ATTR_COLOR_TEMP) state_kwargs = {} if rgb_color: state_kwargs['color_xy'] = color_util.color_RGB_to_xy(*rgb_color) if color_temp_mired: state_kwargs['color_kelvin'] = mired_to_kelvin(color_temp_mired) if brightness: state_kwargs['brightness'] = brightness / 255.0 self.wink.set_state(True, **state_kwargs)
def test_color_RGB_to_xy(self): """Test color_RGB_to_xy.""" self.assertEqual((0, 0), color_util.color_RGB_to_xy(0, 0, 0)) self.assertEqual((0.32, 0.336), color_util.color_RGB_to_xy(255, 255, 255)) self.assertEqual((0.136, 0.04), color_util.color_RGB_to_xy(0, 0, 255)) self.assertEqual((0.172, 0.747), color_util.color_RGB_to_xy(0, 255, 0)) self.assertEqual((0.679, 0.321), color_util.color_RGB_to_xy(255, 0, 0)) self.assertEqual((0.679, 0.321), color_util.color_RGB_to_xy(128, 0, 0))
def turn_on(self, **kwargs): """Turn the specified or all lights on.""" command = {'on': True} if ATTR_TRANSITION in kwargs: command['transitiontime'] = kwargs[ATTR_TRANSITION] * 10 if ATTR_XY_COLOR in kwargs: command['xy'] = kwargs[ATTR_XY_COLOR] elif ATTR_RGB_COLOR in kwargs: xyb = color_util.color_RGB_to_xy( *(int(val) for val in kwargs[ATTR_RGB_COLOR])) command['xy'] = xyb[0], xyb[1] command['bri'] = xyb[2] if ATTR_BRIGHTNESS in kwargs: command['bri'] = kwargs[ATTR_BRIGHTNESS] if ATTR_COLOR_TEMP in kwargs: command['ct'] = kwargs[ATTR_COLOR_TEMP] flash = kwargs.get(ATTR_FLASH) if flash == FLASH_LONG: command['alert'] = 'lselect' del command['on'] elif flash == FLASH_SHORT: command['alert'] = 'select' del command['on'] elif self.bridge_type == 'hue': command['alert'] = 'none' effect = kwargs.get(ATTR_EFFECT) if effect == EFFECT_COLORLOOP: command['effect'] = 'colorloop' elif effect == EFFECT_RANDOM: command['hue'] = random.randrange(0, 65535) command['sat'] = random.randrange(150, 254) elif self.bridge_type == 'hue': command['effect'] = 'none' self.bridge.set_light(self.light_id, command)
def turn_on(self, **kwargs): """Turn the switch on.""" brightness = kwargs.get(ATTR_BRIGHTNESS) rgb_color = kwargs.get(ATTR_RGB_COLOR) color_temp_mired = kwargs.get(ATTR_COLOR_TEMP) state_kwargs = { } if rgb_color: state_kwargs['color_xy'] = color_util.color_RGB_to_xy(*rgb_color) if color_temp_mired: state_kwargs['color_kelvin'] = mired_to_kelvin(color_temp_mired) if brightness: state_kwargs['brightness'] = brightness / 255.0 self.wink.set_state(True, **state_kwargs)
def turn_on(self, **kwargs): """Turn the specified or all lights on.""" command = {"on": True} if ATTR_TRANSITION in kwargs: command["transitiontime"] = kwargs[ATTR_TRANSITION] * 10 if ATTR_XY_COLOR in kwargs: command["xy"] = kwargs[ATTR_XY_COLOR] elif ATTR_RGB_COLOR in kwargs: xyb = color_util.color_RGB_to_xy(*(int(val) for val in kwargs[ATTR_RGB_COLOR])) command["xy"] = xyb[0], xyb[1] command["bri"] = xyb[2] if ATTR_BRIGHTNESS in kwargs: command["bri"] = kwargs[ATTR_BRIGHTNESS] if ATTR_COLOR_TEMP in kwargs: command["ct"] = kwargs[ATTR_COLOR_TEMP] flash = kwargs.get(ATTR_FLASH) if flash == FLASH_LONG: command["alert"] = "lselect" del command["on"] elif flash == FLASH_SHORT: command["alert"] = "select" del command["on"] elif self.bridge_type == "hue": command["alert"] = "none" effect = kwargs.get(ATTR_EFFECT) if effect == EFFECT_COLORLOOP: command["effect"] = "colorloop" elif effect == EFFECT_RANDOM: command["hue"] = random.randrange(0, 65535) command["sat"] = random.randrange(150, 254) elif self.bridge_type == "hue": command["effect"] = "none" self.bridge.set_light(self.light_id, command)
def async_turn_on(self, **kwargs): """Turn the entity on.""" duration = kwargs.get(light.ATTR_TRANSITION, DEFAULT_DURATION) duration = duration * 10 # tenths of s if light.ATTR_COLOR_TEMP in kwargs: temperature = kwargs[light.ATTR_COLOR_TEMP] yield from self._endpoint.light_color.move_to_color_temp( temperature, duration) self._color_temp = temperature if light.ATTR_XY_COLOR in kwargs: self._xy_color = kwargs[light.ATTR_XY_COLOR] elif light.ATTR_RGB_COLOR in kwargs: xyb = color_RGB_to_xy( *(int(val) for val in kwargs[light.ATTR_RGB_COLOR])) self._xy_color = (xyb[0], xyb[1]) self._brightness = xyb[2] if light.ATTR_XY_COLOR in kwargs or light.ATTR_RGB_COLOR in kwargs: yield from self._endpoint.light_color.move_to_color( int(self._xy_color[0] * 65535), int(self._xy_color[1] * 65535), duration, ) if self._brightness is not None: brightness = kwargs.get( light.ATTR_BRIGHTNESS, self._brightness or 255) self._brightness = brightness # Move to level with on/off: yield from self._endpoint.level.move_to_level_with_on_off( brightness, duration ) self._state = 1 self.async_schedule_update_ha_state() return yield from self._endpoint.on_off.on() self._state = 1 self.async_schedule_update_ha_state()
def async_turn_on(self, **kwargs): """Turn the entity on.""" duration = kwargs.get(light.ATTR_TRANSITION, DEFAULT_DURATION) duration = duration * 10 # tenths of s if light.ATTR_COLOR_TEMP in kwargs: temperature = kwargs[light.ATTR_COLOR_TEMP] yield from self._endpoint.light_color.move_to_color_temp( temperature, duration) self._color_temp = temperature if light.ATTR_XY_COLOR in kwargs: self._xy_color = kwargs[light.ATTR_XY_COLOR] elif light.ATTR_RGB_COLOR in kwargs: xyb = color_RGB_to_xy(*(int(val) for val in kwargs[light.ATTR_RGB_COLOR])) self._xy_color = (xyb[0], xyb[1]) self._brightness = xyb[2] if light.ATTR_XY_COLOR in kwargs or light.ATTR_RGB_COLOR in kwargs: yield from self._endpoint.light_color.move_to_color( int(self._xy_color[0] * 65535), int(self._xy_color[1] * 65535), duration, ) if self._brightness is not None: brightness = kwargs.get(light.ATTR_BRIGHTNESS, self._brightness or 255) self._brightness = brightness # Move to level with on/off: yield from self._endpoint.level.move_to_level_with_on_off( brightness, duration) self._state = 1 self.hass.async_add_job(self.async_update_ha_state()) return yield from self._endpoint.on_off.on() self._state = 1 self.hass.async_add_job(self.async_update_ha_state())
def turn_on(self, **kwargs): """ Turn the specified or all lights on. """ command = {'on': True} if ATTR_TRANSITION in kwargs: # Transition time is in 1/10th seconds and cannot exceed # 900 seconds. command['transitiontime'] = min(9000, kwargs[ATTR_TRANSITION] * 10) if ATTR_BRIGHTNESS in kwargs: command['bri'] = kwargs[ATTR_BRIGHTNESS] if ATTR_XY_COLOR in kwargs: command['xy'] = kwargs[ATTR_XY_COLOR] elif ATTR_RGB_COLOR in kwargs: command['xy'] = color_util.color_RGB_to_xy( *(int(val) for val in kwargs[ATTR_RGB_COLOR])) if ATTR_COLOR_TEMP in kwargs: command['ct'] = kwargs[ATTR_COLOR_TEMP] flash = kwargs.get(ATTR_FLASH) if flash == FLASH_LONG: command['alert'] = 'lselect' elif flash == FLASH_SHORT: command['alert'] = 'select' else: command['alert'] = 'none' effect = kwargs.get(ATTR_EFFECT) if effect == EFFECT_COLORLOOP: command['effect'] = 'colorloop' else: command['effect'] = 'none' self.bridge.set_light(self.light_id, command)
def async_api_set_color(hass, config, request, entity): """Process a set color request.""" supported = entity.attributes.get(ATTR_SUPPORTED_FEATURES) rgb = color_util.color_hsb_to_RGB( float(request[API_PAYLOAD]['color']['hue']), float(request[API_PAYLOAD]['color']['saturation']), float(request[API_PAYLOAD]['color']['brightness']) ) if supported & light.SUPPORT_RGB_COLOR > 0: yield from hass.services.async_call(entity.domain, SERVICE_TURN_ON, { ATTR_ENTITY_ID: entity.entity_id, light.ATTR_RGB_COLOR: rgb, }, blocking=False) else: xyz = color_util.color_RGB_to_xy(*rgb) yield from hass.services.async_call(entity.domain, SERVICE_TURN_ON, { ATTR_ENTITY_ID: entity.entity_id, light.ATTR_XY_COLOR: (xyz[0], xyz[1]), light.ATTR_BRIGHTNESS: xyz[2], }, blocking=False) return api_message(request)
def async_turn_on(self, **kwargs): """Turn on light.""" data = {'on': True} if ATTR_COLOR_TEMP in kwargs: data['ct'] = kwargs[ATTR_COLOR_TEMP] if ATTR_RGB_COLOR in kwargs: xyb = color_RGB_to_xy( *(int(val) for val in kwargs[ATTR_RGB_COLOR])) data['xy'] = xyb[0], xyb[1] data['bri'] = xyb[2] if ATTR_XY_COLOR in kwargs: data['xy'] = kwargs[ATTR_XY_COLOR] if ATTR_BRIGHTNESS in kwargs: data['bri'] = kwargs[ATTR_BRIGHTNESS] if ATTR_TRANSITION in kwargs: data['transitiontime'] = int(kwargs[ATTR_TRANSITION]) * 10 if ATTR_FLASH in kwargs: if kwargs[ATTR_FLASH] == FLASH_SHORT: data['alert'] = 'select' del data['on'] elif kwargs[ATTR_FLASH] == FLASH_LONG: data['alert'] = 'lselect' del data['on'] if ATTR_EFFECT in kwargs: if kwargs[ATTR_EFFECT] == EFFECT_COLORLOOP: data['effect'] = 'colorloop' else: data['effect'] = 'none' yield from self._light.async_set_state(data)
def test_color_RGB_to_xy(self): """Test color_RGB_to_xy.""" self.assertEqual((0, 0), color_util.color_RGB_to_xy(0, 0, 0)) self.assertEqual((0.323, 0.329), color_util.color_RGB_to_xy(255, 255, 255)) self.assertEqual((0.136, 0.04), color_util.color_RGB_to_xy(0, 0, 255)) self.assertEqual((0.172, 0.747), color_util.color_RGB_to_xy(0, 255, 0)) self.assertEqual((0.701, 0.299), color_util.color_RGB_to_xy(255, 0, 0)) self.assertEqual((0.701, 0.299), color_util.color_RGB_to_xy(128, 0, 0))
def test_services(self): """ Test the provided services. """ platform = loader.get_component('light.test') platform.init() self.assertTrue( light.setup(self.hass, {light.DOMAIN: { CONF_PLATFORM: 'test' }})) dev1, dev2, dev3 = platform.DEVICES # Test init self.assertTrue(light.is_on(self.hass, dev1.entity_id)) self.assertFalse(light.is_on(self.hass, dev2.entity_id)) self.assertFalse(light.is_on(self.hass, dev3.entity_id)) # Test basic turn_on, turn_off services light.turn_off(self.hass, entity_id=dev1.entity_id) light.turn_on(self.hass, entity_id=dev2.entity_id) self.hass.pool.block_till_done() self.assertFalse(light.is_on(self.hass, dev1.entity_id)) self.assertTrue(light.is_on(self.hass, dev2.entity_id)) # turn on all lights light.turn_on(self.hass) self.hass.pool.block_till_done() self.assertTrue(light.is_on(self.hass, dev1.entity_id)) self.assertTrue(light.is_on(self.hass, dev2.entity_id)) self.assertTrue(light.is_on(self.hass, dev3.entity_id)) # turn off all lights light.turn_off(self.hass) self.hass.pool.block_till_done() self.assertFalse(light.is_on(self.hass, dev1.entity_id)) self.assertFalse(light.is_on(self.hass, dev2.entity_id)) self.assertFalse(light.is_on(self.hass, dev3.entity_id)) # Ensure all attributes process correctly light.turn_on(self.hass, dev1.entity_id, transition=10, brightness=20) light.turn_on(self.hass, dev2.entity_id, rgb_color=[255, 255, 255]) light.turn_on(self.hass, dev3.entity_id, xy_color=[.4, .6]) self.hass.pool.block_till_done() method, data = dev1.last_call('turn_on') self.assertEqual({ light.ATTR_TRANSITION: 10, light.ATTR_BRIGHTNESS: 20 }, data) method, data = dev2.last_call('turn_on') self.assertEqual( {light.ATTR_XY_COLOR: color_util.color_RGB_to_xy(255, 255, 255)}, data) method, data = dev3.last_call('turn_on') self.assertEqual({light.ATTR_XY_COLOR: [.4, .6]}, data) # One of the light profiles prof_name, prof_x, prof_y, prof_bri = 'relax', 0.5119, 0.4147, 144 # Test light profiles light.turn_on(self.hass, dev1.entity_id, profile=prof_name) # Specify a profile and attributes to overwrite it light.turn_on(self.hass, dev2.entity_id, profile=prof_name, brightness=100, xy_color=[.4, .6]) self.hass.pool.block_till_done() method, data = dev1.last_call('turn_on') self.assertEqual( { light.ATTR_BRIGHTNESS: prof_bri, light.ATTR_XY_COLOR: [prof_x, prof_y] }, data) method, data = dev2.last_call('turn_on') self.assertEqual( { light.ATTR_BRIGHTNESS: 100, light.ATTR_XY_COLOR: [.4, .6] }, data) # Test shitty data light.turn_on(self.hass, dev1.entity_id, profile="nonexisting") light.turn_on(self.hass, dev2.entity_id, xy_color=["bla-di-bla", 5]) light.turn_on(self.hass, dev3.entity_id, rgb_color=[255, None, 2]) self.hass.pool.block_till_done() method, data = dev1.last_call('turn_on') self.assertEqual({}, data) method, data = dev2.last_call('turn_on') self.assertEqual({}, data) method, data = dev3.last_call('turn_on') self.assertEqual({}, data) # faulty attributes should not overwrite profile data light.turn_on(self.hass, dev1.entity_id, profile=prof_name, brightness='bright', rgb_color='yellowish') self.hass.pool.block_till_done() method, data = dev1.last_call('turn_on') self.assertEqual( { light.ATTR_BRIGHTNESS: prof_bri, light.ATTR_XY_COLOR: [prof_x, prof_y] }, data)
def flux_update(self, now=None): """Update all the lights using flux.""" if now is None: now = dt_now() sunset = get_astral_event_date(self.hass, 'sunset', now.date()) start_time = self.find_start_time(now) stop_time = now.replace( hour=self._stop_time.hour, minute=self._stop_time.minute, second=0) if stop_time <= start_time: # stop_time does not happen in the same day as start_time if start_time < now: # stop time is tomorrow stop_time += datetime.timedelta(days=1) elif now < start_time: # stop_time was yesterday since the new start_time is not reached stop_time -= datetime.timedelta(days=1) if start_time < now < sunset: # Daytime time_state = 'day' temp_range = abs(self._start_colortemp - self._sunset_colortemp) day_length = int(sunset.timestamp() - start_time.timestamp()) seconds_from_start = int(now.timestamp() - start_time.timestamp()) percentage_complete = seconds_from_start / day_length temp_offset = temp_range * percentage_complete if self._start_colortemp > self._sunset_colortemp: temp = self._start_colortemp - temp_offset else: temp = self._start_colortemp + temp_offset else: # Nightime time_state = 'night' if now < stop_time: if stop_time < start_time and stop_time.day == sunset.day: # we need to use yesterday's sunset time sunset_time = sunset - datetime.timedelta(days=1) else: sunset_time = sunset # pylint: disable=no-member night_length = int(stop_time.timestamp() - sunset_time.timestamp()) seconds_from_sunset = int(now.timestamp() - sunset_time.timestamp()) percentage_complete = seconds_from_sunset / night_length else: percentage_complete = 1 temp_range = abs(self._sunset_colortemp - self._stop_colortemp) temp_offset = temp_range * percentage_complete if self._sunset_colortemp > self._stop_colortemp: temp = self._sunset_colortemp - temp_offset else: temp = self._sunset_colortemp + temp_offset rgb = color_temperature_to_rgb(temp) x_val, y_val, b_val = color_RGB_to_xy(*rgb) brightness = self._brightness if self._brightness else b_val if self._disable_brightness_adjust: brightness = None if self._mode == MODE_XY: set_lights_xy(self.hass, self._lights, x_val, y_val, brightness) _LOGGER.info("Lights updated to x:%s y:%s brightness:%s, %s%% " "of %s cycle complete at %s", x_val, y_val, brightness, round( percentage_complete * 100), time_state, now) elif self._mode == MODE_RGB: set_lights_rgb(self.hass, self._lights, rgb) _LOGGER.info("Lights updated to rgb:%s, %s%% " "of %s cycle complete at %s", rgb, round(percentage_complete * 100), time_state, now) else: # Convert to mired and clamp to allowed values mired = color_temperature_kelvin_to_mired(temp) set_lights_temp(self.hass, self._lights, mired, brightness) _LOGGER.info("Lights updated to mired:%s brightness:%s, %s%% " "of %s cycle complete at %s", mired, brightness, round(percentage_complete * 100), time_state, now)
def handle_light_service(service): """ Hande a turn light on or off service call. """ # Get and validate data dat = service.data # Convert the entity ids to valid light ids target_lights = component.extract_from_service(service) params = {} transition = util.convert(dat.get(ATTR_TRANSITION), int) if transition is not None: params[ATTR_TRANSITION] = transition if service.service == SERVICE_TURN_OFF: for light in target_lights: light.turn_off(**params) for light in target_lights: if light.should_poll: light.update_ha_state(True) return # Processing extra data for turn light on request # We process the profile first so that we get the desired # behavior that extra service data attributes overwrite # profile values profile = profiles.get(dat.get(ATTR_PROFILE)) if profile: *params[ATTR_XY_COLOR], params[ATTR_BRIGHTNESS] = profile if ATTR_BRIGHTNESS in dat: # We pass in the old value as the default parameter if parsing # of the new one goes wrong. params[ATTR_BRIGHTNESS] = util.convert( dat.get(ATTR_BRIGHTNESS), int, params.get(ATTR_BRIGHTNESS)) if ATTR_XY_COLOR in dat: try: # xy_color should be a list containing 2 floats xycolor = dat.get(ATTR_XY_COLOR) # Without this check, a xycolor with value '99' would work if not isinstance(xycolor, str): params[ATTR_XY_COLOR] = [float(val) for val in xycolor] except (TypeError, ValueError): # TypeError if xy_color is not iterable # ValueError if value could not be converted to float pass if ATTR_RGB_COLOR in dat: try: # rgb_color should be a list containing 3 ints rgb_color = dat.get(ATTR_RGB_COLOR) if len(rgb_color) == 3: params[ATTR_XY_COLOR] = \ color_util.color_RGB_to_xy(int(rgb_color[0]), int(rgb_color[1]), int(rgb_color[2])) except (TypeError, ValueError): # TypeError if rgb_color is not iterable # ValueError if not all values can be converted to int pass if ATTR_FLASH in dat: if dat[ATTR_FLASH] == FLASH_SHORT: params[ATTR_FLASH] = FLASH_SHORT elif dat[ATTR_FLASH] == FLASH_LONG: params[ATTR_FLASH] = FLASH_LONG if ATTR_EFFECT in dat: if dat[ATTR_EFFECT] == EFFECT_COLORLOOP: params[ATTR_EFFECT] = EFFECT_COLORLOOP for light in target_lights: light.turn_on(**params) for light in target_lights: if light.should_poll: light.update_ha_state(True)
params[ATTR_RGBWW_COLOR] = color_util.color_rgb_to_rgbww( *rgb_color, light.min_mireds, light.max_mireds) elif ColorMode.XY in supported_color_modes: params[ATTR_XY_COLOR] = color_util.color_hs_to_xy(*hs_color) elif ATTR_RGB_COLOR in params and ColorMode.RGB not in supported_color_modes: rgb_color = params.pop(ATTR_RGB_COLOR) if ColorMode.RGBW in supported_color_modes: params[ATTR_RGBW_COLOR] = color_util.color_rgb_to_rgbw( *rgb_color) elif ColorMode.RGBWW in supported_color_modes: params[ATTR_RGBWW_COLOR] = color_util.color_rgb_to_rgbww( *rgb_color, light.min_mireds, light.max_mireds) elif ColorMode.HS in supported_color_modes: params[ATTR_HS_COLOR] = color_util.color_RGB_to_hs(*rgb_color) elif ColorMode.XY in supported_color_modes: params[ATTR_XY_COLOR] = color_util.color_RGB_to_xy(*rgb_color) elif ATTR_XY_COLOR in params and ColorMode.XY not in supported_color_modes: xy_color = params.pop(ATTR_XY_COLOR) if ColorMode.HS in supported_color_modes: params[ATTR_HS_COLOR] = color_util.color_xy_to_hs(*xy_color) elif ColorMode.RGB in supported_color_modes: params[ATTR_RGB_COLOR] = color_util.color_xy_to_RGB(*xy_color) elif ColorMode.RGBW in supported_color_modes: rgb_color = color_util.color_xy_to_RGB(*xy_color) params[ATTR_RGBW_COLOR] = color_util.color_rgb_to_rgbw( *rgb_color) elif ColorMode.RGBWW in supported_color_modes: rgb_color = color_util.color_xy_to_RGB(*xy_color) params[ATTR_RGBWW_COLOR] = color_util.color_rgb_to_rgbww( *rgb_color, light.min_mireds, light.max_mireds) elif ATTR_RGBW_COLOR in params and ColorMode.RGBW not in supported_color_modes:
def test_services(self): """ Test the provided services. """ platform = loader.get_component('light.test') platform.init() self.assertTrue( light.setup(self.hass, {light.DOMAIN: {CONF_PLATFORM: 'test'}})) dev1, dev2, dev3 = platform.DEVICES # Test init self.assertTrue(light.is_on(self.hass, dev1.entity_id)) self.assertFalse(light.is_on(self.hass, dev2.entity_id)) self.assertFalse(light.is_on(self.hass, dev3.entity_id)) # Test basic turn_on, turn_off services light.turn_off(self.hass, entity_id=dev1.entity_id) light.turn_on(self.hass, entity_id=dev2.entity_id) self.hass.pool.block_till_done() self.assertFalse(light.is_on(self.hass, dev1.entity_id)) self.assertTrue(light.is_on(self.hass, dev2.entity_id)) # turn on all lights light.turn_on(self.hass) self.hass.pool.block_till_done() self.assertTrue(light.is_on(self.hass, dev1.entity_id)) self.assertTrue(light.is_on(self.hass, dev2.entity_id)) self.assertTrue(light.is_on(self.hass, dev3.entity_id)) # turn off all lights light.turn_off(self.hass) self.hass.pool.block_till_done() self.assertFalse(light.is_on(self.hass, dev1.entity_id)) self.assertFalse(light.is_on(self.hass, dev2.entity_id)) self.assertFalse(light.is_on(self.hass, dev3.entity_id)) # Ensure all attributes process correctly light.turn_on(self.hass, dev1.entity_id, transition=10, brightness=20) light.turn_on( self.hass, dev2.entity_id, rgb_color=[255, 255, 255]) light.turn_on(self.hass, dev3.entity_id, xy_color=[.4, .6]) self.hass.pool.block_till_done() method, data = dev1.last_call('turn_on') self.assertEqual( {light.ATTR_TRANSITION: 10, light.ATTR_BRIGHTNESS: 20}, data) method, data = dev2.last_call('turn_on') self.assertEqual( {light.ATTR_XY_COLOR: color_util.color_RGB_to_xy(255, 255, 255)}, data) method, data = dev3.last_call('turn_on') self.assertEqual({light.ATTR_XY_COLOR: [.4, .6]}, data) # One of the light profiles prof_name, prof_x, prof_y, prof_bri = 'relax', 0.5119, 0.4147, 144 # Test light profiles light.turn_on(self.hass, dev1.entity_id, profile=prof_name) # Specify a profile and attributes to overwrite it light.turn_on( self.hass, dev2.entity_id, profile=prof_name, brightness=100, xy_color=[.4, .6]) self.hass.pool.block_till_done() method, data = dev1.last_call('turn_on') self.assertEqual( {light.ATTR_BRIGHTNESS: prof_bri, light.ATTR_XY_COLOR: [prof_x, prof_y]}, data) method, data = dev2.last_call('turn_on') self.assertEqual( {light.ATTR_BRIGHTNESS: 100, light.ATTR_XY_COLOR: [.4, .6]}, data) # Test shitty data light.turn_on(self.hass, dev1.entity_id, profile="nonexisting") light.turn_on(self.hass, dev2.entity_id, xy_color=["bla-di-bla", 5]) light.turn_on(self.hass, dev3.entity_id, rgb_color=[255, None, 2]) self.hass.pool.block_till_done() method, data = dev1.last_call('turn_on') self.assertEqual({}, data) method, data = dev2.last_call('turn_on') self.assertEqual({}, data) method, data = dev3.last_call('turn_on') self.assertEqual({}, data) # faulty attributes should not overwrite profile data light.turn_on( self.hass, dev1.entity_id, profile=prof_name, brightness='bright', rgb_color='yellowish') self.hass.pool.block_till_done() method, data = dev1.last_call('turn_on') self.assertEqual( {light.ATTR_BRIGHTNESS: prof_bri, light.ATTR_XY_COLOR: [prof_x, prof_y]}, data)
def flux_update(self, now=None): """Update all the lights using flux.""" if now is None: now = dt_now() sunset = get_astral_event_date(self.hass, 'sunset', now.date()) start_time = self.find_start_time(now) stop_time = now.replace(hour=self._stop_time.hour, minute=self._stop_time.minute, second=0) if stop_time <= start_time: # stop_time does not happen in the same day as start_time if start_time < now: # stop time is tomorrow stop_time += datetime.timedelta(days=1) elif now < start_time: # stop_time was yesterday since the new start_time is not reached stop_time -= datetime.timedelta(days=1) if start_time < now < sunset: # Daytime time_state = 'day' temp_range = abs(self._start_colortemp - self._sunset_colortemp) day_length = int(sunset.timestamp() - start_time.timestamp()) seconds_from_start = int(now.timestamp() - start_time.timestamp()) percentage_complete = seconds_from_start / day_length temp_offset = temp_range * percentage_complete if self._start_colortemp > self._sunset_colortemp: temp = self._start_colortemp - temp_offset else: temp = self._start_colortemp + temp_offset else: # Nightime time_state = 'night' if now < stop_time: if stop_time < start_time and stop_time.day == sunset.day: # we need to use yesterday's sunset time sunset_time = sunset - datetime.timedelta(days=1) else: sunset_time = sunset # pylint: disable=no-member night_length = int(stop_time.timestamp() - sunset_time.timestamp()) seconds_from_sunset = int(now.timestamp() - sunset_time.timestamp()) percentage_complete = seconds_from_sunset / night_length else: percentage_complete = 1 temp_range = abs(self._sunset_colortemp - self._stop_colortemp) temp_offset = temp_range * percentage_complete if self._sunset_colortemp > self._stop_colortemp: temp = self._sunset_colortemp - temp_offset else: temp = self._sunset_colortemp + temp_offset rgb = color_temperature_to_rgb(temp) x_val, y_val, b_val = color_RGB_to_xy(*rgb) brightness = self._brightness if self._brightness else b_val if self._disable_brightness_adjust: brightness = None if self._mode == MODE_XY: set_lights_xy(self.hass, self._lights, x_val, y_val, brightness) _LOGGER.info( "Lights updated to x:%s y:%s brightness:%s, %s%% " "of %s cycle complete at %s", x_val, y_val, brightness, round(percentage_complete * 100), time_state, now) elif self._mode == MODE_RGB: set_lights_rgb(self.hass, self._lights, rgb) _LOGGER.info( "Lights updated to rgb:%s, %s%% " "of %s cycle complete at %s", rgb, round(percentage_complete * 100), time_state, now) else: # Convert to mired and clamp to allowed values mired = color_temperature_kelvin_to_mired(temp) set_lights_temp(self.hass, self._lights, mired, brightness) _LOGGER.info( "Lights updated to mired:%s brightness:%s, %s%% " "of %s cycle complete at %s", mired, brightness, round(percentage_complete * 100), time_state, now)
async def test_device_types(hass: HomeAssistant): """Test different device types.""" properties = {**PROPERTIES} properties.pop("active_mode") properties["color_mode"] = "3" def _create_mocked_bulb(bulb_type, model, unique_id): capabilities = {**CAPABILITIES} capabilities["id"] = f"yeelight.{unique_id}" mocked_bulb = _mocked_bulb() mocked_bulb.bulb_type = bulb_type mocked_bulb.last_properties = properties mocked_bulb.capabilities = capabilities model_specs = _MODEL_SPECS.get(model) type(mocked_bulb).get_model_specs = MagicMock(return_value=model_specs) return mocked_bulb types = { "default": (None, "mono"), "white": (BulbType.White, "mono"), "color": (BulbType.Color, "color"), "white_temp": (BulbType.WhiteTemp, "ceiling1"), "white_temp_mood": (BulbType.WhiteTempMood, "ceiling4"), "ambient": (BulbType.WhiteTempMood, "ceiling4"), } devices = {} mocked_bulbs = [] unique_id = 0 for name, (bulb_type, model) in types.items(): devices[f"{name}.yeelight"] = {CONF_NAME: name} devices[f"{name}_nightlight.yeelight"] = { CONF_NAME: f"{name}_nightlight", CONF_NIGHTLIGHT_SWITCH_TYPE: NIGHTLIGHT_SWITCH_TYPE_LIGHT, } mocked_bulbs.append(_create_mocked_bulb(bulb_type, model, unique_id)) mocked_bulbs.append( _create_mocked_bulb(bulb_type, model, unique_id + 1)) unique_id += 2 with patch(f"{MODULE}.Bulb", side_effect=mocked_bulbs): await async_setup_component(hass, DOMAIN, {DOMAIN: { CONF_DEVICES: devices }}) await hass.async_block_till_done() async def _async_test( name, bulb_type, model, target_properties, nightlight_properties=None, entity_name=None, entity_id=None, ): if entity_id is None: entity_id = f"light.{name}" state = hass.states.get(entity_id) assert state.state == "on" target_properties["friendly_name"] = entity_name or name target_properties["flowing"] = False target_properties["night_light"] = True assert dict(state.attributes) == target_properties # nightlight if nightlight_properties is None: return name += "_nightlight" entity_id = f"light.{name}" assert hass.states.get(entity_id).state == "off" state = hass.states.get(f"{entity_id}_nightlight") assert state.state == "on" nightlight_properties["friendly_name"] = f"{name} nightlight" nightlight_properties["icon"] = "mdi:weather-night" nightlight_properties["flowing"] = False nightlight_properties["night_light"] = True assert dict(state.attributes) == nightlight_properties bright = round(255 * int(PROPERTIES["bright"]) / 100) current_brightness = round(255 * int(PROPERTIES["current_brightness"]) / 100) ct = color_temperature_kelvin_to_mired(int(PROPERTIES["ct"])) hue = int(PROPERTIES["hue"]) sat = int(PROPERTIES["sat"]) hs_color = (round(hue / 360 * 65536, 3), round(sat / 100 * 255, 3)) rgb_color = color_hs_to_RGB(*hs_color) xy_color = color_hs_to_xy(*hs_color) bg_bright = round(255 * int(PROPERTIES["bg_bright"]) / 100) bg_ct = color_temperature_kelvin_to_mired(int(PROPERTIES["bg_ct"])) bg_rgb = int(PROPERTIES["bg_rgb"]) bg_rgb_color = ((bg_rgb >> 16) & 0xFF, (bg_rgb >> 8) & 0xFF, bg_rgb & 0xFF) bg_hs_color = color_RGB_to_hs(*bg_rgb_color) bg_xy_color = color_RGB_to_xy(*bg_rgb_color) nl_br = round(255 * int(PROPERTIES["nl_br"]) / 100) # Default await _async_test( "default", None, "mono", { "effect_list": YEELIGHT_MONO_EFFECT_LIST, "supported_features": SUPPORT_YEELIGHT, "brightness": bright, }, ) # White await _async_test( "white", BulbType.White, "mono", { "effect_list": YEELIGHT_MONO_EFFECT_LIST, "supported_features": SUPPORT_YEELIGHT, "brightness": bright, }, ) # Color model_specs = _MODEL_SPECS["color"] await _async_test( "color", BulbType.Color, "color", { "effect_list": YEELIGHT_COLOR_EFFECT_LIST, "supported_features": SUPPORT_YEELIGHT_RGB, "min_mireds": color_temperature_kelvin_to_mired( model_specs["color_temp"]["max"]), "max_mireds": color_temperature_kelvin_to_mired( model_specs["color_temp"]["min"]), "brightness": current_brightness, "color_temp": ct, "hs_color": hs_color, "rgb_color": rgb_color, "xy_color": xy_color, }, {"supported_features": 0}, ) # WhiteTemp model_specs = _MODEL_SPECS["ceiling1"] await _async_test( "white_temp", BulbType.WhiteTemp, "ceiling1", { "effect_list": YEELIGHT_TEMP_ONLY_EFFECT_LIST, "supported_features": SUPPORT_YEELIGHT_WHITE_TEMP, "min_mireds": color_temperature_kelvin_to_mired( model_specs["color_temp"]["max"]), "max_mireds": color_temperature_kelvin_to_mired( model_specs["color_temp"]["min"]), "brightness": current_brightness, "color_temp": ct, }, { "effect_list": YEELIGHT_TEMP_ONLY_EFFECT_LIST, "supported_features": SUPPORT_YEELIGHT, "brightness": nl_br, }, ) # WhiteTempMood model_specs = _MODEL_SPECS["ceiling4"] await _async_test( "white_temp_mood", BulbType.WhiteTempMood, "ceiling4", { "friendly_name": NAME, "effect_list": YEELIGHT_TEMP_ONLY_EFFECT_LIST, "flowing": False, "night_light": True, "supported_features": SUPPORT_YEELIGHT_WHITE_TEMP, "min_mireds": color_temperature_kelvin_to_mired( model_specs["color_temp"]["max"]), "max_mireds": color_temperature_kelvin_to_mired( model_specs["color_temp"]["min"]), "brightness": current_brightness, "color_temp": ct, }, { "effect_list": YEELIGHT_TEMP_ONLY_EFFECT_LIST, "supported_features": SUPPORT_YEELIGHT, "brightness": nl_br, }, ) await _async_test( "ambient", BulbType.WhiteTempMood, "ceiling4", { "effect_list": YEELIGHT_COLOR_EFFECT_LIST, "supported_features": SUPPORT_YEELIGHT_RGB, "min_mireds": color_temperature_kelvin_to_mired(6500), "max_mireds": color_temperature_kelvin_to_mired(1700), "brightness": bg_bright, "color_temp": bg_ct, "hs_color": bg_hs_color, "rgb_color": bg_rgb_color, "xy_color": bg_xy_color, }, entity_name="ambient ambilight", entity_id="light.ambient_ambilight", )