mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 17:57:11 +00:00
Add suggested area to hue (#47056)
This commit is contained in:
parent
d8633f94f6
commit
7ab2d91bf0
@ -15,3 +15,8 @@ CONF_ALLOW_HUE_GROUPS = "allow_hue_groups"
|
|||||||
DEFAULT_ALLOW_HUE_GROUPS = False
|
DEFAULT_ALLOW_HUE_GROUPS = False
|
||||||
|
|
||||||
DEFAULT_SCENE_TRANSITION = 4
|
DEFAULT_SCENE_TRANSITION = 4
|
||||||
|
|
||||||
|
GROUP_TYPE_LIGHT_GROUP = "LightGroup"
|
||||||
|
GROUP_TYPE_ROOM = "Room"
|
||||||
|
GROUP_TYPE_LUMINAIRE = "Luminaire"
|
||||||
|
GROUP_TYPE_LIGHT_SOURCE = "LightSource"
|
||||||
|
@ -36,7 +36,14 @@ from homeassistant.helpers.update_coordinator import (
|
|||||||
)
|
)
|
||||||
from homeassistant.util import color
|
from homeassistant.util import color
|
||||||
|
|
||||||
from .const import DOMAIN as HUE_DOMAIN, REQUEST_REFRESH_DELAY
|
from .const import (
|
||||||
|
DOMAIN as HUE_DOMAIN,
|
||||||
|
GROUP_TYPE_LIGHT_GROUP,
|
||||||
|
GROUP_TYPE_LIGHT_SOURCE,
|
||||||
|
GROUP_TYPE_LUMINAIRE,
|
||||||
|
GROUP_TYPE_ROOM,
|
||||||
|
REQUEST_REFRESH_DELAY,
|
||||||
|
)
|
||||||
from .helpers import remove_devices
|
from .helpers import remove_devices
|
||||||
|
|
||||||
SCAN_INTERVAL = timedelta(seconds=5)
|
SCAN_INTERVAL = timedelta(seconds=5)
|
||||||
@ -74,24 +81,35 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def create_light(item_class, coordinator, bridge, is_group, api, item_id):
|
def create_light(item_class, coordinator, bridge, is_group, rooms, api, item_id):
|
||||||
"""Create the light."""
|
"""Create the light."""
|
||||||
|
api_item = api[item_id]
|
||||||
|
|
||||||
if is_group:
|
if is_group:
|
||||||
supported_features = 0
|
supported_features = 0
|
||||||
for light_id in api[item_id].lights:
|
for light_id in api_item.lights:
|
||||||
if light_id not in bridge.api.lights:
|
if light_id not in bridge.api.lights:
|
||||||
continue
|
continue
|
||||||
light = bridge.api.lights[light_id]
|
light = bridge.api.lights[light_id]
|
||||||
supported_features |= SUPPORT_HUE.get(light.type, SUPPORT_HUE_EXTENDED)
|
supported_features |= SUPPORT_HUE.get(light.type, SUPPORT_HUE_EXTENDED)
|
||||||
supported_features = supported_features or SUPPORT_HUE_EXTENDED
|
supported_features = supported_features or SUPPORT_HUE_EXTENDED
|
||||||
else:
|
else:
|
||||||
supported_features = SUPPORT_HUE.get(api[item_id].type, SUPPORT_HUE_EXTENDED)
|
supported_features = SUPPORT_HUE.get(api_item.type, SUPPORT_HUE_EXTENDED)
|
||||||
return item_class(coordinator, bridge, is_group, api[item_id], supported_features)
|
return item_class(
|
||||||
|
coordinator, bridge, is_group, api_item, supported_features, rooms
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
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]
|
||||||
|
api_version = tuple(int(v) for v in bridge.api.config.apiversion.split("."))
|
||||||
|
rooms = {}
|
||||||
|
|
||||||
|
allow_groups = bridge.allow_groups
|
||||||
|
supports_groups = api_version >= GROUP_MIN_API_VERSION
|
||||||
|
if allow_groups and not supports_groups:
|
||||||
|
_LOGGER.warning("Please update your Hue bridge to support groups")
|
||||||
|
|
||||||
light_coordinator = DataUpdateCoordinator(
|
light_coordinator = DataUpdateCoordinator(
|
||||||
hass,
|
hass,
|
||||||
@ -111,27 +129,20 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
if not light_coordinator.last_update_success:
|
if not light_coordinator.last_update_success:
|
||||||
raise PlatformNotReady
|
raise PlatformNotReady
|
||||||
|
|
||||||
update_lights = partial(
|
if not supports_groups:
|
||||||
async_update_items,
|
update_lights_without_group_support = partial(
|
||||||
bridge,
|
async_update_items,
|
||||||
bridge.api.lights,
|
bridge,
|
||||||
{},
|
bridge.api.lights,
|
||||||
async_add_entities,
|
{},
|
||||||
partial(create_light, HueLight, light_coordinator, bridge, False),
|
async_add_entities,
|
||||||
)
|
partial(create_light, HueLight, light_coordinator, bridge, False, rooms),
|
||||||
|
None,
|
||||||
# We add a listener after fetching the data, so manually trigger listener
|
)
|
||||||
bridge.reset_jobs.append(light_coordinator.async_add_listener(update_lights))
|
# We add a listener after fetching the data, so manually trigger listener
|
||||||
update_lights()
|
bridge.reset_jobs.append(
|
||||||
|
light_coordinator.async_add_listener(update_lights_without_group_support)
|
||||||
api_version = tuple(int(v) for v in bridge.api.config.apiversion.split("."))
|
)
|
||||||
|
|
||||||
allow_groups = bridge.allow_groups
|
|
||||||
if allow_groups and api_version < GROUP_MIN_API_VERSION:
|
|
||||||
_LOGGER.warning("Please update your Hue bridge to support groups")
|
|
||||||
allow_groups = False
|
|
||||||
|
|
||||||
if not allow_groups:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
group_coordinator = DataUpdateCoordinator(
|
group_coordinator = DataUpdateCoordinator(
|
||||||
@ -145,17 +156,69 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
update_groups = partial(
|
if allow_groups:
|
||||||
|
update_groups = partial(
|
||||||
|
async_update_items,
|
||||||
|
bridge,
|
||||||
|
bridge.api.groups,
|
||||||
|
{},
|
||||||
|
async_add_entities,
|
||||||
|
partial(create_light, HueLight, group_coordinator, bridge, True, None),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
|
||||||
|
bridge.reset_jobs.append(group_coordinator.async_add_listener(update_groups))
|
||||||
|
|
||||||
|
cancel_update_rooms_listener = None
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _async_update_rooms():
|
||||||
|
"""Update rooms."""
|
||||||
|
nonlocal cancel_update_rooms_listener
|
||||||
|
rooms.clear()
|
||||||
|
for item_id in bridge.api.groups:
|
||||||
|
group = bridge.api.groups[item_id]
|
||||||
|
if group.type != GROUP_TYPE_ROOM:
|
||||||
|
continue
|
||||||
|
for light_id in group.lights:
|
||||||
|
rooms[light_id] = group.name
|
||||||
|
|
||||||
|
# Once we do a rooms update, we cancel the listener
|
||||||
|
# until the next time lights are added
|
||||||
|
bridge.reset_jobs.remove(cancel_update_rooms_listener)
|
||||||
|
cancel_update_rooms_listener() # pylint: disable=not-callable
|
||||||
|
cancel_update_rooms_listener = None
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _setup_rooms_listener():
|
||||||
|
nonlocal cancel_update_rooms_listener
|
||||||
|
if cancel_update_rooms_listener is not None:
|
||||||
|
# If there are new lights added before _async_update_rooms
|
||||||
|
# is called we should not add another listener
|
||||||
|
return
|
||||||
|
|
||||||
|
cancel_update_rooms_listener = group_coordinator.async_add_listener(
|
||||||
|
_async_update_rooms
|
||||||
|
)
|
||||||
|
bridge.reset_jobs.append(cancel_update_rooms_listener)
|
||||||
|
|
||||||
|
_setup_rooms_listener()
|
||||||
|
await group_coordinator.async_refresh()
|
||||||
|
|
||||||
|
update_lights_with_group_support = partial(
|
||||||
async_update_items,
|
async_update_items,
|
||||||
bridge,
|
bridge,
|
||||||
bridge.api.groups,
|
bridge.api.lights,
|
||||||
{},
|
{},
|
||||||
async_add_entities,
|
async_add_entities,
|
||||||
partial(create_light, HueLight, group_coordinator, bridge, True),
|
partial(create_light, HueLight, light_coordinator, bridge, False, rooms),
|
||||||
|
_setup_rooms_listener,
|
||||||
)
|
)
|
||||||
|
# We add a listener after fetching the data, so manually trigger listener
|
||||||
bridge.reset_jobs.append(group_coordinator.async_add_listener(update_groups))
|
bridge.reset_jobs.append(
|
||||||
await group_coordinator.async_refresh()
|
light_coordinator.async_add_listener(update_lights_with_group_support)
|
||||||
|
)
|
||||||
|
update_lights_with_group_support()
|
||||||
|
|
||||||
|
|
||||||
async def async_safe_fetch(bridge, fetch_method):
|
async def async_safe_fetch(bridge, fetch_method):
|
||||||
@ -171,7 +234,9 @@ async def async_safe_fetch(bridge, fetch_method):
|
|||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_update_items(bridge, api, current, async_add_entities, create_item):
|
def async_update_items(
|
||||||
|
bridge, api, current, async_add_entities, create_item, new_items_callback
|
||||||
|
):
|
||||||
"""Update items."""
|
"""Update items."""
|
||||||
new_items = []
|
new_items = []
|
||||||
|
|
||||||
@ -185,6 +250,9 @@ def async_update_items(bridge, api, current, async_add_entities, create_item):
|
|||||||
bridge.hass.async_create_task(remove_devices(bridge, api, current))
|
bridge.hass.async_create_task(remove_devices(bridge, api, current))
|
||||||
|
|
||||||
if new_items:
|
if new_items:
|
||||||
|
# This is currently used to setup the listener to update rooms
|
||||||
|
if new_items_callback:
|
||||||
|
new_items_callback()
|
||||||
async_add_entities(new_items)
|
async_add_entities(new_items)
|
||||||
|
|
||||||
|
|
||||||
@ -201,13 +269,14 @@ def hass_to_hue_brightness(value):
|
|||||||
class HueLight(CoordinatorEntity, LightEntity):
|
class HueLight(CoordinatorEntity, LightEntity):
|
||||||
"""Representation of a Hue light."""
|
"""Representation of a Hue light."""
|
||||||
|
|
||||||
def __init__(self, coordinator, bridge, is_group, light, supported_features):
|
def __init__(self, coordinator, bridge, is_group, light, supported_features, rooms):
|
||||||
"""Initialize the light."""
|
"""Initialize the light."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self.light = light
|
self.light = light
|
||||||
self.bridge = bridge
|
self.bridge = bridge
|
||||||
self.is_group = is_group
|
self.is_group = is_group
|
||||||
self._supported_features = supported_features
|
self._supported_features = supported_features
|
||||||
|
self._rooms = rooms
|
||||||
|
|
||||||
if is_group:
|
if is_group:
|
||||||
self.is_osram = False
|
self.is_osram = False
|
||||||
@ -355,10 +424,15 @@ class HueLight(CoordinatorEntity, LightEntity):
|
|||||||
@property
|
@property
|
||||||
def device_info(self):
|
def device_info(self):
|
||||||
"""Return the device info."""
|
"""Return the device info."""
|
||||||
if self.light.type in ("LightGroup", "Room", "Luminaire", "LightSource"):
|
if self.light.type in (
|
||||||
|
GROUP_TYPE_LIGHT_GROUP,
|
||||||
|
GROUP_TYPE_ROOM,
|
||||||
|
GROUP_TYPE_LUMINAIRE,
|
||||||
|
GROUP_TYPE_LIGHT_SOURCE,
|
||||||
|
):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return {
|
info = {
|
||||||
"identifiers": {(HUE_DOMAIN, self.device_id)},
|
"identifiers": {(HUE_DOMAIN, self.device_id)},
|
||||||
"name": self.name,
|
"name": self.name,
|
||||||
"manufacturer": self.light.manufacturername,
|
"manufacturer": self.light.manufacturername,
|
||||||
@ -370,6 +444,11 @@ class HueLight(CoordinatorEntity, LightEntity):
|
|||||||
"via_device": (HUE_DOMAIN, self.bridge.api.config.bridgeid),
|
"via_device": (HUE_DOMAIN, self.bridge.api.config.bridgeid),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.light.id in self._rooms:
|
||||||
|
info["suggested_area"] = self._rooms[self.light.id]
|
||||||
|
|
||||||
|
return info
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs):
|
async def async_turn_on(self, **kwargs):
|
||||||
"""Turn the specified or all lights on."""
|
"""Turn the specified or all lights on."""
|
||||||
command = {"on": True}
|
command = {"on": True}
|
||||||
|
@ -7,6 +7,12 @@ import aiohue
|
|||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.components import hue
|
from homeassistant.components import hue
|
||||||
from homeassistant.components.hue import light as hue_light
|
from homeassistant.components.hue import light as hue_light
|
||||||
|
from homeassistant.helpers.device_registry import (
|
||||||
|
async_get_registry as async_get_device_registry,
|
||||||
|
)
|
||||||
|
from homeassistant.helpers.entity_registry import (
|
||||||
|
async_get_registry as async_get_entity_registry,
|
||||||
|
)
|
||||||
from homeassistant.util import color
|
from homeassistant.util import color
|
||||||
|
|
||||||
HUE_LIGHT_NS = "homeassistant.components.light.hue."
|
HUE_LIGHT_NS = "homeassistant.components.light.hue."
|
||||||
@ -211,8 +217,10 @@ async def test_no_lights_or_groups(hass, mock_bridge):
|
|||||||
async def test_lights(hass, mock_bridge):
|
async def test_lights(hass, mock_bridge):
|
||||||
"""Test the update_lights function with some lights."""
|
"""Test the update_lights function with some lights."""
|
||||||
mock_bridge.mock_light_responses.append(LIGHT_RESPONSE)
|
mock_bridge.mock_light_responses.append(LIGHT_RESPONSE)
|
||||||
|
mock_bridge.mock_group_responses.append(GROUP_RESPONSE)
|
||||||
|
|
||||||
await setup_bridge(hass, mock_bridge)
|
await setup_bridge(hass, mock_bridge)
|
||||||
assert len(mock_bridge.mock_requests) == 1
|
assert len(mock_bridge.mock_requests) == 2
|
||||||
# 2 lights
|
# 2 lights
|
||||||
assert len(hass.states.async_all()) == 2
|
assert len(hass.states.async_all()) == 2
|
||||||
|
|
||||||
@ -230,6 +238,8 @@ async def test_lights(hass, mock_bridge):
|
|||||||
async def test_lights_color_mode(hass, mock_bridge):
|
async def test_lights_color_mode(hass, mock_bridge):
|
||||||
"""Test that lights only report appropriate color mode."""
|
"""Test that lights only report appropriate color mode."""
|
||||||
mock_bridge.mock_light_responses.append(LIGHT_RESPONSE)
|
mock_bridge.mock_light_responses.append(LIGHT_RESPONSE)
|
||||||
|
mock_bridge.mock_group_responses.append(GROUP_RESPONSE)
|
||||||
|
|
||||||
await setup_bridge(hass, mock_bridge)
|
await setup_bridge(hass, mock_bridge)
|
||||||
|
|
||||||
lamp_1 = hass.states.get("light.hue_lamp_1")
|
lamp_1 = hass.states.get("light.hue_lamp_1")
|
||||||
@ -249,8 +259,8 @@ async def test_lights_color_mode(hass, mock_bridge):
|
|||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"light", "turn_on", {"entity_id": "light.hue_lamp_2"}, blocking=True
|
"light", "turn_on", {"entity_id": "light.hue_lamp_2"}, blocking=True
|
||||||
)
|
)
|
||||||
# 2x light update, 1 turn on request
|
# 2x light update, 1 group update, 1 turn on request
|
||||||
assert len(mock_bridge.mock_requests) == 3
|
assert len(mock_bridge.mock_requests) == 4
|
||||||
|
|
||||||
lamp_1 = hass.states.get("light.hue_lamp_1")
|
lamp_1 = hass.states.get("light.hue_lamp_1")
|
||||||
assert lamp_1 is not None
|
assert lamp_1 is not None
|
||||||
@ -332,9 +342,10 @@ async def test_new_group_discovered(hass, mock_bridge):
|
|||||||
async def test_new_light_discovered(hass, mock_bridge):
|
async def test_new_light_discovered(hass, mock_bridge):
|
||||||
"""Test if 2nd update has a new light."""
|
"""Test if 2nd update has a new light."""
|
||||||
mock_bridge.mock_light_responses.append(LIGHT_RESPONSE)
|
mock_bridge.mock_light_responses.append(LIGHT_RESPONSE)
|
||||||
|
mock_bridge.mock_group_responses.append(GROUP_RESPONSE)
|
||||||
|
|
||||||
await setup_bridge(hass, mock_bridge)
|
await setup_bridge(hass, mock_bridge)
|
||||||
assert len(mock_bridge.mock_requests) == 1
|
assert len(mock_bridge.mock_requests) == 2
|
||||||
assert len(hass.states.async_all()) == 2
|
assert len(hass.states.async_all()) == 2
|
||||||
|
|
||||||
new_light_response = dict(LIGHT_RESPONSE)
|
new_light_response = dict(LIGHT_RESPONSE)
|
||||||
@ -366,8 +377,8 @@ async def test_new_light_discovered(hass, mock_bridge):
|
|||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"light", "turn_on", {"entity_id": "light.hue_lamp_1"}, blocking=True
|
"light", "turn_on", {"entity_id": "light.hue_lamp_1"}, blocking=True
|
||||||
)
|
)
|
||||||
# 2x light update, 1 turn on request
|
# 2x light update, 1 group update, 1 turn on request
|
||||||
assert len(mock_bridge.mock_requests) == 3
|
assert len(mock_bridge.mock_requests) == 4
|
||||||
assert len(hass.states.async_all()) == 3
|
assert len(hass.states.async_all()) == 3
|
||||||
|
|
||||||
light = hass.states.get("light.hue_lamp_3")
|
light = hass.states.get("light.hue_lamp_3")
|
||||||
@ -407,9 +418,10 @@ async def test_group_removed(hass, mock_bridge):
|
|||||||
async def test_light_removed(hass, mock_bridge):
|
async def test_light_removed(hass, mock_bridge):
|
||||||
"""Test if 2nd update has removed light."""
|
"""Test if 2nd update has removed light."""
|
||||||
mock_bridge.mock_light_responses.append(LIGHT_RESPONSE)
|
mock_bridge.mock_light_responses.append(LIGHT_RESPONSE)
|
||||||
|
mock_bridge.mock_group_responses.append(GROUP_RESPONSE)
|
||||||
|
|
||||||
await setup_bridge(hass, mock_bridge)
|
await setup_bridge(hass, mock_bridge)
|
||||||
assert len(mock_bridge.mock_requests) == 1
|
assert len(mock_bridge.mock_requests) == 2
|
||||||
assert len(hass.states.async_all()) == 2
|
assert len(hass.states.async_all()) == 2
|
||||||
|
|
||||||
mock_bridge.mock_light_responses.clear()
|
mock_bridge.mock_light_responses.clear()
|
||||||
@ -420,8 +432,8 @@ async def test_light_removed(hass, mock_bridge):
|
|||||||
"light", "turn_on", {"entity_id": "light.hue_lamp_1"}, blocking=True
|
"light", "turn_on", {"entity_id": "light.hue_lamp_1"}, blocking=True
|
||||||
)
|
)
|
||||||
|
|
||||||
# 2x light update, 1 turn on request
|
# 2x light update, 1 group update, 1 turn on request
|
||||||
assert len(mock_bridge.mock_requests) == 3
|
assert len(mock_bridge.mock_requests) == 4
|
||||||
assert len(hass.states.async_all()) == 1
|
assert len(hass.states.async_all()) == 1
|
||||||
|
|
||||||
light = hass.states.get("light.hue_lamp_1")
|
light = hass.states.get("light.hue_lamp_1")
|
||||||
@ -487,9 +499,10 @@ async def test_other_group_update(hass, mock_bridge):
|
|||||||
async def test_other_light_update(hass, mock_bridge):
|
async def test_other_light_update(hass, mock_bridge):
|
||||||
"""Test changing one light that will impact state of other light."""
|
"""Test changing one light that will impact state of other light."""
|
||||||
mock_bridge.mock_light_responses.append(LIGHT_RESPONSE)
|
mock_bridge.mock_light_responses.append(LIGHT_RESPONSE)
|
||||||
|
mock_bridge.mock_group_responses.append(GROUP_RESPONSE)
|
||||||
|
|
||||||
await setup_bridge(hass, mock_bridge)
|
await setup_bridge(hass, mock_bridge)
|
||||||
assert len(mock_bridge.mock_requests) == 1
|
assert len(mock_bridge.mock_requests) == 2
|
||||||
assert len(hass.states.async_all()) == 2
|
assert len(hass.states.async_all()) == 2
|
||||||
|
|
||||||
lamp_2 = hass.states.get("light.hue_lamp_2")
|
lamp_2 = hass.states.get("light.hue_lamp_2")
|
||||||
@ -526,8 +539,8 @@ async def test_other_light_update(hass, mock_bridge):
|
|||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"light", "turn_on", {"entity_id": "light.hue_lamp_1"}, blocking=True
|
"light", "turn_on", {"entity_id": "light.hue_lamp_1"}, blocking=True
|
||||||
)
|
)
|
||||||
# 2x light update, 1 turn on request
|
# 2x light update, 1 group update, 1 turn on request
|
||||||
assert len(mock_bridge.mock_requests) == 3
|
assert len(mock_bridge.mock_requests) == 4
|
||||||
assert len(hass.states.async_all()) == 2
|
assert len(hass.states.async_all()) == 2
|
||||||
|
|
||||||
lamp_2 = hass.states.get("light.hue_lamp_2")
|
lamp_2 = hass.states.get("light.hue_lamp_2")
|
||||||
@ -549,7 +562,6 @@ async def test_update_timeout(hass, mock_bridge):
|
|||||||
async def test_update_unauthorized(hass, mock_bridge):
|
async def test_update_unauthorized(hass, mock_bridge):
|
||||||
"""Test bridge marked as not authorized if unauthorized during update."""
|
"""Test bridge marked as not authorized if unauthorized during update."""
|
||||||
mock_bridge.api.lights.update = Mock(side_effect=aiohue.Unauthorized)
|
mock_bridge.api.lights.update = Mock(side_effect=aiohue.Unauthorized)
|
||||||
mock_bridge.api.groups.update = Mock(side_effect=aiohue.Unauthorized)
|
|
||||||
await setup_bridge(hass, mock_bridge)
|
await setup_bridge(hass, mock_bridge)
|
||||||
assert len(mock_bridge.mock_requests) == 0
|
assert len(mock_bridge.mock_requests) == 0
|
||||||
assert len(hass.states.async_all()) == 0
|
assert len(hass.states.async_all()) == 0
|
||||||
@ -559,6 +571,8 @@ async def test_update_unauthorized(hass, mock_bridge):
|
|||||||
async def test_light_turn_on_service(hass, mock_bridge):
|
async def test_light_turn_on_service(hass, mock_bridge):
|
||||||
"""Test calling the turn on service on a light."""
|
"""Test calling the turn on service on a light."""
|
||||||
mock_bridge.mock_light_responses.append(LIGHT_RESPONSE)
|
mock_bridge.mock_light_responses.append(LIGHT_RESPONSE)
|
||||||
|
mock_bridge.mock_group_responses.append(GROUP_RESPONSE)
|
||||||
|
|
||||||
await setup_bridge(hass, mock_bridge)
|
await setup_bridge(hass, mock_bridge)
|
||||||
light = hass.states.get("light.hue_lamp_2")
|
light = hass.states.get("light.hue_lamp_2")
|
||||||
assert light is not None
|
assert light is not None
|
||||||
@ -575,10 +589,10 @@ async def test_light_turn_on_service(hass, mock_bridge):
|
|||||||
{"entity_id": "light.hue_lamp_2", "brightness": 100, "color_temp": 300},
|
{"entity_id": "light.hue_lamp_2", "brightness": 100, "color_temp": 300},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
# 2x light update, 1 turn on request
|
# 2x light update, 1 group update, 1 turn on request
|
||||||
assert len(mock_bridge.mock_requests) == 3
|
assert len(mock_bridge.mock_requests) == 4
|
||||||
|
|
||||||
assert mock_bridge.mock_requests[1]["json"] == {
|
assert mock_bridge.mock_requests[2]["json"] == {
|
||||||
"bri": 100,
|
"bri": 100,
|
||||||
"on": True,
|
"on": True,
|
||||||
"ct": 300,
|
"ct": 300,
|
||||||
@ -599,9 +613,9 @@ async def test_light_turn_on_service(hass, mock_bridge):
|
|||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert len(mock_bridge.mock_requests) == 5
|
assert len(mock_bridge.mock_requests) == 6
|
||||||
|
|
||||||
assert mock_bridge.mock_requests[3]["json"] == {
|
assert mock_bridge.mock_requests[4]["json"] == {
|
||||||
"on": True,
|
"on": True,
|
||||||
"xy": (0.138, 0.08),
|
"xy": (0.138, 0.08),
|
||||||
"alert": "none",
|
"alert": "none",
|
||||||
@ -611,6 +625,8 @@ async def test_light_turn_on_service(hass, mock_bridge):
|
|||||||
async def test_light_turn_off_service(hass, mock_bridge):
|
async def test_light_turn_off_service(hass, mock_bridge):
|
||||||
"""Test calling the turn on service on a light."""
|
"""Test calling the turn on service on a light."""
|
||||||
mock_bridge.mock_light_responses.append(LIGHT_RESPONSE)
|
mock_bridge.mock_light_responses.append(LIGHT_RESPONSE)
|
||||||
|
mock_bridge.mock_group_responses.append(GROUP_RESPONSE)
|
||||||
|
|
||||||
await setup_bridge(hass, mock_bridge)
|
await setup_bridge(hass, mock_bridge)
|
||||||
light = hass.states.get("light.hue_lamp_1")
|
light = hass.states.get("light.hue_lamp_1")
|
||||||
assert light is not None
|
assert light is not None
|
||||||
@ -624,10 +640,11 @@ async def test_light_turn_off_service(hass, mock_bridge):
|
|||||||
await hass.services.async_call(
|
await hass.services.async_call(
|
||||||
"light", "turn_off", {"entity_id": "light.hue_lamp_1"}, blocking=True
|
"light", "turn_off", {"entity_id": "light.hue_lamp_1"}, blocking=True
|
||||||
)
|
)
|
||||||
# 2x light update, 1 turn on request
|
|
||||||
assert len(mock_bridge.mock_requests) == 3
|
|
||||||
|
|
||||||
assert mock_bridge.mock_requests[1]["json"] == {"on": False, "alert": "none"}
|
# 2x light update, 1 for group update, 1 turn on request
|
||||||
|
assert len(mock_bridge.mock_requests) == 4
|
||||||
|
|
||||||
|
assert mock_bridge.mock_requests[2]["json"] == {"on": False, "alert": "none"}
|
||||||
|
|
||||||
assert len(hass.states.async_all()) == 2
|
assert len(hass.states.async_all()) == 2
|
||||||
|
|
||||||
@ -649,6 +666,7 @@ def test_available():
|
|||||||
bridge=Mock(allow_unreachable=False),
|
bridge=Mock(allow_unreachable=False),
|
||||||
is_group=False,
|
is_group=False,
|
||||||
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
||||||
|
rooms={},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert light.available is False
|
assert light.available is False
|
||||||
@ -664,6 +682,7 @@ def test_available():
|
|||||||
bridge=Mock(allow_unreachable=True),
|
bridge=Mock(allow_unreachable=True),
|
||||||
is_group=False,
|
is_group=False,
|
||||||
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
||||||
|
rooms={},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert light.available is True
|
assert light.available is True
|
||||||
@ -679,6 +698,7 @@ def test_available():
|
|||||||
bridge=Mock(allow_unreachable=False),
|
bridge=Mock(allow_unreachable=False),
|
||||||
is_group=True,
|
is_group=True,
|
||||||
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
||||||
|
rooms={},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert light.available is True
|
assert light.available is True
|
||||||
@ -697,6 +717,7 @@ def test_hs_color():
|
|||||||
bridge=Mock(),
|
bridge=Mock(),
|
||||||
is_group=False,
|
is_group=False,
|
||||||
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
||||||
|
rooms={},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert light.hs_color is None
|
assert light.hs_color is None
|
||||||
@ -712,6 +733,7 @@ def test_hs_color():
|
|||||||
bridge=Mock(),
|
bridge=Mock(),
|
||||||
is_group=False,
|
is_group=False,
|
||||||
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
supported_features=hue_light.SUPPORT_HUE_EXTENDED,
|
||||||
|
rooms={},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert light.hs_color is None
|
assert light.hs_color is None
|
||||||
@ -727,6 +749,7 @@ def test_hs_color():
|
|||||||
bridge=Mock(),
|
bridge=Mock(),
|
||||||
is_group=False,
|
is_group=False,
|
||||||
supported_features=hue_light.SUPPORT_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)
|
assert light.hs_color == color.color_xy_to_hs(0.4, 0.5, LIGHT_GAMUT)
|
||||||
@ -742,7 +765,7 @@ async def test_group_features(hass, mock_bridge):
|
|||||||
"1": {
|
"1": {
|
||||||
"name": "Group 1",
|
"name": "Group 1",
|
||||||
"lights": ["1", "2"],
|
"lights": ["1", "2"],
|
||||||
"type": "Room",
|
"type": "LightGroup",
|
||||||
"action": {
|
"action": {
|
||||||
"on": True,
|
"on": True,
|
||||||
"bri": 254,
|
"bri": 254,
|
||||||
@ -757,8 +780,8 @@ async def test_group_features(hass, mock_bridge):
|
|||||||
"state": {"any_on": True, "all_on": False},
|
"state": {"any_on": True, "all_on": False},
|
||||||
},
|
},
|
||||||
"2": {
|
"2": {
|
||||||
"name": "Group 2",
|
"name": "Living Room",
|
||||||
"lights": ["3", "4"],
|
"lights": ["2", "3"],
|
||||||
"type": "Room",
|
"type": "Room",
|
||||||
"action": {
|
"action": {
|
||||||
"on": True,
|
"on": True,
|
||||||
@ -774,8 +797,8 @@ async def test_group_features(hass, mock_bridge):
|
|||||||
"state": {"any_on": True, "all_on": False},
|
"state": {"any_on": True, "all_on": False},
|
||||||
},
|
},
|
||||||
"3": {
|
"3": {
|
||||||
"name": "Group 3",
|
"name": "Dining Room",
|
||||||
"lights": ["1", "3"],
|
"lights": ["4"],
|
||||||
"type": "Room",
|
"type": "Room",
|
||||||
"action": {
|
"action": {
|
||||||
"on": True,
|
"on": True,
|
||||||
@ -900,6 +923,7 @@ async def test_group_features(hass, mock_bridge):
|
|||||||
mock_bridge.mock_light_responses.append(light_response)
|
mock_bridge.mock_light_responses.append(light_response)
|
||||||
mock_bridge.mock_group_responses.append(group_response)
|
mock_bridge.mock_group_responses.append(group_response)
|
||||||
await setup_bridge(hass, mock_bridge)
|
await setup_bridge(hass, mock_bridge)
|
||||||
|
assert len(mock_bridge.mock_requests) == 2
|
||||||
|
|
||||||
color_temp_feature = hue_light.SUPPORT_HUE["Color temperature light"]
|
color_temp_feature = hue_light.SUPPORT_HUE["Color temperature light"]
|
||||||
extended_color_feature = hue_light.SUPPORT_HUE["Extended color light"]
|
extended_color_feature = hue_light.SUPPORT_HUE["Extended color light"]
|
||||||
@ -907,8 +931,27 @@ async def test_group_features(hass, mock_bridge):
|
|||||||
group_1 = hass.states.get("light.group_1")
|
group_1 = hass.states.get("light.group_1")
|
||||||
assert group_1.attributes["supported_features"] == color_temp_feature
|
assert group_1.attributes["supported_features"] == color_temp_feature
|
||||||
|
|
||||||
group_2 = hass.states.get("light.group_2")
|
group_2 = hass.states.get("light.living_room")
|
||||||
assert group_2.attributes["supported_features"] == extended_color_feature
|
assert group_2.attributes["supported_features"] == extended_color_feature
|
||||||
|
|
||||||
group_3 = hass.states.get("light.group_3")
|
group_3 = hass.states.get("light.dining_room")
|
||||||
assert group_3.attributes["supported_features"] == extended_color_feature
|
assert group_3.attributes["supported_features"] == extended_color_feature
|
||||||
|
|
||||||
|
entity_registry = await async_get_entity_registry(hass)
|
||||||
|
device_registry = await async_get_device_registry(hass)
|
||||||
|
|
||||||
|
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"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user