From 579dd6785d6e5a6a5d9545b4acac819f48033553 Mon Sep 17 00:00:00 2001 From: Artur Pragacz <49985303+arturpragacz@users.noreply.github.com> Date: Mon, 23 Mar 2026 18:33:45 +0100 Subject: [PATCH] Add entity name template function (#166078) --- homeassistant/helpers/template/__init__.py | 17 ++++++++++++ tests/helpers/template/test_init.py | 31 ++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/homeassistant/helpers/template/__init__.py b/homeassistant/helpers/template/__init__.py index 05f16f4355e..00a823f6636 100644 --- a/homeassistant/helpers/template/__init__.py +++ b/homeassistant/helpers/template/__init__.py @@ -1405,6 +1405,19 @@ def distance(hass: HomeAssistant, *args: Any) -> float | None: ) +def entity_name(hass: HomeAssistant, entity_id: str) -> str | None: + """Get the name of an entity from its entity ID.""" + ent_reg = er.async_get(hass) + if (entry := ent_reg.async_get(entity_id)) is not None: + return entry.name if entry.name is not None else entry.original_name + + # Fall back to state for entities without a unique_id (not in the registry) + if (state := hass.states.get(entity_id)) is not None: + return state.name + + return None + + def is_hidden_entity(hass: HomeAssistant, entity_id: str) -> bool: """Test if an entity is hidden.""" entity_reg = er.async_get(hass) @@ -2029,6 +2042,7 @@ class TemplateEnvironment(ImmutableSandboxedEnvironment): "area_name", "closest", "distance", + "entity_name", "expand", "has_value", "is_hidden_entity", @@ -2043,6 +2057,7 @@ class TemplateEnvironment(ImmutableSandboxedEnvironment): "area_id", "area_name", "closest", + "entity_name", "expand", "has_value", ] @@ -2073,6 +2088,8 @@ class TemplateEnvironment(ImmutableSandboxedEnvironment): # Entity extensions + self.globals["entity_name"] = hassfunction(entity_name) + self.filters["entity_name"] = self.globals["entity_name"] self.globals["is_hidden_entity"] = hassfunction(is_hidden_entity) self.tests["is_hidden_entity"] = hassfunction( is_hidden_entity, pass_eval_context diff --git a/tests/helpers/template/test_init.py b/tests/helpers/template/test_init.py index 1f8bdb4c22e..0b24953ea58 100644 --- a/tests/helpers/template/test_init.py +++ b/tests/helpers/template/test_init.py @@ -807,6 +807,37 @@ def test_if_state_exists(hass: HomeAssistant) -> None: assert result == "exists" +def test_entity_name( + hass: HomeAssistant, + entity_registry: er.EntityRegistry, +) -> None: + """Test entity_name method.""" + assert render(hass, "{{ entity_name('sensor.fake') }}") is None + + entry = entity_registry.async_get_or_create( + "sensor", "test", "unique_1", original_name="Registry Sensor" + ) + assert render(hass, f"{{{{ entity_name('{entry.entity_id}') }}}}") == ( + "Registry Sensor" + ) + assert render(hass, f"{{{{ '{entry.entity_id}' | entity_name }}}}") == ( + "Registry Sensor" + ) + + entity_registry.async_update_entity(entry.entity_id, name="My Custom Sensor") + assert render(hass, f"{{{{ entity_name('{entry.entity_id}') }}}}") == ( + "My Custom Sensor" + ) + + # Falls back to state for entities not in the registry + hass.states.async_set( + "light.no_unique_id", "on", {"friendly_name": "No Unique ID Light"} + ) + assert render(hass, "{{ entity_name('light.no_unique_id') }}") == ( + "No Unique ID Light" + ) + + def test_is_hidden_entity( hass: HomeAssistant, entity_registry: er.EntityRegistry,