"""Support for the Switchbot Light.""" import asyncio from typing import Any from switchbot_api import ( CeilingLightCommands, CommonCommands, Device, Remote, RGBWLightCommands, RGBWWLightCommands, SwitchBotAPI, ) from homeassistant.components.light import ColorMode, LightEntity from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from . import SwitchbotCloudData, SwitchBotCoordinator from .const import AFTER_COMMAND_REFRESH, DOMAIN from .entity import SwitchBotCloudEntity def value_map_brightness(value: int) -> int: """Return value for brightness map.""" return int(value / 255 * 100) def brightness_map_value(value: int) -> int: """Return brightness from map value.""" return int(value * 255 / 100) async def async_setup_entry( hass: HomeAssistant, config: ConfigEntry, async_add_entities: AddConfigEntryEntitiesCallback, ) -> None: """Set up SwitchBot Cloud entry.""" data: SwitchbotCloudData = hass.data[DOMAIN][config.entry_id] async_add_entities( _async_make_entity(data.api, device, coordinator) for device, coordinator in data.devices.lights ) class SwitchBotCloudLight(SwitchBotCloudEntity, LightEntity): """Base Class for SwitchBot Light.""" _attr_is_on: bool | None = None _attr_name: str | None = None _attr_color_mode = ColorMode.UNKNOWN def _get_default_color_mode(self) -> ColorMode: """Return the default color mode.""" if not self.supported_color_modes: return ColorMode.UNKNOWN if ColorMode.RGB in self.supported_color_modes: return ColorMode.RGB if ColorMode.COLOR_TEMP in self.supported_color_modes: return ColorMode.COLOR_TEMP return ColorMode.UNKNOWN def _set_attributes(self) -> None: """Set attributes from coordinator data.""" if self.coordinator.data is None: return power: str | None = self.coordinator.data.get("power") brightness: int | None = self.coordinator.data.get("brightness") color: str | None = self.coordinator.data.get("color") color_temperature: int | None = self.coordinator.data.get("colorTemperature") self._attr_is_on = power == "on" if power else None self._attr_brightness: int | None = ( brightness_map_value(brightness) if brightness else None ) self._attr_rgb_color: tuple | None = ( (tuple(int(i) for i in color.split(":"))) if color else None ) self._attr_color_temp_kelvin: int | None = color_temperature or None async def async_turn_off(self, **kwargs: Any) -> None: """Turn the light off.""" await self.send_api_command(CommonCommands.OFF) await asyncio.sleep(AFTER_COMMAND_REFRESH) await self.coordinator.async_request_refresh() async def async_turn_on(self, **kwargs: Any) -> None: """Turn the light on.""" brightness: int | None = kwargs.get("brightness") rgb_color: tuple[int, int, int] | None = kwargs.get("rgb_color") color_temp_kelvin: int | None = kwargs.get("color_temp_kelvin") if brightness is not None: self._attr_color_mode = self._get_default_color_mode() await self._send_brightness_command(brightness) elif rgb_color is not None: self._attr_color_mode = ColorMode.RGB await self._send_rgb_color_command(rgb_color) elif color_temp_kelvin is not None: self._attr_color_mode = ColorMode.COLOR_TEMP await self._send_color_temperature_command(color_temp_kelvin) else: self._attr_color_mode = self._get_default_color_mode() await self.send_api_command(CommonCommands.ON) await asyncio.sleep(AFTER_COMMAND_REFRESH) await self.coordinator.async_request_refresh() async def _send_brightness_command(self, brightness: int) -> None: """Send a brightness command.""" await self.send_api_command( RGBWLightCommands.SET_BRIGHTNESS, parameters=str(value_map_brightness(brightness)), ) async def _send_rgb_color_command(self, rgb_color: tuple) -> None: """Send an RGB command.""" await self.send_api_command( RGBWLightCommands.SET_COLOR, parameters=f"{rgb_color[2]}:{rgb_color[1]}:{rgb_color[0]}", ) async def _send_color_temperature_command(self, color_temp_kelvin: int) -> None: """Send a color temperature command.""" await self.send_api_command( RGBWWLightCommands.SET_COLOR_TEMPERATURE, parameters=str(color_temp_kelvin), ) class SwitchBotCloudCandleWarmerLamp(SwitchBotCloudLight): """Representation of a SwitchBotCloud CandleWarmerLamp.""" # Brightness adjustment _attr_supported_color_modes = {ColorMode.BRIGHTNESS} class SwitchBotCloudStripLight(SwitchBotCloudLight): """Representation of a SwitchBot Strip Light.""" # Brightness adjustment # RGB color control _attr_supported_color_modes = {ColorMode.RGB} class SwitchBotCloudRGBICLight(SwitchBotCloudLight): """Representation of a SwitchBotCloudRGBICLight.""" # Brightness adjustment # RGB color control _attr_supported_color_modes = {ColorMode.RGB} async def _send_rgb_color_command(self, rgb_color: tuple) -> None: """Send an RGB command.""" await self.send_api_command( RGBWLightCommands.SET_COLOR, parameters=f"{rgb_color[0]}:{rgb_color[1]}:{rgb_color[2]}", ) class SwitchBotCloudRGBWWLight(SwitchBotCloudLight): """Representation of SwitchBot |Strip Light|Floor Lamp|Color Bulb.""" # Brightness adjustment # RGB color control # Color temperature control _attr_max_color_temp_kelvin = 6500 _attr_min_color_temp_kelvin = 2700 _attr_supported_color_modes = {ColorMode.RGB, ColorMode.COLOR_TEMP} async def _send_brightness_command(self, brightness: int) -> None: """Send a brightness command.""" await self.send_api_command( RGBWWLightCommands.SET_BRIGHTNESS, parameters=str(value_map_brightness(brightness)), ) async def _send_rgb_color_command(self, rgb_color: tuple) -> None: """Send an RGB command.""" await self.send_api_command( RGBWWLightCommands.SET_COLOR, parameters=f"{rgb_color[0]}:{rgb_color[1]}:{rgb_color[2]}", ) class SwitchBotCloudCeilingLight(SwitchBotCloudLight): """Representation of SwitchBot Ceiling Light.""" # Brightness adjustment # Color temperature control _attr_max_color_temp_kelvin = 6500 _attr_min_color_temp_kelvin = 2700 _attr_supported_color_modes = {ColorMode.COLOR_TEMP} async def _send_brightness_command(self, brightness: int) -> None: """Send a brightness command.""" await self.send_api_command( CeilingLightCommands.SET_BRIGHTNESS, parameters=str(value_map_brightness(brightness)), ) async def _send_color_temperature_command(self, color_temp_kelvin: int) -> None: """Send a color temperature command.""" await self.send_api_command( CeilingLightCommands.SET_COLOR_TEMPERATURE, parameters=str(color_temp_kelvin), ) @callback def _async_make_entity( api: SwitchBotAPI, device: Device | Remote, coordinator: SwitchBotCoordinator ) -> SwitchBotCloudLight: """Make a SwitchBotCloudLight.""" if device.device_type == "Strip Light": return SwitchBotCloudStripLight(api, device, coordinator) if device.device_type in ["Ceiling Light", "Ceiling Light Pro"]: return SwitchBotCloudCeilingLight(api, device, coordinator) if device.device_type == "Candle Warmer Lamp": return SwitchBotCloudCandleWarmerLamp(api, device, coordinator) if device.device_type in ["RGBIC Neon Rope Light", "RGBIC Neon Wire Rope Light"]: return SwitchBotCloudRGBICLight(api, device, coordinator) return SwitchBotCloudRGBWWLight(api, device, coordinator)