Remove obsolete entities from System Monitor automatically (#111231)

* Remove obsolete entities from System Monitor automatically

* callback
This commit is contained in:
G Johansson 2024-02-24 20:50:53 +01:00 committed by GitHub
parent 47b7dd4a01
commit c45cae3665
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 105 additions and 9 deletions

View File

@ -37,7 +37,8 @@ from homeassistant.const import (
UnitOfInformation,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import entity_registry as er
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
@ -569,7 +570,7 @@ async def async_setup_entry( # noqa: C901
is_enabled = check_legacy_resource(
f"{_type}_{argument}", legacy_resources
)
loaded_resources.add(f"{_type}_{argument}")
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
net_addr_coordinator,
@ -584,7 +585,7 @@ async def async_setup_entry( # noqa: C901
if _type == "last_boot":
argument = ""
is_enabled = check_legacy_resource(f"{_type}_{argument}", legacy_resources)
loaded_resources.add(f"{_type}_{argument}")
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
boot_time_coordinator,
@ -599,7 +600,7 @@ async def async_setup_entry( # noqa: C901
if _type.startswith("load_"):
argument = ""
is_enabled = check_legacy_resource(f"{_type}_{argument}", legacy_resources)
loaded_resources.add(f"{_type}_{argument}")
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
system_load_coordinator,
@ -614,7 +615,7 @@ async def async_setup_entry( # noqa: C901
if _type.startswith("memory_"):
argument = ""
is_enabled = check_legacy_resource(f"{_type}_{argument}", legacy_resources)
loaded_resources.add(f"{_type}_{argument}")
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
memory_coordinator,
@ -630,7 +631,7 @@ async def async_setup_entry( # noqa: C901
is_enabled = check_legacy_resource(
f"{_type}_{argument}", legacy_resources
)
loaded_resources.add(f"{_type}_{argument}")
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
net_io_coordinator,
@ -674,7 +675,7 @@ async def async_setup_entry( # noqa: C901
if _type == "processor_use":
argument = ""
is_enabled = check_legacy_resource(f"{_type}_{argument}", legacy_resources)
loaded_resources.add(f"{_type}_{argument}")
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
processor_coordinator,
@ -692,7 +693,7 @@ async def async_setup_entry( # noqa: C901
continue
argument = ""
is_enabled = check_legacy_resource(f"{_type}_{argument}", legacy_resources)
loaded_resources.add(f"{_type}_{argument}")
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
cpu_temp_coordinator,
@ -707,7 +708,7 @@ async def async_setup_entry( # noqa: C901
if _type.startswith("swap_"):
argument = ""
is_enabled = check_legacy_resource(f"{_type}_{argument}", legacy_resources)
loaded_resources.add(f"{_type}_{argument}")
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
swap_coordinator,
@ -729,6 +730,7 @@ async def async_setup_entry( # noqa: C901
loaded_resources,
)
if check_resource not in loaded_resources:
loaded_resources.add(check_resource)
split_index = resource.rfind("_")
_type = resource[:split_index]
argument = resource[split_index + 1 :]
@ -764,6 +766,27 @@ async def async_setup_entry( # noqa: C901
for coordinator in hass.data[DOMAIN_COORDINATORS].values():
await coordinator.async_request_refresh()
@callback
def clean_obsolete_entities() -> None:
"""Remove entities which are disabled and not supported from setup."""
entity_registry = er.async_get(hass)
entities = entity_registry.entities.get_entries_for_config_entry_id(
entry.entry_id
)
for entity in entities:
if (
entity.unique_id not in loaded_resources
and entity.disabled is True
and (
entity_id := entity_registry.async_get_entity_id(
SENSOR_DOMAIN, DOMAIN, entity.unique_id
)
)
):
entity_registry.async_remove(entity_id)
clean_obsolete_entities()
async_add_entities(entities)

View File

@ -550,3 +550,76 @@ async def test_cpu_percentage_is_zero_returns_unknown(
cpu_sensor = hass.states.get("sensor.system_monitor_processor_use")
assert cpu_sensor is not None
assert cpu_sensor.state == "15"
async def test_remove_obsolete_entities(
hass: HomeAssistant,
mock_psutil: Mock,
mock_added_config_entry: ConfigEntry,
caplog: pytest.LogCaptureFixture,
freezer: FrozenDateTimeFactory,
entity_registry: er.EntityRegistry,
) -> None:
"""Test we remove sensors that are not actual and disabled."""
cpu_sensor = hass.states.get("sensor.system_monitor_processor_use")
assert cpu_sensor is None
cpu_sensor_entity = entity_registry.async_get("sensor.system_monitor_processor_use")
assert cpu_sensor_entity.disabled is True
assert (
len(
entity_registry.entities.get_entries_for_config_entry_id(
mock_added_config_entry.entry_id
)
)
== 37
)
entity_registry.async_update_entity(
"sensor.system_monitor_processor_use", disabled_by=None
)
freezer.tick(timedelta(minutes=5))
async_fire_time_changed(hass)
await hass.async_block_till_done()
# Fake an entity which should be removed as not supported and disabled
entity_registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"network_out_veth12345",
disabled_by=er.RegistryEntryDisabler.INTEGRATION,
config_entry=mock_added_config_entry,
has_entity_name=True,
device_id=cpu_sensor_entity.device_id,
translation_key="network_out",
)
# Fake an entity which should not be removed as not supported but not disabled
entity_registry.async_get_or_create(
SENSOR_DOMAIN,
DOMAIN,
"network_out_veth54321",
disabled_by=None,
config_entry=mock_added_config_entry,
has_entity_name=True,
device_id=cpu_sensor_entity.device_id,
translation_key="network_out",
)
await hass.config_entries.async_reload(mock_added_config_entry.entry_id)
await hass.async_block_till_done()
assert (
len(
entity_registry.entities.get_entries_for_config_entry_id(
mock_added_config_entry.entry_id
)
)
== 38
)
assert (
entity_registry.async_get("sensor.systemmonitor_network_out_veth12345") is None
)
assert (
entity_registry.async_get("sensor.systemmonitor_network_out_veth54321")
is not None
)