core/tests/components/hue/test_light_v1.py

981 lines
31 KiB
Python

"""Philips Hue lights platform tests."""
from unittest.mock import Mock
import aiohue
from homeassistant.components import hue
from homeassistant.components.hue.const import CONF_ALLOW_HUE_GROUPS
from homeassistant.components.hue.v1 import light as hue_light
from homeassistant.components.light import ColorMode
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.util import color
from .conftest import create_config_entry
HUE_LIGHT_NS = "homeassistant.components.light.hue."
GROUP_RESPONSE = {
"1": {
"name": "Group 1",
"lights": ["1", "2"],
"type": "LightGroup",
"action": {
"on": True,
"bri": 254,
"hue": 10000,
"sat": 254,
"effect": "none",
"xy": [0.5, 0.5],
"ct": 250,
"alert": "select",
"colormode": "ct",
},
"state": {"any_on": True, "all_on": False},
},
"2": {
"name": "Group 2",
"lights": ["3", "4", "5"],
"type": "LightGroup",
"action": {
"on": True,
"bri": 153,
"hue": 4345,
"sat": 254,
"effect": "none",
"xy": [0.5, 0.5],
"ct": 250,
"alert": "select",
"colormode": "ct",
},
"state": {"any_on": True, "all_on": False},
},
}
LIGHT_1_CAPABILITIES = {
"certified": True,
"control": {
"mindimlevel": 5000,
"maxlumen": 600,
"colorgamuttype": "A",
"colorgamut": [[0.704, 0.296], [0.2151, 0.7106], [0.138, 0.08]],
"ct": {"min": 153, "max": 500},
},
"streaming": {"renderer": True, "proxy": False},
}
LIGHT_1_ON = {
"state": {
"on": True,
"bri": 144,
"hue": 13088,
"sat": 212,
"xy": [0.5128, 0.4147],
"ct": 467,
"alert": "none",
"effect": "none",
"colormode": "xy",
"reachable": True,
},
"capabilities": LIGHT_1_CAPABILITIES,
"type": "Extended color light",
"name": "Hue Lamp 1",
"modelid": "LCT001",
"swversion": "66009461",
"manufacturername": "Philips",
"uniqueid": "456",
}
LIGHT_1_OFF = {
"state": {
"on": False,
"bri": 0,
"hue": 0,
"sat": 0,
"xy": [0, 0],
"ct": 0,
"alert": "none",
"effect": "none",
"colormode": "xy",
"reachable": True,
},
"capabilities": LIGHT_1_CAPABILITIES,
"type": "Extended color light",
"name": "Hue Lamp 1",
"modelid": "LCT001",
"swversion": "66009461",
"manufacturername": "Philips",
"uniqueid": "456",
}
LIGHT_2_CAPABILITIES = {
"certified": True,
"control": {
"mindimlevel": 5000,
"maxlumen": 600,
"colorgamuttype": "A",
"colorgamut": [[0.704, 0.296], [0.2151, 0.7106], [0.138, 0.08]],
},
"streaming": {"renderer": True, "proxy": False},
}
LIGHT_2_OFF = {
"state": {
"on": False,
"bri": 0,
"hue": 0,
"sat": 0,
"xy": [0, 0],
"ct": 0,
"alert": "none",
"effect": "none",
"colormode": "hs",
"reachable": True,
},
"capabilities": LIGHT_2_CAPABILITIES,
"type": "Extended color light",
"name": "Hue Lamp 2",
"modelid": "LCT001",
"swversion": "66009461",
"manufacturername": "Philips",
"uniqueid": "123",
}
LIGHT_2_ON = {
"state": {
"on": True,
"bri": 100,
"hue": 13088,
"sat": 210,
"xy": [0.5, 0.4],
"ct": 420,
"alert": "none",
"effect": "none",
"colormode": "hs",
"reachable": True,
},
"capabilities": LIGHT_2_CAPABILITIES,
"type": "Extended color light",
"name": "Hue Lamp 2 new",
"modelid": "LCT001",
"swversion": "66009461",
"manufacturername": "Philips",
"uniqueid": "123",
}
LIGHT_RESPONSE = {"1": LIGHT_1_ON, "2": LIGHT_2_OFF}
LIGHT_RAW = {
"capabilities": {
"control": {
"colorgamuttype": "A",
"colorgamut": [[0.704, 0.296], [0.2151, 0.7106], [0.138, 0.08]],
}
},
"swversion": "66009461",
}
LIGHT_GAMUT = color.GamutType(
color.XYPoint(0.704, 0.296),
color.XYPoint(0.2151, 0.7106),
color.XYPoint(0.138, 0.08),
)
LIGHT_GAMUT_TYPE = "A"
async def setup_bridge(hass: HomeAssistant, mock_bridge_v1: Mock) -> None:
"""Load the Hue light platform with the provided bridge."""
hass.config.components.add(hue.DOMAIN)
config_entry = create_config_entry()
config_entry.add_to_hass(hass)
hass.config_entries.async_update_entry(
config_entry, options={CONF_ALLOW_HUE_GROUPS: True}
)
config_entry.mock_state(hass, ConfigEntryState.LOADED)
mock_bridge_v1.config_entry = config_entry
hass.data[hue.DOMAIN] = {config_entry.entry_id: mock_bridge_v1}
await hass.config_entries.async_forward_entry_setups(config_entry, ["light"])
# To flush out the service call to update the group
await hass.async_block_till_done()
async def test_not_load_groups_if_old_bridge(
hass: HomeAssistant, mock_bridge_v1: Mock
) -> None:
"""Test that we don't try to load groups if bridge runs old software."""
mock_bridge_v1.api.config.apiversion = "1.12.0"
mock_bridge_v1.mock_light_responses.append({})
mock_bridge_v1.mock_group_responses.append(GROUP_RESPONSE)
await setup_bridge(hass, mock_bridge_v1)
assert len(mock_bridge_v1.mock_requests) == 1
assert len(hass.states.async_all()) == 0
async def test_no_lights_or_groups(hass: HomeAssistant, mock_bridge_v1: Mock) -> None:
"""Test the update_lights function when no lights are found."""
mock_bridge_v1.mock_light_responses.append({})
mock_bridge_v1.mock_group_responses.append({})
await setup_bridge(hass, mock_bridge_v1)
assert len(mock_bridge_v1.mock_requests) == 2
assert len(hass.states.async_all()) == 0
async def test_lights(hass: HomeAssistant, mock_bridge_v1: Mock) -> None:
"""Test the update_lights function with some lights."""
mock_bridge_v1.mock_light_responses.append(LIGHT_RESPONSE)
await setup_bridge(hass, mock_bridge_v1)
assert len(mock_bridge_v1.mock_requests) == 2
# 2 lights
assert len(hass.states.async_all()) == 2
lamp_1 = hass.states.get("light.hue_lamp_1")
assert lamp_1 is not None
assert lamp_1.state == "on"
assert lamp_1.attributes["brightness"] == 145
assert lamp_1.attributes["hs_color"] == (36.067, 69.804)
lamp_2 = hass.states.get("light.hue_lamp_2")
assert lamp_2 is not None
assert lamp_2.state == "off"
async def test_lights_color_mode(hass: HomeAssistant, mock_bridge_v1: Mock) -> None:
"""Test that lights only report appropriate color mode."""
mock_bridge_v1.mock_light_responses.append(LIGHT_RESPONSE)
mock_bridge_v1.mock_group_responses.append(GROUP_RESPONSE)
await setup_bridge(hass, mock_bridge_v1)
lamp_1 = hass.states.get("light.hue_lamp_1")
assert lamp_1 is not None
assert lamp_1.state == "on"
assert lamp_1.attributes["brightness"] == 145
assert lamp_1.attributes["hs_color"] == (36.067, 69.804)
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,
ColorMode.HS,
]
new_light1_on = LIGHT_1_ON.copy()
new_light1_on["state"] = new_light1_on["state"].copy()
new_light1_on["state"]["colormode"] = "ct"
mock_bridge_v1.mock_light_responses.append({"1": new_light1_on})
mock_bridge_v1.mock_group_responses.append({})
# Calling a service will trigger the updates to run
await hass.services.async_call(
"light", "turn_on", {"entity_id": "light.hue_lamp_2"}, blocking=True
)
# 2x light update, 1 group update, 1 turn on request
assert len(mock_bridge_v1.mock_requests) == 4
lamp_1 = hass.states.get("light.hue_lamp_1")
assert lamp_1 is not None
assert lamp_1.state == "on"
assert lamp_1.attributes["brightness"] == 145
assert lamp_1.attributes["color_temp"] == 467
assert "hs_color" in lamp_1.attributes
assert lamp_1.attributes["color_mode"] == ColorMode.COLOR_TEMP
assert lamp_1.attributes["supported_color_modes"] == [
ColorMode.COLOR_TEMP,
ColorMode.HS,
]
async def test_groups(
hass: HomeAssistant, entity_registry: er.EntityRegistry, mock_bridge_v1: Mock
) -> None:
"""Test the update_lights function with some lights."""
mock_bridge_v1.mock_light_responses.append({})
mock_bridge_v1.mock_group_responses.append(GROUP_RESPONSE)
await setup_bridge(hass, mock_bridge_v1)
assert len(mock_bridge_v1.mock_requests) == 2
# 2 hue group lights
assert len(hass.states.async_all()) == 2
lamp_1 = hass.states.get("light.group_1")
assert lamp_1 is not None
assert lamp_1.state == "on"
assert lamp_1.attributes["brightness"] == 255
assert lamp_1.attributes["color_temp"] == 250
lamp_2 = hass.states.get("light.group_2")
assert lamp_2 is not None
assert lamp_2.state == "on"
assert entity_registry.async_get("light.group_1").unique_id == "1"
assert entity_registry.async_get("light.group_2").unique_id == "2"
async def test_new_group_discovered(hass: HomeAssistant, mock_bridge_v1: Mock) -> None:
"""Test if 2nd update has a new group."""
mock_bridge_v1.allow_groups = True
mock_bridge_v1.mock_light_responses.append({})
mock_bridge_v1.mock_group_responses.append(GROUP_RESPONSE)
await setup_bridge(hass, mock_bridge_v1)
assert len(mock_bridge_v1.mock_requests) == 2
assert len(hass.states.async_all()) == 2
new_group_response = dict(GROUP_RESPONSE)
new_group_response["3"] = {
"name": "Group 3",
"lights": ["3", "4", "5"],
"type": "LightGroup",
"action": {
"on": True,
"bri": 153,
"hue": 4345,
"sat": 254,
"effect": "none",
"xy": [0.5, 0.5],
"ct": 250,
"alert": "select",
"colormode": "ct",
},
"state": {"any_on": True, "all_on": False},
}
mock_bridge_v1.mock_light_responses.append({})
mock_bridge_v1.mock_group_responses.append(new_group_response)
# Calling a service will trigger the updates to run
await hass.services.async_call(
"light", "turn_on", {"entity_id": "light.group_1"}, blocking=True
)
# 2x group update, 1x light update, 1 turn on request
assert len(mock_bridge_v1.mock_requests) == 4
assert len(hass.states.async_all()) == 3
new_group = hass.states.get("light.group_3")
assert new_group is not None
assert new_group.state == "on"
assert new_group.attributes["brightness"] == 154
assert new_group.attributes["color_temp"] == 250
async def test_new_light_discovered(hass: HomeAssistant, mock_bridge_v1: Mock) -> None:
"""Test if 2nd update has a new light."""
mock_bridge_v1.mock_light_responses.append(LIGHT_RESPONSE)
await setup_bridge(hass, mock_bridge_v1)
assert len(mock_bridge_v1.mock_requests) == 2
assert len(hass.states.async_all()) == 2
new_light_response = dict(LIGHT_RESPONSE)
new_light_response["3"] = {
"state": {
"on": False,
"bri": 0,
"hue": 0,
"sat": 0,
"xy": [0, 0],
"ct": 0,
"alert": "none",
"effect": "none",
"colormode": "hs",
"reachable": True,
},
"capabilities": LIGHT_1_CAPABILITIES,
"type": "Extended color light",
"name": "Hue Lamp 3",
"modelid": "LCT001",
"swversion": "66009461",
"manufacturername": "Philips",
"uniqueid": "789",
}
mock_bridge_v1.mock_light_responses.append(new_light_response)
# Calling a service will trigger the updates to run
await hass.services.async_call(
"light", "turn_on", {"entity_id": "light.hue_lamp_1"}, blocking=True
)
# 2x light update, 1 group update, 1 turn on request
assert len(mock_bridge_v1.mock_requests) == 4
assert len(hass.states.async_all()) == 3
light = hass.states.get("light.hue_lamp_3")
assert light is not None
assert light.state == "off"
async def test_group_removed(hass: HomeAssistant, mock_bridge_v1: Mock) -> None:
"""Test if 2nd update has removed group."""
mock_bridge_v1.allow_groups = True
mock_bridge_v1.mock_light_responses.append({})
mock_bridge_v1.mock_group_responses.append(GROUP_RESPONSE)
await setup_bridge(hass, mock_bridge_v1)
assert len(mock_bridge_v1.mock_requests) == 2
assert len(hass.states.async_all()) == 2
mock_bridge_v1.mock_light_responses.append({})
mock_bridge_v1.mock_group_responses.append({"1": GROUP_RESPONSE["1"]})
# Calling a service will trigger the updates to run
await hass.services.async_call(
"light", "turn_on", {"entity_id": "light.group_1"}, blocking=True
)
# Wait for the group to be updated
await hass.async_block_till_done()
# 2x group update, 1x light update, 1 turn on request
assert len(mock_bridge_v1.mock_requests) == 4
assert len(hass.states.async_all()) == 1
group = hass.states.get("light.group_1")
assert group is not None
removed_group = hass.states.get("light.group_2")
assert removed_group is None
async def test_light_removed(hass: HomeAssistant, mock_bridge_v1: Mock) -> None:
"""Test if 2nd update has removed light."""
mock_bridge_v1.mock_light_responses.append(LIGHT_RESPONSE)
await setup_bridge(hass, mock_bridge_v1)
assert len(mock_bridge_v1.mock_requests) == 2
assert len(hass.states.async_all()) == 2
mock_bridge_v1.mock_light_responses.clear()
mock_bridge_v1.mock_light_responses.append({"1": LIGHT_RESPONSE.get("1")})
# Calling a service will trigger the updates to run
await hass.services.async_call(
"light", "turn_on", {"entity_id": "light.hue_lamp_1"}, blocking=True
)
# Wait for the light to be updated
await hass.async_block_till_done()
# 2x light update, 1 group update, 1 turn on request
assert len(mock_bridge_v1.mock_requests) == 4
assert len(hass.states.async_all()) == 1
light = hass.states.get("light.hue_lamp_1")
assert light is not None
removed_light = hass.states.get("light.hue_lamp_2")
assert removed_light is None
async def test_other_group_update(hass: HomeAssistant, mock_bridge_v1: Mock) -> None:
"""Test changing one group that will impact the state of other light."""
mock_bridge_v1.allow_groups = True
mock_bridge_v1.mock_light_responses.append({})
mock_bridge_v1.mock_group_responses.append(GROUP_RESPONSE)
await setup_bridge(hass, mock_bridge_v1)
assert len(mock_bridge_v1.mock_requests) == 2
assert len(hass.states.async_all()) == 2
group_2 = hass.states.get("light.group_2")
assert group_2 is not None
assert group_2.name == "Group 2"
assert group_2.state == "on"
assert group_2.attributes["brightness"] == 154
assert group_2.attributes["color_temp"] == 250
updated_group_response = dict(GROUP_RESPONSE)
updated_group_response["2"] = {
"name": "Group 2 new",
"lights": ["3", "4", "5"],
"type": "LightGroup",
"action": {
"on": False,
"bri": 0,
"hue": 0,
"sat": 0,
"effect": "none",
"xy": [0, 0],
"ct": 0,
"alert": "none",
"colormode": "ct",
},
"state": {"any_on": False, "all_on": False},
}
mock_bridge_v1.mock_light_responses.append({})
mock_bridge_v1.mock_group_responses.append(updated_group_response)
# Calling a service will trigger the updates to run
await hass.services.async_call(
"light", "turn_on", {"entity_id": "light.group_1"}, blocking=True
)
# 2x group update, 1x light update, 1 turn on request
assert len(mock_bridge_v1.mock_requests) == 4
assert len(hass.states.async_all()) == 2
group_2 = hass.states.get("light.group_2")
assert group_2 is not None
assert group_2.name == "Group 2 new"
assert group_2.state == "off"
async def test_other_light_update(hass: HomeAssistant, mock_bridge_v1: Mock) -> None:
"""Test changing one light that will impact state of other light."""
mock_bridge_v1.mock_light_responses.append(LIGHT_RESPONSE)
await setup_bridge(hass, mock_bridge_v1)
assert len(mock_bridge_v1.mock_requests) == 2
assert len(hass.states.async_all()) == 2
lamp_2 = hass.states.get("light.hue_lamp_2")
assert lamp_2 is not None
assert lamp_2.name == "Hue Lamp 2"
assert lamp_2.state == "off"
updated_light_response = dict(LIGHT_RESPONSE)
updated_light_response["2"] = {
"state": {
"on": True,
"bri": 100,
"hue": 13088,
"sat": 210,
"xy": [0.5, 0.4],
"ct": 420,
"alert": "none",
"effect": "none",
"colormode": "hs",
"reachable": True,
},
"capabilities": LIGHT_2_CAPABILITIES,
"type": "Extended color light",
"name": "Hue Lamp 2 new",
"modelid": "LCT001",
"swversion": "66009461",
"manufacturername": "Philips",
"uniqueid": "123",
}
mock_bridge_v1.mock_light_responses.append(updated_light_response)
# Calling a service will trigger the updates to run
await hass.services.async_call(
"light", "turn_on", {"entity_id": "light.hue_lamp_1"}, blocking=True
)
# 2x light update, 1 group update, 1 turn on request
assert len(mock_bridge_v1.mock_requests) == 4
assert len(hass.states.async_all()) == 2
lamp_2 = hass.states.get("light.hue_lamp_2")
assert lamp_2 is not None
assert lamp_2.name == "Hue Lamp 2 new"
assert lamp_2.state == "on"
assert lamp_2.attributes["brightness"] == 100
async def test_update_timeout(hass: HomeAssistant, mock_bridge_v1: Mock) -> None:
"""Test bridge marked as not available if timeout error during update."""
mock_bridge_v1.api.lights.update = Mock(side_effect=TimeoutError)
mock_bridge_v1.api.groups.update = Mock(side_effect=TimeoutError)
await setup_bridge(hass, mock_bridge_v1)
assert len(mock_bridge_v1.mock_requests) == 0
assert len(hass.states.async_all()) == 0
async def test_update_unauthorized(hass: HomeAssistant, mock_bridge_v1: Mock) -> None:
"""Test bridge marked as not authorized if unauthorized during update."""
mock_bridge_v1.api.lights.update = Mock(side_effect=aiohue.Unauthorized)
await setup_bridge(hass, mock_bridge_v1)
assert len(mock_bridge_v1.mock_requests) == 0
assert len(hass.states.async_all()) == 0
assert len(mock_bridge_v1.handle_unauthorized_error.mock_calls) == 1
async def test_light_turn_on_service(hass: HomeAssistant, mock_bridge_v1: Mock) -> None:
"""Test calling the turn on service on a light."""
mock_bridge_v1.mock_light_responses.append(LIGHT_RESPONSE)
await setup_bridge(hass, mock_bridge_v1)
light = hass.states.get("light.hue_lamp_2")
assert light is not None
assert light.state == "off"
updated_light_response = dict(LIGHT_RESPONSE)
updated_light_response["2"] = LIGHT_2_ON
mock_bridge_v1.mock_light_responses.append(updated_light_response)
await hass.services.async_call(
"light",
"turn_on",
{"entity_id": "light.hue_lamp_2", "brightness": 100, "color_temp": 300},
blocking=True,
)
# 2x light update, 1x group update, 1 turn on request
assert len(mock_bridge_v1.mock_requests) == 4
assert mock_bridge_v1.mock_requests[2]["json"] == {
"bri": 100,
"on": True,
"ct": 300,
"alert": "none",
}
assert len(hass.states.async_all()) == 2
light = hass.states.get("light.hue_lamp_2")
assert light is not None
assert light.state == "on"
# test hue gamut in turn_on service
await hass.services.async_call(
"light",
"turn_on",
{"entity_id": "light.hue_lamp_2", "rgb_color": [0, 0, 255]},
blocking=True,
)
assert len(mock_bridge_v1.mock_requests) == 5
assert mock_bridge_v1.mock_requests[4]["json"] == {
"on": True,
"xy": (0.138, 0.08),
"alert": "none",
}
async def test_light_turn_off_service(
hass: HomeAssistant, mock_bridge_v1: Mock
) -> None:
"""Test calling the turn on service on a light."""
mock_bridge_v1.mock_light_responses.append(LIGHT_RESPONSE)
await setup_bridge(hass, mock_bridge_v1)
light = hass.states.get("light.hue_lamp_1")
assert light is not None
assert light.state == "on"
updated_light_response = dict(LIGHT_RESPONSE)
updated_light_response["1"] = LIGHT_1_OFF
mock_bridge_v1.mock_light_responses.append(updated_light_response)
await hass.services.async_call(
"light", "turn_off", {"entity_id": "light.hue_lamp_1"}, blocking=True
)
# 2x light update, 1 for group update, 1 turn on request
assert len(mock_bridge_v1.mock_requests) == 4
assert mock_bridge_v1.mock_requests[2]["json"] == {"on": False, "alert": "none"}
assert len(hass.states.async_all()) == 2
light = hass.states.get("light.hue_lamp_1")
assert light is not None
assert light.state == "off"
def test_available() -> None:
"""Test available property."""
light = hue_light.HueLight(
light=Mock(
state={"reachable": False},
raw=LIGHT_RAW,
colorgamuttype=LIGHT_GAMUT_TYPE,
colorgamut=LIGHT_GAMUT,
),
bridge=Mock(config_entry=Mock(options={"allow_unreachable": False})),
coordinator=Mock(last_update_success=True),
is_group=False,
supported_color_modes=hue_light.COLOR_MODES_HUE_EXTENDED,
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
rooms={},
)
assert light.available is False
light = hue_light.HueLight(
light=Mock(
state={"reachable": False},
raw=LIGHT_RAW,
colorgamuttype=LIGHT_GAMUT_TYPE,
colorgamut=LIGHT_GAMUT,
),
coordinator=Mock(last_update_success=True),
is_group=False,
supported_color_modes=hue_light.COLOR_MODES_HUE_EXTENDED,
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
rooms={},
bridge=Mock(config_entry=Mock(options={"allow_unreachable": True})),
)
assert light.available is True
light = hue_light.HueLight(
light=Mock(
state={"reachable": False},
raw=LIGHT_RAW,
colorgamuttype=LIGHT_GAMUT_TYPE,
colorgamut=LIGHT_GAMUT,
),
coordinator=Mock(last_update_success=True),
is_group=True,
supported_color_modes=hue_light.COLOR_MODES_HUE_EXTENDED,
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
rooms={},
bridge=Mock(config_entry=Mock(options={"allow_unreachable": False})),
)
assert light.available is True
def test_hs_color() -> None:
"""Test hs_color property."""
light = hue_light.HueLight(
light=Mock(
state={"colormode": "ct", "hue": 1234, "sat": 123},
raw=LIGHT_RAW,
colorgamuttype=LIGHT_GAMUT_TYPE,
colorgamut=LIGHT_GAMUT,
),
coordinator=Mock(last_update_success=True),
bridge=Mock(),
is_group=False,
supported_color_modes=hue_light.COLOR_MODES_HUE_EXTENDED,
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
rooms={},
)
assert light.hs_color is None
light = hue_light.HueLight(
light=Mock(
state={"colormode": "hs", "hue": 1234, "sat": 123},
raw=LIGHT_RAW,
colorgamuttype=LIGHT_GAMUT_TYPE,
colorgamut=LIGHT_GAMUT,
),
coordinator=Mock(last_update_success=True),
bridge=Mock(),
is_group=False,
supported_color_modes=hue_light.COLOR_MODES_HUE_EXTENDED,
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
rooms={},
)
assert light.hs_color is None
light = hue_light.HueLight(
light=Mock(
state={"colormode": "xy", "hue": 1234, "sat": 123, "xy": [0.4, 0.5]},
raw=LIGHT_RAW,
colorgamuttype=LIGHT_GAMUT_TYPE,
colorgamut=LIGHT_GAMUT,
),
coordinator=Mock(last_update_success=True),
bridge=Mock(),
is_group=False,
supported_color_modes=hue_light.COLOR_MODES_HUE_EXTENDED,
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
rooms={},
)
assert light.hs_color == color.color_xy_to_hs(0.4, 0.5, LIGHT_GAMUT)
async def test_group_features(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
device_registry: dr.DeviceRegistry,
mock_bridge_v1: Mock,
) -> None:
"""Test group features."""
color_temp_type = "Color temperature light"
extended_color_type = "Extended color light"
group_response = {
"1": {
"name": "Group 1",
"lights": ["1", "2"],
"type": "LightGroup",
"action": {
"on": True,
"bri": 254,
"hue": 10000,
"sat": 254,
"effect": "none",
"xy": [0.5, 0.5],
"ct": 250,
"alert": "select",
"colormode": "ct",
},
"state": {"any_on": True, "all_on": False},
},
"2": {
"name": "Living Room",
"lights": ["2", "3"],
"type": "Room",
"action": {
"on": True,
"bri": 153,
"hue": 4345,
"sat": 254,
"effect": "none",
"xy": [0.5, 0.5],
"ct": 250,
"alert": "select",
"colormode": "ct",
},
"state": {"any_on": True, "all_on": False},
},
"3": {
"name": "Dining Room",
"lights": ["4"],
"type": "Room",
"action": {
"on": True,
"bri": 153,
"hue": 4345,
"sat": 254,
"effect": "none",
"xy": [0.5, 0.5],
"ct": 250,
"alert": "select",
"colormode": "ct",
},
"state": {"any_on": True, "all_on": False},
},
}
light_1 = {
"state": {
"on": True,
"bri": 144,
"ct": 467,
"alert": "none",
"effect": "none",
"reachable": True,
},
"capabilities": {
"control": {
"colorgamuttype": "A",
"colorgamut": [[0.704, 0.296], [0.2151, 0.7106], [0.138, 0.08]],
}
},
"type": color_temp_type,
"name": "Hue Lamp 1",
"modelid": "LCT001",
"swversion": "66009461",
"manufacturername": "Philips",
"uniqueid": "456",
}
light_2 = {
"state": {
"on": False,
"bri": 0,
"ct": 0,
"alert": "none",
"effect": "none",
"colormode": "xy",
"reachable": True,
},
"capabilities": {
"control": {
"colorgamuttype": "A",
"colorgamut": [[0.704, 0.296], [0.2151, 0.7106], [0.138, 0.08]],
}
},
"type": color_temp_type,
"name": "Hue Lamp 2",
"modelid": "LCT001",
"swversion": "66009461",
"manufacturername": "Philips",
"uniqueid": "4567",
}
light_3 = {
"state": {
"on": False,
"bri": 0,
"hue": 0,
"sat": 0,
"xy": [0, 0],
"ct": 0,
"alert": "none",
"effect": "none",
"colormode": "hs",
"reachable": True,
},
"capabilities": {
"control": {
"colorgamuttype": "A",
"colorgamut": [[0.704, 0.296], [0.2151, 0.7106], [0.138, 0.08]],
}
},
"type": extended_color_type,
"name": "Hue Lamp 3",
"modelid": "LCT001",
"swversion": "66009461",
"manufacturername": "Philips",
"uniqueid": "123",
}
light_4 = {
"state": {
"on": True,
"bri": 100,
"hue": 13088,
"sat": 210,
"xy": [0.5, 0.4],
"ct": 420,
"alert": "none",
"effect": "none",
"colormode": "hs",
"reachable": True,
},
"capabilities": {
"control": {
"colorgamuttype": "A",
"colorgamut": [[0.704, 0.296], [0.2151, 0.7106], [0.138, 0.08]],
}
},
"type": extended_color_type,
"name": "Hue Lamp 4",
"modelid": "LCT001",
"swversion": "66009461",
"manufacturername": "Philips",
"uniqueid": "1234",
}
light_response = {
"1": light_1,
"2": light_2,
"3": light_3,
"4": light_4,
}
mock_bridge_v1.mock_light_responses.append(light_response)
mock_bridge_v1.mock_group_responses.append(group_response)
await setup_bridge(hass, mock_bridge_v1)
assert len(mock_bridge_v1.mock_requests) == 2
color_temp_feature = hue_light.SUPPORT_HUE["Color temperature light"]
color_temp_mode = sorted(hue_light.COLOR_MODES_HUE["Color temperature light"])
extended_color_feature = hue_light.SUPPORT_HUE["Extended color light"]
extended_color_mode = sorted(hue_light.COLOR_MODES_HUE["Extended color light"])
group_1 = hass.states.get("light.group_1")
assert group_1.attributes["supported_color_modes"] == color_temp_mode
assert group_1.attributes["supported_features"] == color_temp_feature
group_2 = hass.states.get("light.living_room")
assert group_2.attributes["supported_color_modes"] == extended_color_mode
assert group_2.attributes["supported_features"] == extended_color_feature
group_3 = hass.states.get("light.dining_room")
assert group_3.attributes["supported_color_modes"] == extended_color_mode
assert group_3.attributes["supported_features"] == extended_color_feature
entry = entity_registry.async_get("light.hue_lamp_1")
device_entry = device_registry.async_get(entry.device_id)
assert device_entry.suggested_area is None
entry = entity_registry.async_get("light.hue_lamp_2")
device_entry = device_registry.async_get(entry.device_id)
assert device_entry.suggested_area == "Living Room"
entry = entity_registry.async_get("light.hue_lamp_3")
device_entry = device_registry.async_get(entry.device_id)
assert device_entry.suggested_area == "Living Room"
entry = entity_registry.async_get("light.hue_lamp_4")
device_entry = device_registry.async_get(entry.device_id)
assert device_entry.suggested_area == "Dining Room"