Return 'None' for light attributes when off instead of removing them (#101946)

pull/102275/head
Paul Bottein 2023-10-19 01:08:08 +02:00 committed by GitHub
parent 606b76c681
commit c98c18f25e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 363 additions and 111 deletions

View File

@ -1769,8 +1769,10 @@ class ModesTrait(_Trait):
elif self.state.domain == humidifier.DOMAIN:
if ATTR_MODE in attrs:
mode_settings["mode"] = attrs.get(ATTR_MODE)
elif self.state.domain == light.DOMAIN and light.ATTR_EFFECT in attrs:
mode_settings["effect"] = attrs.get(light.ATTR_EFFECT)
elif self.state.domain == light.DOMAIN and (
effect := attrs.get(light.ATTR_EFFECT)
):
mode_settings["effect"] = effect
if mode_settings:
response["on"] = self.state.state not in (STATE_OFF, STATE_UNKNOWN)

View File

@ -999,58 +999,83 @@ class LightEntity(ToggleEntity):
@property
def state_attributes(self) -> dict[str, Any] | None:
"""Return state attributes."""
if not self.is_on:
return None
data: dict[str, Any] = {}
supported_features = self.supported_features
color_mode = self._light_internal_color_mode
supported_color_modes = self._light_internal_supported_color_modes
color_mode = self._light_internal_color_mode if self.is_on else None
if color_mode not in self._light_internal_supported_color_modes:
if color_mode and color_mode not in supported_color_modes:
# Increase severity to warning in 2021.6, reject in 2021.10
_LOGGER.debug(
"%s: set to unsupported color_mode: %s, supported_color_modes: %s",
self.entity_id,
color_mode,
self._light_internal_supported_color_modes,
supported_color_modes,
)
data[ATTR_COLOR_MODE] = color_mode
if color_mode in COLOR_MODES_BRIGHTNESS:
data[ATTR_BRIGHTNESS] = self.brightness
if brightness_supported(self.supported_color_modes):
if color_mode in COLOR_MODES_BRIGHTNESS:
data[ATTR_BRIGHTNESS] = self.brightness
else:
data[ATTR_BRIGHTNESS] = None
elif supported_features & SUPPORT_BRIGHTNESS:
# Backwards compatibility for ambiguous / incomplete states
# Add warning in 2021.6, remove in 2021.10
data[ATTR_BRIGHTNESS] = self.brightness
if color_mode == ColorMode.COLOR_TEMP:
data[ATTR_COLOR_TEMP_KELVIN] = self.color_temp_kelvin
if not self.color_temp_kelvin:
data[ATTR_COLOR_TEMP] = None
if self.is_on:
data[ATTR_BRIGHTNESS] = self.brightness
else:
data[ATTR_COLOR_TEMP] = color_util.color_temperature_kelvin_to_mired(
self.color_temp_kelvin
)
data[ATTR_BRIGHTNESS] = None
if color_mode in COLOR_MODES_COLOR or color_mode == ColorMode.COLOR_TEMP:
data.update(self._light_internal_convert_color(color_mode))
if supported_features & SUPPORT_COLOR_TEMP and not self.supported_color_modes:
if color_temp_supported(self.supported_color_modes):
if color_mode == ColorMode.COLOR_TEMP:
data[ATTR_COLOR_TEMP_KELVIN] = self.color_temp_kelvin
if self.color_temp_kelvin:
data[
ATTR_COLOR_TEMP
] = color_util.color_temperature_kelvin_to_mired(
self.color_temp_kelvin
)
else:
data[ATTR_COLOR_TEMP] = None
else:
data[ATTR_COLOR_TEMP_KELVIN] = None
data[ATTR_COLOR_TEMP] = None
elif supported_features & SUPPORT_COLOR_TEMP:
# Backwards compatibility
# Add warning in 2021.6, remove in 2021.10
data[ATTR_COLOR_TEMP_KELVIN] = self.color_temp_kelvin
if not self.color_temp_kelvin:
data[ATTR_COLOR_TEMP] = None
if self.is_on:
data[ATTR_COLOR_TEMP_KELVIN] = self.color_temp_kelvin
if self.color_temp_kelvin:
data[
ATTR_COLOR_TEMP
] = color_util.color_temperature_kelvin_to_mired(
self.color_temp_kelvin
)
else:
data[ATTR_COLOR_TEMP] = None
else:
data[ATTR_COLOR_TEMP] = color_util.color_temperature_kelvin_to_mired(
self.color_temp_kelvin
)
data[ATTR_COLOR_TEMP_KELVIN] = None
data[ATTR_COLOR_TEMP] = None
if color_supported(supported_color_modes) or color_temp_supported(
supported_color_modes
):
data[ATTR_HS_COLOR] = None
data[ATTR_RGB_COLOR] = None
data[ATTR_XY_COLOR] = None
if ColorMode.RGBW in supported_color_modes:
data[ATTR_RGBW_COLOR] = None
if ColorMode.RGBWW in supported_color_modes:
data[ATTR_RGBWW_COLOR] = None
if color_mode:
data.update(self._light_internal_convert_color(color_mode))
if supported_features & LightEntityFeature.EFFECT:
data[ATTR_EFFECT] = self.effect
data[ATTR_EFFECT] = self.effect if self.is_on else None
return {key: val for key, val in data.items() if val is not None}
return data
@property
def _light_internal_supported_color_modes(self) -> set[ColorMode] | set[str]:

View File

@ -197,7 +197,7 @@ async def test_dimmer_off(dimmer, hass: HomeAssistant) -> None:
state = hass.states.get(entity_id)
assert state.state == STATE_OFF
assert ATTR_BRIGHTNESS not in state.attributes
assert state.attributes[ATTR_BRIGHTNESS] is None
@pytest.fixture(name="wlightbox_s")
@ -236,7 +236,7 @@ async def test_wlightbox_s_init(wlightbox_s, hass: HomeAssistant) -> None:
color_modes = state.attributes[ATTR_SUPPORTED_COLOR_MODES]
assert color_modes == [ColorMode.BRIGHTNESS]
assert ATTR_BRIGHTNESS not in state.attributes
assert state.attributes[ATTR_BRIGHTNESS] is None
assert state.state == STATE_UNKNOWN
device_registry = dr.async_get(hass)
@ -339,8 +339,8 @@ async def test_wlightbox_init(wlightbox, hass: HomeAssistant) -> None:
color_modes = state.attributes[ATTR_SUPPORTED_COLOR_MODES]
assert color_modes == [ColorMode.RGBW]
assert ATTR_BRIGHTNESS not in state.attributes
assert ATTR_RGBW_COLOR not in state.attributes
assert state.attributes[ATTR_BRIGHTNESS] is None
assert state.attributes[ATTR_RGBW_COLOR] is None
assert state.state == STATE_UNKNOWN
device_registry = dr.async_get(hass)
@ -487,7 +487,7 @@ async def test_wlightbox_off(wlightbox, hass: HomeAssistant) -> None:
)
state = hass.states.get(entity_id)
assert ATTR_RGBW_COLOR not in state.attributes
assert state.attributes[ATTR_RGBW_COLOR] is None
assert state.state == STATE_OFF

View File

@ -726,7 +726,7 @@ async def test_brightness_support(hass: HomeAssistant) -> None:
state = hass.states.get("light.name_1")
assert state.state == "off"
assert ATTR_COLOR_MODE not in state.attributes
assert state.attributes[ATTR_COLOR_MODE] is None
assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.BRIGHTNESS]
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
@ -752,7 +752,7 @@ async def test_brightness_not_supported(hass: HomeAssistant) -> None:
state = hass.states.get("light.name_1")
assert state.state == "off"
assert ATTR_COLOR_MODE not in state.attributes
assert state.attributes[ATTR_COLOR_MODE] is None
assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.ONOFF]
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0

View File

@ -1184,9 +1184,9 @@ async def test_non_color_light_reports_color(
await hass.async_block_till_done()
# Bug is fixed if we reach this point, but device won't have neither color temp nor color
with pytest.raises(KeyError):
assert hass.states.get("light.group").attributes[ATTR_COLOR_TEMP]
assert hass.states.get("light.group").attributes[ATTR_HS_COLOR]
with pytest.raises(AssertionError):
assert hass.states.get("light.group").attributes.get(ATTR_COLOR_TEMP) is None
assert hass.states.get("light.group").attributes.get(ATTR_HS_COLOR) is None
async def test_verify_group_supported_features(

View File

@ -220,6 +220,8 @@
'attributes': ReadOnlyDict({
'brightness': 128,
'color_mode': <ColorMode.HS: 'hs'>,
'color_temp': None,
'color_temp_kelvin': None,
'friendly_name': 'Frenck',
'hs_color': tuple(
358.0,

View File

@ -96,7 +96,7 @@ async def test_setup_non_color_non_level(hass: HomeAssistant, fritz: Mock) -> No
assert state
assert state.state == STATE_ON
assert state.attributes[ATTR_FRIENDLY_NAME] == "fake_name"
assert state.attributes[ATTR_BRIGHTNESS] == 100
assert ATTR_BRIGHTNESS not in state.attributes
assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == ["onoff"]

View File

@ -1646,11 +1646,16 @@
}),
'state': dict({
'attributes': dict({
'brightness': None,
'color_mode': None,
'friendly_name': 'Aqara Hub-1563 Lightbulb-1563',
'hs_color': None,
'rgb_color': None,
'supported_color_modes': list([
<ColorMode.HS: 'hs'>,
]),
'supported_features': <LightEntityFeature: 0>,
'xy_color': None,
}),
'entity_id': 'light.aqara_hub_1563_lightbulb_1563',
'state': 'off',
@ -2027,11 +2032,16 @@
}),
'state': dict({
'attributes': dict({
'brightness': None,
'color_mode': None,
'friendly_name': 'ArloBabyA0 Nightlight',
'hs_color': None,
'rgb_color': None,
'supported_color_modes': list([
<ColorMode.HS: 'hs'>,
]),
'supported_features': <LightEntityFeature: 0>,
'xy_color': None,
}),
'entity_id': 'light.arlobabya0_nightlight',
'state': 'off',
@ -7231,15 +7241,22 @@
}),
'state': dict({
'attributes': dict({
'brightness': None,
'color_mode': None,
'color_temp': None,
'color_temp_kelvin': None,
'friendly_name': 'Hue ambiance candle',
'hs_color': None,
'max_color_temp_kelvin': 6535,
'max_mireds': 454,
'min_color_temp_kelvin': 2202,
'min_mireds': 153,
'rgb_color': None,
'supported_color_modes': list([
<ColorMode.COLOR_TEMP: 'color_temp'>,
]),
'supported_features': <LightEntityFeature: 0>,
'xy_color': None,
}),
'entity_id': 'light.hue_ambiance_candle_4',
'state': 'off',
@ -7348,15 +7365,22 @@
}),
'state': dict({
'attributes': dict({
'brightness': None,
'color_mode': None,
'color_temp': None,
'color_temp_kelvin': None,
'friendly_name': 'Hue ambiance candle',
'hs_color': None,
'max_color_temp_kelvin': 6535,
'max_mireds': 454,
'min_color_temp_kelvin': 2202,
'min_mireds': 153,
'rgb_color': None,
'supported_color_modes': list([
<ColorMode.COLOR_TEMP: 'color_temp'>,
]),
'supported_features': <LightEntityFeature: 0>,
'xy_color': None,
}),
'entity_id': 'light.hue_ambiance_candle_3',
'state': 'off',
@ -7465,15 +7489,22 @@
}),
'state': dict({
'attributes': dict({
'brightness': None,
'color_mode': None,
'color_temp': None,
'color_temp_kelvin': None,
'friendly_name': 'Hue ambiance candle',
'hs_color': None,
'max_color_temp_kelvin': 6535,
'max_mireds': 454,
'min_color_temp_kelvin': 2202,
'min_mireds': 153,
'rgb_color': None,
'supported_color_modes': list([
<ColorMode.COLOR_TEMP: 'color_temp'>,
]),
'supported_features': <LightEntityFeature: 0>,
'xy_color': None,
}),
'entity_id': 'light.hue_ambiance_candle_2',
'state': 'off',
@ -7582,15 +7613,22 @@
}),
'state': dict({
'attributes': dict({
'brightness': None,
'color_mode': None,
'color_temp': None,
'color_temp_kelvin': None,
'friendly_name': 'Hue ambiance candle',
'hs_color': None,
'max_color_temp_kelvin': 6535,
'max_mireds': 454,
'min_color_temp_kelvin': 2202,
'min_mireds': 153,
'rgb_color': None,
'supported_color_modes': list([
<ColorMode.COLOR_TEMP: 'color_temp'>,
]),
'supported_features': <LightEntityFeature: 0>,
'xy_color': None,
}),
'entity_id': 'light.hue_ambiance_candle',
'state': 'off',
@ -8250,6 +8288,8 @@
}),
'state': dict({
'attributes': dict({
'brightness': None,
'color_mode': None,
'friendly_name': 'Hue white lamp',
'supported_color_modes': list([
<ColorMode.BRIGHTNESS: 'brightness'>,
@ -8359,6 +8399,8 @@
}),
'state': dict({
'attributes': dict({
'brightness': None,
'color_mode': None,
'friendly_name': 'Hue white lamp',
'supported_color_modes': list([
<ColorMode.BRIGHTNESS: 'brightness'>,
@ -8468,6 +8510,8 @@
}),
'state': dict({
'attributes': dict({
'brightness': None,
'color_mode': None,
'friendly_name': 'Hue white lamp',
'supported_color_modes': list([
<ColorMode.BRIGHTNESS: 'brightness'>,
@ -8577,6 +8621,8 @@
}),
'state': dict({
'attributes': dict({
'brightness': None,
'color_mode': None,
'friendly_name': 'Hue white lamp',
'supported_color_modes': list([
<ColorMode.BRIGHTNESS: 'brightness'>,
@ -8686,6 +8732,8 @@
}),
'state': dict({
'attributes': dict({
'brightness': None,
'color_mode': None,
'friendly_name': 'Hue white lamp',
'supported_color_modes': list([
<ColorMode.BRIGHTNESS: 'brightness'>,
@ -8795,6 +8843,8 @@
}),
'state': dict({
'attributes': dict({
'brightness': None,
'color_mode': None,
'friendly_name': 'Hue white lamp',
'supported_color_modes': list([
<ColorMode.BRIGHTNESS: 'brightness'>,
@ -8904,6 +8954,8 @@
}),
'state': dict({
'attributes': dict({
'brightness': None,
'color_mode': None,
'friendly_name': 'Hue white lamp',
'supported_color_modes': list([
<ColorMode.BRIGHTNESS: 'brightness'>,
@ -9082,11 +9134,16 @@
}),
'state': dict({
'attributes': dict({
'brightness': None,
'color_mode': None,
'friendly_name': 'Koogeek-LS1-20833F Light Strip',
'hs_color': None,
'rgb_color': None,
'supported_color_modes': list([
<ColorMode.HS: 'hs'>,
]),
'supported_features': <LightEntityFeature: 0>,
'xy_color': None,
}),
'entity_id': 'light.koogeek_ls1_20833f_light_strip',
'state': 'off',
@ -10544,6 +10601,8 @@
}),
'state': dict({
'attributes': dict({
'brightness': None,
'color_mode': None,
'friendly_name': 'Mysa-85dda9 Display',
'supported_color_modes': list([
<ColorMode.BRIGHTNESS: 'brightness'>,
@ -10828,6 +10887,8 @@
'attributes': dict({
'brightness': 255.0,
'color_mode': <ColorMode.HS: 'hs'>,
'color_temp': None,
'color_temp_kelvin': None,
'friendly_name': 'Nanoleaf Strip 3B32 Nanoleaf Light Strip',
'hs_color': tuple(
30.0,

View File

@ -270,6 +270,11 @@ async def test_config_entry(
"friendly_name": "Koogeek-LS1-20833F Light Strip",
"supported_color_modes": ["hs"],
"supported_features": 0,
"brightness": None,
"color_mode": None,
"hs_color": None,
"rgb_color": None,
"xy_color": None,
},
"entity_id": "light.koogeek_ls1_20833f_light_strip",
"last_changed": ANY,
@ -541,6 +546,11 @@ async def test_device(
"friendly_name": "Koogeek-LS1-20833F Light Strip",
"supported_color_modes": ["hs"],
"supported_features": 0,
"brightness": None,
"color_mode": None,
"hs_color": None,
"rgb_color": None,
"xy_color": None,
},
"entity_id": "light.koogeek_ls1_20833f_light_strip",
"last_changed": ANY,

View File

@ -114,7 +114,7 @@ async def test_switch_read_light_state_dimmer(hass: HomeAssistant, utcnow) -> No
# Initial state is that the light is off
state = await helper.poll_and_get_state()
assert state.state == "off"
assert ATTR_COLOR_MODE not in state.attributes
assert state.attributes[ATTR_COLOR_MODE] is None
assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.BRIGHTNESS]
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
@ -177,7 +177,7 @@ async def test_switch_read_light_state_hs(hass: HomeAssistant, utcnow) -> None:
# Initial state is that the light is off
state = await helper.poll_and_get_state()
assert state.state == "off"
assert ATTR_COLOR_MODE not in state.attributes
assert state.attributes[ATTR_COLOR_MODE] is None
assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.HS]
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
@ -246,7 +246,7 @@ async def test_switch_read_light_state_color_temp(hass: HomeAssistant, utcnow) -
# Initial state is that the light is off
state = await helper.poll_and_get_state()
assert state.state == "off"
assert ATTR_COLOR_MODE not in state.attributes
assert state.attributes[ATTR_COLOR_MODE] is None
assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.COLOR_TEMP]
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0

View File

@ -55,7 +55,7 @@ async def test_hmip_light(hass: HomeAssistant, default_mock_hap_factory) -> None
await async_manipulate_test_data(hass, hmip_device, "on", False)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_OFF
assert ATTR_COLOR_MODE not in ha_state.attributes
assert ha_state.attributes[ATTR_COLOR_MODE] is None
assert ha_state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.ONOFF]
assert ha_state.attributes[ATTR_SUPPORTED_FEATURES] == 0
@ -87,7 +87,7 @@ async def test_hmip_notification_light(
)
assert ha_state.state == STATE_OFF
assert ATTR_COLOR_MODE not in ha_state.attributes
assert ha_state.attributes[ATTR_COLOR_MODE] is None
assert ha_state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.HS]
assert ha_state.attributes[ATTR_SUPPORTED_FEATURES] == LightEntityFeature.TRANSITION
service_call_counter = len(hmip_device.mock_calls)
@ -184,7 +184,7 @@ async def test_hmip_dimmer(hass: HomeAssistant, default_mock_hap_factory) -> Non
)
assert ha_state.state == STATE_OFF
assert ATTR_COLOR_MODE not in ha_state.attributes
assert ha_state.attributes[ATTR_COLOR_MODE] is None
assert ha_state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.BRIGHTNESS]
assert ha_state.attributes[ATTR_SUPPORTED_FEATURES] == 0
service_call_counter = len(hmip_device.mock_calls)
@ -244,7 +244,7 @@ async def test_hmip_light_measuring(
)
assert ha_state.state == STATE_OFF
assert ATTR_COLOR_MODE not in ha_state.attributes
assert ha_state.attributes[ATTR_COLOR_MODE] is None
assert ha_state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.ONOFF]
assert ha_state.attributes[ATTR_SUPPORTED_FEATURES] == 0
service_call_counter = len(hmip_device.mock_calls)
@ -290,7 +290,7 @@ async def test_hmip_wired_multi_dimmer(
)
assert ha_state.state == STATE_OFF
assert ATTR_COLOR_MODE not in ha_state.attributes
assert ha_state.attributes[ATTR_COLOR_MODE] is None
assert ha_state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.BRIGHTNESS]
assert ha_state.attributes[ATTR_SUPPORTED_FEATURES] == 0
service_call_counter = len(hmip_device.mock_calls)

View File

@ -242,7 +242,7 @@ async def test_lights_color_mode(hass: HomeAssistant, mock_bridge_v1) -> None:
assert lamp_1.state == "on"
assert lamp_1.attributes["brightness"] == 145
assert lamp_1.attributes["hs_color"] == (36.067, 69.804)
assert "color_temp" not in lamp_1.attributes
assert lamp_1.attributes["color_temp"] is None
assert lamp_1.attributes["color_mode"] == ColorMode.HS
assert lamp_1.attributes["supported_color_modes"] == [
ColorMode.COLOR_TEMP,

View File

@ -71,6 +71,12 @@ async def test_init(hass: HomeAssistant, mock_light) -> None:
ATTR_FRIENDLY_NAME: "Bedroom",
ATTR_SUPPORTED_COLOR_MODES: [ColorMode.RGBW],
ATTR_SUPPORTED_FEATURES: 0,
ATTR_COLOR_MODE: None,
ATTR_BRIGHTNESS: None,
ATTR_HS_COLOR: None,
ATTR_RGB_COLOR: None,
ATTR_XY_COLOR: None,
ATTR_RGBW_COLOR: None,
}
with patch.object(hass.loop, "stop"):
@ -191,6 +197,12 @@ async def test_light_update(hass: HomeAssistant, mock_light) -> None:
ATTR_FRIENDLY_NAME: "Bedroom",
ATTR_SUPPORTED_COLOR_MODES: [ColorMode.RGBW],
ATTR_SUPPORTED_FEATURES: 0,
ATTR_COLOR_MODE: None,
ATTR_BRIGHTNESS: None,
ATTR_HS_COLOR: None,
ATTR_RGB_COLOR: None,
ATTR_RGBW_COLOR: None,
ATTR_XY_COLOR: None,
}
# Test an exception during discovery

View File

@ -1151,28 +1151,28 @@ async def test_light_backwards_compatibility_supported_color_modes(
state = hass.states.get(entity0.entity_id)
assert state.attributes["supported_color_modes"] == [light.ColorMode.ONOFF]
if light_state == STATE_OFF:
assert "color_mode" not in state.attributes
assert state.attributes["color_mode"] is None
else:
assert state.attributes["color_mode"] == light.ColorMode.ONOFF
state = hass.states.get(entity1.entity_id)
assert state.attributes["supported_color_modes"] == [light.ColorMode.BRIGHTNESS]
if light_state == STATE_OFF:
assert "color_mode" not in state.attributes
assert state.attributes["color_mode"] is None
else:
assert state.attributes["color_mode"] == light.ColorMode.UNKNOWN
state = hass.states.get(entity2.entity_id)
assert state.attributes["supported_color_modes"] == [light.ColorMode.COLOR_TEMP]
if light_state == STATE_OFF:
assert "color_mode" not in state.attributes
assert state.attributes["color_mode"] is None
else:
assert state.attributes["color_mode"] == light.ColorMode.UNKNOWN
state = hass.states.get(entity3.entity_id)
assert state.attributes["supported_color_modes"] == [light.ColorMode.HS]
if light_state == STATE_OFF:
assert "color_mode" not in state.attributes
assert state.attributes["color_mode"] is None
else:
assert state.attributes["color_mode"] == light.ColorMode.UNKNOWN
@ -1182,7 +1182,7 @@ async def test_light_backwards_compatibility_supported_color_modes(
light.ColorMode.HS,
]
if light_state == STATE_OFF:
assert "color_mode" not in state.attributes
assert state.attributes["color_mode"] is None
else:
assert state.attributes["color_mode"] == light.ColorMode.UNKNOWN
@ -1285,6 +1285,79 @@ async def test_light_service_call_rgbw(
assert data == {"brightness": 255, "rgbw_color": (10, 20, 30, 40)}
async def test_light_state_off(
hass: HomeAssistant, enable_custom_integrations: None
) -> None:
"""Test rgbw color conversion in state updates."""
platform = getattr(hass.components, "test.light")
platform.init(empty=True)
platform.ENTITIES.append(platform.MockLight("Test_onoff", STATE_OFF))
platform.ENTITIES.append(platform.MockLight("Test_brightness", STATE_OFF))
platform.ENTITIES.append(platform.MockLight("Test_ct", STATE_OFF))
platform.ENTITIES.append(platform.MockLight("Test_rgbw", STATE_OFF))
entity0 = platform.ENTITIES[0]
entity0.supported_color_modes = {light.ColorMode.ONOFF}
entity1 = platform.ENTITIES[1]
entity1.supported_color_modes = {light.ColorMode.BRIGHTNESS}
entity2 = platform.ENTITIES[2]
entity2.supported_color_modes = {light.ColorMode.COLOR_TEMP}
entity3 = platform.ENTITIES[3]
entity3.supported_color_modes = {light.ColorMode.RGBW}
assert await async_setup_component(hass, "light", {"light": {"platform": "test"}})
await hass.async_block_till_done()
state = hass.states.get(entity0.entity_id)
assert state.attributes == {
"color_mode": None,
"friendly_name": "Test_onoff",
"supported_color_modes": [light.ColorMode.ONOFF],
"supported_features": 0,
}
state = hass.states.get(entity1.entity_id)
assert state.attributes == {
"color_mode": None,
"friendly_name": "Test_brightness",
"supported_color_modes": [light.ColorMode.BRIGHTNESS],
"supported_features": 0,
"brightness": None,
}
state = hass.states.get(entity2.entity_id)
assert state.attributes == {
"color_mode": None,
"friendly_name": "Test_ct",
"supported_color_modes": [light.ColorMode.COLOR_TEMP],
"supported_features": 0,
"brightness": None,
"color_temp": None,
"color_temp_kelvin": None,
"hs_color": None,
"rgb_color": None,
"xy_color": None,
"max_color_temp_kelvin": 6500,
"max_mireds": 500,
"min_color_temp_kelvin": 2000,
"min_mireds": 153,
}
state = hass.states.get(entity3.entity_id)
assert state.attributes == {
"color_mode": None,
"friendly_name": "Test_rgbw",
"supported_color_modes": [light.ColorMode.RGBW],
"supported_features": 0,
"brightness": None,
"rgbw_color": None,
"hs_color": None,
"rgb_color": None,
"xy_color": None,
}
async def test_light_state_rgbw(
hass: HomeAssistant, enable_custom_integrations: None
) -> None:
@ -1295,6 +1368,7 @@ async def test_light_state_rgbw(
platform.ENTITIES.append(platform.MockLight("Test_rgbw", STATE_ON))
entity0 = platform.ENTITIES[0]
entity0.brightness = 255
entity0.supported_color_modes = {light.ColorMode.RGBW}
entity0.color_mode = light.ColorMode.RGBW
entity0.hs_color = "Invalid" # Should be ignored
@ -1316,6 +1390,7 @@ async def test_light_state_rgbw(
"rgb_color": (3, 3, 4),
"rgbw_color": (1, 2, 3, 4),
"xy_color": (0.301, 0.295),
"brightness": 255,
}
@ -1336,12 +1411,13 @@ async def test_light_state_rgbww(
entity0.rgbw_color = "Invalid" # Should be ignored
entity0.rgbww_color = (1, 2, 3, 4, 5)
entity0.xy_color = "Invalid" # Should be ignored
entity0.brightness = 255
assert await async_setup_component(hass, "light", {"light": {"platform": "test"}})
await hass.async_block_till_done()
state = hass.states.get(entity0.entity_id)
assert dict(state.attributes) == {
assert state.attributes == {
"color_mode": light.ColorMode.RGBWW,
"friendly_name": "Test_rgbww",
"supported_color_modes": [light.ColorMode.RGBWW],
@ -1350,6 +1426,7 @@ async def test_light_state_rgbww(
"rgb_color": (5, 5, 4),
"rgbww_color": (1, 2, 3, 4, 5),
"xy_color": (0.339, 0.354),
"brightness": 255,
}

View File

@ -8,7 +8,7 @@ import pytest
from homeassistant.components import light
from homeassistant.components.light import (
ATTR_EFFECT,
ATTR_EFFECT_LIST,
ATTR_MAX_COLOR_TEMP_KELVIN,
ATTR_MAX_MIREDS,
ATTR_MIN_COLOR_TEMP_KELVIN,
@ -57,7 +57,7 @@ async def test_exclude_attributes(recorder_mock: Recorder, hass: HomeAssistant)
assert ATTR_MIN_MIREDS not in state.attributes
assert ATTR_MAX_MIREDS not in state.attributes
assert ATTR_SUPPORTED_COLOR_MODES not in state.attributes
assert ATTR_EFFECT not in state.attributes
assert ATTR_EFFECT_LIST not in state.attributes
assert ATTR_FRIENDLY_NAME in state.attributes
assert ATTR_MAX_COLOR_TEMP_KELVIN not in state.attributes
assert ATTR_MIN_COLOR_TEMP_KELVIN not in state.attributes

View File

@ -525,7 +525,7 @@ async def test_controlling_state_via_topic(
async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON", "color_temp":null}')
light_state = hass.states.get("light.test")
assert "color_temp" not in light_state.attributes
assert light_state.attributes.get("color_temp") is None
async_fire_mqtt_message(
hass, "test_light_rgb", '{"state":"ON", "effect":"colorloop"}'
@ -983,8 +983,8 @@ async def test_sending_mqtt_commands_and_optimistic2(
assert state.attributes["hs_color"] == (359, 78)
assert state.attributes["rgb_color"] == (255, 56, 59)
assert state.attributes["xy_color"] == (0.654, 0.301)
assert "rgbw_color" not in state.attributes
assert "rgbww_color" not in state.attributes
assert state.attributes["rgbw_color"] is None
assert state.attributes["rgbww_color"] is None
mqtt_mock.async_publish.assert_called_once_with(
"test_light_rgb/set",
JsonValidator(
@ -1004,8 +1004,8 @@ async def test_sending_mqtt_commands_and_optimistic2(
assert state.attributes["hs_color"] == (30.118, 100.0)
assert state.attributes["rgb_color"] == (255, 128, 0)
assert state.attributes["xy_color"] == (0.611, 0.375)
assert "rgbw_color" not in state.attributes
assert "rgbww_color" not in state.attributes
assert state.attributes["rgbw_color"] is None
assert state.attributes["rgbww_color"] is None
mqtt_mock.async_publish.assert_called_once_with(
"test_light_rgb/set",
JsonValidator('{"state": "ON", "color": {"r": 255, "g": 128, "b": 0} }'),
@ -1023,7 +1023,7 @@ async def test_sending_mqtt_commands_and_optimistic2(
assert state.attributes["rgbw_color"] == (255, 128, 0, 123)
assert state.attributes["hs_color"] == (30.0, 67.451)
assert state.attributes["rgb_color"] == (255, 169, 83)
assert "rgbww_color" not in state.attributes
assert state.attributes["rgbww_color"] is None
assert state.attributes["xy_color"] == (0.526, 0.393)
mqtt_mock.async_publish.assert_called_once_with(
"test_light_rgb/set",
@ -1044,7 +1044,7 @@ async def test_sending_mqtt_commands_and_optimistic2(
assert state.attributes["rgbww_color"] == (255, 128, 0, 45, 32)
assert state.attributes["hs_color"] == (29.872, 92.157)
assert state.attributes["rgb_color"] == (255, 137, 20)
assert "rgbw_color" not in state.attributes
assert state.attributes["rgbw_color"] is None
assert state.attributes["xy_color"] == (0.596, 0.382)
mqtt_mock.async_publish.assert_called_once_with(
"test_light_rgb/set",
@ -1067,8 +1067,8 @@ async def test_sending_mqtt_commands_and_optimistic2(
assert state.attributes["hs_color"] == (196.471, 100.0)
assert state.attributes["rgb_color"] == (0, 185, 255)
assert state.attributes["xy_color"] == (0.123, 0.223)
assert "rgbw_color" not in state.attributes
assert "rgbww_color" not in state.attributes
assert state.attributes["rgbw_color"] is None
assert state.attributes["rgbww_color"] is None
mqtt_mock.async_publish.assert_called_once_with(
"test_light_rgb/set",
JsonValidator(
@ -1085,11 +1085,11 @@ async def test_sending_mqtt_commands_and_optimistic2(
assert state.state == STATE_ON
assert state.attributes["brightness"] == 75
assert state.attributes["color_mode"] == "white"
assert "hs_color" not in state.attributes
assert "rgb_color" not in state.attributes
assert "xy_color" not in state.attributes
assert "rgbw_color" not in state.attributes
assert "rgbww_color" not in state.attributes
assert state.attributes["hs_color"] is None
assert state.attributes["rgb_color"] is None
assert state.attributes["xy_color"] is None
assert state.attributes["rgbw_color"] is None
assert state.attributes["rgbww_color"] is None
mqtt_mock.async_publish.assert_called_once_with(
"test_light_rgb/set",
JsonValidator('{"state": "ON", "white": 75}'),
@ -1104,11 +1104,11 @@ async def test_sending_mqtt_commands_and_optimistic2(
assert state.state == STATE_ON
assert state.attributes["brightness"] == 60
assert state.attributes["color_mode"] == "white"
assert "hs_color" not in state.attributes
assert "rgb_color" not in state.attributes
assert "xy_color" not in state.attributes
assert "rgbw_color" not in state.attributes
assert "rgbww_color" not in state.attributes
assert state.attributes["hs_color"] is None
assert state.attributes["rgb_color"] is None
assert state.attributes["xy_color"] is None
assert state.attributes["rgbw_color"] is None
assert state.attributes["rgbww_color"] is None
mqtt_mock.async_publish.assert_called_once_with(
"test_light_rgb/set",
JsonValidator('{"state": "ON", "white": 60}'),

View File

@ -351,7 +351,7 @@ async def test_controlling_state_via_mqtt_on_off(
state = hass.states.get("light.tasmota_test")
assert state.state == STATE_OFF
assert not state.attributes.get(ATTR_ASSUMED_STATE)
assert "color_mode" not in state.attributes
assert not state.attributes["color_mode"]
async_fire_mqtt_message(hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"ON"}')
state = hass.states.get("light.tasmota_test")
@ -361,7 +361,7 @@ async def test_controlling_state_via_mqtt_on_off(
async_fire_mqtt_message(hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"OFF"}')
state = hass.states.get("light.tasmota_test")
assert state.state == STATE_OFF
assert "color_mode" not in state.attributes
assert not state.attributes["color_mode"]
async_fire_mqtt_message(hass, "tasmota_49A3BC/stat/RESULT", '{"POWER":"ON"}')
@ -373,7 +373,7 @@ async def test_controlling_state_via_mqtt_on_off(
state = hass.states.get("light.tasmota_test")
assert state.state == STATE_OFF
assert "color_mode" not in state.attributes
assert not state.attributes["color_mode"]
async def test_controlling_state_via_mqtt_ct(
@ -402,7 +402,7 @@ async def test_controlling_state_via_mqtt_ct(
state = hass.states.get("light.tasmota_test")
assert state.state == STATE_OFF
assert not state.attributes.get(ATTR_ASSUMED_STATE)
assert "color_mode" not in state.attributes
assert not state.attributes["color_mode"]
async_fire_mqtt_message(hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"ON"}')
state = hass.states.get("light.tasmota_test")
@ -412,7 +412,7 @@ async def test_controlling_state_via_mqtt_ct(
async_fire_mqtt_message(hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"OFF"}')
state = hass.states.get("light.tasmota_test")
assert state.state == STATE_OFF
assert "color_mode" not in state.attributes
assert not state.attributes["color_mode"]
async_fire_mqtt_message(
hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"ON","Dimmer":50}'
@ -467,7 +467,7 @@ async def test_controlling_state_via_mqtt_rgbw(
state = hass.states.get("light.tasmota_test")
assert state.state == STATE_OFF
assert not state.attributes.get(ATTR_ASSUMED_STATE)
assert "color_mode" not in state.attributes
assert not state.attributes["color_mode"]
async_fire_mqtt_message(hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"ON"}')
state = hass.states.get("light.tasmota_test")
@ -477,7 +477,7 @@ async def test_controlling_state_via_mqtt_rgbw(
async_fire_mqtt_message(hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"OFF"}')
state = hass.states.get("light.tasmota_test")
assert state.state == STATE_OFF
assert "color_mode" not in state.attributes
assert not state.attributes["color_mode"]
async_fire_mqtt_message(
hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"ON","Dimmer":50,"White":0}'
@ -568,7 +568,7 @@ async def test_controlling_state_via_mqtt_rgbww(
state = hass.states.get("light.tasmota_test")
assert state.state == STATE_OFF
assert not state.attributes.get(ATTR_ASSUMED_STATE)
assert "color_mode" not in state.attributes
assert not state.attributes["color_mode"]
async_fire_mqtt_message(hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"ON"}')
state = hass.states.get("light.tasmota_test")
@ -578,7 +578,7 @@ async def test_controlling_state_via_mqtt_rgbww(
async_fire_mqtt_message(hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"OFF"}')
state = hass.states.get("light.tasmota_test")
assert state.state == STATE_OFF
assert "color_mode" not in state.attributes
assert not state.attributes["color_mode"]
async_fire_mqtt_message(
hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"ON","Dimmer":50}'
@ -604,7 +604,7 @@ async def test_controlling_state_via_mqtt_rgbww(
state = hass.states.get("light.tasmota_test")
assert state.state == STATE_ON
# Setting white > 0 should clear the color
assert "rgb_color" not in state.attributes
assert not state.attributes.get("hs_color")
assert state.attributes.get("color_mode") == "color_temp"
async_fire_mqtt_message(
@ -621,7 +621,7 @@ async def test_controlling_state_via_mqtt_rgbww(
state = hass.states.get("light.tasmota_test")
assert state.state == STATE_ON
# Setting white to 0 should clear the color_temp
assert "color_temp" not in state.attributes
assert not state.attributes.get("color_temp")
assert state.attributes.get("hs_color") == (30, 100)
assert state.attributes.get("color_mode") == "hs"
@ -670,7 +670,7 @@ async def test_controlling_state_via_mqtt_rgbww_tuya(
state = hass.states.get("light.tasmota_test")
assert state.state == STATE_OFF
assert not state.attributes.get(ATTR_ASSUMED_STATE)
assert "color_mode" not in state.attributes
assert not state.attributes["color_mode"]
async_fire_mqtt_message(hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"ON"}')
state = hass.states.get("light.tasmota_test")
@ -680,7 +680,7 @@ async def test_controlling_state_via_mqtt_rgbww_tuya(
async_fire_mqtt_message(hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"OFF"}')
state = hass.states.get("light.tasmota_test")
assert state.state == STATE_OFF
assert "color_mode" not in state.attributes
assert not state.attributes["color_mode"]
async_fire_mqtt_message(
hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"ON","Dimmer":50}'
@ -716,7 +716,7 @@ async def test_controlling_state_via_mqtt_rgbww_tuya(
state = hass.states.get("light.tasmota_test")
assert state.state == STATE_ON
# Setting white > 0 should clear the color
assert "rgb_color" not in state.attributes
assert not state.attributes.get("hs_color")
assert state.attributes.get("color_mode") == "color_temp"
async_fire_mqtt_message(

View File

@ -130,7 +130,7 @@ async def test_template_state_invalid(
"""Test template state with render error."""
state = hass.states.get("light.test_template_light")
assert state.state == STATE_OFF
assert "color_mode" not in state.attributes
assert state.attributes["color_mode"] is None
assert state.attributes["supported_color_modes"] == supported_color_modes
assert state.attributes["supported_features"] == supported_features
@ -163,7 +163,7 @@ async def test_template_state_text(hass: HomeAssistant, setup_light) -> None:
await hass.async_block_till_done()
state = hass.states.get("light.test_template_light")
assert state.state == set_state
assert "color_mode" not in state.attributes
assert state.attributes["color_mode"] is None
assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
assert state.attributes["supported_features"] == 0
@ -281,7 +281,7 @@ async def test_on_action(hass: HomeAssistant, setup_light, calls) -> None:
state = hass.states.get("light.test_template_light")
assert state.state == STATE_OFF
assert "color_mode" not in state.attributes
assert state.attributes["color_mode"] is None
assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
assert state.attributes["supported_features"] == 0
@ -297,7 +297,7 @@ async def test_on_action(hass: HomeAssistant, setup_light, calls) -> None:
assert calls[-1].data["caller"] == "light.test_template_light"
assert state.state == STATE_OFF
assert "color_mode" not in state.attributes
assert state.attributes["color_mode"] is None
assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
assert state.attributes["supported_features"] == 0
@ -341,7 +341,7 @@ async def test_on_action_with_transition(
state = hass.states.get("light.test_template_light")
assert state.state == STATE_OFF
assert "color_mode" not in state.attributes
assert state.attributes["color_mode"] is None
assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
assert state.attributes["supported_features"] == LightEntityFeature.TRANSITION
@ -356,7 +356,7 @@ async def test_on_action_with_transition(
assert calls[0].data["transition"] == 5
assert state.state == STATE_OFF
assert "color_mode" not in state.attributes
assert state.attributes["color_mode"] is None
assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
assert state.attributes["supported_features"] == LightEntityFeature.TRANSITION
@ -383,7 +383,7 @@ async def test_on_action_optimistic(
state = hass.states.get("light.test_template_light")
assert state.state == STATE_OFF
assert "color_mode" not in state.attributes
assert state.attributes["color_mode"] is None
assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
assert state.attributes["supported_features"] == 0
@ -533,7 +533,7 @@ async def test_off_action_optimistic(hass: HomeAssistant, setup_light, calls) ->
"""Test off action with optimistic state."""
state = hass.states.get("light.test_template_light")
assert state.state == STATE_OFF
assert "color_mode" not in state.attributes
assert state.attributes["color_mode"] is None
assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
assert state.attributes["supported_features"] == 0
@ -547,7 +547,7 @@ async def test_off_action_optimistic(hass: HomeAssistant, setup_light, calls) ->
assert len(calls) == 1
state = hass.states.get("light.test_template_light")
assert state.state == STATE_OFF
assert "color_mode" not in state.attributes
assert state.attributes["color_mode"] is None
assert state.attributes["supported_color_modes"] == [ColorMode.BRIGHTNESS]
assert state.attributes["supported_features"] == 0
@ -921,7 +921,7 @@ async def test_color_and_temperature_actions_no_template(
state = hass.states.get("light.test_template_light")
assert state.attributes["color_mode"] == ColorMode.HS
assert "color_temp" not in state.attributes
assert state.attributes["color_temp"] is None
assert state.attributes["hs_color"] == (40, 50)
assert state.attributes["supported_color_modes"] == [
ColorMode.COLOR_TEMP,
@ -964,7 +964,7 @@ async def test_color_and_temperature_actions_no_template(
state = hass.states.get("light.test_template_light")
assert state.attributes["color_mode"] == ColorMode.HS
assert "color_temp" not in state.attributes
assert state.attributes["color_temp"] is None
assert state.attributes["hs_color"] == (10, 20)
assert state.attributes["supported_color_modes"] == [
ColorMode.COLOR_TEMP,

View File

@ -442,7 +442,7 @@ async def test_smart_strip_effects(hass: HomeAssistant) -> None:
state = hass.states.get(entity_id)
assert state.state == STATE_ON
assert ATTR_EFFECT not in state.attributes
assert state.attributes[ATTR_EFFECT] is None
strip.is_off = True
strip.is_on = False
@ -451,7 +451,7 @@ async def test_smart_strip_effects(hass: HomeAssistant) -> None:
state = hass.states.get(entity_id)
assert state.state == STATE_OFF
assert ATTR_EFFECT not in state.attributes
assert state.attributes[ATTR_EFFECT] is None
await hass.services.async_call(
LIGHT_DOMAIN,
@ -574,7 +574,7 @@ async def test_smart_strip_custom_random_effect(hass: HomeAssistant) -> None:
state = hass.states.get(entity_id)
assert state.state == STATE_OFF
assert ATTR_EFFECT not in state.attributes
assert state.attributes[ATTR_EFFECT] is None
await hass.services.async_call(
LIGHT_DOMAIN,

View File

@ -4,6 +4,7 @@
'attributes': dict({
'brightness': 26,
'color_mode': 'brightness',
'effect': None,
'effect_list': list([
]),
'friendly_name': 'twinkly_test_device_name',

View File

@ -419,15 +419,22 @@
# name: test_light_state[Temperature Light][light.temperature_light]
StateSnapshot({
'attributes': ReadOnlyDict({
'brightness': None,
'color_mode': None,
'color_temp': None,
'color_temp_kelvin': None,
'friendly_name': 'Temperature Light',
'hs_color': None,
'max_color_temp_kelvin': 6493,
'max_mireds': 370,
'min_color_temp_kelvin': 2702,
'min_mireds': 154,
'rgb_color': None,
'supported_color_modes': list([
<ColorMode.COLOR_TEMP: 'color_temp'>,
]),
'supported_features': <LightEntityFeature: 0>,
'xy_color': None,
}),
'context': <ANY>,
'entity_id': 'light.temperature_light',

View File

@ -889,6 +889,7 @@ async def test_device_types(
"mono",
{
"effect_list": YEELIGHT_MONO_EFFECT_LIST,
"effect": None,
"supported_features": SUPPORT_YEELIGHT,
"brightness": bright,
"color_mode": "brightness",
@ -903,6 +904,7 @@ async def test_device_types(
{
"effect_list": YEELIGHT_MONO_EFFECT_LIST,
"supported_features": SUPPORT_YEELIGHT,
"effect": None,
"brightness": bright,
"color_mode": "brightness",
"supported_color_modes": ["brightness"],
@ -917,6 +919,7 @@ async def test_device_types(
"color",
{
"effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"effect": None,
"supported_features": SUPPORT_YEELIGHT,
"min_color_temp_kelvin": model_specs["color_temp"]["min"],
"max_color_temp_kelvin": color_temperature_mired_to_kelvin(
@ -944,6 +947,7 @@ async def test_device_types(
},
nightlight_mode_properties={
"effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"effect": None,
"supported_features": SUPPORT_YEELIGHT,
"hs_color": (28.401, 100.0),
"rgb_color": (255, 120, 0),
@ -976,6 +980,7 @@ async def test_device_types(
"color",
{
"effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"effect": None,
"supported_features": SUPPORT_YEELIGHT,
"min_color_temp_kelvin": model_specs["color_temp"]["min"],
"max_color_temp_kelvin": color_temperature_mired_to_kelvin(
@ -991,6 +996,8 @@ async def test_device_types(
"hs_color": hs_color,
"rgb_color": color_hs_to_RGB(*hs_color),
"xy_color": color_hs_to_xy(*hs_color),
"color_temp": None,
"color_temp_kelvin": None,
"color_mode": "hs",
"supported_color_modes": ["color_temp", "hs", "rgb"],
},
@ -1009,6 +1016,7 @@ async def test_device_types(
"color",
{
"effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"effect": None,
"supported_features": SUPPORT_YEELIGHT,
"min_color_temp_kelvin": model_specs["color_temp"]["min"],
"max_color_temp_kelvin": color_temperature_mired_to_kelvin(
@ -1024,6 +1032,8 @@ async def test_device_types(
"hs_color": color_RGB_to_hs(*rgb_color),
"rgb_color": rgb_color,
"xy_color": color_RGB_to_xy(*rgb_color),
"color_temp": None,
"color_temp_kelvin": None,
"color_mode": "rgb",
"supported_color_modes": ["color_temp", "hs", "rgb"],
},
@ -1043,6 +1053,7 @@ async def test_device_types(
"color",
{
"effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"effect": None,
"supported_features": SUPPORT_YEELIGHT,
"min_color_temp_kelvin": model_specs["color_temp"]["min"],
"max_color_temp_kelvin": color_temperature_mired_to_kelvin(
@ -1055,6 +1066,11 @@ async def test_device_types(
model_specs["color_temp"]["min"]
),
"brightness": bright,
"hs_color": None,
"rgb_color": None,
"xy_color": None,
"color_temp": None,
"color_temp_kelvin": None,
"color_mode": "hs",
"supported_color_modes": ["color_temp", "hs", "rgb"],
},
@ -1074,6 +1090,7 @@ async def test_device_types(
"color",
{
"effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"effect": None,
"supported_features": SUPPORT_YEELIGHT,
"min_color_temp_kelvin": model_specs["color_temp"]["min"],
"max_color_temp_kelvin": color_temperature_mired_to_kelvin(
@ -1086,6 +1103,11 @@ async def test_device_types(
model_specs["color_temp"]["min"]
),
"brightness": bright,
"hs_color": None,
"rgb_color": None,
"xy_color": None,
"color_temp": None,
"color_temp_kelvin": None,
"color_mode": "rgb",
"supported_color_modes": ["color_temp", "hs", "rgb"],
},
@ -1104,6 +1126,7 @@ async def test_device_types(
"color",
{
"effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"effect": None,
"supported_features": SUPPORT_YEELIGHT,
"min_color_temp_kelvin": model_specs["color_temp"]["min"],
"max_color_temp_kelvin": color_temperature_mired_to_kelvin(
@ -1115,6 +1138,12 @@ async def test_device_types(
"max_mireds": color_temperature_kelvin_to_mired(
model_specs["color_temp"]["min"]
),
"brightness": None,
"hs_color": None,
"rgb_color": None,
"xy_color": None,
"color_temp": None,
"color_temp_kelvin": None,
"color_mode": "unknown",
"supported_color_modes": ["color_temp", "hs", "rgb"],
},
@ -1133,6 +1162,7 @@ async def test_device_types(
"ceiling1",
{
"effect_list": YEELIGHT_TEMP_ONLY_EFFECT_LIST,
"effect": None,
"supported_features": SUPPORT_YEELIGHT,
"min_color_temp_kelvin": color_temperature_mired_to_kelvin(
color_temperature_kelvin_to_mired(model_specs["color_temp"]["min"])
@ -1163,6 +1193,7 @@ async def test_device_types(
},
nightlight_mode_properties={
"effect_list": YEELIGHT_TEMP_ONLY_EFFECT_LIST,
"effect": None,
"supported_features": SUPPORT_YEELIGHT,
"min_color_temp_kelvin": color_temperature_mired_to_kelvin(
color_temperature_kelvin_to_mired(model_specs["color_temp"]["min"])
@ -1201,6 +1232,7 @@ async def test_device_types(
{
"friendly_name": NAME,
"effect_list": YEELIGHT_TEMP_ONLY_EFFECT_LIST,
"effect": None,
"flowing": False,
"night_light": True,
"supported_features": SUPPORT_YEELIGHT,
@ -1234,6 +1266,7 @@ async def test_device_types(
nightlight_mode_properties={
"friendly_name": NAME,
"effect_list": YEELIGHT_TEMP_ONLY_EFFECT_LIST,
"effect": None,
"flowing": False,
"night_light": True,
"supported_features": SUPPORT_YEELIGHT,
@ -1270,6 +1303,7 @@ async def test_device_types(
"ceiling4",
{
"effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"effect": None,
"supported_features": SUPPORT_YEELIGHT,
"min_color_temp_kelvin": 1700,
"max_color_temp_kelvin": color_temperature_mired_to_kelvin(
@ -1297,6 +1331,7 @@ async def test_device_types(
"ceiling4",
{
"effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"effect": None,
"supported_features": SUPPORT_YEELIGHT,
"min_color_temp_kelvin": 1700,
"max_color_temp_kelvin": color_temperature_mired_to_kelvin(
@ -1308,6 +1343,8 @@ async def test_device_types(
"hs_color": bg_hs_color,
"rgb_color": color_hs_to_RGB(*bg_hs_color),
"xy_color": color_hs_to_xy(*bg_hs_color),
"color_temp": None,
"color_temp_kelvin": None,
"color_mode": "hs",
"supported_color_modes": ["color_temp", "hs", "rgb"],
},
@ -1322,6 +1359,7 @@ async def test_device_types(
"ceiling4",
{
"effect_list": YEELIGHT_COLOR_EFFECT_LIST,
"effect": None,
"supported_features": SUPPORT_YEELIGHT,
"min_color_temp_kelvin": 1700,
"max_color_temp_kelvin": color_temperature_mired_to_kelvin(
@ -1333,6 +1371,8 @@ async def test_device_types(
"hs_color": color_RGB_to_hs(*bg_rgb_color),
"rgb_color": bg_rgb_color,
"xy_color": color_RGB_to_xy(*bg_rgb_color),
"color_temp": None,
"color_temp_kelvin": None,
"color_mode": "rgb",
"supported_color_modes": ["color_temp", "hs", "rgb"],
},

View File

@ -102,6 +102,11 @@ async def test_init(hass: HomeAssistant, mock_entry) -> None:
ATTR_SUPPORTED_COLOR_MODES: [ColorMode.HS],
ATTR_SUPPORTED_FEATURES: 0,
ATTR_ICON: "mdi:string-lights",
ATTR_COLOR_MODE: None,
ATTR_BRIGHTNESS: None,
ATTR_HS_COLOR: None,
ATTR_RGB_COLOR: None,
ATTR_XY_COLOR: None,
}
state = hass.states.get("light.ledblue_33445566")
@ -283,6 +288,11 @@ async def test_light_update(hass: HomeAssistant, mock_light) -> None:
ATTR_SUPPORTED_COLOR_MODES: [ColorMode.HS],
ATTR_SUPPORTED_FEATURES: 0,
ATTR_ICON: "mdi:string-lights",
ATTR_COLOR_MODE: None,
ATTR_BRIGHTNESS: None,
ATTR_HS_COLOR: None,
ATTR_RGB_COLOR: None,
ATTR_XY_COLOR: None,
}
# Make sure no discovery calls are made while we emulate time passing
@ -320,6 +330,11 @@ async def test_light_update(hass: HomeAssistant, mock_light) -> None:
ATTR_SUPPORTED_COLOR_MODES: [ColorMode.HS],
ATTR_SUPPORTED_FEATURES: 0,
ATTR_ICON: "mdi:string-lights",
ATTR_COLOR_MODE: None,
ATTR_BRIGHTNESS: None,
ATTR_HS_COLOR: None,
ATTR_RGB_COLOR: None,
ATTR_XY_COLOR: None,
}
with patch.object(

View File

@ -1669,7 +1669,7 @@ async def test_zha_group_light_entity(
ColorMode.XY,
]
# Light which is off has no color mode
assert "color_mode" not in group_state.attributes
assert group_state.attributes["color_mode"] is None
# test turning the lights on and off from the HA
await async_test_on_off_from_hass(hass, group_cluster_on_off, group_entity_id)

View File

@ -129,7 +129,7 @@ async def test_light(
assert state.attributes[ATTR_COLOR_MODE] == "color_temp"
assert state.attributes[ATTR_BRIGHTNESS] == 255
assert state.attributes[ATTR_COLOR_TEMP] == 370
assert ATTR_RGB_COLOR in state.attributes
assert state.attributes[ATTR_RGB_COLOR] is not None
# Test turning on with same brightness
await hass.services.async_call(
@ -254,7 +254,7 @@ async def test_light(
assert state.attributes[ATTR_COLOR_MODE] == "hs"
assert state.attributes[ATTR_BRIGHTNESS] == 255
assert state.attributes[ATTR_RGB_COLOR] == (255, 76, 255)
assert ATTR_COLOR_TEMP not in state.attributes
assert state.attributes[ATTR_COLOR_TEMP] is None
client.async_send_command.reset_mock()
@ -432,8 +432,8 @@ async def test_light(
state = hass.states.get(BULB_6_MULTI_COLOR_LIGHT_ENTITY)
assert state.state == STATE_UNKNOWN
assert ATTR_COLOR_MODE not in state.attributes
assert ATTR_BRIGHTNESS not in state.attributes
assert state.attributes[ATTR_COLOR_MODE] is None
assert state.attributes[ATTR_BRIGHTNESS] is None
async def test_v4_dimmer_light(