diff --git a/homeassistant/components/systemmonitor/binary_sensor.py b/homeassistant/components/systemmonitor/binary_sensor.py index 3968e94ec03a..ad84e727129a 100644 --- a/homeassistant/components/systemmonitor/binary_sensor.py +++ b/homeassistant/components/systemmonitor/binary_sensor.py @@ -9,8 +9,6 @@ import logging import sys from typing import Literal -from psutil import NoSuchProcess - from homeassistant.components.binary_sensor import ( DOMAIN as BINARY_SENSOR_DOMAIN, BinarySensorDeviceClass, @@ -25,7 +23,7 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.util import slugify from . import SystemMonitorConfigEntry -from .const import CONF_PROCESS, DOMAIN +from .const import CONF_PROCESS, DOMAIN, PROCESS_ERRORS from .coordinator import SystemMonitorCoordinator _LOGGER = logging.getLogger(__name__) @@ -59,12 +57,8 @@ def get_process(entity: SystemMonitorSensor) -> bool: if entity.argument == proc.name(): state = True break - except NoSuchProcess as err: - _LOGGER.warning( - "Failed to load process with ID: %s, old name: %s", - err.pid, - err.name, - ) + except PROCESS_ERRORS: + continue return state diff --git a/homeassistant/components/systemmonitor/const.py b/homeassistant/components/systemmonitor/const.py index 798cb82f8eff..72fd3384687c 100644 --- a/homeassistant/components/systemmonitor/const.py +++ b/homeassistant/components/systemmonitor/const.py @@ -1,5 +1,7 @@ """Constants for System Monitor.""" +from psutil import AccessDenied, Error, NoSuchProcess, TimeoutExpired, ZombieProcess + DOMAIN = "systemmonitor" CONF_INDEX = "index" @@ -14,6 +16,8 @@ NET_IO_TYPES = [ "packets_out", ] +PROCESS_ERRORS = (NoSuchProcess, AccessDenied, Error, TimeoutExpired, ZombieProcess) + # There might be additional keys to be added for different # platforms / hardware combinations. # Taken from last version of "glances" integration before they moved to diff --git a/homeassistant/components/systemmonitor/coordinator.py b/homeassistant/components/systemmonitor/coordinator.py index 03b769ee2e23..36dfff898f7a 100644 --- a/homeassistant/components/systemmonitor/coordinator.py +++ b/homeassistant/components/systemmonitor/coordinator.py @@ -12,11 +12,14 @@ from psutil import Process from psutil._common import sdiskusage, shwtemp, snetio, snicaddr, sswap import psutil_home_assistant as ha_psutil +from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_component import DEFAULT_SCAN_INTERVAL from homeassistant.helpers.update_coordinator import TimestampDataUpdateCoordinator from homeassistant.util import dt as dt_util +from .const import CONF_PROCESS, PROCESS_ERRORS + if TYPE_CHECKING: from . import SystemMonitorConfigEntry @@ -83,6 +86,8 @@ class VirtualMemory(NamedTuple): class SystemMonitorCoordinator(TimestampDataUpdateCoordinator[SensorData]): """A System monitor Data Update Coordinator.""" + config_entry: SystemMonitorConfigEntry + def __init__( self, hass: HomeAssistant, @@ -203,11 +208,30 @@ class SystemMonitorCoordinator(TimestampDataUpdateCoordinator[SensorData]): self.boot_time = dt_util.utc_from_timestamp(self._psutil.boot_time()) _LOGGER.debug("boot time: %s", self.boot_time) - processes = None + selected_processes: list[Process] = [] if self.update_subscribers[("processes", "")] or self._initial_update: processes = self._psutil.process_iter() _LOGGER.debug("processes: %s", processes) - processes = list(processes) + user_options: list[str] = self.config_entry.options.get( + BINARY_SENSOR_DOMAIN, {} + ).get(CONF_PROCESS, []) + for process in processes: + try: + if process.name() in user_options: + selected_processes.append(process) + except PROCESS_ERRORS as err: + if not hasattr(err, "pid") or not hasattr(err, "name"): + _LOGGER.warning( + "Failed to load process: %s", + str(err), + ) + else: + _LOGGER.warning( + "Failed to load process with ID: %s, old name: %s", + err.pid, + err.name, + ) + continue temps: dict[str, list[shwtemp]] = {} if self.update_subscribers[("temperatures", "")] or self._initial_update: @@ -224,6 +248,6 @@ class SystemMonitorCoordinator(TimestampDataUpdateCoordinator[SensorData]): "io_counters": io_counters, "addresses": addresses, "boot_time": self.boot_time, - "processes": processes, + "processes": selected_processes, "temperatures": temps, }