From 17061f360f4d3870d70e714b67a018deb832cd23 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Mon, 29 Aug 2022 18:28:54 -0700 Subject: [PATCH 1/5] Add test_area test, reproduce issue of #75 --- tests/test_switch.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/tests/test_switch.py b/tests/test_switch.py index 2038fe8d..1473a29e 100644 --- a/tests/test_switch.py +++ b/tests/test_switch.py @@ -59,11 +59,12 @@ from homeassistant.const import ( STATE_ON, ) from homeassistant.core import Context, State +from homeassistant.helpers import device_registry, entity_registry from homeassistant.setup import async_setup_component import homeassistant.util.dt as dt_util import pytest -from tests.common import MockConfigEntry +from tests.common import MockConfigEntry, mock_device_registry, mock_registry from tests.components.demo.test_light import ENTITY_LIGHT _LOGGER = logging.getLogger(__name__) @@ -867,3 +868,32 @@ async def test_separate_turn_on_commands(hass, separate_turn_on_commands): assert sleep_brightness != brightness assert sleep_color_temp != color_temp + + +async def test_area(hass): + _, (light, *_) = await setup_lights_and_switch(hass) + device_in_area = device_registry.DeviceEntry(area_id="test-area") + + mock_device_registry(hass, {device_in_area.id: device_in_area}) + entity_in_area = entity_registry.RegistryEntry( + entity_id=light.entity_id, + unique_id="in-area-id", + platform="test", + device_id=device_in_area.id, + ) + mock_registry(hass, {entity_in_area.entity_id: entity_in_area}) + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: light.entity_id}, + blocking=True, + ) + await hass.async_block_till_done() + + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_OFF, + {"area_id": "in-area-id"}, + blocking=True, + ) + await hass.async_block_till_done() From b64c44fc8dcbef3fac728686522de666f01d71e3 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Mon, 29 Aug 2022 18:51:24 -0700 Subject: [PATCH 2/5] Use area_entities to extract entity_ids from area --- custom_components/adaptive_lighting/switch.py | 13 ++++++++++++- tests/test_switch.py | 7 ++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/custom_components/adaptive_lighting/switch.py b/custom_components/adaptive_lighting/switch.py index 73f6ed31..a8349f65 100755 --- a/custom_components/adaptive_lighting/switch.py +++ b/custom_components/adaptive_lighting/switch.py @@ -48,6 +48,7 @@ from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN from homeassistant.components.switch import SwitchEntity from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( + ATTR_AREA_ID, ATTR_DOMAIN, ATTR_ENTITY_ID, ATTR_SERVICE, @@ -80,6 +81,7 @@ from homeassistant.helpers.event import ( ) from homeassistant.helpers.restore_state import RestoreEntity from homeassistant.helpers.sun import get_astral_location +from homeassistant.helpers.template import area_entities from homeassistant.util import slugify from homeassistant.util.color import ( color_RGB_to_xy, @@ -1276,7 +1278,16 @@ class TurnOnOffListener: service = event.data[ATTR_SERVICE] service_data = event.data[ATTR_SERVICE_DATA] - entity_ids = cv.ensure_list_csv(service_data[ATTR_ENTITY_ID]) + if ATTR_ENTITY_ID in service_data: + entity_ids = cv.ensure_list_csv(service_data[ATTR_ENTITY_ID]) + elif ATTR_AREA_ID in service_data: + area_ids = cv.ensure_list_csv(service_data[ATTR_AREA_ID]) + entity_ids = [] + for area_id in area_ids: + entity_ids.extend(area_entities(self.hass, area_id)) + _LOGGER.debug( + "Found entity_ids '%s' in area area_id %s: %s", entity_ids, area_id + ) if not any(eid in self.lights for eid in entity_ids): return diff --git a/tests/test_switch.py b/tests/test_switch.py index 1473a29e..1de95909 100644 --- a/tests/test_switch.py +++ b/tests/test_switch.py @@ -871,7 +871,7 @@ async def test_separate_turn_on_commands(hass, separate_turn_on_commands): async def test_area(hass): - _, (light, *_) = await setup_lights_and_switch(hass) + switch, (light, *_) = await setup_lights_and_switch(hass) device_in_area = device_registry.DeviceEntry(area_id="test-area") mock_device_registry(hass, {device_in_area.id: device_in_area}) @@ -897,3 +897,8 @@ async def test_area(hass): blocking=True, ) await hass.async_block_till_done() + + _LOGGER.debug( + "switch.turn_on_off_listener.last_service_data: %s", + switch.turn_on_off_listener.last_service_data, + ) From acd506aeebc152676ab9d496d90ea202a6df07bb Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Mon, 29 Aug 2022 19:07:34 -0700 Subject: [PATCH 3/5] Only add the lights for an area --- custom_components/adaptive_lighting/switch.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/custom_components/adaptive_lighting/switch.py b/custom_components/adaptive_lighting/switch.py index a8349f65..00555ef0 100755 --- a/custom_components/adaptive_lighting/switch.py +++ b/custom_components/adaptive_lighting/switch.py @@ -1284,9 +1284,12 @@ class TurnOnOffListener: area_ids = cv.ensure_list_csv(service_data[ATTR_AREA_ID]) entity_ids = [] for area_id in area_ids: - entity_ids.extend(area_entities(self.hass, area_id)) + area_entity_ids = area_entities(self.hass, area_id) + for entity_id in area_entity_ids: + if entity_id.startswith(LIGHT_DOMAIN): + entity_ids.append(entity_id) _LOGGER.debug( - "Found entity_ids '%s' in area area_id %s: %s", entity_ids, area_id + "Found entity_ids '%s' for area_id '%s'", entity_ids, area_id ) if not any(eid in self.lights for eid in entity_ids): From 7bcd70cbecfa7e72bb1a28ee66e15bd4460dddb0 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Mon, 29 Aug 2022 19:25:04 -0700 Subject: [PATCH 4/5] Add TODO to the test --- tests/test_switch.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/test_switch.py b/tests/test_switch.py index 1de95909..38f9ea91 100644 --- a/tests/test_switch.py +++ b/tests/test_switch.py @@ -50,6 +50,7 @@ from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN import homeassistant.config as config_util from homeassistant.config_entries import ConfigEntryState from homeassistant.const import ( + ATTR_AREA_ID, ATTR_ENTITY_ID, CONF_LIGHTS, CONF_NAME, @@ -59,12 +60,12 @@ from homeassistant.const import ( STATE_ON, ) from homeassistant.core import Context, State -from homeassistant.helpers import device_registry, entity_registry +from homeassistant.helpers import entity_registry from homeassistant.setup import async_setup_component import homeassistant.util.dt as dt_util import pytest -from tests.common import MockConfigEntry, mock_device_registry, mock_registry +from tests.common import MockConfigEntry from tests.components.demo.test_light import ENTITY_LIGHT _LOGGER = logging.getLogger(__name__) @@ -872,16 +873,14 @@ async def test_separate_turn_on_commands(hass, separate_turn_on_commands): async def test_area(hass): switch, (light, *_) = await setup_lights_and_switch(hass) - device_in_area = device_registry.DeviceEntry(area_id="test-area") - - mock_device_registry(hass, {device_in_area.id: device_in_area}) - entity_in_area = entity_registry.RegistryEntry( - entity_id=light.entity_id, - unique_id="in-area-id", - platform="test", - device_id=device_in_area.id, + # TODO: this doesn't set up the area correctly because I get: + # MainThread ... Unable to find referenced areas test_area or it + # is/they are currently not available + # Therefore the area currently doesn't report to have lights in it. + entity = entity_registry.async_get(hass).async_get_or_create( + LIGHT_DOMAIN, "demo", light.unique_id, area_id="test_area" ) - mock_registry(hass, {entity_in_area.entity_id: entity_in_area}) + _LOGGER.debug("test_area entity: %s", entity) await hass.services.async_call( LIGHT_DOMAIN, SERVICE_TURN_ON, @@ -893,7 +892,7 @@ async def test_area(hass): await hass.services.async_call( LIGHT_DOMAIN, SERVICE_TURN_OFF, - {"area_id": "in-area-id"}, + {ATTR_AREA_ID: entity.area_id}, blocking=True, ) await hass.async_block_till_done() @@ -902,3 +901,4 @@ async def test_area(hass): "switch.turn_on_off_listener.last_service_data: %s", switch.turn_on_off_listener.last_service_data, ) + raise Exception(str(switch.turn_on_off_listener)) From 48b7bc43985beecb3f31693f9fee1f8752cf680b Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Mon, 29 Aug 2022 19:36:15 -0700 Subject: [PATCH 5/5] Fix test_area --- tests/test_switch.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/test_switch.py b/tests/test_switch.py index 38f9ea91..4739855e 100644 --- a/tests/test_switch.py +++ b/tests/test_switch.py @@ -65,7 +65,7 @@ from homeassistant.setup import async_setup_component import homeassistant.util.dt as dt_util import pytest -from tests.common import MockConfigEntry +from tests.common import MockConfigEntry, mock_area_registry from tests.components.demo.test_light import ENTITY_LIGHT _LOGGER = logging.getLogger(__name__) @@ -873,10 +873,10 @@ async def test_separate_turn_on_commands(hass, separate_turn_on_commands): async def test_area(hass): switch, (light, *_) = await setup_lights_and_switch(hass) - # TODO: this doesn't set up the area correctly because I get: - # MainThread ... Unable to find referenced areas test_area or it - # is/they are currently not available - # Therefore the area currently doesn't report to have lights in it. + + area_registry = mock_area_registry(hass) + area_registry.async_create("test_area") + entity = entity_registry.async_get(hass).async_get_or_create( LIGHT_DOMAIN, "demo", light.unique_id, area_id="test_area" ) @@ -884,11 +884,11 @@ async def test_area(hass): await hass.services.async_call( LIGHT_DOMAIN, SERVICE_TURN_ON, - {ATTR_ENTITY_ID: light.entity_id}, + {ATTR_AREA_ID: entity.area_id}, blocking=True, ) await hass.async_block_till_done() - + assert light.entity_id in switch.turn_on_off_listener.last_service_data await hass.services.async_call( LIGHT_DOMAIN, SERVICE_TURN_OFF, @@ -901,4 +901,4 @@ async def test_area(hass): "switch.turn_on_off_listener.last_service_data: %s", switch.turn_on_off_listener.last_service_data, ) - raise Exception(str(switch.turn_on_off_listener)) + assert light.entity_id not in switch.turn_on_off_listener.last_service_data