From 8936c91f5059a95848c8d58aa8ee70128e676f63 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 30 Aug 2022 20:45:52 +0200 Subject: [PATCH] Migrate smartthings light to color_mode (#70968) --- homeassistant/components/smartthings/light.py | 71 ++++++++++++------- tests/components/smartthings/test_light.py | 33 ++++----- 2 files changed, 57 insertions(+), 47 deletions(-) diff --git a/homeassistant/components/smartthings/light.py b/homeassistant/components/smartthings/light.py index 918e8b4258c..ccf63582e86 100644 --- a/homeassistant/components/smartthings/light.py +++ b/homeassistant/components/smartthings/light.py @@ -12,11 +12,10 @@ from homeassistant.components.light import ( ATTR_COLOR_TEMP, ATTR_HS_COLOR, ATTR_TRANSITION, - SUPPORT_BRIGHTNESS, - SUPPORT_COLOR, - SUPPORT_COLOR_TEMP, + ColorMode, LightEntity, LightEntityFeature, + brightness_supported, ) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant @@ -74,26 +73,40 @@ def convert_scale(value, value_scale, target_scale, round_digits=4): class SmartThingsLight(SmartThingsEntity, LightEntity): """Define a SmartThings Light.""" + _attr_supported_color_modes: set[ColorMode] + def __init__(self, device): """Initialize a SmartThingsLight.""" super().__init__(device) self._brightness = None self._color_temp = None self._hs_color = None - self._supported_features = self._determine_features() + self._attr_supported_color_modes = self._determine_color_modes() + self._attr_supported_features = self._determine_features() + + def _determine_color_modes(self): + """Get features supported by the device.""" + color_modes = set() + # Color Temperature + if Capability.color_temperature in self._device.capabilities: + color_modes.add(ColorMode.COLOR_TEMP) + # Color + if Capability.color_control in self._device.capabilities: + color_modes.add(ColorMode.HS) + # Brightness + if not color_modes and Capability.switch_level in self._device.capabilities: + color_modes.add(ColorMode.BRIGHTNESS) + if not color_modes: + color_modes.add(ColorMode.ONOFF) + + return color_modes def _determine_features(self): """Get features supported by the device.""" features = 0 - # Brightness and transition + # Transition if Capability.switch_level in self._device.capabilities: - features |= SUPPORT_BRIGHTNESS | LightEntityFeature.TRANSITION - # Color Temperature - if Capability.color_temperature in self._device.capabilities: - features |= SUPPORT_COLOR_TEMP - # Color - if Capability.color_control in self._device.capabilities: - features |= SUPPORT_COLOR + features |= LightEntityFeature.TRANSITION return features @@ -101,17 +114,17 @@ class SmartThingsLight(SmartThingsEntity, LightEntity): """Turn the light on.""" tasks = [] # Color temperature - if self._supported_features & SUPPORT_COLOR_TEMP and ATTR_COLOR_TEMP in kwargs: + if ATTR_COLOR_TEMP in kwargs: tasks.append(self.async_set_color_temp(kwargs[ATTR_COLOR_TEMP])) # Color - if self._supported_features & SUPPORT_COLOR and ATTR_HS_COLOR in kwargs: + if ATTR_HS_COLOR in kwargs: tasks.append(self.async_set_color(kwargs[ATTR_HS_COLOR])) if tasks: # Set temp/color first await asyncio.gather(*tasks) # Switch/brightness/transition - if self._supported_features & SUPPORT_BRIGHTNESS and ATTR_BRIGHTNESS in kwargs: + if ATTR_BRIGHTNESS in kwargs: await self.async_set_level( kwargs[ATTR_BRIGHTNESS], kwargs.get(ATTR_TRANSITION, 0) ) @@ -125,10 +138,7 @@ class SmartThingsLight(SmartThingsEntity, LightEntity): async def async_turn_off(self, **kwargs: Any) -> None: """Turn the light off.""" # Switch/transition - if ( - self._supported_features & LightEntityFeature.TRANSITION - and ATTR_TRANSITION in kwargs - ): + if ATTR_TRANSITION in kwargs: await self.async_set_level(0, int(kwargs[ATTR_TRANSITION])) else: await self._device.switch_off(set_status=True) @@ -140,17 +150,17 @@ class SmartThingsLight(SmartThingsEntity, LightEntity): async def async_update(self) -> None: """Update entity attributes when the device status has changed.""" # Brightness and transition - if self._supported_features & SUPPORT_BRIGHTNESS: + if brightness_supported(self._attr_supported_color_modes): self._brightness = int( convert_scale(self._device.status.level, 100, 255, 0) ) # Color Temperature - if self._supported_features & SUPPORT_COLOR_TEMP: + if ColorMode.COLOR_TEMP in self._attr_supported_color_modes: self._color_temp = color_util.color_temperature_kelvin_to_mired( self._device.status.color_temperature ) # Color - if self._supported_features & SUPPORT_COLOR: + if ColorMode.HS in self._attr_supported_color_modes: self._hs_color = ( convert_scale(self._device.status.hue, 100, 360), self._device.status.saturation, @@ -179,6 +189,18 @@ class SmartThingsLight(SmartThingsEntity, LightEntity): duration = int(transition) await self._device.set_level(level, duration, set_status=True) + @property + def color_mode(self) -> ColorMode: + """Return the color mode of the light.""" + if len(self._attr_supported_color_modes) == 1: + # The light supports only a single color mode + return list(self._attr_supported_color_modes)[0] + + # The light supports hs + color temp, determine which one it is + if self._hs_color and self._hs_color[1]: + return ColorMode.HS + return ColorMode.COLOR_TEMP + @property def brightness(self): """Return the brightness of this light between 0..255.""" @@ -214,8 +236,3 @@ class SmartThingsLight(SmartThingsEntity, LightEntity): # implemented within each device-type handler. This value is the # highest kelvin found supported across 20+ handlers. return 111 # 9000K - - @property - def supported_features(self) -> int: - """Flag supported features.""" - return self._supported_features diff --git a/tests/components/smartthings/test_light.py b/tests/components/smartthings/test_light.py index 0fff1403985..4bff370fb60 100644 --- a/tests/components/smartthings/test_light.py +++ b/tests/components/smartthings/test_light.py @@ -11,11 +11,10 @@ from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_HS_COLOR, + ATTR_SUPPORTED_COLOR_MODES, ATTR_TRANSITION, DOMAIN as LIGHT_DOMAIN, - SUPPORT_BRIGHTNESS, - SUPPORT_COLOR, - SUPPORT_COLOR_TEMP, + ColorMode, LightEntityFeature, ) from homeassistant.components.smartthings.const import DOMAIN, SIGNAL_SMARTTHINGS_UPDATE @@ -66,7 +65,7 @@ def light_devices_fixture(device_factory): Attribute.switch: "on", Attribute.level: 100, Attribute.hue: 76.0, - Attribute.saturation: 55.0, + Attribute.saturation: 0.0, Attribute.color_temperature: 4500, }, ), @@ -80,33 +79,27 @@ async def test_entity_state(hass, light_devices): # Dimmer 1 state = hass.states.get("light.dimmer_1") assert state.state == "on" - assert ( - state.attributes[ATTR_SUPPORTED_FEATURES] - == SUPPORT_BRIGHTNESS | LightEntityFeature.TRANSITION - ) + assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.BRIGHTNESS] + assert state.attributes[ATTR_SUPPORTED_FEATURES] == LightEntityFeature.TRANSITION assert isinstance(state.attributes[ATTR_BRIGHTNESS], int) assert state.attributes[ATTR_BRIGHTNESS] == 255 # Color Dimmer 1 state = hass.states.get("light.color_dimmer_1") assert state.state == "off" - assert ( - state.attributes[ATTR_SUPPORTED_FEATURES] - == SUPPORT_BRIGHTNESS | LightEntityFeature.TRANSITION | SUPPORT_COLOR - ) + assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.HS] + assert state.attributes[ATTR_SUPPORTED_FEATURES] == LightEntityFeature.TRANSITION # Color Dimmer 2 state = hass.states.get("light.color_dimmer_2") assert state.state == "on" - assert ( - state.attributes[ATTR_SUPPORTED_FEATURES] - == SUPPORT_BRIGHTNESS - | LightEntityFeature.TRANSITION - | SUPPORT_COLOR - | SUPPORT_COLOR_TEMP - ) + assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ + ColorMode.COLOR_TEMP, + ColorMode.HS, + ] + assert state.attributes[ATTR_SUPPORTED_FEATURES] == LightEntityFeature.TRANSITION assert state.attributes[ATTR_BRIGHTNESS] == 255 - assert state.attributes[ATTR_HS_COLOR] == (273.6, 55.0) + assert ATTR_HS_COLOR not in state.attributes[ATTR_HS_COLOR] assert isinstance(state.attributes[ATTR_COLOR_TEMP], int) assert state.attributes[ATTR_COLOR_TEMP] == 222