diff --git a/homeassistant/components/smartthings/light.py b/homeassistant/components/smartthings/light.py index 1b1738a94d428..2a9a3162f7bb5 100644 --- a/homeassistant/components/smartthings/light.py +++ b/homeassistant/components/smartthings/light.py @@ -11,11 +11,10 @@ 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 @@ -73,26 +72,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_features(self): + def _determine_color_modes(self): """Get features supported by the device.""" - features = 0 - # Brightness and transition - if Capability.switch_level in self._device.capabilities: - features |= SUPPORT_BRIGHTNESS | LightEntityFeature.TRANSITION + color_modes = set() # Color Temperature if Capability.color_temperature in self._device.capabilities: - features |= SUPPORT_COLOR_TEMP + color_modes.add(ColorMode.COLOR_TEMP) # Color if Capability.color_control in self._device.capabilities: - features |= SUPPORT_COLOR + 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 + # Transition + if Capability.switch_level in self._device.capabilities: + features |= LightEntityFeature.TRANSITION return features @@ -100,17 +113,17 @@ async def async_turn_on(self, **kwargs) -> None: """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) ) @@ -124,10 +137,7 @@ async def async_turn_on(self, **kwargs) -> None: async def async_turn_off(self, **kwargs) -> 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) @@ -139,17 +149,17 @@ async def async_turn_off(self, **kwargs) -> None: async def async_update(self): """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, @@ -178,6 +188,18 @@ async def async_set_level(self, brightness: int, transition: int): 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.""" @@ -213,8 +235,3 @@ def min_mireds(self): # 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 0fff14039854f..4bff370fb600f 100644 --- a/tests/components/smartthings/test_light.py +++ b/tests/components/smartthings/test_light.py @@ -11,11 +11,10 @@ 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