Add parent device name part to generated entity IDs (#179996)

This commit is contained in:
Artur Pragacz
2026-09-10 16:07:59 +03:00
committed by GitHub
parent 06206cfa02
commit 2d8957b5ce
9 changed files with 347 additions and 258 deletions
+23 -1
View File
@@ -150,6 +150,7 @@ class EntityNamePart(StrEnum):
DEVICE = "device"
ENTITY = "entity"
FLOOR = "floor"
PARENT_DEVICE = "parent_device"
@dataclass(frozen=True, kw_only=True, slots=True)
@@ -521,11 +522,26 @@ def _async_get_full_entity_name(
elif not use_legacy_naming or name is None:
device_name: str | None = None
parent_device_name: str | None = None
if device_id is not None:
device_registry = dr.async_get(hass)
if (device := device_registry.async_get(device_id)) is not None:
device_name = device.name_by_user or device.name
if (
EntityNamePart.PARENT_DEVICE in parts
and isinstance(device, dr.ChildDeviceEntry)
and (
parent_device := device_registry.async_get(
device.parent_device_id, include_child_devices=False
)
)
is not None
):
parent_device_name = (
parent_device.name_by_user or parent_device.name
)
if area_id is None:
area_id = dr.async_get_effective_area_id(hass, device)
@@ -569,6 +585,7 @@ def _async_get_full_entity_name(
EntityNamePart.DEVICE: device_name,
EntityNamePart.ENTITY: entity_name,
EntityNamePart.FLOOR: floor_name,
EntityNamePart.PARENT_DEVICE: parent_device_name,
}
full_name = " ".join(
part_name for part in parts if (part_name := part_names[part])
@@ -1370,7 +1387,12 @@ class EntityRegistry(BaseRegistry):
"""
parts = self.settings.entity_id_parts
if parts is None:
parts = (EntityNamePart.AREA, EntityNamePart.DEVICE, EntityNamePart.ENTITY)
parts = (
EntityNamePart.AREA,
EntityNamePart.PARENT_DEVICE,
EntityNamePart.DEVICE,
EntityNamePart.ENTITY,
)
object_id = _async_get_full_entity_name(
self.hass,
area_id=area_id,
@@ -1,248 +1,4 @@
# serializer version: 1
# name: test_all_entities[sensor.heating_circuit_1_flow_temperature-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': dict({
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.heating_circuit_1_flow_temperature',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Flow temperature',
'options': dict({
'sensor': dict({
'suggested_display_precision': 1,
}),
}),
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
'original_icon': None,
'original_name': 'Flow temperature',
'platform': 'guntamatic',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'circuit_temperature',
'unique_id': '959103_circuit_1_temp',
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
})
# ---
# name: test_all_entities[sensor.heating_circuit_1_flow_temperature-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Heating circuit 1 Flow temperature',
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
}),
'context': <ANY>,
'entity_id': 'sensor.heating_circuit_1_flow_temperature',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '55.00',
})
# ---
# name: test_all_entities[sensor.heating_circuit_1_program-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': dict({
<SensorEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'off',
'timer',
'heat',
'hibernate',
'hibernate_to',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.heating_circuit_1_program',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Program',
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
'original_icon': None,
'original_name': 'Program',
'platform': 'guntamatic',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'heating_circulation_program',
'unique_id': '959103_heating_circulation_program_1',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[sensor.heating_circuit_1_program-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'enum',
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Heating circuit 1 Program',
<SensorEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'off',
'timer',
'heat',
'hibernate',
'hibernate_to',
]),
}),
'context': <ANY>,
'entity_id': 'sensor.heating_circuit_1_program',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
})
# ---
# name: test_all_entities[sensor.heating_circuit_1_pump-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': dict({
<SensorEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'auto',
'off',
'nonstop',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.heating_circuit_1_pump',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Pump',
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
'original_icon': None,
'original_name': 'Pump',
'platform': 'guntamatic',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'heating_circulation_pump',
'unique_id': '959103_heating_circulation_pump_1',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[sensor.heating_circuit_1_pump-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'enum',
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Heating circuit 1 Pump',
<SensorEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'auto',
'off',
'nonstop',
]),
}),
'context': <ANY>,
'entity_id': 'sensor.heating_circuit_1_pump',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'auto',
})
# ---
# name: test_all_entities[sensor.heating_circuit_1_room_temperature-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': dict({
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.heating_circuit_1_room_temperature',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Room temperature',
'options': dict({
'sensor': dict({
'suggested_display_precision': 1,
}),
}),
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
'original_icon': None,
'original_name': 'Room temperature',
'platform': 'guntamatic',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'room_temperature',
'unique_id': '959103_room_1_temperature',
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
})
# ---
# name: test_all_entities[sensor.heating_circuit_1_room_temperature-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Heating circuit 1 Room temperature',
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
}),
'context': <ANY>,
'entity_id': 'sensor.heating_circuit_1_room_temperature',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '21.50',
})
# ---
# name: test_all_entities[sensor.mock_title_auxiliary_pump_1-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
@@ -1283,6 +1039,250 @@
'state': '12',
})
# ---
# name: test_all_entities[sensor.mock_title_heating_circuit_1_flow_temperature-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': dict({
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.mock_title_heating_circuit_1_flow_temperature',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Flow temperature',
'options': dict({
'sensor': dict({
'suggested_display_precision': 1,
}),
}),
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
'original_icon': None,
'original_name': 'Flow temperature',
'platform': 'guntamatic',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'circuit_temperature',
'unique_id': '959103_circuit_1_temp',
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
})
# ---
# name: test_all_entities[sensor.mock_title_heating_circuit_1_flow_temperature-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Heating circuit 1 Flow temperature',
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
}),
'context': <ANY>,
'entity_id': 'sensor.mock_title_heating_circuit_1_flow_temperature',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '55.00',
})
# ---
# name: test_all_entities[sensor.mock_title_heating_circuit_1_program-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': dict({
<SensorEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'off',
'timer',
'heat',
'hibernate',
'hibernate_to',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.mock_title_heating_circuit_1_program',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Program',
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
'original_icon': None,
'original_name': 'Program',
'platform': 'guntamatic',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'heating_circulation_program',
'unique_id': '959103_heating_circulation_program_1',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[sensor.mock_title_heating_circuit_1_program-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'enum',
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Heating circuit 1 Program',
<SensorEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'off',
'timer',
'heat',
'hibernate',
'hibernate_to',
]),
}),
'context': <ANY>,
'entity_id': 'sensor.mock_title_heating_circuit_1_program',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'heat',
})
# ---
# name: test_all_entities[sensor.mock_title_heating_circuit_1_pump-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': dict({
<SensorEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'auto',
'off',
'nonstop',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.mock_title_heating_circuit_1_pump',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Pump',
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
'original_icon': None,
'original_name': 'Pump',
'platform': 'guntamatic',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'heating_circulation_pump',
'unique_id': '959103_heating_circulation_pump_1',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[sensor.mock_title_heating_circuit_1_pump-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'enum',
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Heating circuit 1 Pump',
<SensorEntityCapabilityAttribute.OPTIONS: 'options'>: list([
'auto',
'off',
'nonstop',
]),
}),
'context': <ANY>,
'entity_id': 'sensor.mock_title_heating_circuit_1_pump',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'auto',
})
# ---
# name: test_all_entities[sensor.mock_title_heating_circuit_1_room_temperature-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
None,
]),
'area_id': None,
'capabilities': dict({
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.mock_title_heating_circuit_1_room_temperature',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Room temperature',
'options': dict({
'sensor': dict({
'suggested_display_precision': 1,
}),
}),
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
'original_icon': None,
'original_name': 'Room temperature',
'platform': 'guntamatic',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'room_temperature',
'unique_id': '959103_room_1_temperature',
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
})
# ---
# name: test_all_entities[sensor.mock_title_heating_circuit_1_room_temperature-state]
StateSnapshot({
'attributes': ReadOnlyDict({
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Heating circuit 1 Room temperature',
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
}),
'context': <ANY>,
'entity_id': 'sensor.mock_title_heating_circuit_1_room_temperature',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '21.50',
})
# ---
# name: test_all_entities[sensor.mock_title_interruption_1-entry]
EntityRegistryEntrySnapshot({
'aliases': list([
+1 -1
View File
@@ -171,7 +171,7 @@ async def test_enum_sensor_unmapped_value(
await setup_integration(hass, mock_config_entry)
await hass.async_block_till_done()
state = hass.states.get("sensor.heating_circuit_1_pump")
state = hass.states.get("sensor.mock_title_heating_circuit_1_pump")
assert state is not None
assert state.state == STATE_UNKNOWN
@@ -9,7 +9,7 @@
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfPower.WATT: 'W'>,
}),
'context': <ANY>,
'entity_id': 'sensor.outlet_1_power',
'entity_id': 'sensor.power_strip_with_2_sockets_outlet_1_power',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
@@ -23,7 +23,7 @@
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfPower.WATT: 'W'>,
}),
'context': <ANY>,
'entity_id': 'sensor.outlet_2_power',
'entity_id': 'sensor.power_strip_with_2_sockets_outlet_2_power',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
@@ -93,7 +93,7 @@
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfPower.WATT: 'W'>,
}),
'context': <ANY>,
'entity_id': 'sensor.outlet_1_power',
'entity_id': 'sensor.power_strip_with_2_sockets_outlet_1_power',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
@@ -107,7 +107,7 @@
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfPower.WATT: 'W'>,
}),
'context': <ANY>,
'entity_id': 'sensor.outlet_2_power',
'entity_id': 'sensor.power_strip_with_2_sockets_outlet_2_power',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
@@ -5,7 +5,7 @@
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Outlet 1',
}),
'context': <ANY>,
'entity_id': 'switch.outlet_1',
'entity_id': 'switch.power_strip_with_2_sockets_outlet_1',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
@@ -26,7 +26,7 @@
'disabled_by': None,
'domain': 'switch',
'entity_category': None,
'entity_id': 'switch.outlet_1',
'entity_id': 'switch.power_strip_with_2_sockets_outlet_1',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
@@ -105,7 +105,7 @@
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: 'Outlet 2',
}),
'context': <ANY>,
'entity_id': 'switch.outlet_2',
'entity_id': 'switch.power_strip_with_2_sockets_outlet_2',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
@@ -126,7 +126,7 @@
'disabled_by': None,
'domain': 'switch',
'entity_category': None,
'entity_id': 'switch.outlet_2',
'entity_id': 'switch.power_strip_with_2_sockets_outlet_2',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
+4 -1
View File
@@ -46,7 +46,10 @@ async def test_outlet_power_sensors_on_child_devices(
entity_registry: er.EntityRegistry,
) -> None:
"""Test the outlet power sensors are placed on child devices of the power strip."""
for entity_id in ("sensor.outlet_1_power", "sensor.outlet_2_power"):
for entity_id in (
"sensor.power_strip_with_2_sockets_outlet_1_power",
"sensor.power_strip_with_2_sockets_outlet_2_power",
):
entity_entry = entity_registry.async_get(entity_id)
assert entity_entry is not None
child_device = device_registry.async_get(entity_entry.device_id)
+4 -1
View File
@@ -17,7 +17,10 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.setup import async_setup_component
SWITCH_ENTITY_IDS = ["switch.outlet_1", "switch.outlet_2"]
SWITCH_ENTITY_IDS = [
"switch.power_strip_with_2_sockets_outlet_1",
"switch.power_strip_with_2_sockets_outlet_2",
]
@pytest.fixture
+2 -2
View File
@@ -3077,8 +3077,8 @@ async def test_device_info_child_device(
entity_id = entity_registry.async_get_entity_id(
"test_domain", config_entry.domain, "power"
)
# The child device's name is the device part of the generated entity id
assert entity_id == "test_domain.outlet_1_power"
# The generated entity id includes the parent and child device names
assert entity_id == "test_domain.power_strip_outlet_1_power"
entry = entity_registry.async_get(entity_id)
assert entry is not None
assert entry.device_id == child_device.id
+61
View File
@@ -1176,6 +1176,67 @@ def test_generate_entity_id_parts_entity_area(
assert new_entity_id == "sensor.second_floor_garage_lamp_temperature"
def test_generate_entity_id_parent_device_part(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test the parent device part for entities on child devices."""
config_entry = MockConfigEntry(domain="sensor")
config_entry.add_to_hass(hass)
parent_device = device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
identifiers={("test", "strip")},
name="Power strip",
)
child_device = device_registry.async_get_or_create_child(
config_entry_id=config_entry.entry_id,
identifiers={("test", "strip_outlet_1")},
parent_device_id=parent_device.id,
name="Outlet 1",
)
# The default parts include the parent device name
entry = entity_registry.async_get_or_create(
"sensor",
"test",
"1234",
config_entry=config_entry,
device_id=child_device.id,
has_entity_name=True,
object_id_base="Power",
original_name="Power",
)
assert entry.entity_id == "sensor.power_strip_outlet_1_power"
# A parent device name set by the user is used
device_registry.async_update_device(parent_device.id, name_by_user="Kitchen strip")
assert (
entity_registry.async_regenerate_entity_id(entry)
== "sensor.kitchen_strip_outlet_1_power"
)
# An entity on a main device is not affected by the parent device part
main_entry = entity_registry.async_get_or_create(
"sensor",
"test",
"5678",
config_entry=config_entry,
device_id=parent_device.id,
has_entity_name=True,
object_id_base="Power",
original_name="Power",
)
assert main_entry.entity_id == "sensor.kitchen_strip_power"
# Parts without the parent device part exclude the parent device name
entity_registry.async_update_settings(
entity_id_parts=[er.EntityNamePart.DEVICE, er.EntityNamePart.ENTITY]
)
assert entity_registry.async_regenerate_entity_id(entry) == "sensor.outlet_1_power"
def test_regenerate_entity_id_after_settings_change(
hass: HomeAssistant,
area_registry: ar.AreaRegistry,