This commit is contained in:
J. Nick Koston
2025-06-23 17:49:47 +02:00
parent 792060aa1c
commit a653d08e91
3 changed files with 148 additions and 1 deletions

View File

@@ -836,7 +836,7 @@ def _async_setup_device_registry(
sub_device_entry = device_registry.async_get_or_create(
config_entry_id=entry.entry_id,
identifiers={(DOMAIN, f"{device_info.mac_address}_{sub_device.device_id}")},
name=sub_device.name,
name=sub_device.name or device_entry.name,
manufacturer=manufacturer,
model=model,
sw_version=sw_version,

View File

@@ -797,3 +797,107 @@ async def test_entity_assignment_to_sub_device(
assert hass.states.get("binary_sensor.test_main_sensor").state == STATE_ON
assert hass.states.get("binary_sensor.test_motion").state == STATE_OFF
assert hass.states.get("binary_sensor.test_door").state == STATE_ON
# Check entity friendly names
# Main device entity should have: "{device_name} {entity_name}"
main_sensor_state = hass.states.get("binary_sensor.test_main_sensor")
assert main_sensor_state.attributes[ATTR_FRIENDLY_NAME] == "Test Main Sensor"
# Sub device 1 entity should have: "Motion Sensor Motion"
motion_sensor_state = hass.states.get("binary_sensor.test_motion")
assert motion_sensor_state.attributes[ATTR_FRIENDLY_NAME] == "Motion Sensor Motion"
# Sub device 2 entity should have: "Door Sensor Door"
door_sensor_state = hass.states.get("binary_sensor.test_door")
assert door_sensor_state.attributes[ATTR_FRIENDLY_NAME] == "Door Sensor Door"
async def test_entity_friendly_names_with_empty_device_names(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
device_registry: dr.DeviceRegistry,
mock_client: APIClient,
mock_esphome_device: MockESPHomeDeviceType,
) -> None:
"""Test entity friendly names when sub-devices have empty names."""
# Define sub devices with different name scenarios
sub_devices = [
SubDeviceInfo(device_id=11111111, name="", area_id=0), # Empty name
SubDeviceInfo(
device_id=22222222, name="Kitchen Light", area_id=0
), # Valid name
]
device_info = {
"devices": sub_devices,
"friendly_name": "Main Device",
}
# Entity on sub-device with empty name
entity_info = [
BinarySensorInfo(
object_id="motion",
key=1,
name="Motion Detected",
device_id=11111111,
),
# Entity on sub-device with valid name
BinarySensorInfo(
object_id="status",
key=2,
name="Status",
device_id=22222222,
),
# Entity with empty name on sub-device with valid name
BinarySensorInfo(
object_id="sensor",
key=3,
name="", # Empty entity name
device_id=22222222,
),
# Entity on main device
BinarySensorInfo(
object_id="main_status",
key=4,
name="Main Status",
device_id=0,
),
]
states = [
BinarySensorState(key=1, state=True, missing_state=False),
BinarySensorState(key=2, state=False, missing_state=False),
BinarySensorState(key=3, state=True, missing_state=False),
BinarySensorState(key=4, state=True, missing_state=False),
]
await mock_esphome_device(
mock_client=mock_client,
device_info=device_info,
entity_info=entity_info,
states=states,
)
# Check entity friendly name on sub-device with empty name
state_1 = hass.states.get("binary_sensor.test_motion")
assert state_1 is not None
# With has_entity_name, friendly name is "{device_name} {entity_name}"
# Since sub-device falls back to main device name: "Main Device Motion Detected"
assert state_1.attributes[ATTR_FRIENDLY_NAME] == "Main Device Motion Detected"
# Check entity friendly name on sub-device with valid name
state_2 = hass.states.get("binary_sensor.test_status")
assert state_2 is not None
# Device has name "Kitchen Light", entity has name "Status"
assert state_2.attributes[ATTR_FRIENDLY_NAME] == "Kitchen Light Status"
# Test entity with empty name on sub-device
state_3 = hass.states.get("binary_sensor.test")
assert state_3 is not None
# Entity has empty name, so friendly name is just the device name
assert state_3.attributes[ATTR_FRIENDLY_NAME] == "Kitchen Light"
# Test entity on main device
state_4 = hass.states.get("binary_sensor.test_main_status")
assert state_4 is not None
assert state_4.attributes[ATTR_FRIENDLY_NAME] == "Main Device Main Status"

View File

@@ -1680,6 +1680,49 @@ async def test_sub_device_cleanup(
)
async def test_sub_device_with_empty_name(
hass: HomeAssistant,
mock_client: APIClient,
mock_esphome_device: MockESPHomeDeviceType,
) -> None:
"""Test sub devices with empty names are handled correctly."""
device_registry = dr.async_get(hass)
# Define sub devices with empty names
sub_devices = [
SubDeviceInfo(device_id=11111111, name="", area_id=0), # Empty name
SubDeviceInfo(device_id=22222222, name="Valid Name", area_id=0),
]
device_info = {
"devices": sub_devices,
}
device = await mock_esphome_device(
mock_client=mock_client,
device_info=device_info,
)
await hass.async_block_till_done()
# Check sub device with empty name
sub_device_1 = device_registry.async_get_device(
identifiers={(DOMAIN, f"{device.device_info.mac_address}_11111111")}
)
assert sub_device_1 is not None
# Empty sub-device names should fall back to main device name
main_device = device_registry.async_get_device(
connections={(dr.CONNECTION_NETWORK_MAC, device.device_info.mac_address)}
)
assert sub_device_1.name == main_device.name
# Check sub device with valid name
sub_device_2 = device_registry.async_get_device(
identifiers={(DOMAIN, f"{device.device_info.mac_address}_22222222")}
)
assert sub_device_2 is not None
assert sub_device_2.name == "Valid Name"
async def test_sub_device_references_main_device_area(
hass: HomeAssistant,
mock_client: APIClient,