def update_properties(self): """Update internal properties based on zwave values.""" super().update_properties() # Color Channels self._color_channels = self._value_color_channels.data # Color Data String data = self._value_color.data # RGB is always present in the openzwave color data string. self._rgb = [ int(data[1:3], 16), int(data[3:5], 16), int(data[5:7], 16) ] # Parse remaining color channels. Openzwave appends white channels # that are present. index = 7 # Warm white if self._color_channels & COLOR_CHANNEL_WARM_WHITE: warm_white = int(data[index:index + 2], 16) index += 2 else: warm_white = 0 # Cold white if self._color_channels & COLOR_CHANNEL_COLD_WHITE: cold_white = int(data[index:index + 2], 16) index += 2 else: cold_white = 0 # Color temperature. With the AEOTEC ZW098 bulb, only two color # temperatures are supported. The warm and cold channel values # indicate brightness for warm/cold color temperature. if self._zw098: if warm_white > 0: self._ct = TEMP_WARM_HASS self._rgb = ct_to_rgb(self._ct) elif cold_white > 0: self._ct = TEMP_COLD_HASS self._rgb = ct_to_rgb(self._ct) else: # RGB color is being used. Just report midpoint. self._ct = TEMP_MID_HASS elif self._color_channels & COLOR_CHANNEL_WARM_WHITE: self._rgb = list(color_rgbw_to_rgb(*self._rgb, w=warm_white)) elif self._color_channels & COLOR_CHANNEL_COLD_WHITE: self._rgb = list(color_rgbw_to_rgb(*self._rgb, w=cold_white)) # If no rgb channels supported, report None. if not (self._color_channels & COLOR_CHANNEL_RED or self._color_channels & COLOR_CHANNEL_GREEN or self._color_channels & COLOR_CHANNEL_BLUE): self._rgb = None
def update_properties(self): """Update internal properties based on zwave values.""" super().update_properties() # Color Channels self._color_channels = self._value_color_channels.data # Color Data String data = self._value_color.data # RGB is always present in the openzwave color data string. self._rgb = [ int(data[1:3], 16), int(data[3:5], 16), int(data[5:7], 16)] # Parse remaining color channels. Openzwave appends white channels # that are present. index = 7 # Warm white if self._color_channels & COLOR_CHANNEL_WARM_WHITE: warm_white = int(data[index:index+2], 16) index += 2 else: warm_white = 0 # Cold white if self._color_channels & COLOR_CHANNEL_COLD_WHITE: cold_white = int(data[index:index+2], 16) index += 2 else: cold_white = 0 # Color temperature. With the AEOTEC ZW098 bulb, only two color # temperatures are supported. The warm and cold channel values # indicate brightness for warm/cold color temperature. if self._zw098: if warm_white > 0: self._ct = TEMP_WARM_HASS self._rgb = ct_to_rgb(self._ct) elif cold_white > 0: self._ct = TEMP_COLD_HASS self._rgb = ct_to_rgb(self._ct) else: # RGB color is being used. Just report midpoint. self._ct = TEMP_MID_HASS elif self._color_channels & COLOR_CHANNEL_WARM_WHITE: self._rgb = list(color_rgbw_to_rgb(*self._rgb, w=warm_white)) elif self._color_channels & COLOR_CHANNEL_COLD_WHITE: self._rgb = list(color_rgbw_to_rgb(*self._rgb, w=cold_white)) # If no rgb channels supported, report None. if not (self._color_channels & COLOR_CHANNEL_RED or self._color_channels & COLOR_CHANNEL_GREEN or self._color_channels & COLOR_CHANNEL_BLUE): self._rgb = None
def test_color_rgbw_to_rgb(self): """Test color_rgbw_to_rgb.""" assert (0, 0, 0) == \ color_util.color_rgbw_to_rgb(0, 0, 0, 0) assert (255, 255, 255) == \ color_util.color_rgbw_to_rgb(0, 0, 0, 255) assert (255, 0, 0) == \ color_util.color_rgbw_to_rgb(255, 0, 0, 0) assert (0, 255, 0) == \ color_util.color_rgbw_to_rgb(0, 255, 0, 0) assert (0, 0, 255) == \ color_util.color_rgbw_to_rgb(0, 0, 255, 0) assert (255, 127, 0) == \ color_util.color_rgbw_to_rgb(255, 127, 0, 0) assert (255, 127, 127) == \ color_util.color_rgbw_to_rgb(255, 0, 0, 253) assert (127, 127, 127) == \ color_util.color_rgbw_to_rgb(0, 0, 0, 127)
def test_color_rgbw_to_rgb(self): """Test color_rgbw_to_rgb.""" self.assertEqual((0, 0, 0), color_util.color_rgbw_to_rgb(0, 0, 0, 0)) self.assertEqual((255, 255, 255), color_util.color_rgbw_to_rgb(0, 0, 0, 255)) self.assertEqual((255, 0, 0), color_util.color_rgbw_to_rgb(255, 0, 0, 0)) self.assertEqual((0, 255, 0), color_util.color_rgbw_to_rgb(0, 255, 0, 0)) self.assertEqual((0, 0, 255), color_util.color_rgbw_to_rgb(0, 0, 255, 0)) self.assertEqual((255, 127, 0), color_util.color_rgbw_to_rgb(255, 127, 0, 0)) self.assertEqual((255, 127, 127), color_util.color_rgbw_to_rgb(255, 0, 0, 253)) self.assertEqual((127, 127, 127), color_util.color_rgbw_to_rgb(0, 0, 0, 127))
async def _wled_update(self) -> None: """Update WLED entity.""" self._brightness = self.wled.device.state.brightness self._effect = self.wled.device.state.segments[ self._segment].effect.name self._state = self.wled.device.state.on color = self.wled.device.state.segments[self._segment].color_primary if self._rgbw: color = color_util.color_rgbw_to_rgb(*color) self._color = color_util.color_RGB_to_hs(*color) playlist = self.wled.device.state.playlist if playlist == -1: playlist = None preset = self.wled.device.state.preset if preset == -1: preset = None self._attributes = { ATTR_INTENSITY: self.wled.device.state.segments[self._segment].intensity, ATTR_PALETTE: self.wled.device.state.segments[self._segment].palette.name, ATTR_PLAYLIST: playlist, ATTR_PRESET: preset, ATTR_SPEED: self.wled.device.state.segments[self._segment].speed, }
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 test_color_rgbw_to_rgb(): """Test color_rgbw_to_rgb.""" assert color_util.color_rgbw_to_rgb(0, 0, 0, 0) == (0, 0, 0) assert color_util.color_rgbw_to_rgb(0, 0, 0, 255) == (255, 255, 255) assert color_util.color_rgbw_to_rgb(255, 0, 0, 0) == (255, 0, 0) assert color_util.color_rgbw_to_rgb(0, 255, 0, 0) == (0, 255, 0) assert color_util.color_rgbw_to_rgb(0, 0, 255, 0) == (0, 0, 255) assert color_util.color_rgbw_to_rgb(255, 127, 0, 0) == (255, 127, 0) assert color_util.color_rgbw_to_rgb(255, 0, 0, 253) == (255, 127, 127) assert color_util.color_rgbw_to_rgb(0, 0, 0, 127) == (127, 127, 127)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa: C901 """Expose light control via state machine and services.""" component = hass.data[DOMAIN] = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL) await component.async_setup(config) profiles = hass.data[DATA_PROFILES] = Profiles(hass) await profiles.async_initialize() def preprocess_data(data): """Preprocess the service data.""" base = { entity_field: data.pop(entity_field) for entity_field in cv.ENTITY_SERVICE_FIELDS if entity_field in data } preprocess_turn_on_alternatives(hass, data) base["params"] = data return base 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) legacy_supported_color_modes = ( light._light_internal_supported_color_modes # pylint: disable=protected-access ) 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: if (ColorMode.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 temperature is specified, emulate it if not supported by the light if ATTR_COLOR_TEMP in params: if (supported_color_modes and ColorMode.COLOR_TEMP not in supported_color_modes and ColorMode.RGBWW in supported_color_modes): color_temp = params.pop(ATTR_COLOR_TEMP) brightness = params.get(ATTR_BRIGHTNESS, light.brightness) params[ ATTR_RGBWW_COLOR] = color_util.color_temperature_to_rgbww( color_temp, brightness, light.min_mireds, light.max_mireds) elif ColorMode.COLOR_TEMP not in legacy_supported_color_modes: color_temp = params.pop(ATTR_COLOR_TEMP) if color_supported(legacy_supported_color_modes): temp_k = color_util.color_temperature_mired_to_kelvin( color_temp) params[ATTR_HS_COLOR] = color_util.color_temperature_to_hs( temp_k) # 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) elif (rgbw_color := params.pop(ATTR_RGBW_COLOR, None)) is not None: rgb_color = color_util.color_rgbw_to_rgb(*rgbw_color) params[ATTR_HS_COLOR] = color_util.color_RGB_to_hs(*rgb_color)
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: rgbw_color = params.pop(ATTR_RGBW_COLOR) rgb_color = color_util.color_rgbw_to_rgb(*rgbw_color) if ColorMode.RGB in supported_color_modes: params[ATTR_RGB_COLOR] = 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_RGBWW_COLOR in params and ColorMode.RGBWW not in supported_color_modes): rgbww_color = params.pop(ATTR_RGBWW_COLOR) rgb_color = color_util.color_rgbww_to_rgb(*rgbww_color, light.min_mireds, light.max_mireds)
def rgb_color(self) -> tuple[int, int, int] | None: """Return the rgb color value [int, int, int].""" if (rgbw := self.rgbw_color) is not None: # used in brightness calculation when no address is given return color_util.color_rgbw_to_rgb(*rgbw)