Move all System Monitor updates into single Data Update Coordinator (#112055)

This commit is contained in:
G Johansson
2024-03-03 18:24:04 +01:00
committed by GitHub
parent faee9d996d
commit cdd7b94a95
8 changed files with 395 additions and 399 deletions

View File

@ -10,11 +10,9 @@ import logging
import socket
import sys
import time
from typing import Any, Generic, Literal
from typing import Any, Literal
from psutil import NoSuchProcess, Process
from psutil._common import sdiskusage, shwtemp, snetio, snicaddr, sswap
import psutil_home_assistant as ha_psutil
from psutil import NoSuchProcess
import voluptuous as vol
from homeassistant.components.sensor import (
@ -47,22 +45,8 @@ from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType, StateTyp
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.util import slugify
from .const import CONF_PROCESS, DOMAIN, DOMAIN_COORDINATORS, NET_IO_TYPES
from .coordinator import (
MonitorCoordinator,
SystemMonitorBootTimeCoordinator,
SystemMonitorCPUtempCoordinator,
SystemMonitorDiskCoordinator,
SystemMonitorLoadCoordinator,
SystemMonitorMemoryCoordinator,
SystemMonitorNetAddrCoordinator,
SystemMonitorNetIOCoordinator,
SystemMonitorProcessCoordinator,
SystemMonitorProcessorCoordinator,
SystemMonitorSwapCoordinator,
VirtualMemory,
dataT,
)
from .const import CONF_PROCESS, DOMAIN, DOMAIN_COORDINATOR, NET_IO_TYPES
from .coordinator import SystemMonitorCoordinator
from .util import get_all_disk_mounts, get_all_network_interfaces, read_cpu_temperature
_LOGGER = logging.getLogger(__name__)
@ -88,16 +72,16 @@ def get_cpu_icon() -> Literal["mdi:cpu-64-bit", "mdi:cpu-32-bit"]:
def get_processor_temperature(
entity: SystemMonitorSensor[dict[str, list[shwtemp]]],
entity: SystemMonitorSensor,
) -> float | None:
"""Return processor temperature."""
return read_cpu_temperature(entity.hass, entity.coordinator.data)
return read_cpu_temperature(entity.hass, entity.coordinator.data.temperatures)
def get_process(entity: SystemMonitorSensor[list[Process]]) -> str:
def get_process(entity: SystemMonitorSensor) -> str:
"""Return process."""
state = STATE_OFF
for proc in entity.coordinator.data:
for proc in entity.coordinator.data.processes:
try:
_LOGGER.debug("process %s for argument %s", proc.name(), entity.argument)
if entity.argument == proc.name():
@ -112,26 +96,26 @@ def get_process(entity: SystemMonitorSensor[list[Process]]) -> str:
return state
def get_network(entity: SystemMonitorSensor[dict[str, snetio]]) -> float | None:
def get_network(entity: SystemMonitorSensor) -> float | None:
"""Return network in and out."""
counters = entity.coordinator.data
counters = entity.coordinator.data.io_counters
if entity.argument in counters:
counter = counters[entity.argument][IO_COUNTER[entity.entity_description.key]]
return round(counter / 1024**2, 1)
return None
def get_packets(entity: SystemMonitorSensor[dict[str, snetio]]) -> float | None:
def get_packets(entity: SystemMonitorSensor) -> float | None:
"""Return packets in and out."""
counters = entity.coordinator.data
counters = entity.coordinator.data.io_counters
if entity.argument in counters:
return counters[entity.argument][IO_COUNTER[entity.entity_description.key]]
return None
def get_throughput(entity: SystemMonitorSensor[dict[str, snetio]]) -> float | None:
def get_throughput(entity: SystemMonitorSensor) -> float | None:
"""Return network throughput in and out."""
counters = entity.coordinator.data
counters = entity.coordinator.data.io_counters
state = None
if entity.argument in counters:
counter = counters[entity.argument][IO_COUNTER[entity.entity_description.key]]
@ -151,10 +135,10 @@ def get_throughput(entity: SystemMonitorSensor[dict[str, snetio]]) -> float | No
def get_ip_address(
entity: SystemMonitorSensor[dict[str, list[snicaddr]]],
entity: SystemMonitorSensor,
) -> str | None:
"""Return network ip address."""
addresses = entity.coordinator.data
addresses = entity.coordinator.data.addresses
if entity.argument in addresses:
for addr in addresses[entity.argument]:
if addr.family == IF_ADDRS_FAMILY[entity.entity_description.key]:
@ -163,16 +147,18 @@ def get_ip_address(
@dataclass(frozen=True, kw_only=True)
class SysMonitorSensorEntityDescription(SensorEntityDescription, Generic[dataT]):
class SysMonitorSensorEntityDescription(SensorEntityDescription):
"""Describes System Monitor sensor entities."""
value_fn: Callable[[SystemMonitorSensor[dataT]], StateType | datetime]
value_fn: Callable[[SystemMonitorSensor], StateType | datetime]
add_to_update: Callable[[SystemMonitorSensor], tuple[str, str]]
none_is_unavailable: bool = False
mandatory_arg: bool = False
placeholder: str | None = None
SENSOR_TYPES: dict[str, SysMonitorSensorEntityDescription[Any]] = {
"disk_free": SysMonitorSensorEntityDescription[sdiskusage](
SENSOR_TYPES: dict[str, SysMonitorSensorEntityDescription] = {
"disk_free": SysMonitorSensorEntityDescription(
key="disk_free",
translation_key="disk_free",
placeholder="mount_point",
@ -180,9 +166,15 @@ SENSOR_TYPES: dict[str, SysMonitorSensorEntityDescription[Any]] = {
device_class=SensorDeviceClass.DATA_SIZE,
icon="mdi:harddisk",
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda entity: round(entity.coordinator.data.free / 1024**3, 1),
value_fn=lambda entity: round(
entity.coordinator.data.disk_usage[entity.argument].free / 1024**3, 1
)
if entity.argument in entity.coordinator.data.disk_usage
else None,
none_is_unavailable=True,
add_to_update=lambda entity: ("disks", entity.argument),
),
"disk_use": SysMonitorSensorEntityDescription[sdiskusage](
"disk_use": SysMonitorSensorEntityDescription(
key="disk_use",
translation_key="disk_use",
placeholder="mount_point",
@ -190,70 +182,91 @@ SENSOR_TYPES: dict[str, SysMonitorSensorEntityDescription[Any]] = {
device_class=SensorDeviceClass.DATA_SIZE,
icon="mdi:harddisk",
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda entity: round(entity.coordinator.data.used / 1024**3, 1),
value_fn=lambda entity: round(
entity.coordinator.data.disk_usage[entity.argument].used / 1024**3, 1
)
if entity.argument in entity.coordinator.data.disk_usage
else None,
none_is_unavailable=True,
add_to_update=lambda entity: ("disks", entity.argument),
),
"disk_use_percent": SysMonitorSensorEntityDescription[sdiskusage](
"disk_use_percent": SysMonitorSensorEntityDescription(
key="disk_use_percent",
translation_key="disk_use_percent",
placeholder="mount_point",
native_unit_of_measurement=PERCENTAGE,
icon="mdi:harddisk",
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda entity: entity.coordinator.data.percent,
value_fn=lambda entity: entity.coordinator.data.disk_usage[
entity.argument
].percent
if entity.argument in entity.coordinator.data.disk_usage
else None,
none_is_unavailable=True,
add_to_update=lambda entity: ("disks", entity.argument),
),
"ipv4_address": SysMonitorSensorEntityDescription[dict[str, list[snicaddr]]](
"ipv4_address": SysMonitorSensorEntityDescription(
key="ipv4_address",
translation_key="ipv4_address",
placeholder="ip_address",
icon="mdi:ip-network",
mandatory_arg=True,
value_fn=get_ip_address,
add_to_update=lambda entity: ("addresses", ""),
),
"ipv6_address": SysMonitorSensorEntityDescription[dict[str, list[snicaddr]]](
"ipv6_address": SysMonitorSensorEntityDescription(
key="ipv6_address",
translation_key="ipv6_address",
placeholder="ip_address",
icon="mdi:ip-network",
mandatory_arg=True,
value_fn=get_ip_address,
add_to_update=lambda entity: ("addresses", ""),
),
"last_boot": SysMonitorSensorEntityDescription[datetime](
"last_boot": SysMonitorSensorEntityDescription(
key="last_boot",
translation_key="last_boot",
device_class=SensorDeviceClass.TIMESTAMP,
value_fn=lambda entity: entity.coordinator.data,
value_fn=lambda entity: entity.coordinator.data.boot_time,
add_to_update=lambda entity: ("boot", ""),
),
"load_15m": SysMonitorSensorEntityDescription[tuple[float, float, float]](
"load_15m": SysMonitorSensorEntityDescription(
key="load_15m",
translation_key="load_15m",
icon=get_cpu_icon(),
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda entity: round(entity.coordinator.data[2], 2),
value_fn=lambda entity: round(entity.coordinator.data.load[2], 2),
add_to_update=lambda entity: ("load", ""),
),
"load_1m": SysMonitorSensorEntityDescription[tuple[float, float, float]](
"load_1m": SysMonitorSensorEntityDescription(
key="load_1m",
translation_key="load_1m",
icon=get_cpu_icon(),
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda entity: round(entity.coordinator.data[0], 2),
value_fn=lambda entity: round(entity.coordinator.data.load[0], 2),
add_to_update=lambda entity: ("load", ""),
),
"load_5m": SysMonitorSensorEntityDescription[tuple[float, float, float]](
"load_5m": SysMonitorSensorEntityDescription(
key="load_5m",
translation_key="load_5m",
icon=get_cpu_icon(),
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda entity: round(entity.coordinator.data[1], 2),
value_fn=lambda entity: round(entity.coordinator.data.load[1], 2),
add_to_update=lambda entity: ("load", ""),
),
"memory_free": SysMonitorSensorEntityDescription[VirtualMemory](
"memory_free": SysMonitorSensorEntityDescription(
key="memory_free",
translation_key="memory_free",
native_unit_of_measurement=UnitOfInformation.MEBIBYTES,
device_class=SensorDeviceClass.DATA_SIZE,
icon="mdi:memory",
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda entity: round(entity.coordinator.data.available / 1024**2, 1),
value_fn=lambda entity: round(
entity.coordinator.data.memory.available / 1024**2, 1
),
add_to_update=lambda entity: ("memory", ""),
),
"memory_use": SysMonitorSensorEntityDescription[VirtualMemory](
"memory_use": SysMonitorSensorEntityDescription(
key="memory_use",
translation_key="memory_use",
native_unit_of_measurement=UnitOfInformation.MEBIBYTES,
@ -261,20 +274,25 @@ SENSOR_TYPES: dict[str, SysMonitorSensorEntityDescription[Any]] = {
icon="mdi:memory",
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda entity: round(
(entity.coordinator.data.total - entity.coordinator.data.available)
(
entity.coordinator.data.memory.total
- entity.coordinator.data.memory.available
)
/ 1024**2,
1,
),
add_to_update=lambda entity: ("memory", ""),
),
"memory_use_percent": SysMonitorSensorEntityDescription[VirtualMemory](
"memory_use_percent": SysMonitorSensorEntityDescription(
key="memory_use_percent",
translation_key="memory_use_percent",
native_unit_of_measurement=PERCENTAGE,
icon="mdi:memory",
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda entity: entity.coordinator.data.percent,
value_fn=lambda entity: entity.coordinator.data.memory.percent,
add_to_update=lambda entity: ("memory", ""),
),
"network_in": SysMonitorSensorEntityDescription[dict[str, snetio]](
"network_in": SysMonitorSensorEntityDescription(
key="network_in",
translation_key="network_in",
placeholder="interface",
@ -284,8 +302,9 @@ SENSOR_TYPES: dict[str, SysMonitorSensorEntityDescription[Any]] = {
state_class=SensorStateClass.TOTAL_INCREASING,
mandatory_arg=True,
value_fn=get_network,
add_to_update=lambda entity: ("io_counters", ""),
),
"network_out": SysMonitorSensorEntityDescription[dict[str, snetio]](
"network_out": SysMonitorSensorEntityDescription(
key="network_out",
translation_key="network_out",
placeholder="interface",
@ -295,8 +314,9 @@ SENSOR_TYPES: dict[str, SysMonitorSensorEntityDescription[Any]] = {
state_class=SensorStateClass.TOTAL_INCREASING,
mandatory_arg=True,
value_fn=get_network,
add_to_update=lambda entity: ("io_counters", ""),
),
"packets_in": SysMonitorSensorEntityDescription[dict[str, snetio]](
"packets_in": SysMonitorSensorEntityDescription(
key="packets_in",
translation_key="packets_in",
placeholder="interface",
@ -304,8 +324,9 @@ SENSOR_TYPES: dict[str, SysMonitorSensorEntityDescription[Any]] = {
state_class=SensorStateClass.TOTAL_INCREASING,
mandatory_arg=True,
value_fn=get_packets,
add_to_update=lambda entity: ("io_counters", ""),
),
"packets_out": SysMonitorSensorEntityDescription[dict[str, snetio]](
"packets_out": SysMonitorSensorEntityDescription(
key="packets_out",
translation_key="packets_out",
placeholder="interface",
@ -313,8 +334,9 @@ SENSOR_TYPES: dict[str, SysMonitorSensorEntityDescription[Any]] = {
state_class=SensorStateClass.TOTAL_INCREASING,
mandatory_arg=True,
value_fn=get_packets,
add_to_update=lambda entity: ("io_counters", ""),
),
"throughput_network_in": SysMonitorSensorEntityDescription[dict[str, snetio]](
"throughput_network_in": SysMonitorSensorEntityDescription(
key="throughput_network_in",
translation_key="throughput_network_in",
placeholder="interface",
@ -323,8 +345,9 @@ SENSOR_TYPES: dict[str, SysMonitorSensorEntityDescription[Any]] = {
state_class=SensorStateClass.MEASUREMENT,
mandatory_arg=True,
value_fn=get_throughput,
add_to_update=lambda entity: ("io_counters", ""),
),
"throughput_network_out": SysMonitorSensorEntityDescription[dict[str, snetio]](
"throughput_network_out": SysMonitorSensorEntityDescription(
key="throughput_network_out",
translation_key="throughput_network_out",
placeholder="interface",
@ -333,60 +356,68 @@ SENSOR_TYPES: dict[str, SysMonitorSensorEntityDescription[Any]] = {
state_class=SensorStateClass.MEASUREMENT,
mandatory_arg=True,
value_fn=get_throughput,
add_to_update=lambda entity: ("io_counters", ""),
),
"process": SysMonitorSensorEntityDescription[list[Process]](
"process": SysMonitorSensorEntityDescription(
key="process",
translation_key="process",
placeholder="process",
icon=get_cpu_icon(),
mandatory_arg=True,
value_fn=get_process,
add_to_update=lambda entity: ("processes", ""),
),
"processor_use": SysMonitorSensorEntityDescription[float](
"processor_use": SysMonitorSensorEntityDescription(
key="processor_use",
translation_key="processor_use",
native_unit_of_measurement=PERCENTAGE,
icon=get_cpu_icon(),
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda entity: (
round(entity.coordinator.data) if entity.coordinator.data else None
round(entity.coordinator.data.cpu_percent)
if entity.coordinator.data.cpu_percent
else None
),
add_to_update=lambda entity: ("cpu_percent", ""),
),
"processor_temperature": SysMonitorSensorEntityDescription[
dict[str, list[shwtemp]]
](
"processor_temperature": SysMonitorSensorEntityDescription(
key="processor_temperature",
translation_key="processor_temperature",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=get_processor_temperature,
none_is_unavailable=True,
add_to_update=lambda entity: ("temperatures", ""),
),
"swap_free": SysMonitorSensorEntityDescription[sswap](
"swap_free": SysMonitorSensorEntityDescription(
key="swap_free",
translation_key="swap_free",
native_unit_of_measurement=UnitOfInformation.MEBIBYTES,
device_class=SensorDeviceClass.DATA_SIZE,
icon="mdi:harddisk",
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda entity: round(entity.coordinator.data.free / 1024**2, 1),
value_fn=lambda entity: round(entity.coordinator.data.swap.free / 1024**2, 1),
add_to_update=lambda entity: ("swap", ""),
),
"swap_use": SysMonitorSensorEntityDescription[sswap](
"swap_use": SysMonitorSensorEntityDescription(
key="swap_use",
translation_key="swap_use",
native_unit_of_measurement=UnitOfInformation.MEBIBYTES,
device_class=SensorDeviceClass.DATA_SIZE,
icon="mdi:harddisk",
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda entity: round(entity.coordinator.data.used / 1024**2, 1),
value_fn=lambda entity: round(entity.coordinator.data.swap.used / 1024**2, 1),
add_to_update=lambda entity: ("swap", ""),
),
"swap_use_percent": SysMonitorSensorEntityDescription[sswap](
"swap_use_percent": SysMonitorSensorEntityDescription(
key="swap_use_percent",
translation_key="swap_use_percent",
native_unit_of_measurement=PERCENTAGE,
icon="mdi:harddisk",
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda entity: entity.coordinator.data.percent,
value_fn=lambda entity: entity.coordinator.data.swap.percent,
add_to_update=lambda entity: ("swap", ""),
),
}
@ -489,7 +520,7 @@ async def async_setup_entry( # noqa: C901
entities: list[SystemMonitorSensor] = []
legacy_resources: set[str] = set(entry.options.get("resources", []))
loaded_resources: set[str] = set()
psutil_wrapper: ha_psutil.PsutilWrapper = hass.data[DOMAIN]
coordinator: SystemMonitorCoordinator = hass.data[DOMAIN_COORDINATOR]
def get_arguments() -> dict[str, Any]:
"""Return startup information."""
@ -507,44 +538,6 @@ async def async_setup_entry( # noqa: C901
startup_arguments = await hass.async_add_executor_job(get_arguments)
disk_coordinators: dict[str, SystemMonitorDiskCoordinator] = {}
for argument in startup_arguments["disk_arguments"]:
disk_coordinators[argument] = SystemMonitorDiskCoordinator(
hass, psutil_wrapper, f"Disk {argument} coordinator", argument
)
swap_coordinator = SystemMonitorSwapCoordinator(
hass, psutil_wrapper, "Swap coordinator"
)
memory_coordinator = SystemMonitorMemoryCoordinator(
hass, psutil_wrapper, "Memory coordinator"
)
net_io_coordinator = SystemMonitorNetIOCoordinator(
hass, psutil_wrapper, "Net IO coordnator"
)
net_addr_coordinator = SystemMonitorNetAddrCoordinator(
hass, psutil_wrapper, "Net address coordinator"
)
system_load_coordinator = SystemMonitorLoadCoordinator(
hass, psutil_wrapper, "System load coordinator"
)
processor_coordinator = SystemMonitorProcessorCoordinator(
hass, psutil_wrapper, "Processor coordinator"
)
boot_time_coordinator = SystemMonitorBootTimeCoordinator(
hass, psutil_wrapper, "Boot time coordinator"
)
process_coordinator = SystemMonitorProcessCoordinator(
hass, psutil_wrapper, "Process coordinator"
)
cpu_temp_coordinator = SystemMonitorCPUtempCoordinator(
hass, psutil_wrapper, "CPU temperature coordinator"
)
for argument in startup_arguments["disk_arguments"]:
disk_coordinators[argument] = SystemMonitorDiskCoordinator(
hass, psutil_wrapper, f"Disk {argument} coordinator", argument
)
_LOGGER.debug("Setup from options %s", entry.options)
for _type, sensor_description in SENSOR_TYPES.items():
@ -556,7 +549,7 @@ async def async_setup_entry( # noqa: C901
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
disk_coordinators[argument],
coordinator,
sensor_description,
entry.entry_id,
argument,
@ -573,7 +566,7 @@ async def async_setup_entry( # noqa: C901
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
net_addr_coordinator,
coordinator,
sensor_description,
entry.entry_id,
argument,
@ -588,7 +581,7 @@ async def async_setup_entry( # noqa: C901
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
boot_time_coordinator,
coordinator,
sensor_description,
entry.entry_id,
argument,
@ -603,7 +596,7 @@ async def async_setup_entry( # noqa: C901
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
system_load_coordinator,
coordinator,
sensor_description,
entry.entry_id,
argument,
@ -618,7 +611,7 @@ async def async_setup_entry( # noqa: C901
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
memory_coordinator,
coordinator,
sensor_description,
entry.entry_id,
argument,
@ -634,7 +627,7 @@ async def async_setup_entry( # noqa: C901
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
net_io_coordinator,
coordinator,
sensor_description,
entry.entry_id,
argument,
@ -649,7 +642,7 @@ async def async_setup_entry( # noqa: C901
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
process_coordinator,
coordinator,
sensor_description,
entry.entry_id,
argument,
@ -678,7 +671,7 @@ async def async_setup_entry( # noqa: C901
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
processor_coordinator,
coordinator,
sensor_description,
entry.entry_id,
argument,
@ -696,7 +689,7 @@ async def async_setup_entry( # noqa: C901
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
cpu_temp_coordinator,
coordinator,
sensor_description,
entry.entry_id,
argument,
@ -711,7 +704,7 @@ async def async_setup_entry( # noqa: C901
loaded_resources.add(slugify(f"{_type}_{argument}"))
entities.append(
SystemMonitorSensor(
swap_coordinator,
coordinator,
sensor_description,
entry.entry_id,
argument,
@ -735,13 +728,9 @@ async def async_setup_entry( # noqa: C901
_type = resource[:split_index]
argument = resource[split_index + 1 :]
_LOGGER.debug("Loading legacy %s with argument %s", _type, argument)
if not disk_coordinators.get(argument):
disk_coordinators[argument] = SystemMonitorDiskCoordinator(
hass, psutil_wrapper, f"Disk {argument} coordinator", argument
)
entities.append(
SystemMonitorSensor(
disk_coordinators[argument],
coordinator,
SENSOR_TYPES[_type],
entry.entry_id,
argument,
@ -749,23 +738,6 @@ async def async_setup_entry( # noqa: C901
)
)
hass.data[DOMAIN_COORDINATORS] = {}
# No gathering to avoid swamping the executor
for argument, coordinator in disk_coordinators.items():
hass.data[DOMAIN_COORDINATORS][f"disk_{argument}"] = coordinator
hass.data[DOMAIN_COORDINATORS]["boot_time"] = boot_time_coordinator
hass.data[DOMAIN_COORDINATORS]["cpu_temp"] = cpu_temp_coordinator
hass.data[DOMAIN_COORDINATORS]["memory"] = memory_coordinator
hass.data[DOMAIN_COORDINATORS]["net_addr"] = net_addr_coordinator
hass.data[DOMAIN_COORDINATORS]["net_io"] = net_io_coordinator
hass.data[DOMAIN_COORDINATORS]["process"] = process_coordinator
hass.data[DOMAIN_COORDINATORS]["processor"] = processor_coordinator
hass.data[DOMAIN_COORDINATORS]["swap"] = swap_coordinator
hass.data[DOMAIN_COORDINATORS]["system_load"] = system_load_coordinator
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."""
@ -790,17 +762,18 @@ async def async_setup_entry( # noqa: C901
async_add_entities(entities)
class SystemMonitorSensor(CoordinatorEntity[MonitorCoordinator[dataT]], SensorEntity):
class SystemMonitorSensor(CoordinatorEntity[SystemMonitorCoordinator], SensorEntity):
"""Implementation of a system monitor sensor."""
_attr_has_entity_name = True
_attr_entity_category = EntityCategory.DIAGNOSTIC
entity_description: SysMonitorSensorEntityDescription[dataT]
entity_description: SysMonitorSensorEntityDescription
argument: str
def __init__(
self,
coordinator: MonitorCoordinator[dataT],
sensor_description: SysMonitorSensorEntityDescription[dataT],
coordinator: SystemMonitorCoordinator,
sensor_description: SysMonitorSensorEntityDescription,
entry_id: str,
argument: str,
legacy_enabled: bool = False,
@ -824,7 +797,31 @@ class SystemMonitorSensor(CoordinatorEntity[MonitorCoordinator[dataT]], SensorEn
self.value: int | None = None
self.update_time: float | None = None
async def async_added_to_hass(self) -> None:
"""When added to hass."""
self.coordinator.update_subscribers[
self.entity_description.add_to_update(self)
].add(self.entity_id)
return await super().async_added_to_hass()
async def async_will_remove_from_hass(self) -> None:
"""When removed from hass."""
self.coordinator.update_subscribers[
self.entity_description.add_to_update(self)
].remove(self.entity_id)
return await super().async_will_remove_from_hass()
@property
def native_value(self) -> StateType | datetime:
"""Return the state."""
return self.entity_description.value_fn(self)
@property
def available(self) -> bool:
"""Return if entity is available."""
if self.entity_description.none_is_unavailable:
return bool(
self.coordinator.last_update_success is True
and self.native_value is not None
)
return super().available