Color mode support for fibaro light (#69189)

* color_mode support for fibaro light

* color_mode support for fibaro light

* color_mode support for fibaro light

* Improve based on code review

* Updated to use the ColorMode enum
This commit is contained in:
rappenze 2022-04-26 09:34:22 +02:00 committed by GitHub
parent 68832178b7
commit c5abf54f10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -7,38 +7,41 @@ from functools import partial
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_BRIGHTNESS,
ATTR_HS_COLOR, ATTR_RGB_COLOR,
ATTR_WHITE_VALUE, ATTR_RGBW_COLOR,
ENTITY_ID_FORMAT, ENTITY_ID_FORMAT,
SUPPORT_BRIGHTNESS, ColorMode,
SUPPORT_COLOR,
SUPPORT_WHITE_VALUE,
LightEntity, LightEntity,
brightness_supported,
color_supported,
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
import homeassistant.util.color as color_util
from . import FIBARO_DEVICES, FibaroDevice from . import FIBARO_DEVICES, FibaroDevice
from .const import DOMAIN from .const import DOMAIN
def scaleto255(value): def scaleto255(value: int | None) -> int:
"""Scale the input value from 0-100 to 0-255.""" """Scale the input value from 0-100 to 0-255."""
if value is None:
return 0
# Fibaro has a funny way of storing brightness either 0-100 or 0-99 # Fibaro has a funny way of storing brightness either 0-100 or 0-99
# depending on device type (e.g. dimmer vs led) # depending on device type (e.g. dimmer vs led)
if value > 98: if value > 98:
value = 100 value = 100
return max(0, min(255, ((value * 255.0) / 100.0))) return round(value * 2.55)
def scaleto100(value): def scaleto99(value: int | None) -> int:
"""Scale the input value from 0-255 to 0-100.""" """Scale the input value from 0-255 to 0-99."""
if value is None:
return 0
# Make sure a low but non-zero value is not rounded down to zero # Make sure a low but non-zero value is not rounded down to zero
if 0 < value < 3: if 0 < value < 3:
return 1 return 1
return max(0, min(100, ((value * 100.0) / 255.0))) return min(round(value / 2.55), 99)
async def async_setup_entry( async def async_setup_entry(
@ -61,14 +64,8 @@ class FibaroLight(FibaroDevice, LightEntity):
def __init__(self, fibaro_device): def __init__(self, fibaro_device):
"""Initialize the light.""" """Initialize the light."""
self._brightness = None
self._color = (0, 0)
self._last_brightness = 0
self._supported_flags = 0
self._update_lock = asyncio.Lock() self._update_lock = asyncio.Lock()
self._white = 0
self._reset_color = False
supports_color = ( supports_color = (
"color" in fibaro_device.properties "color" in fibaro_device.properties
or "colorComponents" in fibaro_device.properties or "colorComponents" in fibaro_device.properties
@ -84,43 +81,24 @@ class FibaroLight(FibaroDevice, LightEntity):
or "RGBW" in fibaro_device.type or "RGBW" in fibaro_device.type
or "rgbw" in fibaro_device.type or "rgbw" in fibaro_device.type
) )
supports_dimming = ( supports_dimming = "levelChange" in fibaro_device.interfaces
"levelChange" in fibaro_device.interfaces
or supports_color
or supports_white_v
)
# Configuration can override default capability detection if supports_color and supports_white_v:
if supports_dimming: self._attr_supported_color_modes = {ColorMode.RGBW}
self._supported_flags |= SUPPORT_BRIGHTNESS self._attr_color_mode = ColorMode.RGBW
if supports_color: elif supports_color:
self._supported_flags |= SUPPORT_COLOR self._attr_supported_color_modes = {ColorMode.RGB}
if supports_white_v: self._attr_color_mode = ColorMode.RGB
self._supported_flags |= SUPPORT_WHITE_VALUE elif supports_dimming:
self._attr_supported_color_modes = {ColorMode.BRIGHTNESS}
self._attr_color_mode = ColorMode.BRIGHTNESS
else:
self._attr_supported_color_modes = {ColorMode.ONOFF}
self._attr_color_mode = ColorMode.ONOFF
super().__init__(fibaro_device) super().__init__(fibaro_device)
self.entity_id = ENTITY_ID_FORMAT.format(self.ha_id) self.entity_id = ENTITY_ID_FORMAT.format(self.ha_id)
@property
def brightness(self):
"""Return the brightness of the light."""
return scaleto255(self._brightness)
@property
def hs_color(self):
"""Return the color of the light."""
return self._color
@property
def white_value(self):
"""Return the white value of this light between 0..255."""
return self._white
@property
def supported_features(self):
"""Flag supported features."""
return self._supported_flags
async def async_turn_on(self, **kwargs): async def async_turn_on(self, **kwargs):
"""Turn the light on.""" """Turn the light on."""
async with self._update_lock: async with self._update_lock:
@ -128,49 +106,20 @@ class FibaroLight(FibaroDevice, LightEntity):
def _turn_on(self, **kwargs): def _turn_on(self, **kwargs):
"""Really turn the light on.""" """Really turn the light on."""
if self._supported_flags & SUPPORT_BRIGHTNESS: if ATTR_BRIGHTNESS in kwargs:
target_brightness = kwargs.get(ATTR_BRIGHTNESS) self._attr_brightness = kwargs[ATTR_BRIGHTNESS]
self.set_level(scaleto99(self._attr_brightness))
# No brightness specified, so we either restore it to
# last brightness or switch it on at maximum level
if target_brightness is None:
if self._brightness == 0:
if self._last_brightness:
self._brightness = self._last_brightness
else:
self._brightness = 100
else:
# We set it to the target brightness and turn it on
self._brightness = scaleto100(target_brightness)
if self._supported_flags & SUPPORT_COLOR and (
kwargs.get(ATTR_WHITE_VALUE) is not None
or kwargs.get(ATTR_HS_COLOR) is not None
):
if self._reset_color:
self._color = (100, 0)
if ATTR_RGB_COLOR in kwargs:
# Update based on parameters # Update based on parameters
self._white = kwargs.get(ATTR_WHITE_VALUE, self._white) self._attr_rgb_color = kwargs[ATTR_RGB_COLOR]
self._color = kwargs.get(ATTR_HS_COLOR, self._color) self.call_set_color(*self._attr_rgb_color, 0)
rgb = color_util.color_hs_to_RGB(*self._color)
self.call_set_color(
round(rgb[0]),
round(rgb[1]),
round(rgb[2]),
round(self._white),
)
if self.state == "off":
self.set_level(min(int(self._brightness), 99))
return return
if self._reset_color: if ATTR_RGBW_COLOR in kwargs:
bri255 = scaleto255(self._brightness) # Update based on parameters
self.call_set_color(bri255, bri255, bri255, bri255) self._attr_rgbw_color = kwargs[ATTR_RGBW_COLOR]
self.call_set_color(*self._attr_rgbw_color)
if self._supported_flags & SUPPORT_BRIGHTNESS:
self.set_level(min(int(self._brightness), 99))
return return
# The simplest case is left for last. No dimming, just switch on # The simplest case is left for last. No dimming, just switch on
@ -183,14 +132,6 @@ class FibaroLight(FibaroDevice, LightEntity):
def _turn_off(self, **kwargs): def _turn_off(self, **kwargs):
"""Really turn the light off.""" """Really turn the light off."""
# Let's save the last brightness level before we switch it off
if (
(self._supported_flags & SUPPORT_BRIGHTNESS)
and self._brightness
and self._brightness > 0
):
self._last_brightness = self._brightness
self._brightness = 0
self.call_turn_off() self.call_turn_off()
@property @property
@ -225,15 +166,12 @@ class FibaroLight(FibaroDevice, LightEntity):
def _update(self): def _update(self):
"""Really update the state.""" """Really update the state."""
# Brightness handling # Brightness handling
if self._supported_flags & SUPPORT_BRIGHTNESS: if brightness_supported(self.supported_color_modes):
self._brightness = float(self.fibaro_device.properties.value) self._attr_brightness = scaleto255(int(self.fibaro_device.properties.value))
# Fibaro might report 0-99 or 0-100 for brightness,
# based on device type, so we round up here
if self._brightness > 99:
self._brightness = 100
# Color handling # Color handling
if ( if (
self._supported_flags & SUPPORT_COLOR color_supported(self.supported_color_modes)
and "color" in self.fibaro_device.properties and "color" in self.fibaro_device.properties
and "," in self.fibaro_device.properties.color and "," in self.fibaro_device.properties.color
): ):
@ -242,7 +180,8 @@ class FibaroLight(FibaroDevice, LightEntity):
if rgbw_s == "0,0,0,0" and "lastColorSet" in self.fibaro_device.properties: if rgbw_s == "0,0,0,0" and "lastColorSet" in self.fibaro_device.properties:
rgbw_s = self.fibaro_device.properties.lastColorSet rgbw_s = self.fibaro_device.properties.lastColorSet
rgbw_list = [int(i) for i in rgbw_s.split(",")][:4] rgbw_list = [int(i) for i in rgbw_s.split(",")][:4]
if rgbw_list[0] or rgbw_list[1] or rgbw_list[2]:
self._color = color_util.color_RGB_to_hs(*rgbw_list[:3]) if self._attr_color_mode == ColorMode.RGB:
if (self._supported_flags & SUPPORT_WHITE_VALUE) and self.brightness != 0: self._attr_rgb_color = tuple(*rgbw_list[:3])
self._white = min(255, max(0, rgbw_list[3])) else:
self._attr_rgbw_color = tuple(rgbw_list)