async def async_update(self): """Retrieve latest state.""" result = await zha.safe_read(self._endpoint.on_off, ['on_off'], allow_cache=False, only_cache=(not self._initialized)) self._state = result.get('on_off', self._state) if self._supported_features & light.SUPPORT_BRIGHTNESS: result = await zha.safe_read(self._endpoint.level, ['current_level'], allow_cache=False, only_cache=(not self._initialized)) self._brightness = result.get('current_level', self._brightness) if self._supported_features & light.SUPPORT_COLOR_TEMP: result = await zha.safe_read(self._endpoint.light_color, ['color_temperature'], allow_cache=False, only_cache=(not self._initialized)) self._color_temp = result.get('color_temperature', self._color_temp) if self._supported_features & light.SUPPORT_COLOR: result = await zha.safe_read(self._endpoint.light_color, ['current_x', 'current_y'], allow_cache=False, only_cache=(not self._initialized)) if 'current_x' in result and 'current_y' in result: xy_color = (round(result['current_x']/65535, 3), round(result['current_y']/65535, 3)) self._hs_color = color_util.color_xy_to_hs(*xy_color)
def test_color_xy_to_hs(self): """Test color_xy_to_hs.""" self.assertEqual((47.294, 100), color_util.color_xy_to_hs(1, 1)) self.assertEqual((38.182, 12.941), color_util.color_xy_to_hs(.35, .35)) self.assertEqual((345.882, 100), color_util.color_xy_to_hs(1, 0)) self.assertEqual((120, 100), color_util.color_xy_to_hs(0, 1)) self.assertEqual((225.176, 100), color_util.color_xy_to_hs(0, 0))
def find_hsbk(**kwargs): """Find the desired color from a number of possible inputs.""" hue, saturation, brightness, kelvin = [None]*4 preprocess_turn_on_alternatives(kwargs) if ATTR_RGB_COLOR in kwargs: hue, saturation, brightness = \ color_util.color_RGB_to_hsv(*kwargs[ATTR_RGB_COLOR]) saturation = convert_8_to_16(saturation) brightness = convert_8_to_16(brightness) kelvin = 3500 if ATTR_XY_COLOR in kwargs: hue, saturation = color_util.color_xy_to_hs(*kwargs[ATTR_XY_COLOR]) saturation = convert_8_to_16(saturation) kelvin = 3500 if ATTR_COLOR_TEMP in kwargs: kelvin = int(color_util.color_temperature_mired_to_kelvin( kwargs[ATTR_COLOR_TEMP])) saturation = 0 if ATTR_BRIGHTNESS in kwargs: brightness = convert_8_to_16(kwargs[ATTR_BRIGHTNESS]) hsbk = [hue, saturation, brightness, kelvin] return None if hsbk == [None]*4 else hsbk
def preprocess_turn_on_alternatives(params): """Process extra data for turn light on request.""" profile = Profiles.get(params.pop(ATTR_PROFILE, None)) if profile is not None: params.setdefault(ATTR_XY_COLOR, profile[:2]) params.setdefault(ATTR_BRIGHTNESS, profile[2]) color_name = params.pop(ATTR_COLOR_NAME, None) if color_name is not None: try: params[ATTR_RGB_COLOR] = color_util.color_name_to_rgb(color_name) except ValueError: _LOGGER.warning('Got unknown color %s, falling back to white', color_name) params[ATTR_RGB_COLOR] = (255, 255, 255) kelvin = params.pop(ATTR_KELVIN, None) if kelvin is not None: mired = color_util.color_temperature_kelvin_to_mired(kelvin) params[ATTR_COLOR_TEMP] = int(mired) brightness_pct = params.pop(ATTR_BRIGHTNESS_PCT, None) if brightness_pct is not None: params[ATTR_BRIGHTNESS] = int(255 * brightness_pct/100) xy_color = params.pop(ATTR_XY_COLOR, None) if xy_color is not None: params[ATTR_HS_COLOR] = color_util.color_xy_to_hs(*xy_color) rgb_color = params.pop(ATTR_RGB_COLOR, None) if rgb_color is not None: params[ATTR_HS_COLOR] = color_util.color_RGB_to_hs(*rgb_color)
def test_color_xy_to_hs(self): """Test color_xy_to_hs.""" self.assertEqual((8609, 255), color_util.color_xy_to_hs(1, 1)) self.assertEqual((6950, 32), color_util.color_xy_to_hs(.35, .35)) self.assertEqual((62965, 255), color_util.color_xy_to_hs(1, 0)) self.assertEqual((21845, 255), color_util.color_xy_to_hs(0, 1)) self.assertEqual((40992, 255), color_util.color_xy_to_hs(0, 0))
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": hue, sat = color_util.color_xy_to_hs(*kwargs[ATTR_XY_COLOR]) command['hue'] = hue command['sat'] = sat command['bri'] = self.info['bri'] 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: temp = kwargs[ATTR_COLOR_TEMP] command['ct'] = max(self.min_mireds, min(temp, self.max_mireds)) 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 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 command['sat'] = sat 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] 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'] 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' and self.info.get('manufacturername') == 'Philips'): command['effect'] = 'none' self._command_func(self.light_id, command)
def hs_color(self): """Return the hs color value.""" mode = self._color_mode source = self.light.action if self.is_group else self.light.state if mode in ("xy", "hs") and "xy" in source: return color.color_xy_to_hs(*source["xy"], self.gamut) return None
def hs_color(self): """Return the hs color value.""" if self._device.colormode in ("xy", "hs"): if self._device.xy: return color_util.color_xy_to_hs(*self._device.xy) if self._device.hue and self._device.sat: return (self._device.hue / 65535 * 360, self._device.sat / 255 * 100) return None
def hs_color(self): """Return the hs color value.""" mode = self._color_mode source = self.light.action if self.is_group else self.light.state if mode in ('xy', 'hs') and 'xy' in source: return color.color_xy_to_hs(*source['xy'], self.gamut) return None
def __post_init__(self) -> None: """Convert xy to hs color.""" if None in (self.color_x, self.color_y): self.hs_color = None return self.hs_color = color_util.color_xy_to_hs( cast(float, self.color_x), cast(float, self.color_y) )
def hs_color(self): """Return the hs color value.""" mode = self._color_mode source = self.light.action if self.is_group else self.light.state if mode in ('xy', 'hs') and 'xy' in source: return color.color_xy_to_hs(*source['xy']) return None
def test_hs_color(): """Test hs_color property.""" light = hue_light.HueLight( light=Mock( state={ "colormode": "ct", "hue": 1234, "sat": 123 }, raw=LIGHT_RAW, colorgamuttype=LIGHT_GAMUT_TYPE, colorgamut=LIGHT_GAMUT, ), request_bridge_update=None, bridge=Mock(), is_group=False, ) assert light.hs_color is None light = hue_light.HueLight( light=Mock( state={ "colormode": "hs", "hue": 1234, "sat": 123 }, raw=LIGHT_RAW, colorgamuttype=LIGHT_GAMUT_TYPE, colorgamut=LIGHT_GAMUT, ), request_bridge_update=None, bridge=Mock(), is_group=False, ) assert light.hs_color is None light = hue_light.HueLight( light=Mock( state={ "colormode": "xy", "hue": 1234, "sat": 123, "xy": [0.4, 0.5] }, raw=LIGHT_RAW, colorgamuttype=LIGHT_GAMUT_TYPE, colorgamut=LIGHT_GAMUT, ), request_bridge_update=None, bridge=Mock(), is_group=False, ) assert light.hs_color == color.color_xy_to_hs(0.4, 0.5, LIGHT_GAMUT)
def xy_received(msg): """Handle new MQTT messages for xy color.""" payload = templates[CONF_XY](msg.payload) if not payload: _LOGGER.debug("Ignoring empty xy-color message from '%s'", msg.topic) return xy_color = [float(val) for val in payload.split(",")] self._hs = color_util.color_xy_to_hs(*xy_color) self.async_write_ha_state()
def xy_received(topic, payload, qos): """Handle new MQTT messages for xy color.""" payload = templates[CONF_XY](payload) if not payload: _LOGGER.debug("Ignoring empty xy-color message from '%s'", topic) return xy_color = [float(val) for val in payload.split(',')] self._hs = color_util.color_xy_to_hs(*xy_color) self.async_schedule_update_ha_state()
def __init__(self, unique_id, zha_device: ZhaDeviceType, channels, **kwargs): """Initialize the ZHA light.""" super().__init__(unique_id, zha_device, channels, **kwargs) self._on_off_channel = self.cluster_channels.get(CHANNEL_ON_OFF) self._state = bool(self._on_off_channel.on_off) self._level_channel = self.cluster_channels.get(CHANNEL_LEVEL) self._color_channel = self.cluster_channels.get(CHANNEL_COLOR) self._identify_channel = self.zha_device.channels.identify_ch if self._color_channel: self._min_mireds: int | None = self._color_channel.min_mireds self._max_mireds: int | None = self._color_channel.max_mireds self._cancel_refresh_handle = None effect_list = [] if self._level_channel: self._supported_features |= light.SUPPORT_BRIGHTNESS self._supported_features |= light.SUPPORT_TRANSITION self._brightness = self._level_channel.current_level if self._color_channel: color_capabilities = self._color_channel.color_capabilities if color_capabilities & CAPABILITIES_COLOR_TEMP: self._supported_features |= light.SUPPORT_COLOR_TEMP self._color_temp = self._color_channel.color_temperature if color_capabilities & CAPABILITIES_COLOR_XY: self._supported_features |= light.SUPPORT_COLOR curr_x = self._color_channel.current_x curr_y = self._color_channel.current_y if curr_x is not None and curr_y is not None: self._hs_color = color_util.color_xy_to_hs( float(curr_x / 65535), float(curr_y / 65535)) else: self._hs_color = (0, 0) if color_capabilities & CAPABILITIES_COLOR_LOOP: self._supported_features |= light.SUPPORT_EFFECT effect_list.append(light.EFFECT_COLORLOOP) if self._color_channel.color_loop_active == 1: self._effect = light.EFFECT_COLORLOOP if self._identify_channel: self._supported_features |= light.SUPPORT_FLASH if effect_list: self._effect_list = effect_list self._default_transition = async_get_zha_config_value( zha_device.gateway.config_entry, ZHA_OPTIONS, CONF_DEFAULT_LIGHT_TRANSITION, 0, )
def test_hs_color(): """Test hs_color property.""" light = hue_light.HueLight( light=Mock(state={ 'colormode': 'ct', 'hue': 1234, 'sat': 123, }), request_bridge_update=None, bridge=Mock(), is_group=False, ) assert light.hs_color is None light = hue_light.HueLight( light=Mock(state={ 'colormode': 'hs', 'hue': 1234, 'sat': 123, }), request_bridge_update=None, bridge=Mock(), is_group=False, ) assert light.hs_color == (1234 / 65535 * 360, 123 / 255 * 100) light = hue_light.HueLight( light=Mock(state={ 'colormode': 'xy', 'hue': 1234, 'sat': 123, }), request_bridge_update=None, bridge=Mock(), is_group=False, ) assert light.hs_color == (1234 / 65535 * 360, 123 / 255 * 100) light = hue_light.HueLight( light=Mock(state={ 'colormode': 'xy', 'hue': None, 'sat': 123, 'xy': [0.4, 0.5] }), request_bridge_update=None, bridge=Mock(), is_group=False, ) assert light.hs_color == color.color_xy_to_hs(0.4, 0.5)
def xy_received(msg): """Handle new MQTT messages for xy color.""" payload = templates[CONF_XY](msg.payload) if not payload: _LOGGER.debug("Ignoring empty xy-color message from '%s'", msg.topic) return xy_color = [float(val) for val in payload.split(',')] self._hs = color_util.color_xy_to_hs(*xy_color) self.async_write_ha_state()
def hs_color(self): """Define current bulb color.""" if self.wink.supports_xy_color(): return color_util.color_xy_to_hs(*self.wink.color_xy()) if self.wink.supports_hue_saturation(): hue = self.wink.color_hue() saturation = self.wink.color_saturation() if hue is not None and saturation is not None: return hue * 360, saturation * 100 return None
def hs_color(self): """Define current bulb color.""" if self.wink.supports_xy_color(): return color_util.color_xy_to_hs(*self.wink.color_xy()) if self.wink.supports_hue_saturation(): hue = self.wink.color_hue() saturation = self.wink.color_saturation() if hue is not None and saturation is not None: return hue*360, saturation*100 return None
async def async_get_state(self): """Attempt to retrieve the state from the light.""" if not self.available: return self.debug("polling current state") if self._on_off_channel: state = await self._on_off_channel.get_attribute_value( "on_off", from_cache=False ) if state is not None: self._state = state if self._level_channel: level = await self._level_channel.get_attribute_value( "current_level", from_cache=False ) if level is not None: self._brightness = level if self._color_channel: attributes = [ "color_mode", "color_temperature", "current_x", "current_y", "color_loop_active", ] results = await self._color_channel.get_attributes( attributes, from_cache=False ) color_mode = results.get("color_mode") if color_mode is not None: if color_mode == LightColorMode.COLOR_TEMP: color_temp = results.get("color_temperature") if color_temp is not None and color_mode: self._color_temp = color_temp self._hs_color = None else: color_x = results.get("current_x") color_y = results.get("current_y") if color_x is not None and color_y is not None: self._hs_color = color_util.color_xy_to_hs( float(color_x / 65535), float(color_y / 65535) ) self._color_temp = None color_loop_active = results.get("color_loop_active") if color_loop_active is not None: if color_loop_active == 1: self._effect = light.EFFECT_COLORLOOP else: self._effect = None
async def test_default_profiles_light(hass, mock_light_profiles): """Test default turn-on light profile for a specific light.""" platform = getattr(hass.components, "test.light") platform.init() assert await async_setup_component(hass, light.DOMAIN, {light.DOMAIN: { CONF_PLATFORM: "test" }}) await hass.async_block_till_done() mock_light_profiles["group.all_lights.default"] = color.color_xy_to_hs( 0.3, 0.5) + ( 200, 0, ) mock_light_profiles["light.ceiling_2.default"] = color.color_xy_to_hs( 0.6, 0.6) + ( 100, 3, ) dev = next( filter(lambda x: x.entity_id == "light.ceiling_2", platform.ENTITIES)) await hass.services.async_call( light.DOMAIN, SERVICE_TURN_ON, { ATTR_ENTITY_ID: dev.entity_id, }, blocking=True, ) _, data = dev.last_call("turn_on") assert data == { light.ATTR_HS_COLOR: (50.353, 100), light.ATTR_BRIGHTNESS: 100, light.ATTR_TRANSITION: 3, }
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)
async def async_handle_light_on_service(light, call): """Handle turning a light on. If brightness is set to 0, this service will turn the light off. """ params = dict(call.data["params"]) # Only process params once we processed brightness step if params and ( ATTR_BRIGHTNESS_STEP in params or ATTR_BRIGHTNESS_STEP_PCT in params ): brightness = light.brightness if light.is_on else 0 if ATTR_BRIGHTNESS_STEP in params: brightness += params.pop(ATTR_BRIGHTNESS_STEP) else: brightness += round(params.pop(ATTR_BRIGHTNESS_STEP_PCT) / 100 * 255) params[ATTR_BRIGHTNESS] = max(0, min(255, brightness)) preprocess_turn_on_alternatives(hass, params) if (not params or not light.is_on) or ( params and ATTR_TRANSITION not in params ): profiles.apply_default(light.entity_id, light.is_on, params) supported_color_modes = light.supported_color_modes # Backwards compatibility: if an RGBWW color is specified, convert to RGB + W # for legacy lights if ATTR_RGBW_COLOR in params: legacy_supported_color_modes = ( light._light_internal_supported_color_modes # pylint: disable=protected-access ) if ( COLOR_MODE_RGBW in legacy_supported_color_modes and not supported_color_modes ): rgbw_color = params.pop(ATTR_RGBW_COLOR) params[ATTR_RGB_COLOR] = rgbw_color[0:3] params[ATTR_WHITE_VALUE] = rgbw_color[3] # If a color is specified, convert to the color space supported by the light # Backwards compatibility: Fall back to hs color if light.supported_color_modes # is not implemented if not supported_color_modes: if (rgb_color := params.pop(ATTR_RGB_COLOR, None)) is not None: params[ATTR_HS_COLOR] = color_util.color_RGB_to_hs(*rgb_color) elif (xy_color := params.pop(ATTR_XY_COLOR, None)) is not None: params[ATTR_HS_COLOR] = color_util.color_xy_to_hs(*xy_color)
def test_hs_color(): """Test hs_color property.""" light = hue_light.HueLight( light=Mock(state={ 'colormode': 'ct', 'hue': 1234, 'sat': 123, }, raw=LIGHT_RAW, colorgamuttype=LIGHT_GAMUT_TYPE, colorgamut=LIGHT_GAMUT), request_bridge_update=None, bridge=Mock(), is_group=False, ) assert light.hs_color is None light = hue_light.HueLight( light=Mock(state={ 'colormode': 'hs', 'hue': 1234, 'sat': 123, }, raw=LIGHT_RAW, colorgamuttype=LIGHT_GAMUT_TYPE, colorgamut=LIGHT_GAMUT), request_bridge_update=None, bridge=Mock(), is_group=False, ) assert light.hs_color is None light = hue_light.HueLight( light=Mock(state={ 'colormode': 'xy', 'hue': 1234, 'sat': 123, 'xy': [0.4, 0.5] }, raw=LIGHT_RAW, colorgamuttype=LIGHT_GAMUT_TYPE, colorgamut=LIGHT_GAMUT), request_bridge_update=None, bridge=Mock(), is_group=False, ) assert light.hs_color == color.color_xy_to_hs(0.4, 0.5, LIGHT_GAMUT)
def test_hs_color(): """Test hs_color property.""" light = hue_light.HueLight( light=Mock( state={"colormode": "ct", "hue": 1234, "sat": 123}, raw=LIGHT_RAW, colorgamuttype=LIGHT_GAMUT_TYPE, colorgamut=LIGHT_GAMUT, ), coordinator=Mock(last_update_success=True), bridge=Mock(), is_group=False, supported_features=hue_light.SUPPORT_HUE_EXTENDED, rooms={}, ) assert light.hs_color is None light = hue_light.HueLight( light=Mock( state={"colormode": "hs", "hue": 1234, "sat": 123}, raw=LIGHT_RAW, colorgamuttype=LIGHT_GAMUT_TYPE, colorgamut=LIGHT_GAMUT, ), coordinator=Mock(last_update_success=True), bridge=Mock(), is_group=False, supported_features=hue_light.SUPPORT_HUE_EXTENDED, rooms={}, ) assert light.hs_color is None light = hue_light.HueLight( light=Mock( state={"colormode": "xy", "hue": 1234, "sat": 123, "xy": [0.4, 0.5]}, raw=LIGHT_RAW, colorgamuttype=LIGHT_GAMUT_TYPE, colorgamut=LIGHT_GAMUT, ), coordinator=Mock(last_update_success=True), bridge=Mock(), is_group=False, supported_features=hue_light.SUPPORT_HUE_EXTENDED, rooms={}, ) assert light.hs_color == color.color_xy_to_hs(0.4, 0.5, LIGHT_GAMUT)
def test_color_xy_to_hs(): """Test color_xy_to_hs.""" assert color_util.color_xy_to_hs(1, 1) == (47.294, 100) assert color_util.color_xy_to_hs(0.35, 0.35) == (38.182, 12.941) assert color_util.color_xy_to_hs(1, 0) == (345.882, 100) assert color_util.color_xy_to_hs(0, 1) == (120, 100) assert color_util.color_xy_to_hs(0, 0) == (225.176, 100) assert color_util.color_xy_to_hs(1, 0, GAMUT) == (359.294, 100) assert color_util.color_xy_to_hs(0, 1, GAMUT) == (100.706, 100) assert color_util.color_xy_to_hs(0, 0, GAMUT) == (221.463, 96.471)
def xy_received(msg): """Handle new MQTT messages for xy color.""" payload = self._value_templates[CONF_XY_VALUE_TEMPLATE](msg.payload, None) if not payload: _LOGGER.debug("Ignoring empty xy-color message from '%s'", msg.topic) return xy_color = tuple(float(val) for val in payload.split(",")) if self._optimistic_color_mode: self._color_mode = COLOR_MODE_XY if self._legacy_mode: self._hs_color = color_util.color_xy_to_hs(*xy_color) else: self._xy_color = xy_color self.async_write_ha_state()
def _update(self, force_update=True): """Synchronize state with bridge.""" self._update_lights(no_throttle=force_update) self._state = self.wemo.state self._is_on = self._state.get('onoff') != 0 self._brightness = self._state.get('level', 255) self._color_temp = self._state.get('temperature_mireds') self._available = True xy_color = self._state.get('color_xy') if xy_color: self._hs_color = color_util.color_xy_to_hs(*xy_color) else: self._hs_color = None
def _update(self, force_update=True): """Synchronize state with bridge.""" with self._wemo_exception_handler("update status") as handler: self._update_lights(no_throttle=force_update) self._state = self.wemo.state if handler.success: self._is_on = self._state.get("onoff") != WEMO_OFF self._brightness = self._state.get("level", 255) self._color_temp = self._state.get("temperature_mireds") xy_color = self._state.get("color_xy") if xy_color: self._hs_color = color_util.color_xy_to_hs(*xy_color) else: self._hs_color = None
async def test_light_profiles(hass, mock_light_profiles): """Test light profiles.""" platform = getattr(hass.components, "test.light") platform.init() mock_light_profiles["test"] = color.color_xy_to_hs(0.4, 0.6) + (100, 0) mock_light_profiles["test_off"] = 0, 0, 0, 0 assert await async_setup_component(hass, light.DOMAIN, {light.DOMAIN: { CONF_PLATFORM: "test" }}) await hass.async_block_till_done() ent1, _, _ = platform.ENTITIES await hass.services.async_call( light.DOMAIN, SERVICE_TURN_ON, { ATTR_ENTITY_ID: ent1.entity_id, light.ATTR_PROFILE: "test", }, blocking=True, ) _, data = ent1.last_call("turn_on") assert light.is_on(hass, ent1.entity_id) assert data == { light.ATTR_HS_COLOR: (71.059, 100), light.ATTR_BRIGHTNESS: 100, light.ATTR_TRANSITION: 0, } await hass.services.async_call( light.DOMAIN, SERVICE_TURN_ON, { ATTR_ENTITY_ID: ent1.entity_id, light.ATTR_PROFILE: "test_off" }, blocking=True, ) _, data = ent1.last_call("turn_off") assert not light.is_on(hass, ent1.entity_id) assert data == {light.ATTR_TRANSITION: 0}
def find_hsbk(self, **kwargs): """Find the desired color from a number of possible inputs.""" changed_color = False hsbk = kwargs.pop(ATTR_HSBK, None) if hsbk is not None: return [hsbk, True] preprocess_turn_on_alternatives(kwargs) if ATTR_RGB_COLOR in kwargs: hue, saturation, brightness = \ color_util.color_RGB_to_hsv(*kwargs[ATTR_RGB_COLOR]) saturation = convert_8_to_16(saturation) brightness = convert_8_to_16(brightness) changed_color = True else: hue = self._hue saturation = self._sat brightness = self._bri if ATTR_XY_COLOR in kwargs: hue, saturation = color_util.color_xy_to_hs(*kwargs[ATTR_XY_COLOR]) saturation = convert_8_to_16(saturation) changed_color = True # When color or temperature is set, use a default value for the other if ATTR_COLOR_TEMP in kwargs: kelvin = int(color_util.color_temperature_mired_to_kelvin( kwargs[ATTR_COLOR_TEMP])) if not changed_color: saturation = 0 changed_color = True else: if changed_color: kelvin = 3500 else: kelvin = self._kel if ATTR_BRIGHTNESS in kwargs: brightness = convert_8_to_16(kwargs[ATTR_BRIGHTNESS]) changed_color = True else: brightness = self._bri return [[hue, saturation, brightness, kelvin], changed_color]
async def async_get_state(self, from_cache=True): """Attempt to retrieve on off state from the light.""" if not from_cache and not self.available: return self.debug("polling current state - from cache: %s", from_cache) if self._on_off_channel: state = await self._on_off_channel.get_attribute_value( "on_off", from_cache=from_cache) if state is not None: self._state = state if self._level_channel: level = await self._level_channel.get_attribute_value( "current_level", from_cache=from_cache) if level is not None: self._brightness = level if self._color_channel: attributes = [] color_capabilities = self._color_channel.get_color_capabilities() if (color_capabilities is not None and color_capabilities & CAPABILITIES_COLOR_TEMP): attributes.append("color_temperature") if (color_capabilities is not None and color_capabilities & CAPABILITIES_COLOR_XY): attributes.append("current_x") attributes.append("current_y") if (color_capabilities is not None and color_capabilities & CAPABILITIES_COLOR_LOOP): attributes.append("color_loop_active") results = await self._color_channel.get_attributes( attributes, from_cache=from_cache) if ("color_temperature" in results and results["color_temperature"] is not None): self._color_temp = results["color_temperature"] color_x = results.get("current_x") color_y = results.get("current_y") if color_x is not None and color_y is not None: self._hs_color = color_util.color_xy_to_hs( float(color_x / 65535), float(color_y / 65535)) if ("color_loop_active" in results and results["color_loop_active"] is not None): color_loop_active = results["color_loop_active"] if color_loop_active == 1: self._effect = light.EFFECT_COLORLOOP
def state_attributes(self): """Return state attributes.""" if not self.is_on: return None data = {} data[ATTR_BRIGHTNESS] = self.brightness data[ATTR_COLOR_TEMP] = self.color_temp data[ATTR_XY_COLOR] = ( self._lamp_state.x_chromaticity, self._lamp_state.y_chromaticity, ) data[ATTR_HS_COLOR] = color_util.color_xy_to_hs(*data[ATTR_XY_COLOR]) data[ATTR_RGB_COLOR] = color_util.color_xy_to_RGB(*data[ATTR_XY_COLOR]) data[ATTR_WHITE_VALUE] = self.white_value return {key: val for key, val in data.items() if val is not None}
def find_hsbk(self, **kwargs): """Find the desired color from a number of possible inputs.""" changed_color = False hsbk = kwargs.pop(ATTR_HSBK, None) if hsbk is not None: return [hsbk, True] color_name = kwargs.pop(ATTR_COLOR_NAME, None) if color_name is not None: kwargs[ATTR_RGB_COLOR] = color_util.color_name_to_rgb(color_name) if ATTR_RGB_COLOR in kwargs: hue, saturation, brightness = \ convert_rgb_to_hsv(kwargs[ATTR_RGB_COLOR]) changed_color = True else: hue = self._hue saturation = self._sat brightness = self._bri if ATTR_XY_COLOR in kwargs: hue, saturation = color_util.color_xy_to_hs(*kwargs[ATTR_XY_COLOR]) saturation = saturation * (BYTE_MAX + 1) changed_color = True # When color or temperature is set, use a default value for the other if ATTR_COLOR_TEMP in kwargs: kelvin = int(color_temperature_mired_to_kelvin( kwargs[ATTR_COLOR_TEMP])) if not changed_color: saturation = 0 changed_color = True else: if changed_color: kelvin = 3500 else: kelvin = self._kel if ATTR_BRIGHTNESS in kwargs: brightness = kwargs[ATTR_BRIGHTNESS] * (BYTE_MAX + 1) changed_color = True else: brightness = self._bri return [[hue, saturation, brightness, kelvin], changed_color]
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) return data
def _light_internal_convert_color(self, color_mode: ColorMode | str) -> dict: data: dict[str, tuple] = {} if color_mode == ColorMode.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 == ColorMode.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 == ColorMode.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 == ColorMode.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 == ColorMode.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) elif color_mode == ColorMode.COLOR_TEMP and self.color_temp: hs_color = color_util.color_temperature_to_hs( color_util.color_temperature_mired_to_kelvin(self.color_temp)) 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) return data
def preprocess_turn_on_alternatives(params): """Process extra data for turn light on request.""" profile = Profiles.get(params.pop(ATTR_PROFILE, None)) if profile is not None: _LOGGER.debug(f"Turning on light with profile {profile}") profile_xy_color = profile[:2] if profile_xy_color[0] is not None and profile_xy_color[1] is not None: params.setdefault(ATTR_XY_COLOR, profile_xy_color) if profile[2] is not None: params.setdefault(ATTR_BRIGHTNESS, profile[2]) if len(profile) > 3: params.setdefault(ATTR_TRANSITION, profile[3]) color_name = params.pop(ATTR_COLOR_NAME, None) if color_name is not None: try: params[ATTR_RGB_COLOR] = color_util.color_name_to_rgb(color_name) except ValueError: _LOGGER.warning("Got unknown color %s, falling back to white", color_name) params[ATTR_RGB_COLOR] = (255, 255, 255) kelvin = params.pop(ATTR_KELVIN, None) if kelvin is not None: mired = color_util.color_temperature_kelvin_to_mired(kelvin) params[ATTR_COLOR_TEMP] = int(mired) brightness_pct = params.pop(ATTR_BRIGHTNESS_PCT, None) if brightness_pct is not None: params[ATTR_BRIGHTNESS] = round(255 * brightness_pct / 100) xy_color = params.pop(ATTR_XY_COLOR, None) if xy_color is not None: params[ATTR_HS_COLOR] = color_util.color_xy_to_hs(*xy_color) rgb_color = params.pop(ATTR_RGB_COLOR, None) if rgb_color is not None: params[ATTR_HS_COLOR] = color_util.color_RGB_to_hs(*rgb_color) return params
def hs_color(self): """Return the hs color value.""" # pylint: disable=redefined-outer-name mode = self._color_mode if mode not in ('hs', 'xy'): return source = self.light.action if self.is_group else self.light.state hue = source.get('hue') sat = source.get('sat') # Sometimes the state will not include valid hue/sat values. # Reported as issue 13434 if hue is not None and sat is not None: return hue / 65535 * 360, sat / 255 * 100 if 'xy' not in source: return None return color.color_xy_to_hs(*source['xy'])
def _update(self, force_update=True): """Synchronize state with bridge.""" try: self._update_lights(no_throttle=force_update) self._state = self.wemo.state except (AttributeError, ActionException) as err: _LOGGER.warning("Could not update status for %s (%s)", self.name, err) self._available = False self.wemo.bridge.reconnect_with_device() else: self._is_on = self._state.get("onoff") != WEMO_OFF self._brightness = self._state.get("level", 255) self._color_temp = self._state.get("temperature_mireds") self._available = True xy_color = self._state.get("color_xy") if xy_color: self._hs_color = color_util.color_xy_to_hs(*xy_color) else: self._hs_color = None
def hs_color(self): """Return the hs color value.""" if self._light.colormode in ('xy', 'hs') and self._light.xy: return color_util.color_xy_to_hs(*self._light.xy) return None
def state_received(topic, payload, qos): """Handle new MQTT messages.""" values = json.loads(payload) if values['state'] == 'ON': self._state = True elif values['state'] == 'OFF': self._state = False if self._hs is not None: try: red = int(values['color']['r']) green = int(values['color']['g']) blue = int(values['color']['b']) self._hs = color_util.color_RGB_to_hs(red, green, blue) except KeyError: pass except ValueError: _LOGGER.warning("Invalid RGB color value received") try: x_color = float(values['color']['x']) y_color = float(values['color']['y']) self._hs = color_util.color_xy_to_hs(x_color, y_color) except KeyError: pass except ValueError: _LOGGER.warning("Invalid XY color value received") if self._brightness is not None: try: self._brightness = int(values['brightness'] / float(self._brightness_scale) * 255) except KeyError: pass except ValueError: _LOGGER.warning("Invalid brightness value received") if self._color_temp is not None: try: self._color_temp = int(values['color_temp']) except KeyError: pass except ValueError: _LOGGER.warning("Invalid color temp value received") if self._effect is not None: try: self._effect = values['effect'] except KeyError: pass except ValueError: _LOGGER.warning("Invalid effect value received") if self._white_value is not None: try: self._white_value = int(values['white_value']) except KeyError: pass except ValueError: _LOGGER.warning("Invalid white value received") self.async_schedule_update_ha_state()
def hs_color(self): """Define current bulb color.""" if not self.wink.supports_xy_color(): return None return color_util.color_xy_to_hs(*self.wink.color_xy())
def state_received(msg): """Handle new MQTT messages.""" values = json.loads(msg.payload) if values['state'] == 'ON': self._state = True elif values['state'] == 'OFF': self._state = False if self._hs is not None: try: red = int(values['color']['r']) green = int(values['color']['g']) blue = int(values['color']['b']) self._hs = color_util.color_RGB_to_hs(red, green, blue) except KeyError: pass except ValueError: _LOGGER.warning("Invalid RGB color value received") try: x_color = float(values['color']['x']) y_color = float(values['color']['y']) self._hs = color_util.color_xy_to_hs(x_color, y_color) except KeyError: pass except ValueError: _LOGGER.warning("Invalid XY color value received") try: hue = float(values['color']['h']) saturation = float(values['color']['s']) self._hs = (hue, saturation) except KeyError: pass except ValueError: _LOGGER.warning("Invalid HS color value received") if self._brightness is not None: try: self._brightness = int( values['brightness'] / float(self._config.get(CONF_BRIGHTNESS_SCALE)) * 255) except KeyError: pass except ValueError: _LOGGER.warning("Invalid brightness value received") if self._color_temp is not None: try: self._color_temp = int(values['color_temp']) except KeyError: pass except ValueError: _LOGGER.warning("Invalid color temp value received") if self._effect is not None: try: self._effect = values['effect'] except KeyError: pass except ValueError: _LOGGER.warning("Invalid effect value received") if self._white_value is not None: try: self._white_value = int(values['white_value']) except KeyError: pass except ValueError: _LOGGER.warning("Invalid white value received") self.async_write_ha_state()
def xy_received(topic, payload, qos): """Handle new MQTT messages for color.""" xy_color = [float(val) for val in templates[CONF_XY](payload).split(',')] self._hs = color_util.color_xy_to_hs(*xy_color) self.async_schedule_update_ha_state()
def hs_color(self): """Return the hs color values of this light.""" xy_color = self.device.state.get('color_xy') return color_util.color_xy_to_hs(*xy_color) if xy_color else None