hass-core/homeassistant/components/wiz/light.py

149 lines
5.3 KiB
Python
Raw Normal View History

"""WiZ integration light platform."""
from __future__ import annotations
import logging
from typing import Any
from pywizlight import PilotBuilder
from pywizlight.bulblibrary import BulbClass, BulbType
from pywizlight.rgbcw import convertHSfromRGBCW
from pywizlight.scenes import get_id_from_scene_name
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
ATTR_COLOR_TEMP,
ATTR_EFFECT,
ATTR_HS_COLOR,
COLOR_MODE_BRIGHTNESS,
COLOR_MODE_COLOR_TEMP,
COLOR_MODE_HS,
SUPPORT_EFFECT,
LightEntity,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util.color import (
color_temperature_kelvin_to_mired,
color_temperature_mired_to_kelvin,
)
from .const import DOMAIN, SOCKET_DEVICE_STR
from .entity import WizToggleEntity
from .models import WizData
_LOGGER = logging.getLogger(__name__)
DEFAULT_COLOR_MODES = {COLOR_MODE_HS, COLOR_MODE_COLOR_TEMP}
DEFAULT_MIN_MIREDS = 153
DEFAULT_MAX_MIREDS = 454
def get_supported_color_modes(bulb_type: BulbType) -> set[str]:
"""Flag supported features."""
color_modes = set()
features = bulb_type.features
if features.color:
color_modes.add(COLOR_MODE_HS)
if features.color_tmp:
color_modes.add(COLOR_MODE_COLOR_TEMP)
if not color_modes and features.brightness:
color_modes.add(COLOR_MODE_BRIGHTNESS)
return color_modes
def get_min_max_mireds(bulb_type: BulbType) -> tuple[int, int]:
"""Return the coldest and warmest color_temp that this light supports."""
# DW bulbs have no kelvin
if bulb_type.bulb_type == BulbClass.DW:
return 0, 0
# If bulbtype is TW or RGB then return the kelvin value
return color_temperature_kelvin_to_mired(
bulb_type.kelvin_range.max
), color_temperature_kelvin_to_mired(bulb_type.kelvin_range.min)
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the WiZ Platform from config_flow."""
wiz_data: WizData = hass.data[DOMAIN][entry.entry_id]
if SOCKET_DEVICE_STR not in wiz_data.bulb.bulbtype.name:
async_add_entities([WizBulbEntity(wiz_data, entry.title)])
class WizBulbEntity(WizToggleEntity, LightEntity):
"""Representation of WiZ Light bulb."""
def __init__(self, wiz_data: WizData, name: str) -> None:
"""Initialize an WiZLight."""
super().__init__(wiz_data, name)
bulb_type: BulbType = self._device.bulbtype
self._attr_effect_list = wiz_data.scenes
self._attr_min_mireds, self._attr_max_mireds = get_min_max_mireds(bulb_type)
self._attr_supported_color_modes = get_supported_color_modes(bulb_type)
if bulb_type.features.effect:
self._attr_supported_features = SUPPORT_EFFECT
@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
state = self._device.state
if (brightness := state.get_brightness()) is not None:
self._attr_brightness = max(0, min(255, brightness))
color_modes = self.supported_color_modes
assert color_modes is not None
if COLOR_MODE_COLOR_TEMP in color_modes and state.get_colortemp() is not None:
self._attr_color_mode = COLOR_MODE_COLOR_TEMP
if color_temp := state.get_colortemp():
self._attr_color_temp = color_temperature_kelvin_to_mired(color_temp)
elif (
COLOR_MODE_HS in color_modes
and (rgb := state.get_rgb()) is not None
and rgb[0] is not None
):
if (warm_white := state.get_warm_white()) is not None:
self._attr_hs_color = convertHSfromRGBCW(rgb, warm_white)
self._attr_color_mode = COLOR_MODE_HS
else:
self._attr_color_mode = COLOR_MODE_BRIGHTNESS
self._attr_effect = state.get_scene()
super()._handle_coordinator_update()
@callback
def _async_pilot_builder(self, **kwargs: Any) -> PilotBuilder:
"""Create the PilotBuilder for turn on."""
brightness = kwargs.get(ATTR_BRIGHTNESS)
if ATTR_HS_COLOR in kwargs:
return PilotBuilder(
hucolor=(kwargs[ATTR_HS_COLOR][0], kwargs[ATTR_HS_COLOR][1]),
brightness=brightness,
)
color_temp = None
if ATTR_COLOR_TEMP in kwargs:
color_temp = color_temperature_mired_to_kelvin(kwargs[ATTR_COLOR_TEMP])
scene_id = None
if ATTR_EFFECT in kwargs:
scene_id = get_id_from_scene_name(kwargs[ATTR_EFFECT])
if scene_id == 1000: # rhythm
return PilotBuilder()
_LOGGER.debug(
"[wizlight %s] Pilot will be sent with brightness=%s, color_temp=%s, scene_id=%s",
self._device.ip,
brightness,
color_temp,
scene_id,
)
return PilotBuilder(brightness=brightness, colortemp=color_temp, scene=scene_id)
async def async_turn_on(self, **kwargs: Any) -> None:
"""Instruct the light to turn on."""
await self._device.turn_on(self._async_pilot_builder(**kwargs))
await self.coordinator.async_request_refresh()