diff --git a/homeassistant/components/system_bridge/__init__.py b/homeassistant/components/system_bridge/__init__.py index f016cca798d..cba21ac0271 100644 --- a/homeassistant/components/system_bridge/__init__.py +++ b/homeassistant/components/system_bridge/__init__.py @@ -85,6 +85,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: coordinator.bridge.battery is None or coordinator.bridge.cpu is None or coordinator.bridge.filesystem is None + or coordinator.bridge.graphics is None or coordinator.bridge.information is None or coordinator.bridge.memory is None or coordinator.bridge.network is None @@ -230,17 +231,13 @@ class SystemBridgeEntity(CoordinatorEntity): self, coordinator: SystemBridgeDataUpdateCoordinator, key: str, - name: str, - icon: str | None, - enabled_by_default: bool, + name: str | None, ) -> None: """Initialize the System Bridge entity.""" super().__init__(coordinator) bridge: Bridge = coordinator.data self._key = f"{bridge.information.host}_{key}" self._name = f"{bridge.information.host} {name}" - self._icon = icon - self._enabled_default = enabled_by_default self._hostname = bridge.information.host self._mac = bridge.information.mac self._manufacturer = bridge.system.system.manufacturer @@ -257,16 +254,6 @@ class SystemBridgeEntity(CoordinatorEntity): """Return the name of the entity.""" return self._name - @property - def icon(self) -> str | None: - """Return the mdi icon of the entity.""" - return self._icon - - @property - def entity_registry_enabled_default(self) -> bool: - """Return if the entity should be enabled when first added to the entity registry.""" - return self._enabled_default - class SystemBridgeDeviceEntity(SystemBridgeEntity): """Defines a System Bridge device entity.""" diff --git a/homeassistant/components/system_bridge/binary_sensor.py b/homeassistant/components/system_bridge/binary_sensor.py index f6b765f8079..4280293a434 100644 --- a/homeassistant/components/system_bridge/binary_sensor.py +++ b/homeassistant/components/system_bridge/binary_sensor.py @@ -1,11 +1,15 @@ """Support for System Bridge binary sensors.""" from __future__ import annotations +from dataclasses import dataclass +from typing import Callable + from systembridge import Bridge from homeassistant.components.binary_sensor import ( DEVICE_CLASS_BATTERY_CHARGING, BinarySensorEntity, + BinarySensorEntityDescription, ) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant @@ -15,6 +19,32 @@ from .const import DOMAIN from .coordinator import SystemBridgeDataUpdateCoordinator +@dataclass +class SystemBridgeBinarySensorEntityDescription(BinarySensorEntityDescription): + """Class describing System Bridge binary sensor entities.""" + + value: Callable = round + + +BASE_BINARY_SENSOR_TYPES: tuple[SystemBridgeBinarySensorEntityDescription, ...] = ( + SystemBridgeBinarySensorEntityDescription( + key="version_available", + name="New Version Available", + icon="mdi:counter", + value=lambda bridge: bridge.information.updates.available, + ), +) + +BATTERY_BINARY_SENSOR_TYPES: tuple[SystemBridgeBinarySensorEntityDescription, ...] = ( + SystemBridgeBinarySensorEntityDescription( + key="battery_is_charging", + name="Battery Is Charging", + device_class=DEVICE_CLASS_BATTERY_CHARGING, + value=lambda bridge: bridge.information.updates.available, + ), +) + + async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities ) -> None: @@ -22,49 +52,38 @@ async def async_setup_entry( coordinator: SystemBridgeDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id] bridge: Bridge = coordinator.data + entities = [] + for description in BASE_BINARY_SENSOR_TYPES: + entities.append(SystemBridgeBinarySensor(coordinator, description)) + if bridge.battery and bridge.battery.hasBattery: - async_add_entities([SystemBridgeBatteryIsChargingBinarySensor(coordinator)]) + for description in BATTERY_BINARY_SENSOR_TYPES: + entities.append(SystemBridgeBinarySensor(coordinator, description)) + + async_add_entities(entities) class SystemBridgeBinarySensor(SystemBridgeDeviceEntity, BinarySensorEntity): - """Defines a System Bridge binary sensor.""" + """Define a System Bridge binary sensor.""" + + coordinator: SystemBridgeDataUpdateCoordinator + entity_description: SystemBridgeBinarySensorEntityDescription def __init__( self, coordinator: SystemBridgeDataUpdateCoordinator, - key: str, - name: str, - icon: str | None, - device_class: str | None, - enabled_by_default: bool, + description: SystemBridgeBinarySensorEntityDescription, ) -> None: - """Initialize System Bridge binary sensor.""" - self._device_class = device_class - - super().__init__(coordinator, key, name, icon, enabled_by_default) - - @property - def device_class(self) -> str | None: - """Return the class of this binary sensor.""" - return self._device_class - - -class SystemBridgeBatteryIsChargingBinarySensor(SystemBridgeBinarySensor): - """Defines a Battery is charging binary sensor.""" - - def __init__(self, coordinator: SystemBridgeDataUpdateCoordinator) -> None: - """Initialize System Bridge binary sensor.""" + """Initialize.""" super().__init__( coordinator, - "battery_is_charging", - "Battery Is Charging", - None, - DEVICE_CLASS_BATTERY_CHARGING, - True, + description.key, + description.name, ) + self.entity_description = description @property def is_on(self) -> bool: - """Return if the state is on.""" + """Return the boolean state of the binary sensor.""" bridge: Bridge = self.coordinator.data - return bridge.battery.isCharging + return self.entity_description.value(bridge) diff --git a/homeassistant/components/system_bridge/coordinator.py b/homeassistant/components/system_bridge/coordinator.py index d34e1019a0b..177a09e5d25 100644 --- a/homeassistant/components/system_bridge/coordinator.py +++ b/homeassistant/components/system_bridge/coordinator.py @@ -66,6 +66,7 @@ class SystemBridgeDataUpdateCoordinator(DataUpdateCoordinator[Bridge]): "battery", "cpu", "filesystem", + "graphics", "memory", "network", "os", diff --git a/homeassistant/components/system_bridge/manifest.json b/homeassistant/components/system_bridge/manifest.json index 2f1ec0111cf..73d1d03618f 100644 --- a/homeassistant/components/system_bridge/manifest.json +++ b/homeassistant/components/system_bridge/manifest.json @@ -3,7 +3,7 @@ "name": "System Bridge", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/system_bridge", - "requirements": ["systembridge==2.0.6"], + "requirements": ["systembridge==2.1.0"], "codeowners": ["@timmo001"], "zeroconf": ["_system-bridge._udp.local."], "after_dependencies": ["zeroconf"], diff --git a/homeassistant/components/system_bridge/sensor.py b/homeassistant/components/system_bridge/sensor.py index acfcc54f05c..18227e60800 100644 --- a/homeassistant/components/system_bridge/sensor.py +++ b/homeassistant/components/system_bridge/sensor.py @@ -1,40 +1,195 @@ """Support for System Bridge sensors.""" from __future__ import annotations +from dataclasses import dataclass from datetime import datetime, timedelta -from typing import Any +from typing import Callable, Final, cast from systembridge import Bridge -from homeassistant.components.sensor import SensorEntity +from homeassistant.components.sensor import ( + STATE_CLASS_MEASUREMENT, + SensorEntity, + SensorEntityDescription, +) from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( DATA_GIGABYTES, DEVICE_CLASS_BATTERY, + DEVICE_CLASS_POWER, DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_TIMESTAMP, DEVICE_CLASS_VOLTAGE, ELECTRIC_POTENTIAL_VOLT, FREQUENCY_GIGAHERTZ, + FREQUENCY_MEGAHERTZ, PERCENTAGE, + POWER_WATT, TEMP_CELSIUS, ) from homeassistant.core import HomeAssistant +from homeassistant.helpers.typing import StateType from . import SystemBridgeDeviceEntity from .const import DOMAIN from .coordinator import SystemBridgeDataUpdateCoordinator -ATTR_AVAILABLE = "available" -ATTR_FILESYSTEM = "filesystem" -ATTR_LOAD_AVERAGE = "load_average" -ATTR_LOAD_IDLE = "load_idle" -ATTR_LOAD_SYSTEM = "load_system" -ATTR_LOAD_USER = "load_user" -ATTR_MOUNT = "mount" -ATTR_SIZE = "size" -ATTR_TYPE = "type" -ATTR_USED = "used" +ATTR_AVAILABLE: Final = "available" +ATTR_FILESYSTEM: Final = "filesystem" +ATTR_MOUNT: Final = "mount" +ATTR_SIZE: Final = "size" +ATTR_TYPE: Final = "type" +ATTR_USED: Final = "used" + + +@dataclass +class SystemBridgeSensorEntityDescription(SensorEntityDescription): + """Class describing System Bridge sensor entities.""" + + value: Callable = round + + +BASE_SENSOR_TYPES: tuple[SystemBridgeSensorEntityDescription, ...] = ( + SystemBridgeSensorEntityDescription( + key="bios_version", + name="BIOS Version", + entity_registry_enabled_default=False, + icon="mdi:chip", + value=lambda bridge: bridge.system.bios.version, + ), + SystemBridgeSensorEntityDescription( + key="cpu_speed", + name="CPU Speed", + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=FREQUENCY_GIGAHERTZ, + icon="mdi:speedometer", + value=lambda bridge: bridge.cpu.currentSpeed.avg, + ), + SystemBridgeSensorEntityDescription( + key="cpu_temperature", + name="CPU Temperature", + entity_registry_enabled_default=False, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=TEMP_CELSIUS, + value=lambda bridge: bridge.cpu.temperature.main, + ), + SystemBridgeSensorEntityDescription( + key="cpu_voltage", + name="CPU Voltage", + entity_registry_enabled_default=False, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT, + value=lambda bridge: bridge.cpu.cpu.voltage, + ), + SystemBridgeSensorEntityDescription( + key="kernel", + name="Kernel", + state_class=STATE_CLASS_MEASUREMENT, + icon="mdi:devices", + value=lambda bridge: bridge.os.kernel, + ), + SystemBridgeSensorEntityDescription( + key="memory_free", + name="Memory Free", + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=DATA_GIGABYTES, + icon="mdi:memory", + value=lambda bridge: round(bridge.memory.free / 1000 ** 3, 2), + ), + SystemBridgeSensorEntityDescription( + key="memory_used_percentage", + name="Memory Used %", + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=PERCENTAGE, + icon="mdi:memory", + value=lambda bridge: round((bridge.memory.used / bridge.memory.total) * 100, 2), + ), + SystemBridgeSensorEntityDescription( + key="memory_used", + name="Memory Used", + entity_registry_enabled_default=False, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=DATA_GIGABYTES, + icon="mdi:memory", + value=lambda bridge: round(bridge.memory.used / 1000 ** 3, 2), + ), + SystemBridgeSensorEntityDescription( + key="os", + name="Operating System", + state_class=STATE_CLASS_MEASUREMENT, + icon="mdi:devices", + value=lambda bridge: f"{bridge.os.distro} {bridge.os.release}", + ), + SystemBridgeSensorEntityDescription( + key="processes_load", + name="Load", + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=PERCENTAGE, + icon="mdi:percent", + value=lambda bridge: round(bridge.processes.load.currentLoad, 2), + ), + SystemBridgeSensorEntityDescription( + key="processes_load_idle", + name="Idle Load", + entity_registry_enabled_default=False, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=PERCENTAGE, + icon="mdi:percent", + value=lambda bridge: round(bridge.processes.load.currentLoadIdle, 2), + ), + SystemBridgeSensorEntityDescription( + key="processes_load_system", + name="System Load", + entity_registry_enabled_default=False, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=PERCENTAGE, + icon="mdi:percent", + value=lambda bridge: round(bridge.processes.load.currentLoadSystem, 2), + ), + SystemBridgeSensorEntityDescription( + key="processes_load_user", + name="User Load", + entity_registry_enabled_default=False, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=PERCENTAGE, + icon="mdi:percent", + value=lambda bridge: round(bridge.processes.load.currentLoadUser, 2), + ), + SystemBridgeSensorEntityDescription( + key="version", + name="Version", + icon="mdi:counter", + value=lambda bridge: bridge.information.version, + ), + SystemBridgeSensorEntityDescription( + key="version_latest", + name="Latest Version", + icon="mdi:counter", + value=lambda bridge: bridge.information.updates.version.new, + ), +) + +BATTERY_SENSOR_TYPES: tuple[SystemBridgeSensorEntityDescription, ...] = ( + SystemBridgeSensorEntityDescription( + key="battery", + name="Battery", + device_class=DEVICE_CLASS_BATTERY, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=PERCENTAGE, + value=lambda bridge: bridge.battery.percent, + ), + SystemBridgeSensorEntityDescription( + key="battery_time_remaining", + name="Battery Time Remaining", + device_class=DEVICE_CLASS_TIMESTAMP, + state_class=STATE_CLASS_MEASUREMENT, + value=lambda bridge: str( + datetime.now() + timedelta(minutes=bridge.battery.timeRemaining) + ), + ), +) async def async_setup_entry( @@ -43,395 +198,260 @@ async def async_setup_entry( """Set up System Bridge sensor based on a config entry.""" coordinator: SystemBridgeDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id] - entities = [ - SystemBridgeCpuSpeedSensor(coordinator), - SystemBridgeCpuTemperatureSensor(coordinator), - SystemBridgeCpuVoltageSensor(coordinator), - *( - SystemBridgeFilesystemSensor(coordinator, key) - for key, _ in coordinator.data.filesystem.fsSize.items() - ), - SystemBridgeMemoryFreeSensor(coordinator), - SystemBridgeMemoryUsedSensor(coordinator), - SystemBridgeMemoryUsedPercentageSensor(coordinator), - SystemBridgeKernelSensor(coordinator), - SystemBridgeOsSensor(coordinator), - SystemBridgeProcessesLoadSensor(coordinator), - SystemBridgeBiosVersionSensor(coordinator), - ] + entities = [] + for description in BASE_SENSOR_TYPES: + entities.append(SystemBridgeSensor(coordinator, description)) + + for key, _ in coordinator.data.filesystem.fsSize.items(): + uid = key.replace(":", "") + entities.append( + SystemBridgeSensor( + coordinator, + SystemBridgeSensorEntityDescription( + key=f"filesystem_{uid}", + name=f"{key} Space Used", + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=PERCENTAGE, + icon="mdi:harddisk", + value=lambda bridge, i=key: round( + bridge.filesystem.fsSize[i]["use"], 2 + ), + ), + ) + ) if coordinator.data.battery.hasBattery: - entities.append(SystemBridgeBatterySensor(coordinator)) - entities.append(SystemBridgeBatteryTimeRemainingSensor(coordinator)) + for description in BATTERY_SENSOR_TYPES: + entities.append(SystemBridgeSensor(coordinator, description)) + + for index, _ in enumerate(coordinator.data.graphics.controllers): + if coordinator.data.graphics.controllers[index].name is not None: + # Remove vendor from name + name = ( + coordinator.data.graphics.controllers[index] + .name.replace(coordinator.data.graphics.controllers[index].vendor, "") + .strip() + ) + entities = [ + *entities, + SystemBridgeSensor( + coordinator, + SystemBridgeSensorEntityDescription( + key=f"gpu_{index}_core_clock_speed", + name=f"{name} Clock Speed", + entity_registry_enabled_default=False, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=FREQUENCY_MEGAHERTZ, + icon="mdi:speedometer", + value=lambda bridge, i=index: bridge.graphics.controllers[ + i + ].clockCore, + ), + ), + SystemBridgeSensor( + coordinator, + SystemBridgeSensorEntityDescription( + key=f"gpu_{index}_memory_clock_speed", + name=f"{name} Memory Clock Speed", + entity_registry_enabled_default=False, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=FREQUENCY_MEGAHERTZ, + icon="mdi:speedometer", + value=lambda bridge, i=index: bridge.graphics.controllers[ + i + ].clockMemory, + ), + ), + SystemBridgeSensor( + coordinator, + SystemBridgeSensorEntityDescription( + key=f"gpu_{index}_memory_free", + name=f"{name} Memory Free", + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=DATA_GIGABYTES, + icon="mdi:memory", + value=lambda bridge, i=index: round( + bridge.graphics.controllers[i].memoryFree / 10 ** 3, 2 + ), + ), + ), + SystemBridgeSensor( + coordinator, + SystemBridgeSensorEntityDescription( + key=f"gpu_{index}_memory_used_percentage", + name=f"{name} Memory Used %", + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=PERCENTAGE, + icon="mdi:memory", + value=lambda bridge, i=index: round( + ( + bridge.graphics.controllers[i].memoryUsed + / bridge.graphics.controllers[i].memoryTotal + ) + * 100, + 2, + ), + ), + ), + SystemBridgeSensor( + coordinator, + SystemBridgeSensorEntityDescription( + key=f"gpu_{index}_memory_used", + name=f"{name} Memory Used", + entity_registry_enabled_default=False, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=DATA_GIGABYTES, + icon="mdi:memory", + value=lambda bridge, i=index: round( + bridge.graphics.controllers[i].memoryUsed / 10 ** 3, 2 + ), + ), + ), + SystemBridgeSensor( + coordinator, + SystemBridgeSensorEntityDescription( + key=f"gpu_{index}_fan_speed", + name=f"{name} Fan Speed", + entity_registry_enabled_default=False, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=PERCENTAGE, + icon="mdi:fan", + value=lambda bridge, i=index: bridge.graphics.controllers[ + i + ].fanSpeed, + ), + ), + SystemBridgeSensor( + coordinator, + SystemBridgeSensorEntityDescription( + key=f"gpu_{index}_power_usage", + name=f"{name} Power Usage", + entity_registry_enabled_default=False, + device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=POWER_WATT, + value=lambda bridge, i=index: bridge.graphics.controllers[ + i + ].powerDraw, + ), + ), + SystemBridgeSensor( + coordinator, + SystemBridgeSensorEntityDescription( + key=f"gpu_{index}_temperature", + name=f"{name} Temperature", + entity_registry_enabled_default=False, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=TEMP_CELSIUS, + value=lambda bridge, i=index: bridge.graphics.controllers[ + i + ].temperatureGpu, + ), + ), + SystemBridgeSensor( + coordinator, + SystemBridgeSensorEntityDescription( + key=f"gpu_{index}_usage_percentage", + name=f"{name} Usage %", + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=PERCENTAGE, + icon="mdi:percent", + value=lambda bridge, i=index: bridge.graphics.controllers[ + i + ].utilizationGpu, + ), + ), + ] + + for index, _ in enumerate(coordinator.data.processes.load.cpus): + entities = [ + *entities, + SystemBridgeSensor( + coordinator, + SystemBridgeSensorEntityDescription( + key=f"processes_load_cpu_{index}", + name=f"Load CPU {index}", + entity_registry_enabled_default=False, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=PERCENTAGE, + icon="mdi:percent", + value=lambda bridge: round( + bridge.processes.load.cpus[index].load, 2 + ), + ), + ), + SystemBridgeSensor( + coordinator, + SystemBridgeSensorEntityDescription( + key=f"processes_load_cpu_{index}_idle", + name=f"Idle Load CPU {index}", + entity_registry_enabled_default=False, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=PERCENTAGE, + icon="mdi:percent", + value=lambda bridge: round( + bridge.processes.load.cpus[index].loadIdle, 2 + ), + ), + ), + SystemBridgeSensor( + coordinator, + SystemBridgeSensorEntityDescription( + key=f"processes_load_cpu_{index}_system", + name=f"System Load CPU {index}", + entity_registry_enabled_default=False, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=PERCENTAGE, + icon="mdi:percent", + value=lambda bridge: round( + bridge.processes.load.cpus[index].loadSystem, 2 + ), + ), + ), + SystemBridgeSensor( + coordinator, + SystemBridgeSensorEntityDescription( + key=f"processes_load_cpu_{index}_user", + name=f"User Load CPU {index}", + entity_registry_enabled_default=False, + state_class=STATE_CLASS_MEASUREMENT, + native_unit_of_measurement=PERCENTAGE, + icon="mdi:percent", + value=lambda bridge: round( + bridge.processes.load.cpus[index].loadUser, 2 + ), + ), + ), + ] async_add_entities(entities) class SystemBridgeSensor(SystemBridgeDeviceEntity, SensorEntity): - """Defines a System Bridge sensor.""" + """Define a System Bridge sensor.""" + + coordinator: SystemBridgeDataUpdateCoordinator + entity_description: SystemBridgeSensorEntityDescription def __init__( self, coordinator: SystemBridgeDataUpdateCoordinator, - key: str, - name: str, - icon: str | None, - device_class: str | None, - unit_of_measurement: str | None, - enabled_by_default: bool, + description: SystemBridgeSensorEntityDescription, ) -> None: - """Initialize System Bridge sensor.""" - self._device_class = device_class - self._unit_of_measurement = unit_of_measurement - - super().__init__(coordinator, key, name, icon, enabled_by_default) - - @property - def device_class(self) -> str | None: - """Return the class of this sensor.""" - return self._device_class - - @property - def native_unit_of_measurement(self) -> str | None: - """Return the unit this state is expressed in.""" - return self._unit_of_measurement - - -class SystemBridgeBatterySensor(SystemBridgeSensor): - """Defines a Battery sensor.""" - - def __init__(self, coordinator: SystemBridgeDataUpdateCoordinator) -> None: - """Initialize System Bridge sensor.""" + """Initialize.""" super().__init__( coordinator, - "battery", - "Battery", - None, - DEVICE_CLASS_BATTERY, - PERCENTAGE, - True, + description.key, + description.name, ) + self.entity_description = description @property - def native_value(self) -> float: - """Return the state of the sensor.""" + def native_value(self) -> StateType: + """Return the state.""" bridge: Bridge = self.coordinator.data - return bridge.battery.percent - - -class SystemBridgeBatteryTimeRemainingSensor(SystemBridgeSensor): - """Defines the Battery Time Remaining sensor.""" - - def __init__(self, coordinator: SystemBridgeDataUpdateCoordinator) -> None: - """Initialize System Bridge sensor.""" - super().__init__( - coordinator, - "battery_time_remaining", - "Battery Time Remaining", - None, - DEVICE_CLASS_TIMESTAMP, - None, - True, - ) - - @property - def native_value(self) -> str | None: - """Return the state of the sensor.""" - bridge: Bridge = self.coordinator.data - if bridge.battery.timeRemaining is None: + try: + return cast(StateType, self.entity_description.value(bridge)) + except TypeError: return None - return str(datetime.now() + timedelta(minutes=bridge.battery.timeRemaining)) - - -class SystemBridgeCpuSpeedSensor(SystemBridgeSensor): - """Defines a CPU speed sensor.""" - - def __init__(self, coordinator: SystemBridgeDataUpdateCoordinator) -> None: - """Initialize System Bridge sensor.""" - super().__init__( - coordinator, - "cpu_speed", - "CPU Speed", - "mdi:speedometer", - None, - FREQUENCY_GIGAHERTZ, - True, - ) - - @property - def native_value(self) -> float: - """Return the state of the sensor.""" - bridge: Bridge = self.coordinator.data - return bridge.cpu.currentSpeed.avg - - -class SystemBridgeCpuTemperatureSensor(SystemBridgeSensor): - """Defines a CPU temperature sensor.""" - - def __init__(self, coordinator: SystemBridgeDataUpdateCoordinator) -> None: - """Initialize System Bridge sensor.""" - super().__init__( - coordinator, - "cpu_temperature", - "CPU Temperature", - None, - DEVICE_CLASS_TEMPERATURE, - TEMP_CELSIUS, - False, - ) - - @property - def native_value(self) -> float: - """Return the state of the sensor.""" - bridge: Bridge = self.coordinator.data - return bridge.cpu.temperature.main - - -class SystemBridgeCpuVoltageSensor(SystemBridgeSensor): - """Defines a CPU voltage sensor.""" - - def __init__(self, coordinator: SystemBridgeDataUpdateCoordinator) -> None: - """Initialize System Bridge sensor.""" - super().__init__( - coordinator, - "cpu_voltage", - "CPU Voltage", - None, - DEVICE_CLASS_VOLTAGE, - ELECTRIC_POTENTIAL_VOLT, - False, - ) - - @property - def native_value(self) -> float: - """Return the state of the sensor.""" - bridge: Bridge = self.coordinator.data - return bridge.cpu.cpu.voltage - - -class SystemBridgeFilesystemSensor(SystemBridgeSensor): - """Defines a filesystem sensor.""" - - def __init__( - self, coordinator: SystemBridgeDataUpdateCoordinator, key: str - ) -> None: - """Initialize System Bridge sensor.""" - uid_key = key.replace(":", "") - super().__init__( - coordinator, - f"filesystem_{uid_key}", - f"{key} Space Used", - "mdi:harddisk", - None, - PERCENTAGE, - True, - ) - self._fs_key = key - - @property - def native_value(self) -> float: - """Return the state of the sensor.""" - bridge: Bridge = self.coordinator.data - return ( - round(bridge.filesystem.fsSize[self._fs_key]["use"], 2) - if bridge.filesystem.fsSize[self._fs_key]["use"] is not None - else None - ) - - @property - def extra_state_attributes(self) -> dict[str, Any]: - """Return the state attributes of the entity.""" - bridge: Bridge = self.coordinator.data - return { - ATTR_AVAILABLE: bridge.filesystem.fsSize[self._fs_key]["available"], - ATTR_FILESYSTEM: bridge.filesystem.fsSize[self._fs_key]["fs"], - ATTR_MOUNT: bridge.filesystem.fsSize[self._fs_key]["mount"], - ATTR_SIZE: bridge.filesystem.fsSize[self._fs_key]["size"], - ATTR_TYPE: bridge.filesystem.fsSize[self._fs_key]["type"], - ATTR_USED: bridge.filesystem.fsSize[self._fs_key]["used"], - } - - -class SystemBridgeMemoryFreeSensor(SystemBridgeSensor): - """Defines a memory free sensor.""" - - def __init__(self, coordinator: SystemBridgeDataUpdateCoordinator) -> None: - """Initialize System Bridge sensor.""" - super().__init__( - coordinator, - "memory_free", - "Memory Free", - "mdi:memory", - None, - DATA_GIGABYTES, - True, - ) - - @property - def native_value(self) -> float | None: - """Return the state of the sensor.""" - bridge: Bridge = self.coordinator.data - return ( - round(bridge.memory.free / 1000 ** 3, 2) - if bridge.memory.free is not None - else None - ) - - -class SystemBridgeMemoryUsedSensor(SystemBridgeSensor): - """Defines a memory used sensor.""" - - def __init__(self, coordinator: SystemBridgeDataUpdateCoordinator) -> None: - """Initialize System Bridge sensor.""" - super().__init__( - coordinator, - "memory_used", - "Memory Used", - "mdi:memory", - None, - DATA_GIGABYTES, - False, - ) - - @property - def native_value(self) -> str | None: - """Return the state of the sensor.""" - bridge: Bridge = self.coordinator.data - return ( - round(bridge.memory.used / 1000 ** 3, 2) - if bridge.memory.used is not None - else None - ) - - -class SystemBridgeMemoryUsedPercentageSensor(SystemBridgeSensor): - """Defines a memory used percentage sensor.""" - - def __init__(self, coordinator: SystemBridgeDataUpdateCoordinator) -> None: - """Initialize System Bridge sensor.""" - super().__init__( - coordinator, - "memory_used_percentage", - "Memory Used %", - "mdi:memory", - None, - PERCENTAGE, - True, - ) - - @property - def native_value(self) -> str | None: - """Return the state of the sensor.""" - bridge: Bridge = self.coordinator.data - return ( - round((bridge.memory.used / bridge.memory.total) * 100, 2) - if bridge.memory.used is not None and bridge.memory.total is not None - else None - ) - - -class SystemBridgeKernelSensor(SystemBridgeSensor): - """Defines a kernel sensor.""" - - def __init__(self, coordinator: SystemBridgeDataUpdateCoordinator) -> None: - """Initialize System Bridge sensor.""" - super().__init__( - coordinator, - "kernel", - "Kernel", - "mdi:devices", - None, - None, - True, - ) - - @property - def native_value(self) -> str: - """Return the state of the sensor.""" - bridge: Bridge = self.coordinator.data - return bridge.os.kernel - - -class SystemBridgeOsSensor(SystemBridgeSensor): - """Defines an OS sensor.""" - - def __init__(self, coordinator: SystemBridgeDataUpdateCoordinator) -> None: - """Initialize System Bridge sensor.""" - super().__init__( - coordinator, - "os", - "Operating System", - "mdi:devices", - None, - None, - True, - ) - - @property - def native_value(self) -> str: - """Return the state of the sensor.""" - bridge: Bridge = self.coordinator.data - return f"{bridge.os.distro} {bridge.os.release}" - - -class SystemBridgeProcessesLoadSensor(SystemBridgeSensor): - """Defines a Processes Load sensor.""" - - def __init__(self, coordinator: SystemBridgeDataUpdateCoordinator) -> None: - """Initialize System Bridge sensor.""" - super().__init__( - coordinator, - "processes_load", - "Load", - "mdi:percent", - None, - PERCENTAGE, - True, - ) - - @property - def native_value(self) -> float | None: - """Return the state of the sensor.""" - bridge: Bridge = self.coordinator.data - return ( - round(bridge.processes.load.currentLoad, 2) - if bridge.processes.load.currentLoad is not None - else None - ) - - @property - def extra_state_attributes(self) -> dict[str, Any]: - """Return the state attributes of the entity.""" - bridge: Bridge = self.coordinator.data - attrs = {} - if bridge.processes.load.avgLoad is not None: - attrs[ATTR_LOAD_AVERAGE] = round(bridge.processes.load.avgLoad, 2) - if bridge.processes.load.currentLoadUser is not None: - attrs[ATTR_LOAD_USER] = round(bridge.processes.load.currentLoadUser, 2) - if bridge.processes.load.currentLoadSystem is not None: - attrs[ATTR_LOAD_SYSTEM] = round(bridge.processes.load.currentLoadSystem, 2) - if bridge.processes.load.currentLoadIdle is not None: - attrs[ATTR_LOAD_IDLE] = round(bridge.processes.load.currentLoadIdle, 2) - return attrs - - -class SystemBridgeBiosVersionSensor(SystemBridgeSensor): - """Defines a bios version sensor.""" - - def __init__(self, coordinator: SystemBridgeDataUpdateCoordinator) -> None: - """Initialize System Bridge sensor.""" - super().__init__( - coordinator, - "bios_version", - "BIOS Version", - "mdi:chip", - None, - None, - False, - ) - - @property - def native_value(self) -> str: - """Return the state of the sensor.""" - bridge: Bridge = self.coordinator.data - return bridge.system.bios.version diff --git a/requirements_all.txt b/requirements_all.txt index 0264d83665b..62b889ecde8 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2251,7 +2251,7 @@ swisshydrodata==0.1.0 synology-srm==0.2.0 # homeassistant.components.system_bridge -systembridge==2.0.6 +systembridge==2.1.0 # homeassistant.components.tahoma tahoma-api==0.0.16 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index dec96024ce1..0ed06dae246 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1264,7 +1264,7 @@ sunwatcher==0.2.1 surepy==0.7.0 # homeassistant.components.system_bridge -systembridge==2.0.6 +systembridge==2.1.0 # homeassistant.components.tellduslive tellduslive==0.10.11