From 7ce1ba930480cbae0d3eef7d52281104316e1e86 Mon Sep 17 00:00:00 2001 From: G Johansson Date: Sun, 11 Feb 2024 15:11:31 -0500 Subject: [PATCH] Fix cpu percentage in System Monitor (#110268) * Fix cpu percentage in System Monitor * Tests --- .../components/systemmonitor/coordinator.py | 13 ++++--- .../components/systemmonitor/sensor.py | 4 ++- tests/components/systemmonitor/test_sensor.py | 35 +++++++++++++++++++ 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/systemmonitor/coordinator.py b/homeassistant/components/systemmonitor/coordinator.py index 9143d31f163..bf625eacf9a 100644 --- a/homeassistant/components/systemmonitor/coordinator.py +++ b/homeassistant/components/systemmonitor/coordinator.py @@ -1,4 +1,5 @@ """DataUpdateCoordinators for the System monitor integration.""" + from __future__ import annotations from abc import abstractmethod @@ -43,7 +44,8 @@ dataT = TypeVar( | sswap | VirtualMemory | tuple[float, float, float] - | sdiskusage, + | sdiskusage + | None, ) @@ -130,12 +132,15 @@ class SystemMonitorLoadCoordinator(MonitorCoordinator[tuple[float, float, float] return os.getloadavg() -class SystemMonitorProcessorCoordinator(MonitorCoordinator[float]): +class SystemMonitorProcessorCoordinator(MonitorCoordinator[float | None]): """A System monitor Processor Data Update Coordinator.""" - def update_data(self) -> float: + def update_data(self) -> float | None: """Fetch data.""" - return psutil.cpu_percent(interval=None) + cpu_percent = psutil.cpu_percent(interval=None) + if cpu_percent > 0.0: + return cpu_percent + return None class SystemMonitorBootTimeCoordinator(MonitorCoordinator[datetime]): diff --git a/homeassistant/components/systemmonitor/sensor.py b/homeassistant/components/systemmonitor/sensor.py index 0f8532804c7..91cbdffdee3 100644 --- a/homeassistant/components/systemmonitor/sensor.py +++ b/homeassistant/components/systemmonitor/sensor.py @@ -346,7 +346,9 @@ SENSOR_TYPES: dict[str, SysMonitorSensorEntityDescription[Any]] = { native_unit_of_measurement=PERCENTAGE, icon=get_cpu_icon(), state_class=SensorStateClass.MEASUREMENT, - value_fn=lambda entity: round(entity.coordinator.data), + value_fn=lambda entity: ( + round(entity.coordinator.data) if entity.coordinator.data else None + ), ), "processor_temperature": SysMonitorSensorEntityDescription[ dict[str, list[shwtemp]] diff --git a/tests/components/systemmonitor/test_sensor.py b/tests/components/systemmonitor/test_sensor.py index e64f6dbefa1..1936d727184 100644 --- a/tests/components/systemmonitor/test_sensor.py +++ b/tests/components/systemmonitor/test_sensor.py @@ -1,4 +1,5 @@ """Test System Monitor sensor.""" + from datetime import timedelta import socket from unittest.mock import Mock, patch @@ -529,3 +530,37 @@ async def test_exception_handling_disk_sensor( assert disk_sensor is not None assert disk_sensor.state == "70.0" assert disk_sensor.attributes["unit_of_measurement"] == "%" + + +async def test_cpu_percentage_is_zero_returns_unknown( + hass: HomeAssistant, + entity_registry_enabled_by_default: None, + mock_psutil: Mock, + mock_added_config_entry: ConfigEntry, + caplog: pytest.LogCaptureFixture, + freezer: FrozenDateTimeFactory, +) -> None: + """Test the sensor.""" + cpu_sensor = hass.states.get("sensor.system_monitor_processor_use") + assert cpu_sensor is not None + assert cpu_sensor.state == "10" + + mock_psutil.cpu_percent.return_value = 0.0 + + freezer.tick(timedelta(minutes=1)) + async_fire_time_changed(hass) + await hass.async_block_till_done() + + cpu_sensor = hass.states.get("sensor.system_monitor_processor_use") + assert cpu_sensor is not None + assert cpu_sensor.state == STATE_UNKNOWN + + mock_psutil.cpu_percent.return_value = 15.0 + + freezer.tick(timedelta(minutes=1)) + async_fire_time_changed(hass) + await hass.async_block_till_done() + + cpu_sensor = hass.states.get("sensor.system_monitor_processor_use") + assert cpu_sensor is not None + assert cpu_sensor.state == "15"