diff --git a/homeassistant/helpers/entity_registry.py b/homeassistant/helpers/entity_registry.py index 9665e884a5dc..1bcf61a3cf94 100644 --- a/homeassistant/helpers/entity_registry.py +++ b/homeassistant/helpers/entity_registry.py @@ -458,6 +458,27 @@ class RegistryEntry: hass.states.async_set(self.entity_id, STATE_UNAVAILABLE, attrs) +@callback +def async_get_unprefixed_name(hass: HomeAssistant, entry: RegistryEntry) -> str: + """Get the entity name with device name prefix stripped, if applicable.""" + name = entry.name + if name is not None: + if ( + entry.device_id is not None + and (device := dr.async_get(hass).async_get(entry.device_id)) is not None + ): + device_name = device.name_by_user or device.name + unprefixed_name = _async_strip_prefix_from_entity_name(name, device_name) + if unprefixed_name is not None: + return unprefixed_name + return name + + if entry.original_name_unprefixed is not None: + return entry.original_name_unprefixed + + return entry.original_name or "" + + @callback def _async_get_full_entity_name( hass: HomeAssistant, diff --git a/homeassistant/helpers/template/__init__.py b/homeassistant/helpers/template/__init__.py index df033135460a..22a476fb941e 100644 --- a/homeassistant/helpers/template/__init__.py +++ b/homeassistant/helpers/template/__init__.py @@ -1409,7 +1409,7 @@ 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 + return er.async_get_unprefixed_name(hass, entry) # Fall back to state for entities without a unique_id (not in the registry) if (state := hass.states.get(entity_id)) is not None: diff --git a/tests/helpers/template/test_init.py b/tests/helpers/template/test_init.py index 0b24953ea586..30846eef202a 100644 --- a/tests/helpers/template/test_init.py +++ b/tests/helpers/template/test_init.py @@ -33,7 +33,13 @@ from homeassistant.const import ( ) from homeassistant.core import HomeAssistant from homeassistant.exceptions import TemplateError -from homeassistant.helpers import entity, entity_registry as er, template, translation +from homeassistant.helpers import ( + device_registry as dr, + entity, + entity_registry as er, + template, + translation, +) from homeassistant.helpers.entity_platform import EntityPlatform from homeassistant.helpers.json import json_dumps from homeassistant.helpers.template.render_info import ( @@ -810,6 +816,7 @@ def test_if_state_exists(hass: HomeAssistant) -> None: def test_entity_name( hass: HomeAssistant, entity_registry: er.EntityRegistry, + device_registry: dr.DeviceRegistry, ) -> None: """Test entity_name method.""" assert render(hass, "{{ entity_name('sensor.fake') }}") is None @@ -837,6 +844,34 @@ def test_entity_name( "No Unique ID Light" ) + config_entry = MockConfigEntry(domain="test") + config_entry.add_to_hass(hass) + device_entry = device_registry.async_get_or_create( + config_entry_id=config_entry.entry_id, + connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")}, + name="My Device", + ) + entry2 = entity_registry.async_get_or_create( + "sensor", + "test", + "unique_2", + config_entry=config_entry, + device_id=device_entry.id, + has_entity_name=True, + original_name="Temperature", + ) + assert render(hass, f"{{{{ entity_name('{entry2.entity_id}') }}}}") == ( + "Temperature" + ) + + # Strips device name prefix + entity_registry.async_update_entity( + entry2.entity_id, name="My Device Custom Sensor" + ) + assert render(hass, f"{{{{ entity_name('{entry2.entity_id}') }}}}") == ( + "Custom Sensor" + ) + def test_is_hidden_entity( hass: HomeAssistant,