diff --git a/homeassistant/components/hue/light.py b/homeassistant/components/hue/light.py index 14ed2483cc6..1678dbbfc62 100644 --- a/homeassistant/components/hue/light.py +++ b/homeassistant/components/hue/light.py @@ -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): diff --git a/tests/components/hue/test_light.py b/tests/components/hue/test_light.py index de50d23b947..72546891a63 100644 --- a/tests/components/hue/test_light.py +++ b/tests/components/hue/test_light.py @@ -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