Hue Group features based on the bulbs in it (#31897)
* Computes the features of a hue group as the union of the features of the bulbs in the group * Moved create item to a function * Added test for hue group featurespull/31921/head
parent
81701f7e4c
commit
93a844b1d5
|
@ -72,6 +72,21 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
|
|||
pass
|
||||
|
||||
|
||||
def create_light(item_class, coordinator, bridge, is_group, api, item_id):
|
||||
"""Create the light."""
|
||||
if is_group:
|
||||
supported_features = 0
|
||||
for light_id in api[item_id].lights:
|
||||
if light_id not in bridge.api.lights:
|
||||
continue
|
||||
light = bridge.api.lights[light_id]
|
||||
supported_features |= SUPPORT_HUE.get(light.type, SUPPORT_HUE_EXTENDED)
|
||||
supported_features = supported_features or SUPPORT_HUE_EXTENDED
|
||||
else:
|
||||
supported_features = SUPPORT_HUE.get(api[item_id].type, SUPPORT_HUE_EXTENDED)
|
||||
return item_class(coordinator, bridge, is_group, api[item_id], supported_features)
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
"""Set up the Hue lights from a config entry."""
|
||||
bridge = hass.data[HUE_DOMAIN][config_entry.entry_id]
|
||||
|
@ -100,7 +115,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||
bridge.api.lights,
|
||||
{},
|
||||
async_add_entities,
|
||||
partial(HueLight, light_coordinator, bridge, False),
|
||||
partial(create_light, HueLight, light_coordinator, bridge, False),
|
||||
)
|
||||
|
||||
# We add a listener after fetching the data, so manually trigger listener
|
||||
|
@ -138,7 +153,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||
bridge.api.groups,
|
||||
{},
|
||||
async_add_entities,
|
||||
partial(HueLight, group_coordinator, bridge, True),
|
||||
partial(create_light, HueLight, group_coordinator, bridge, True),
|
||||
)
|
||||
|
||||
group_coordinator.async_add_listener(update_groups)
|
||||
|
@ -170,7 +185,7 @@ def async_update_items(bridge, api, current, async_add_entities, create_item):
|
|||
if item_id in current:
|
||||
continue
|
||||
|
||||
current[item_id] = create_item(api[item_id])
|
||||
current[item_id] = create_item(api, item_id)
|
||||
new_items.append(current[item_id])
|
||||
|
||||
bridge.hass.async_create_task(remove_devices(bridge, api, current))
|
||||
|
@ -182,12 +197,13 @@ def async_update_items(bridge, api, current, async_add_entities, create_item):
|
|||
class HueLight(Light):
|
||||
"""Representation of a Hue light."""
|
||||
|
||||
def __init__(self, coordinator, bridge, is_group, light):
|
||||
def __init__(self, coordinator, bridge, is_group, light, supported_features):
|
||||
"""Initialize the light."""
|
||||
self.light = light
|
||||
self.coordinator = coordinator
|
||||
self.bridge = bridge
|
||||
self.is_group = is_group
|
||||
self._supported_features = supported_features
|
||||
|
||||
if is_group:
|
||||
self.is_osram = False
|
||||
|
@ -290,7 +306,7 @@ class HueLight(Light):
|
|||
@property
|
||||
def supported_features(self):
|
||||
"""Flag supported features."""
|
||||
return SUPPORT_HUE.get(self.light.type, SUPPORT_HUE_EXTENDED)
|
||||
return self._supported_features
|
||||
|
||||
@property
|
||||
def effect(self):
|
||||
|
|
|
@ -706,6 +706,7 @@ def test_available():
|
|||
coordinator=Mock(last_update_success=True),
|
||||
bridge=Mock(allow_unreachable=False),
|
||||
is_group=False,
|
||||
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
||||
)
|
||||
|
||||
assert light.available is False
|
||||
|
@ -720,6 +721,7 @@ def test_available():
|
|||
coordinator=Mock(last_update_success=True),
|
||||
bridge=Mock(allow_unreachable=True),
|
||||
is_group=False,
|
||||
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
||||
)
|
||||
|
||||
assert light.available is True
|
||||
|
@ -734,6 +736,7 @@ def test_available():
|
|||
coordinator=Mock(last_update_success=True),
|
||||
bridge=Mock(allow_unreachable=False),
|
||||
is_group=True,
|
||||
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
||||
)
|
||||
|
||||
assert light.available is True
|
||||
|
@ -751,6 +754,7 @@ def test_hs_color():
|
|||
coordinator=Mock(last_update_success=True),
|
||||
bridge=Mock(),
|
||||
is_group=False,
|
||||
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
||||
)
|
||||
|
||||
assert light.hs_color is None
|
||||
|
@ -765,6 +769,7 @@ def test_hs_color():
|
|||
coordinator=Mock(last_update_success=True),
|
||||
bridge=Mock(),
|
||||
is_group=False,
|
||||
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
||||
)
|
||||
|
||||
assert light.hs_color is None
|
||||
|
@ -779,6 +784,189 @@ def test_hs_color():
|
|||
coordinator=Mock(last_update_success=True),
|
||||
bridge=Mock(),
|
||||
is_group=False,
|
||||
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
||||
)
|
||||
|
||||
assert light.hs_color == color.color_xy_to_hs(0.4, 0.5, LIGHT_GAMUT)
|
||||
|
||||
|
||||
async def test_group_features(hass, mock_bridge):
|
||||
"""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": "Room",
|
||||
"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"],
|
||||
"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": "Group 3",
|
||||
"lights": ["1", "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},
|
||||
},
|
||||
}
|
||||
|
||||
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": "456",
|
||||
}
|
||||
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": "123",
|
||||
}
|
||||
light_response = {
|
||||
"1": light_1,
|
||||
"2": light_2,
|
||||
"3": light_3,
|
||||
"4": light_4,
|
||||
}
|
||||
|
||||
mock_bridge.allow_groups = True
|
||||
mock_bridge.mock_light_responses.append(light_response)
|
||||
mock_bridge.mock_group_responses.append(group_response)
|
||||
await setup_bridge(hass, mock_bridge)
|
||||
|
||||
color_temp_feature = hue_light.SUPPORT_HUE["Color temperature light"]
|
||||
extended_color_feature = hue_light.SUPPORT_HUE["Extended color light"]
|
||||
|
||||
group_1 = hass.states.get("light.group_1")
|
||||
assert group_1.attributes["supported_features"] == color_temp_feature
|
||||
|
||||
group_2 = hass.states.get("light.group_2")
|
||||
assert group_2.attributes["supported_features"] == extended_color_feature
|
||||
|
||||
group_3 = hass.states.get("light.group_3")
|
||||
assert group_3.attributes["supported_features"] == extended_color_feature
|
||||
|
|
Loading…
Reference in New Issue