Use entity description and set state class to all System Monitor sensors (#56140)

This commit is contained in:
Michael 2021-09-13 21:55:33 +02:00 committed by GitHub
parent 20d96ef4ef
commit d661a76462
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -14,7 +14,13 @@ from typing import Any, cast
import psutil
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
STATE_CLASS_TOTAL,
STATE_CLASS_TOTAL_INCREASING,
SensorEntity,
SensorEntityDescription,
)
from homeassistant.const import (
CONF_RESOURCES,
CONF_SCAN_INTERVAL,
@ -60,62 +66,180 @@ SENSOR_TYPE_MANDATORY_ARG = 4
SIGNAL_SYSTEMMONITOR_UPDATE = "systemmonitor_update"
# Schema: [name, unit of measurement, icon, device class, flag if mandatory arg]
SENSOR_TYPES: dict[str, tuple[str, str | None, str | None, str | None, bool]] = {
"disk_free": ("Disk free", DATA_GIBIBYTES, "mdi:harddisk", None, False),
"disk_use": ("Disk use", DATA_GIBIBYTES, "mdi:harddisk", None, False),
"disk_use_percent": (
"Disk use (percent)",
PERCENTAGE,
"mdi:harddisk",
None,
False,
@dataclass
class SysMonitorSensorEntityDescription(SensorEntityDescription):
"""Description for System Monitor sensor entities."""
mandatory_arg: bool = False
SENSOR_TYPES: dict[str, SysMonitorSensorEntityDescription] = {
"disk_free": SysMonitorSensorEntityDescription(
key="disk_free",
name="Disk free",
native_unit_of_measurement=DATA_GIBIBYTES,
icon="mdi:harddisk",
state_class=STATE_CLASS_TOTAL,
),
"ipv4_address": ("IPv4 address", "", "mdi:server-network", None, True),
"ipv6_address": ("IPv6 address", "", "mdi:server-network", None, True),
"last_boot": ("Last boot", None, None, DEVICE_CLASS_TIMESTAMP, False),
"load_15m": ("Load (15m)", " ", CPU_ICON, None, False),
"load_1m": ("Load (1m)", " ", CPU_ICON, None, False),
"load_5m": ("Load (5m)", " ", CPU_ICON, None, False),
"memory_free": ("Memory free", DATA_MEBIBYTES, "mdi:memory", None, False),
"memory_use": ("Memory use", DATA_MEBIBYTES, "mdi:memory", None, False),
"memory_use_percent": (
"Memory use (percent)",
PERCENTAGE,
"mdi:memory",
None,
False,
"disk_use": SysMonitorSensorEntityDescription(
key="disk_use",
name="Disk use",
native_unit_of_measurement=DATA_GIBIBYTES,
icon="mdi:harddisk",
state_class=STATE_CLASS_TOTAL,
),
"network_in": ("Network in", DATA_MEBIBYTES, "mdi:server-network", None, True),
"network_out": ("Network out", DATA_MEBIBYTES, "mdi:server-network", None, True),
"packets_in": ("Packets in", " ", "mdi:server-network", None, True),
"packets_out": ("Packets out", " ", "mdi:server-network", None, True),
"throughput_network_in": (
"Network throughput in",
DATA_RATE_MEGABYTES_PER_SECOND,
"mdi:server-network",
None,
True,
"disk_use_percent": SysMonitorSensorEntityDescription(
key="disk_use_percent",
name="Disk use (percent)",
native_unit_of_measurement=PERCENTAGE,
icon="mdi:harddisk",
state_class=STATE_CLASS_TOTAL,
),
"throughput_network_out": (
"Network throughput out",
DATA_RATE_MEGABYTES_PER_SECOND,
"mdi:server-network",
None,
True,
"ipv4_address": SysMonitorSensorEntityDescription(
key="ipv4_address",
name="IPv4 address",
icon="mdi:server-network",
mandatory_arg=True,
),
"process": ("Process", " ", CPU_ICON, None, True),
"processor_use": ("Processor use (percent)", PERCENTAGE, CPU_ICON, None, False),
"processor_temperature": (
"Processor temperature",
TEMP_CELSIUS,
None,
DEVICE_CLASS_TEMPERATURE,
False,
"ipv6_address": SysMonitorSensorEntityDescription(
key="ipv6_address",
name="IPv6 address",
icon="mdi:server-network",
mandatory_arg=True,
),
"last_boot": SysMonitorSensorEntityDescription(
key="last_boot",
name="Last boot",
device_class=DEVICE_CLASS_TIMESTAMP,
),
"load_15m": SysMonitorSensorEntityDescription(
key="load_15m",
name="Load (15m)",
icon=CPU_ICON,
state_class=STATE_CLASS_TOTAL,
),
"load_1m": SysMonitorSensorEntityDescription(
key="load_1m",
name="Load (1m)",
icon=CPU_ICON,
state_class=STATE_CLASS_TOTAL,
),
"load_5m": SysMonitorSensorEntityDescription(
key="load_5m",
name="Load (5m)",
icon=CPU_ICON,
state_class=STATE_CLASS_TOTAL,
),
"memory_free": SysMonitorSensorEntityDescription(
key="memory_free",
name="Memory free",
native_unit_of_measurement=DATA_MEBIBYTES,
icon="mdi:memory",
state_class=STATE_CLASS_TOTAL,
),
"memory_use": SysMonitorSensorEntityDescription(
key="memory_use",
name="Memory use",
native_unit_of_measurement=DATA_MEBIBYTES,
icon="mdi:memory",
state_class=STATE_CLASS_TOTAL,
),
"memory_use_percent": SysMonitorSensorEntityDescription(
key="memory_use_percent",
name="Memory use (percent)",
native_unit_of_measurement=PERCENTAGE,
icon="mdi:memory",
state_class=STATE_CLASS_TOTAL,
),
"network_in": SysMonitorSensorEntityDescription(
key="network_in",
name="Network in",
native_unit_of_measurement=DATA_MEBIBYTES,
icon="mdi:server-network",
state_class=STATE_CLASS_TOTAL_INCREASING,
mandatory_arg=True,
),
"network_out": SysMonitorSensorEntityDescription(
key="network_out",
name="Network out",
native_unit_of_measurement=DATA_MEBIBYTES,
icon="mdi:server-network",
state_class=STATE_CLASS_TOTAL_INCREASING,
mandatory_arg=True,
),
"packets_in": SysMonitorSensorEntityDescription(
key="packets_in",
name="Packets in",
icon="mdi:server-network",
state_class=STATE_CLASS_TOTAL_INCREASING,
mandatory_arg=True,
),
"packets_out": SysMonitorSensorEntityDescription(
key="packets_out",
name="Packets out",
icon="mdi:server-network",
state_class=STATE_CLASS_TOTAL_INCREASING,
mandatory_arg=True,
),
"throughput_network_in": SysMonitorSensorEntityDescription(
key="throughput_network_in",
name="Network throughput in",
native_unit_of_measurement=DATA_RATE_MEGABYTES_PER_SECOND,
icon="mdi:server-network",
state_class=STATE_CLASS_TOTAL,
mandatory_arg=True,
),
"throughput_network_out": SysMonitorSensorEntityDescription(
key="throughput_network_out",
name="Network throughput out",
native_unit_of_measurement=DATA_RATE_MEGABYTES_PER_SECOND,
icon="mdi:server-network",
state_class=STATE_CLASS_TOTAL,
mandatory_arg=True,
),
"process": SysMonitorSensorEntityDescription(
key="process",
name="Process",
icon=CPU_ICON,
state_class=STATE_CLASS_TOTAL,
mandatory_arg=True,
),
"processor_use": SysMonitorSensorEntityDescription(
key="processor_use",
name="Processor use",
native_unit_of_measurement=PERCENTAGE,
icon=CPU_ICON,
state_class=STATE_CLASS_TOTAL,
),
"processor_temperature": SysMonitorSensorEntityDescription(
key="processor_temperature",
name="Processor temperature",
native_unit_of_measurement=TEMP_CELSIUS,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_TOTAL,
),
"swap_free": SysMonitorSensorEntityDescription(
key="swap_free",
name="Swap free",
native_unit_of_measurement=DATA_MEBIBYTES,
icon="mdi:harddisk",
state_class=STATE_CLASS_TOTAL,
),
"swap_use": SysMonitorSensorEntityDescription(
key="swap_use",
name="Swap use",
native_unit_of_measurement=DATA_MEBIBYTES,
icon="mdi:harddisk",
state_class=STATE_CLASS_TOTAL,
),
"swap_use_percent": SysMonitorSensorEntityDescription(
key="swap_use_percent",
name="Swap use (percent)",
native_unit_of_measurement=PERCENTAGE,
icon="mdi:harddisk",
state_class=STATE_CLASS_TOTAL,
),
"swap_free": ("Swap free", DATA_MEBIBYTES, "mdi:harddisk", None, False),
"swap_use": ("Swap use", DATA_MEBIBYTES, "mdi:harddisk", None, False),
"swap_use_percent": ("Swap use (percent)", PERCENTAGE, "mdi:harddisk", None, False),
}
@ -125,7 +249,7 @@ def check_required_arg(value: Any) -> Any:
sensor_type = sensor[CONF_TYPE]
sensor_arg = sensor.get(CONF_ARG)
if sensor_arg is None and SENSOR_TYPES[sensor_type][SENSOR_TYPE_MANDATORY_ARG]:
if sensor_arg is None and SENSOR_TYPES[sensor_type].mandatory_arg:
raise vol.RequiredFieldInvalid(
f"Mandatory 'arg' is missing for sensor type '{sensor_type}'."
)
@ -230,7 +354,9 @@ async def async_setup_platform(
sensor_registry[(type_, argument)] = SensorData(
argument, None, None, None, None
)
entities.append(SystemMonitorSensor(sensor_registry, type_, argument))
entities.append(
SystemMonitorSensor(sensor_registry, SENSOR_TYPES[type_], argument)
)
scan_interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
await async_setup_sensor_registry_updates(hass, sensor_registry, scan_interval)
@ -297,68 +423,35 @@ async def async_setup_sensor_registry_updates(
class SystemMonitorSensor(SensorEntity):
"""Implementation of a system monitor sensor."""
should_poll = False
def __init__(
self,
sensor_registry: dict[tuple[str, str], SensorData],
sensor_type: str,
sensor_description: SysMonitorSensorEntityDescription,
argument: str = "",
) -> None:
"""Initialize the sensor."""
self._type: str = sensor_type
self._name: str = f"{self.sensor_type[SENSOR_TYPE_NAME]} {argument}".rstrip()
self._unique_id: str = slugify(f"{sensor_type}_{argument}")
self.entity_description = sensor_description
self._attr_name: str = f"{sensor_description.name} {argument}".rstrip()
self._attr_unique_id: str = slugify(f"{sensor_description.key}_{argument}")
self._sensor_registry = sensor_registry
self._argument: str = argument
@property
def name(self) -> str:
"""Return the name of the sensor."""
return self._name
@property
def unique_id(self) -> str:
"""Return the unique ID."""
return self._unique_id
@property
def device_class(self) -> str | None:
"""Return the class of this sensor."""
return self.sensor_type[SENSOR_TYPE_DEVICE_CLASS] # type: ignore[no-any-return]
@property
def icon(self) -> str | None:
"""Icon to use in the frontend, if any."""
return self.sensor_type[SENSOR_TYPE_ICON] # type: ignore[no-any-return]
@property
def native_value(self) -> str | None:
"""Return the state of the device."""
return self.data.state
@property
def native_unit_of_measurement(self) -> str | None:
"""Return the unit of measurement of this entity, if any."""
return self.sensor_type[SENSOR_TYPE_UOM] # type: ignore[no-any-return]
@property
def available(self) -> bool:
"""Return True if entity is available."""
return self.data.last_exception is None
@property
def should_poll(self) -> bool:
"""Entity does not poll."""
return False
@property
def sensor_type(self) -> list:
"""Return sensor type data for the sensor."""
return SENSOR_TYPES[self._type] # type: ignore
@property
def data(self) -> SensorData:
"""Return registry entry for the data."""
return self._sensor_registry[(self._type, self._argument)]
return self._sensor_registry[(self.entity_description.key, self._argument)]
async def async_added_to_hass(self) -> None:
"""When entity is added to hass."""