mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
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 features
This commit is contained in:
parent
81701f7e4c
commit
93a844b1d5
@ -72,6 +72,21 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
|
|||||||
pass
|
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):
|
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
"""Set up the Hue lights from a config entry."""
|
"""Set up the Hue lights from a config entry."""
|
||||||
bridge = hass.data[HUE_DOMAIN][config_entry.entry_id]
|
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,
|
bridge.api.lights,
|
||||||
{},
|
{},
|
||||||
async_add_entities,
|
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
|
# 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,
|
bridge.api.groups,
|
||||||
{},
|
{},
|
||||||
async_add_entities,
|
async_add_entities,
|
||||||
partial(HueLight, group_coordinator, bridge, True),
|
partial(create_light, HueLight, group_coordinator, bridge, True),
|
||||||
)
|
)
|
||||||
|
|
||||||
group_coordinator.async_add_listener(update_groups)
|
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:
|
if item_id in current:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
current[item_id] = create_item(api[item_id])
|
current[item_id] = create_item(api, item_id)
|
||||||
new_items.append(current[item_id])
|
new_items.append(current[item_id])
|
||||||
|
|
||||||
bridge.hass.async_create_task(remove_devices(bridge, api, current))
|
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):
|
class HueLight(Light):
|
||||||
"""Representation of a Hue 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."""
|
"""Initialize the light."""
|
||||||
self.light = light
|
self.light = light
|
||||||
self.coordinator = coordinator
|
self.coordinator = coordinator
|
||||||
self.bridge = bridge
|
self.bridge = bridge
|
||||||
self.is_group = is_group
|
self.is_group = is_group
|
||||||
|
self._supported_features = supported_features
|
||||||
|
|
||||||
if is_group:
|
if is_group:
|
||||||
self.is_osram = False
|
self.is_osram = False
|
||||||
@ -290,7 +306,7 @@ class HueLight(Light):
|
|||||||
@property
|
@property
|
||||||
def supported_features(self):
|
def supported_features(self):
|
||||||
"""Flag supported features."""
|
"""Flag supported features."""
|
||||||
return SUPPORT_HUE.get(self.light.type, SUPPORT_HUE_EXTENDED)
|
return self._supported_features
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def effect(self):
|
def effect(self):
|
||||||
|
@ -706,6 +706,7 @@ def test_available():
|
|||||||
coordinator=Mock(last_update_success=True),
|
coordinator=Mock(last_update_success=True),
|
||||||
bridge=Mock(allow_unreachable=False),
|
bridge=Mock(allow_unreachable=False),
|
||||||
is_group=False,
|
is_group=False,
|
||||||
|
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert light.available is False
|
assert light.available is False
|
||||||
@ -720,6 +721,7 @@ def test_available():
|
|||||||
coordinator=Mock(last_update_success=True),
|
coordinator=Mock(last_update_success=True),
|
||||||
bridge=Mock(allow_unreachable=True),
|
bridge=Mock(allow_unreachable=True),
|
||||||
is_group=False,
|
is_group=False,
|
||||||
|
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert light.available is True
|
assert light.available is True
|
||||||
@ -734,6 +736,7 @@ def test_available():
|
|||||||
coordinator=Mock(last_update_success=True),
|
coordinator=Mock(last_update_success=True),
|
||||||
bridge=Mock(allow_unreachable=False),
|
bridge=Mock(allow_unreachable=False),
|
||||||
is_group=True,
|
is_group=True,
|
||||||
|
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert light.available is True
|
assert light.available is True
|
||||||
@ -751,6 +754,7 @@ def test_hs_color():
|
|||||||
coordinator=Mock(last_update_success=True),
|
coordinator=Mock(last_update_success=True),
|
||||||
bridge=Mock(),
|
bridge=Mock(),
|
||||||
is_group=False,
|
is_group=False,
|
||||||
|
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert light.hs_color is None
|
assert light.hs_color is None
|
||||||
@ -765,6 +769,7 @@ def test_hs_color():
|
|||||||
coordinator=Mock(last_update_success=True),
|
coordinator=Mock(last_update_success=True),
|
||||||
bridge=Mock(),
|
bridge=Mock(),
|
||||||
is_group=False,
|
is_group=False,
|
||||||
|
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert light.hs_color is None
|
assert light.hs_color is None
|
||||||
@ -779,6 +784,189 @@ def test_hs_color():
|
|||||||
coordinator=Mock(last_update_success=True),
|
coordinator=Mock(last_update_success=True),
|
||||||
bridge=Mock(),
|
bridge=Mock(),
|
||||||
is_group=False,
|
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)
|
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…
x
Reference in New Issue
Block a user