From a296c5e9ad301cc56fad055078073bc5bb3386b5 Mon Sep 17 00:00:00 2001 From: Petro31 <35082313+Petro31@users.noreply.github.com> Date: Fri, 28 Feb 2025 06:44:01 -0500 Subject: [PATCH] Add floor_entities function and filter (#136509) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: AbĂ­lio Costa --- homeassistant/helpers/template.py | 12 ++++++ tests/helpers/test_template.py | 69 +++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/homeassistant/helpers/template.py b/homeassistant/helpers/template.py index 7866250d658..7dc3097cdb3 100644 --- a/homeassistant/helpers/template.py +++ b/homeassistant/helpers/template.py @@ -1525,6 +1525,15 @@ def floor_areas(hass: HomeAssistant, floor_id_or_name: str) -> Iterable[str]: return [entry.id for entry in entries if entry.id] +def floor_entities(hass: HomeAssistant, floor_id_or_name: str) -> Iterable[str]: + """Return entity_ids for a given floor ID or name.""" + return [ + entity_id + for area_id in floor_areas(hass, floor_id_or_name) + for entity_id in area_entities(hass, area_id) + ] + + def areas(hass: HomeAssistant) -> Iterable[str | None]: """Return all areas.""" return list(area_registry.async_get(hass).areas) @@ -3048,6 +3057,9 @@ class TemplateEnvironment(ImmutableSandboxedEnvironment): self.globals["floor_areas"] = hassfunction(floor_areas) self.filters["floor_areas"] = self.globals["floor_areas"] + self.globals["floor_entities"] = hassfunction(floor_entities) + self.filters["floor_entities"] = self.globals["floor_entities"] + self.globals["integration_entities"] = hassfunction(integration_entities) self.filters["integration_entities"] = self.globals["integration_entities"] diff --git a/tests/helpers/test_template.py b/tests/helpers/test_template.py index b3a30806cbd..016aedb2f99 100644 --- a/tests/helpers/test_template.py +++ b/tests/helpers/test_template.py @@ -5881,6 +5881,75 @@ async def test_floor_areas( assert info.rate_limit is None +async def test_floor_entities( + hass: HomeAssistant, + floor_registry: fr.FloorRegistry, + area_registry: ar.AreaRegistry, + entity_registry: er.EntityRegistry, +) -> None: + """Test floor_entities function.""" + + # Test non existing floor ID + info = render_to_info(hass, "{{ floor_entities('skyring') }}") + assert_result_info(info, []) + assert info.rate_limit is None + + info = render_to_info(hass, "{{ 'skyring' | floor_entities }}") + assert_result_info(info, []) + assert info.rate_limit is None + + # Test wrong value type + info = render_to_info(hass, "{{ floor_entities(42) }}") + assert_result_info(info, []) + assert info.rate_limit is None + + info = render_to_info(hass, "{{ 42 | floor_entities }}") + assert_result_info(info, []) + assert info.rate_limit is None + + floor = floor_registry.async_create("First floor") + area1 = area_registry.async_create("Living room") + area2 = area_registry.async_create("Dining room") + area_registry.async_update(area1.id, floor_id=floor.floor_id) + area_registry.async_update(area2.id, floor_id=floor.floor_id) + + config_entry = MockConfigEntry(domain="light") + config_entry.add_to_hass(hass) + entity_entry = entity_registry.async_get_or_create( + "light", + "hue", + "living_room", + config_entry=config_entry, + ) + entity_registry.async_update_entity(entity_entry.entity_id, area_id=area1.id) + entity_entry = entity_registry.async_get_or_create( + "light", + "hue", + "dining_room", + config_entry=config_entry, + ) + entity_registry.async_update_entity(entity_entry.entity_id, area_id=area2.id) + + # Get entities by floor ID + expected = ["light.hue_living_room", "light.hue_dining_room"] + info = render_to_info(hass, f"{{{{ floor_entities('{floor.floor_id}') }}}}") + assert_result_info(info, expected) + assert info.rate_limit is None + + info = render_to_info(hass, f"{{{{ '{floor.floor_id}' | floor_entities }}}}") + assert_result_info(info, expected) + assert info.rate_limit is None + + # Get entities by floor name + info = render_to_info(hass, f"{{{{ floor_entities('{floor.name}') }}}}") + assert_result_info(info, expected) + assert info.rate_limit is None + + info = render_to_info(hass, f"{{{{ '{floor.name}' | floor_entities }}}}") + assert_result_info(info, expected) + assert info.rate_limit is None + + async def test_labels( hass: HomeAssistant, label_registry: lr.LabelRegistry,