Clear stale restored entity names in bluetooth passive update processor

This commit is contained in:
Paul Bottein
2026-07-30 15:09:48 +02:00
parent 0e95b79a60
commit 1e1ca36d57
2 changed files with 56 additions and 0 deletions
@@ -165,6 +165,15 @@ class PassiveBluetoothDataUpdate[_T]:
if current.get(key, UNDEFINED) != data:
changed_entity_keys.add(key)
current[key] = data # type: ignore[assignment]
# A key present in the update without a name means the integration
# does not name that entity; clear any stale name restored from storage.
for key in new_data.entity_data.keys() | new_data.entity_descriptions.keys():
if (
key not in new_data.entity_names
and self.entity_names.get(key) is not None
):
changed_entity_keys.add(key)
self.entity_names[key] = None
# If the device changed we don't need to return the changed
# entity keys as all entities will be updated
return None if device_change else changed_entity_keys
@@ -1982,3 +1982,50 @@ def test_deserialize_entity_description(
"""Test deserializing an entity description."""
description = deserialize_entity_description(description_type, description_dict)
assert description == expected_description
def test_update_clears_names_missing_from_the_update() -> None:
"""Test stored entity names are cleared when an update stops providing them.
Names restored from storage must not stick around once the integration
stops naming its entities, else entities keep stale names forever.
"""
temperature_key = PassiveBluetoothEntityKey("temperature", None)
pressure_key = PassiveBluetoothEntityKey("pressure", None)
temperature_description = SensorEntityDescription(
key="temperature",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
device_class=SensorDeviceClass.TEMPERATURE,
)
data = PassiveBluetoothDataUpdate(
devices={None: DeviceInfo(name="Test Device")},
entity_descriptions={temperature_key: temperature_description},
entity_names={temperature_key: "Temperature", pressure_key: "Pressure"},
entity_data={temperature_key: 14.5, pressure_key: 1234},
)
update_without_names = PassiveBluetoothDataUpdate(
devices={None: DeviceInfo(name="Test Device")},
entity_descriptions={temperature_key: temperature_description},
entity_names={},
entity_data={temperature_key: 15.5},
)
# The pressure name is untouched since the update does not include the key
assert data.update(update_without_names) == {temperature_key}
assert data.entity_names == {temperature_key: None, pressure_key: "Pressure"}
# A repeated update reports no changes
assert data.update(update_without_names) == set()
update_with_name = PassiveBluetoothDataUpdate(
devices={None: DeviceInfo(name="Test Device")},
entity_descriptions={temperature_key: temperature_description},
entity_names={temperature_key: "Custom name"},
entity_data={temperature_key: 15.5},
)
assert data.update(update_with_name) == {temperature_key}
assert data.entity_names == {
temperature_key: "Custom name",
pressure_key: "Pressure",
}