mirror of
https://github.com/home-assistant/core.git
synced 2026-10-08 07:19:32 -04:00
Add Sensor Device Classes to Libre Hardware Monitor (#182203)
This commit is contained in:
@@ -2,11 +2,11 @@
|
||||
|
||||
import logging
|
||||
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.const import Platform, UnitOfDataRate
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
|
||||
from .const import DOMAIN
|
||||
from .const import DOMAIN, THROUGHPUT_UNIQUE_ID_FRAGMENT
|
||||
from .coordinator import (
|
||||
LibreHardwareMonitorConfigEntry,
|
||||
LibreHardwareMonitorCoordinator,
|
||||
@@ -20,8 +20,10 @@ _LOGGER = logging.getLogger(__name__)
|
||||
async def async_migrate_entry(
|
||||
hass: HomeAssistant, config_entry: LibreHardwareMonitorConfigEntry
|
||||
) -> bool:
|
||||
"""Migrate non-unique entity and device ids."""
|
||||
_LOGGER.debug("Migrating from version %s", config_entry.version)
|
||||
"""Migrate to current config flow version."""
|
||||
_LOGGER.debug(
|
||||
"Migrating from version %s.%s", config_entry.version, config_entry.minor_version
|
||||
)
|
||||
|
||||
if config_entry.version == 1:
|
||||
# Migrate entity identifiers
|
||||
@@ -61,11 +63,40 @@ async def async_migrate_entry(
|
||||
)
|
||||
|
||||
hass.config_entries.async_update_entry(
|
||||
config_entry, data=config_entry.data, version=2
|
||||
config_entry, data=config_entry.data, version=2, minor_version=1
|
||||
)
|
||||
|
||||
_LOGGER.debug("Migration to version 2 successful")
|
||||
return True
|
||||
_LOGGER.debug("Migration to version 2.1 successful")
|
||||
|
||||
if config_entry.version == 2 and config_entry.minor_version == 1:
|
||||
# Migrate Throughput unit from KB/s to KiB/s
|
||||
entity_registry = er.async_get(hass)
|
||||
registry_entries = er.async_entries_for_config_entry(
|
||||
entity_registry, config_entry.entry_id
|
||||
)
|
||||
|
||||
throughput_entities = [
|
||||
entry
|
||||
for entry in registry_entries
|
||||
if THROUGHPUT_UNIQUE_ID_FRAGMENT in entry.unique_id
|
||||
]
|
||||
for reg_entry in throughput_entities:
|
||||
_LOGGER.debug(
|
||||
"Migrating entity %s unit from %s to %s",
|
||||
reg_entry.entity_id,
|
||||
reg_entry.unit_of_measurement,
|
||||
UnitOfDataRate.KIBIBYTES_PER_SECOND,
|
||||
)
|
||||
entity_registry.async_update_entity(
|
||||
reg_entry.entity_id,
|
||||
unit_of_measurement=UnitOfDataRate.KIBIBYTES_PER_SECOND,
|
||||
)
|
||||
|
||||
hass.config_entries.async_update_entry(
|
||||
config_entry, data=config_entry.data, version=2, minor_version=2
|
||||
)
|
||||
|
||||
_LOGGER.debug("Migration to version 2.2 successful")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ class LibreHardwareMonitorConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
"""Handle a config flow for LibreHardwareMonitor."""
|
||||
|
||||
VERSION = 2
|
||||
MINOR_VERSION = 2
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Init config flow."""
|
||||
|
||||
@@ -4,3 +4,6 @@ DOMAIN = "libre_hardware_monitor"
|
||||
DEFAULT_HOST = "localhost"
|
||||
DEFAULT_PORT = 8085
|
||||
DEFAULT_SCAN_INTERVAL = 10
|
||||
|
||||
LEGACY_THROUGHPUT_UNIT = "KB/s"
|
||||
THROUGHPUT_UNIQUE_ID_FRAGMENT = "throughput"
|
||||
|
||||
@@ -71,7 +71,7 @@ rules:
|
||||
docs-use-cases: todo
|
||||
dynamic-devices: done
|
||||
entity-category: todo
|
||||
entity-device-class: todo
|
||||
entity-device-class: done
|
||||
entity-disabled-by-default: todo
|
||||
entity-translations: todo
|
||||
exception-translations: todo
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
"""Support for LibreHardwareMonitor Recorder Platform."""
|
||||
|
||||
from homeassistant.const import UnitOfDataRate
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from .const import DOMAIN, LEGACY_THROUGHPUT_UNIT, THROUGHPUT_UNIQUE_ID_FRAGMENT
|
||||
|
||||
|
||||
@callback
|
||||
def async_custom_equivalent_units(
|
||||
hass: HomeAssistant,
|
||||
) -> dict[str, dict[str | None, str]]:
|
||||
"""Return custom equivalent units per entity id.
|
||||
|
||||
Throughput sensors reported the unit as "KB/s" before they got a device class.
|
||||
"""
|
||||
entity_registry = er.async_get(hass)
|
||||
|
||||
return {
|
||||
registry_entry.entity_id: {
|
||||
LEGACY_THROUGHPUT_UNIT: UnitOfDataRate.KIBIBYTES_PER_SECOND
|
||||
}
|
||||
for config_entry in hass.config_entries.async_entries(DOMAIN)
|
||||
for registry_entry in er.async_entries_for_config_entry(
|
||||
entity_registry, config_entry.entry_id
|
||||
)
|
||||
if THROUGHPUT_UNIQUE_ID_FRAGMENT in registry_entry.unique_id
|
||||
}
|
||||
@@ -6,7 +6,14 @@ from typing import Any, override
|
||||
from librehardwaremonitor_api.model import DeviceId, LibreHardwareMonitorSensorData
|
||||
from librehardwaremonitor_api.sensor_type import SensorType
|
||||
|
||||
from homeassistant.components.sensor import SensorEntity, SensorStateClass
|
||||
from homeassistant.components.sensor import (
|
||||
AMBIGUOUS_UNITS,
|
||||
UNIT_CONVERTERS,
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.const import UnitOfDataRate
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
@@ -22,6 +29,24 @@ PARALLEL_UPDATES = 0
|
||||
STATE_MIN_VALUE = "min_value"
|
||||
STATE_MAX_VALUE = "max_value"
|
||||
|
||||
DEVICE_CLASSES: dict[SensorType, SensorDeviceClass] = {
|
||||
SensorType.VOLTAGE: SensorDeviceClass.VOLTAGE,
|
||||
SensorType.CURRENT: SensorDeviceClass.CURRENT,
|
||||
SensorType.POWER: SensorDeviceClass.POWER,
|
||||
SensorType.CLOCK: SensorDeviceClass.FREQUENCY,
|
||||
SensorType.FREQUENCY: SensorDeviceClass.FREQUENCY,
|
||||
SensorType.TEMPERATURE: SensorDeviceClass.TEMPERATURE,
|
||||
SensorType.FLOW: SensorDeviceClass.VOLUME_FLOW_RATE,
|
||||
SensorType.DATA: SensorDeviceClass.DATA_SIZE,
|
||||
SensorType.SMALL_DATA: SensorDeviceClass.DATA_SIZE,
|
||||
SensorType.THROUGHPUT: SensorDeviceClass.DATA_RATE,
|
||||
SensorType.TIMESPAN: SensorDeviceClass.DURATION,
|
||||
SensorType.ENERGY: SensorDeviceClass.ENERGY_STORAGE,
|
||||
SensorType.NOISE: SensorDeviceClass.SOUND_PRESSURE,
|
||||
SensorType.CONDUCTIVITY: SensorDeviceClass.CONDUCTIVITY,
|
||||
SensorType.HUMIDITY: SensorDeviceClass.HUMIDITY,
|
||||
}
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
@@ -74,6 +99,21 @@ class LibreHardwareMonitorSensor(
|
||||
|
||||
self._attr_name: str = sensor_data.name
|
||||
|
||||
if sensor_data.type is None:
|
||||
_LOGGER.debug("Missing type for sensor: %s", sensor_data.name)
|
||||
elif device_class := DEVICE_CLASSES.get(sensor_data.type):
|
||||
self._attr_device_class = device_class
|
||||
|
||||
if device_class is SensorDeviceClass.DATA_RATE:
|
||||
self._attr_suggested_unit_of_measurement = (
|
||||
UnitOfDataRate.KIBIBYTES_PER_SECOND
|
||||
)
|
||||
# Device class default rounds throughput to whole KiB/s
|
||||
self._attr_suggested_display_precision = 1
|
||||
elif device_class is SensorDeviceClass.VOLTAGE:
|
||||
# Device class default rounds voltages to whole volts
|
||||
self._attr_suggested_display_precision = 3
|
||||
|
||||
self._set_state(sensor_data)
|
||||
self._attr_unique_id: str = f"{entry_id}_{sensor_data.sensor_id}"
|
||||
|
||||
@@ -86,33 +126,39 @@ class LibreHardwareMonitorSensor(
|
||||
model=sensor_data.device_type,
|
||||
)
|
||||
|
||||
def _set_state(
|
||||
self,
|
||||
sensor_data: LibreHardwareMonitorSensorData,
|
||||
) -> None:
|
||||
value = sensor_data.value
|
||||
min_value = sensor_data.min
|
||||
max_value = sensor_data.max
|
||||
unit = sensor_data.unit
|
||||
def _set_state(self, sensor_data: LibreHardwareMonitorSensorData) -> None:
|
||||
self._attr_native_value: str | None = sensor_data.value
|
||||
self._attr_native_unit_of_measurement = sensor_data.unit
|
||||
self._native_min_value = sensor_data.min
|
||||
self._native_max_value = sensor_data.max
|
||||
|
||||
if sensor_data.type == SensorType.THROUGHPUT:
|
||||
# Temporary fix: convert the B/s value to KB/s to not break existing entries
|
||||
# This will be migrated properly once SensorDeviceClass is introduced
|
||||
value = f"{(float(value) / 1024):.1f}" if value is not None else None
|
||||
min_value = (
|
||||
f"{(float(min_value) / 1024):.1f}" if min_value is not None else None
|
||||
)
|
||||
max_value = (
|
||||
f"{(float(max_value) / 1024):.1f}" if max_value is not None else None
|
||||
)
|
||||
unit = "KB/s"
|
||||
|
||||
self._attr_native_value: str | None = value
|
||||
self._attr_extra_state_attributes: dict[str, Any] = {
|
||||
STATE_MIN_VALUE: min_value,
|
||||
STATE_MAX_VALUE: max_value,
|
||||
@property
|
||||
@override
|
||||
def extra_state_attributes(self) -> dict[str, Any]:
|
||||
"""Return min and max values in the unit the state is reported in."""
|
||||
return {
|
||||
STATE_MIN_VALUE: self._value_in_state_unit(self._native_min_value),
|
||||
STATE_MAX_VALUE: self._value_in_state_unit(self._native_max_value),
|
||||
}
|
||||
self._attr_native_unit_of_measurement = unit
|
||||
|
||||
def _value_in_state_unit(self, native_value: str | None) -> str | float | None:
|
||||
"""Convert a native value to the unit the state is converted to."""
|
||||
# Conductivity uses micro-sign U+00B5 spelling in its unit which cannot be converted
|
||||
# so we swap it with Greek mu U+03BC to get μS/cm as a valid unit
|
||||
native_unit = AMBIGUOUS_UNITS.get(
|
||||
self.native_unit_of_measurement, self.native_unit_of_measurement
|
||||
)
|
||||
unit = self.unit_of_measurement
|
||||
if (
|
||||
native_value is None
|
||||
or native_unit == unit
|
||||
or (converter := UNIT_CONVERTERS.get(self.device_class)) is None
|
||||
or native_unit not in converter.VALID_UNITS
|
||||
or unit not in converter.VALID_UNITS
|
||||
):
|
||||
return native_value
|
||||
|
||||
return converter.convert(float(native_value), native_unit, unit)
|
||||
|
||||
@callback
|
||||
@override
|
||||
|
||||
@@ -49,6 +49,7 @@ def mock_config_entry() -> MockConfigEntry:
|
||||
data=VALID_CONFIG,
|
||||
entry_id="test_entry_id",
|
||||
version=2,
|
||||
minor_version=2,
|
||||
)
|
||||
|
||||
|
||||
@@ -61,6 +62,7 @@ def mock_auth_config_entry() -> MockConfigEntry:
|
||||
data=VALID_CONFIG_WITH_AUTH,
|
||||
entry_id="test_entry_id",
|
||||
version=2,
|
||||
minor_version=2,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -524,12 +524,12 @@
|
||||
{
|
||||
"id": 43,
|
||||
"Text": "GPU PCIe Tx",
|
||||
"Min": "0,0 KB/s",
|
||||
"Min": "1,0 KB/s",
|
||||
"Value": "278,6 MB/s",
|
||||
"Max": "357,6 MB/s",
|
||||
"SensorId": "/gpu-nvidia/0/throughput/1",
|
||||
"Type": "Throughput",
|
||||
"RawMin": "0,0 B/s",
|
||||
"RawMin": "1000,0 B/s",
|
||||
"RawValue": "292149200,0 B/s",
|
||||
"RawMax": "374999000,0 B/s",
|
||||
"ImageURL": "images/transparent.png",
|
||||
|
||||
@@ -213,7 +213,7 @@
|
||||
'device_name': 'NVIDIA GeForce RTX 4080 SUPER',
|
||||
'device_type': 'NVIDIA',
|
||||
'max': '374999000.0',
|
||||
'min': '0.0',
|
||||
'min': '1000.0',
|
||||
'name': 'GPU PCIe Tx Throughput',
|
||||
'sensor_id': 'gpu-nvidia-0-throughput-1',
|
||||
'type': 'Throughput',
|
||||
|
||||
@@ -25,8 +25,11 @@
|
||||
'name': None,
|
||||
'object_id_base': 'Core (Tctl/Tdie) Temperature',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Core (Tctl/Tdie) Temperature',
|
||||
'platform': 'libre_hardware_monitor',
|
||||
@@ -35,17 +38,18 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'test_entry_id_amdcpu-0-temperature-2',
|
||||
'unit_of_measurement': '°C',
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors_are_created[sensor.gaming_pc_amd_ryzen_7_7800x3d_core_tctl_tdie_temperature-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] AMD Ryzen 7 7800X3D Core (Tctl/Tdie) Temperature',
|
||||
'max_value': '69.1',
|
||||
'min_value': '39.4',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_amd_ryzen_7_7800x3d_core_tctl_tdie_temperature',
|
||||
@@ -137,8 +141,11 @@
|
||||
'name': None,
|
||||
'object_id_base': 'Package Power',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 0,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_device_class': <SensorDeviceClass.POWER: 'power'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Package Power',
|
||||
'platform': 'libre_hardware_monitor',
|
||||
@@ -153,6 +160,7 @@
|
||||
# name: test_sensors_are_created[sensor.gaming_pc_amd_ryzen_7_7800x3d_package_power-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'power',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] AMD Ryzen 7 7800X3D Package Power',
|
||||
'max_value': '70.1',
|
||||
'min_value': '25.1',
|
||||
@@ -193,8 +201,11 @@
|
||||
'name': None,
|
||||
'object_id_base': 'Package Temperature',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Package Temperature',
|
||||
'platform': 'libre_hardware_monitor',
|
||||
@@ -203,17 +214,18 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'test_entry_id_amdcpu-0-temperature-3',
|
||||
'unit_of_measurement': '°C',
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors_are_created[sensor.gaming_pc_amd_ryzen_7_7800x3d_package_temperature-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] AMD Ryzen 7 7800X3D Package Temperature',
|
||||
'max_value': '74.0',
|
||||
'min_value': '38.4',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_amd_ryzen_7_7800x3d_package_temperature',
|
||||
@@ -249,8 +261,11 @@
|
||||
'name': None,
|
||||
'object_id_base': 'VDDCR SoC Voltage',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 3,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_device_class': <SensorDeviceClass.VOLTAGE: 'voltage'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'VDDCR SoC Voltage',
|
||||
'platform': 'libre_hardware_monitor',
|
||||
@@ -265,6 +280,7 @@
|
||||
# name: test_sensors_are_created[sensor.gaming_pc_amd_ryzen_7_7800x3d_vddcr_soc_voltage-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'voltage',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] AMD Ryzen 7 7800X3D VDDCR SoC Voltage',
|
||||
'max_value': '1.306',
|
||||
'min_value': '1.305',
|
||||
@@ -305,8 +321,11 @@
|
||||
'name': None,
|
||||
'object_id_base': 'VDDCR Voltage',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 3,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_device_class': <SensorDeviceClass.VOLTAGE: 'voltage'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'VDDCR Voltage',
|
||||
'platform': 'libre_hardware_monitor',
|
||||
@@ -321,6 +340,7 @@
|
||||
# name: test_sensors_are_created[sensor.gaming_pc_amd_ryzen_7_7800x3d_vddcr_voltage-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'voltage',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] AMD Ryzen 7 7800X3D VDDCR Voltage',
|
||||
'max_value': '1.173',
|
||||
'min_value': '0.452',
|
||||
@@ -361,8 +381,11 @@
|
||||
'name': None,
|
||||
'object_id_base': '+12V Voltage',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 3,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_device_class': <SensorDeviceClass.VOLTAGE: 'voltage'>,
|
||||
'original_icon': None,
|
||||
'original_name': '+12V Voltage',
|
||||
'platform': 'libre_hardware_monitor',
|
||||
@@ -377,6 +400,7 @@
|
||||
# name: test_sensors_are_created[sensor.gaming_pc_msi_mag_b650m_mortar_wifi_ms_7d76_12v_voltage-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'voltage',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] MSI MAG B650M MORTAR WIFI (MS-7D76) +12V Voltage',
|
||||
'max_value': '12.096',
|
||||
'min_value': '12.048',
|
||||
@@ -417,8 +441,11 @@
|
||||
'name': None,
|
||||
'object_id_base': '+5V Voltage',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 3,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_device_class': <SensorDeviceClass.VOLTAGE: 'voltage'>,
|
||||
'original_icon': None,
|
||||
'original_name': '+5V Voltage',
|
||||
'platform': 'libre_hardware_monitor',
|
||||
@@ -433,6 +460,7 @@
|
||||
# name: test_sensors_are_created[sensor.gaming_pc_msi_mag_b650m_mortar_wifi_ms_7d76_5v_voltage-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'voltage',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] MSI MAG B650M MORTAR WIFI (MS-7D76) +5V Voltage',
|
||||
'max_value': '5.050',
|
||||
'min_value': '5.020',
|
||||
@@ -529,8 +557,11 @@
|
||||
'name': None,
|
||||
'object_id_base': 'CPU Temperature',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'CPU Temperature',
|
||||
'platform': 'libre_hardware_monitor',
|
||||
@@ -539,17 +570,18 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'test_entry_id_lpc-nct6687d-0-temperature-0',
|
||||
'unit_of_measurement': '°C',
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors_are_created[sensor.gaming_pc_msi_mag_b650m_mortar_wifi_ms_7d76_cpu_temperature-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] MSI MAG B650M MORTAR WIFI (MS-7D76) CPU Temperature',
|
||||
'max_value': '68.0',
|
||||
'min_value': '39.0',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_msi_mag_b650m_mortar_wifi_ms_7d76_cpu_temperature',
|
||||
@@ -696,8 +728,11 @@
|
||||
'name': None,
|
||||
'object_id_base': 'System Temperature',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'System Temperature',
|
||||
'platform': 'libre_hardware_monitor',
|
||||
@@ -706,17 +741,18 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'test_entry_id_lpc-nct6687d-0-temperature-1',
|
||||
'unit_of_measurement': '°C',
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors_are_created[sensor.gaming_pc_msi_mag_b650m_mortar_wifi_ms_7d76_system_temperature-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] MSI MAG B650M MORTAR WIFI (MS-7D76) System Temperature',
|
||||
'max_value': '46.5',
|
||||
'min_value': '32.5',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_msi_mag_b650m_mortar_wifi_ms_7d76_system_temperature',
|
||||
@@ -752,8 +788,11 @@
|
||||
'name': None,
|
||||
'object_id_base': 'Vcore Voltage',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 3,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_device_class': <SensorDeviceClass.VOLTAGE: 'voltage'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Vcore Voltage',
|
||||
'platform': 'libre_hardware_monitor',
|
||||
@@ -768,6 +807,7 @@
|
||||
# name: test_sensors_are_created[sensor.gaming_pc_msi_mag_b650m_mortar_wifi_ms_7d76_vcore_voltage-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'voltage',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] MSI MAG B650M MORTAR WIFI (MS-7D76) Vcore Voltage',
|
||||
'max_value': '1.318',
|
||||
'min_value': '1.310',
|
||||
@@ -808,8 +848,11 @@
|
||||
'name': None,
|
||||
'object_id_base': 'GPU Core Clock',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 2,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_device_class': <SensorDeviceClass.FREQUENCY: 'frequency'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'GPU Core Clock',
|
||||
'platform': 'libre_hardware_monitor',
|
||||
@@ -824,6 +867,7 @@
|
||||
# name: test_sensors_are_created[sensor.gaming_pc_nvidia_geforce_rtx_4080_super_gpu_core_clock-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'frequency',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU Core Clock',
|
||||
'max_value': '2805.0',
|
||||
'min_value': '210.0',
|
||||
@@ -920,8 +964,11 @@
|
||||
'name': None,
|
||||
'object_id_base': 'GPU Core Temperature',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'GPU Core Temperature',
|
||||
'platform': 'libre_hardware_monitor',
|
||||
@@ -930,17 +977,18 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'test_entry_id_gpu-nvidia-0-temperature-0',
|
||||
'unit_of_measurement': '°C',
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors_are_created[sensor.gaming_pc_nvidia_geforce_rtx_4080_super_gpu_core_temperature-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU Core Temperature',
|
||||
'max_value': '37.0',
|
||||
'min_value': '25.0',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_nvidia_geforce_rtx_4080_super_gpu_core_temperature',
|
||||
@@ -1088,8 +1136,11 @@
|
||||
'name': None,
|
||||
'object_id_base': 'GPU Hot Spot Temperature',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'GPU Hot Spot Temperature',
|
||||
'platform': 'libre_hardware_monitor',
|
||||
@@ -1098,17 +1149,18 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'test_entry_id_gpu-nvidia-0-temperature-2',
|
||||
'unit_of_measurement': '°C',
|
||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors_are_created[sensor.gaming_pc_nvidia_geforce_rtx_4080_super_gpu_hot_spot_temperature-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU Hot Spot Temperature',
|
||||
'max_value': '43.3',
|
||||
'min_value': '32.5',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_nvidia_geforce_rtx_4080_super_gpu_hot_spot_temperature',
|
||||
@@ -1144,8 +1196,11 @@
|
||||
'name': None,
|
||||
'object_id_base': 'GPU Memory Clock',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 2,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_device_class': <SensorDeviceClass.FREQUENCY: 'frequency'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'GPU Memory Clock',
|
||||
'platform': 'libre_hardware_monitor',
|
||||
@@ -1160,6 +1215,7 @@
|
||||
# name: test_sensors_are_created[sensor.gaming_pc_nvidia_geforce_rtx_4080_super_gpu_memory_clock-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'frequency',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU Memory Clock',
|
||||
'max_value': '11502.0',
|
||||
'min_value': '405.0',
|
||||
@@ -1256,8 +1312,11 @@
|
||||
'name': None,
|
||||
'object_id_base': 'GPU Package Power',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 0,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_device_class': <SensorDeviceClass.POWER: 'power'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'GPU Package Power',
|
||||
'platform': 'libre_hardware_monitor',
|
||||
@@ -1272,6 +1331,7 @@
|
||||
# name: test_sensors_are_created[sensor.gaming_pc_nvidia_geforce_rtx_4080_super_gpu_package_power-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'power',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU Package Power',
|
||||
'max_value': '66.6',
|
||||
'min_value': '4.1',
|
||||
@@ -1312,8 +1372,14 @@
|
||||
'name': None,
|
||||
'object_id_base': 'GPU PCIe Tx Throughput',
|
||||
'options': dict({
|
||||
'sensor': dict({
|
||||
'suggested_display_precision': 1,
|
||||
}),
|
||||
'sensor.private': dict({
|
||||
'suggested_unit_of_measurement': <UnitOfDataRate.KIBIBYTES_PER_SECOND: 'KiB/s'>,
|
||||
}),
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_device_class': <SensorDeviceClass.DATA_RATE: 'data_rate'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'GPU PCIe Tx Throughput',
|
||||
'platform': 'libre_hardware_monitor',
|
||||
@@ -1322,24 +1388,25 @@
|
||||
'supported_features': 0,
|
||||
'translation_key': None,
|
||||
'unique_id': 'test_entry_id_gpu-nvidia-0-throughput-1',
|
||||
'unit_of_measurement': 'KB/s',
|
||||
'unit_of_measurement': <UnitOfDataRate.KIBIBYTES_PER_SECOND: 'KiB/s'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors_are_created[sensor.gaming_pc_nvidia_geforce_rtx_4080_super_gpu_pcie_tx_throughput-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'data_rate',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU PCIe Tx Throughput',
|
||||
'max_value': '366210.0',
|
||||
'min_value': '0.0',
|
||||
'max_value': 366209.9609375,
|
||||
'min_value': 0.9765625,
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'KB/s',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDataRate.KIBIBYTES_PER_SECOND: 'KiB/s'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_nvidia_geforce_rtx_4080_super_gpu_pcie_tx_throughput',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '285302.0',
|
||||
'state': '285301.953125',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors_are_created[sensor.gaming_pc_nvidia_geforce_rtx_4080_super_gpu_video_engine_load-entry]
|
||||
@@ -1402,6 +1469,7 @@
|
||||
list([
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'voltage',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] MSI MAG B650M MORTAR WIFI (MS-7D76) +12V Voltage',
|
||||
'max_value': '12.096',
|
||||
'min_value': '12.048',
|
||||
@@ -1417,6 +1485,7 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'voltage',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] MSI MAG B650M MORTAR WIFI (MS-7D76) +5V Voltage',
|
||||
'max_value': '5.050',
|
||||
'min_value': '5.020',
|
||||
@@ -1432,6 +1501,7 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'voltage',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] MSI MAG B650M MORTAR WIFI (MS-7D76) Vcore Voltage',
|
||||
'max_value': '1.318',
|
||||
'min_value': '1.310',
|
||||
@@ -1447,11 +1517,12 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] MSI MAG B650M MORTAR WIFI (MS-7D76) CPU Temperature',
|
||||
'max_value': '68.0',
|
||||
'min_value': '39.0',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_msi_mag_b650m_mortar_wifi_ms_7d76_cpu_temperature',
|
||||
@@ -1462,11 +1533,12 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] MSI MAG B650M MORTAR WIFI (MS-7D76) System Temperature',
|
||||
'max_value': '46.5',
|
||||
'min_value': '32.5',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_msi_mag_b650m_mortar_wifi_ms_7d76_system_temperature',
|
||||
@@ -1521,6 +1593,7 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'voltage',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] AMD Ryzen 7 7800X3D VDDCR Voltage',
|
||||
'max_value': '1.173',
|
||||
'min_value': '0.452',
|
||||
@@ -1536,6 +1609,7 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'voltage',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] AMD Ryzen 7 7800X3D VDDCR SoC Voltage',
|
||||
'max_value': '1.306',
|
||||
'min_value': '1.305',
|
||||
@@ -1551,6 +1625,7 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'power',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] AMD Ryzen 7 7800X3D Package Power',
|
||||
'max_value': '70.1',
|
||||
'min_value': '25.1',
|
||||
@@ -1566,11 +1641,12 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] AMD Ryzen 7 7800X3D Core (Tctl/Tdie) Temperature',
|
||||
'max_value': '69.1',
|
||||
'min_value': '39.4',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_amd_ryzen_7_7800x3d_core_tctl_tdie_temperature',
|
||||
@@ -1581,11 +1657,12 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] AMD Ryzen 7 7800X3D Package Temperature',
|
||||
'max_value': '74.0',
|
||||
'min_value': '38.4',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_amd_ryzen_7_7800x3d_package_temperature',
|
||||
@@ -1611,6 +1688,7 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'power',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU Package Power',
|
||||
'max_value': '66.6',
|
||||
'min_value': '4.1',
|
||||
@@ -1626,6 +1704,7 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'frequency',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU Core Clock',
|
||||
'max_value': '2805.0',
|
||||
'min_value': '210.0',
|
||||
@@ -1641,6 +1720,7 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'frequency',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU Memory Clock',
|
||||
'max_value': '11502.0',
|
||||
'min_value': '405.0',
|
||||
@@ -1656,11 +1736,12 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU Core Temperature',
|
||||
'max_value': '37.0',
|
||||
'min_value': '25.0',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_nvidia_geforce_rtx_4080_super_gpu_core_temperature',
|
||||
@@ -1671,11 +1752,12 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU Hot Spot Temperature',
|
||||
'max_value': '43.3',
|
||||
'min_value': '32.5',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_nvidia_geforce_rtx_4080_super_gpu_hot_spot_temperature',
|
||||
@@ -1761,18 +1843,19 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'data_rate',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU PCIe Tx Throughput',
|
||||
'max_value': '366210.0',
|
||||
'min_value': '0.0',
|
||||
'max_value': 366209.9609375,
|
||||
'min_value': 0.9765625,
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'KB/s',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDataRate.KIBIBYTES_PER_SECOND: 'KiB/s'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_nvidia_geforce_rtx_4080_super_gpu_pcie_tx_throughput',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '285302.0',
|
||||
'state': '285301.953125',
|
||||
}),
|
||||
])
|
||||
# ---
|
||||
@@ -1780,6 +1863,7 @@
|
||||
list([
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'voltage',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] MSI MAG B650M MORTAR WIFI (MS-7D76) +12V Voltage',
|
||||
'max_value': '12.096',
|
||||
'min_value': '12.048',
|
||||
@@ -1795,6 +1879,7 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'voltage',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] MSI MAG B650M MORTAR WIFI (MS-7D76) +5V Voltage',
|
||||
'max_value': '5.050',
|
||||
'min_value': '5.020',
|
||||
@@ -1810,6 +1895,7 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'voltage',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] MSI MAG B650M MORTAR WIFI (MS-7D76) Vcore Voltage',
|
||||
'max_value': '1.318',
|
||||
'min_value': '1.310',
|
||||
@@ -1825,11 +1911,12 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] MSI MAG B650M MORTAR WIFI (MS-7D76) CPU Temperature',
|
||||
'max_value': '68.0',
|
||||
'min_value': '39.0',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_msi_mag_b650m_mortar_wifi_ms_7d76_cpu_temperature',
|
||||
@@ -1840,11 +1927,12 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] MSI MAG B650M MORTAR WIFI (MS-7D76) System Temperature',
|
||||
'max_value': '46.5',
|
||||
'min_value': '32.5',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_msi_mag_b650m_mortar_wifi_ms_7d76_system_temperature',
|
||||
@@ -1899,6 +1987,7 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'voltage',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] AMD Ryzen 7 7800X3D VDDCR Voltage',
|
||||
'max_value': '1.173',
|
||||
'min_value': '0.452',
|
||||
@@ -1914,6 +2003,7 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'voltage',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] AMD Ryzen 7 7800X3D VDDCR SoC Voltage',
|
||||
'max_value': '1.306',
|
||||
'min_value': '1.305',
|
||||
@@ -1929,6 +2019,7 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'power',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] AMD Ryzen 7 7800X3D Package Power',
|
||||
'max_value': '70.1',
|
||||
'min_value': '25.1',
|
||||
@@ -1944,11 +2035,12 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] AMD Ryzen 7 7800X3D Core (Tctl/Tdie) Temperature',
|
||||
'max_value': '69.1',
|
||||
'min_value': '39.4',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_amd_ryzen_7_7800x3d_core_tctl_tdie_temperature',
|
||||
@@ -1959,11 +2051,12 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] AMD Ryzen 7 7800X3D Package Temperature',
|
||||
'max_value': '74.0',
|
||||
'min_value': '38.4',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_amd_ryzen_7_7800x3d_package_temperature',
|
||||
@@ -1989,6 +2082,7 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'power',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU Package Power',
|
||||
'max_value': '66.6',
|
||||
'min_value': '4.1',
|
||||
@@ -2004,6 +2098,7 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'frequency',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU Core Clock',
|
||||
'max_value': '2805.0',
|
||||
'min_value': '210.0',
|
||||
@@ -2019,6 +2114,7 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'frequency',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU Memory Clock',
|
||||
'max_value': '11502.0',
|
||||
'min_value': '405.0',
|
||||
@@ -2034,11 +2130,12 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU Core Temperature',
|
||||
'max_value': '37.0',
|
||||
'min_value': '25.0',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_nvidia_geforce_rtx_4080_super_gpu_core_temperature',
|
||||
@@ -2049,11 +2146,12 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'temperature',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU Hot Spot Temperature',
|
||||
'max_value': '43.3',
|
||||
'min_value': '32.5',
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: '°C',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_nvidia_geforce_rtx_4080_super_gpu_hot_spot_temperature',
|
||||
@@ -2139,18 +2237,19 @@
|
||||
}),
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
<EntityStateAttribute.DEVICE_CLASS: 'device_class'>: 'data_rate',
|
||||
<EntityStateAttribute.FRIENDLY_NAME: 'friendly_name'>: '[GAMING-PC] NVIDIA GeForce RTX 4080 SUPER GPU PCIe Tx Throughput',
|
||||
'max_value': '366210.0',
|
||||
'min_value': '0.0',
|
||||
'max_value': 366209.9609375,
|
||||
'min_value': 0.9765625,
|
||||
<SensorEntityCapabilityAttribute.STATE_CLASS: 'state_class'>: <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: 'KB/s',
|
||||
<EntityStateAttribute.UNIT_OF_MEASUREMENT: 'unit_of_measurement'>: <UnitOfDataRate.KIBIBYTES_PER_SECOND: 'KiB/s'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.gaming_pc_nvidia_geforce_rtx_4080_super_gpu_pcie_tx_throughput',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '285302.0',
|
||||
'state': '285301.953125',
|
||||
}),
|
||||
])
|
||||
# ---
|
||||
|
||||
@@ -10,8 +10,13 @@ import pytest
|
||||
from homeassistant.components.libre_hardware_monitor.const import (
|
||||
DEFAULT_SCAN_INTERVAL,
|
||||
DOMAIN,
|
||||
LEGACY_THROUGHPUT_UNIT,
|
||||
)
|
||||
from homeassistant.components.libre_hardware_monitor.recorder import (
|
||||
async_custom_equivalent_units,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import ATTR_UNIT_OF_MEASUREMENT, UnitOfDataRate
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
|
||||
@@ -102,6 +107,69 @@ async def test_migration_to_unique_ids(
|
||||
legacy_config_entry_v1.entry_id
|
||||
)
|
||||
assert updated_config_entry.version == 2
|
||||
assert updated_config_entry.minor_version == 2
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("version", "minor_version", "unique_id_prefix"),
|
||||
[
|
||||
pytest.param(1, 1, "lhm-", id="from_v1"),
|
||||
pytest.param(2, 1, "test_entry_id_", id="from_v2_minor_1"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("mock_lhm_client", "recorder_mock")
|
||||
async def test_migration_to_sensor_device_classes(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
version: int,
|
||||
minor_version: int,
|
||||
unique_id_prefix: str,
|
||||
) -> None:
|
||||
"""Test that throughput sensor units are updated from every legacy version."""
|
||||
legacy_config_entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="192.168.0.20:8085",
|
||||
data=VALID_CONFIG,
|
||||
entry_id="test_entry_id",
|
||||
version=version,
|
||||
minor_version=minor_version,
|
||||
)
|
||||
legacy_config_entry.add_to_hass(hass)
|
||||
|
||||
# Set up throughput sensor with old unit
|
||||
object_id = "nvidia_geforce_rtx_4080_gpu_pcie_tx_throughput"
|
||||
entity_registry.async_get_or_create(
|
||||
"sensor",
|
||||
DOMAIN,
|
||||
f"{unique_id_prefix}gpu-nvidia-0-throughput-1",
|
||||
suggested_object_id=object_id,
|
||||
config_entry=legacy_config_entry,
|
||||
unit_of_measurement=LEGACY_THROUGHPUT_UNIT,
|
||||
)
|
||||
|
||||
await init_integration(hass, legacy_config_entry)
|
||||
|
||||
entity_entry = entity_registry.async_get(f"sensor.{object_id}")
|
||||
assert entity_entry.unit_of_measurement == UnitOfDataRate.KIBIBYTES_PER_SECOND
|
||||
|
||||
# the entity keeps reporting the migrated unit once it is set up
|
||||
state = hass.states.get(f"sensor.{object_id}")
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == (
|
||||
UnitOfDataRate.KIBIBYTES_PER_SECOND
|
||||
)
|
||||
|
||||
custom_equivalent_units = async_custom_equivalent_units(hass)
|
||||
assert custom_equivalent_units == {
|
||||
f"sensor.{object_id}": {
|
||||
LEGACY_THROUGHPUT_UNIT: UnitOfDataRate.KIBIBYTES_PER_SECOND
|
||||
}
|
||||
}
|
||||
|
||||
updated_config_entry = hass.config_entries.async_get_entry(
|
||||
legacy_config_entry.entry_id
|
||||
)
|
||||
assert updated_config_entry.version == 2
|
||||
assert updated_config_entry.minor_version == 2
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_deprecated_lhm_client")
|
||||
|
||||
@@ -24,8 +24,31 @@ from homeassistant.components.libre_hardware_monitor.const import (
|
||||
DEFAULT_SCAN_INTERVAL,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.components.libre_hardware_monitor.sensor import (
|
||||
STATE_MAX_VALUE,
|
||||
STATE_MIN_VALUE,
|
||||
)
|
||||
from homeassistant.components.sensor import SensorDeviceClass
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import STATE_UNAVAILABLE, STATE_UNKNOWN
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
PERCENTAGE,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
UnitOfConductivity,
|
||||
UnitOfDataRate,
|
||||
UnitOfElectricCurrent,
|
||||
UnitOfElectricPotential,
|
||||
UnitOfEnergy,
|
||||
UnitOfFrequency,
|
||||
UnitOfInformation,
|
||||
UnitOfPower,
|
||||
UnitOfSoundPressure,
|
||||
UnitOfTemperature,
|
||||
UnitOfTime,
|
||||
UnitOfVolumeFlowRate,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.helpers.device_registry import DeviceEntry
|
||||
@@ -48,6 +71,218 @@ async def test_sensors_are_created(
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("sensor_type", "lhm_unit", "expected_device_class", "expected_unit"),
|
||||
[
|
||||
pytest.param(
|
||||
SensorType.VOLTAGE,
|
||||
"V",
|
||||
SensorDeviceClass.VOLTAGE,
|
||||
UnitOfElectricPotential.VOLT,
|
||||
id="voltage",
|
||||
),
|
||||
pytest.param(
|
||||
SensorType.CURRENT,
|
||||
"A",
|
||||
SensorDeviceClass.CURRENT,
|
||||
UnitOfElectricCurrent.AMPERE,
|
||||
id="current",
|
||||
),
|
||||
pytest.param(
|
||||
SensorType.POWER,
|
||||
"W",
|
||||
SensorDeviceClass.POWER,
|
||||
UnitOfPower.WATT,
|
||||
id="power",
|
||||
),
|
||||
pytest.param(
|
||||
SensorType.CLOCK,
|
||||
"MHz",
|
||||
SensorDeviceClass.FREQUENCY,
|
||||
UnitOfFrequency.MEGAHERTZ,
|
||||
id="clock",
|
||||
),
|
||||
pytest.param(
|
||||
SensorType.FREQUENCY,
|
||||
"Hz",
|
||||
SensorDeviceClass.FREQUENCY,
|
||||
UnitOfFrequency.HERTZ,
|
||||
id="frequency",
|
||||
),
|
||||
pytest.param(
|
||||
SensorType.TEMPERATURE,
|
||||
"°C",
|
||||
SensorDeviceClass.TEMPERATURE,
|
||||
UnitOfTemperature.CELSIUS,
|
||||
id="temperature",
|
||||
),
|
||||
pytest.param(
|
||||
SensorType.FLOW,
|
||||
"L/h",
|
||||
SensorDeviceClass.VOLUME_FLOW_RATE,
|
||||
UnitOfVolumeFlowRate.LITERS_PER_HOUR,
|
||||
id="flow",
|
||||
),
|
||||
pytest.param(
|
||||
SensorType.DATA,
|
||||
"GB",
|
||||
SensorDeviceClass.DATA_SIZE,
|
||||
UnitOfInformation.GIGABYTES,
|
||||
id="data",
|
||||
),
|
||||
pytest.param(
|
||||
SensorType.SMALL_DATA,
|
||||
"MB",
|
||||
SensorDeviceClass.DATA_SIZE,
|
||||
UnitOfInformation.MEGABYTES,
|
||||
id="small_data",
|
||||
),
|
||||
pytest.param(
|
||||
SensorType.THROUGHPUT,
|
||||
"B/s",
|
||||
SensorDeviceClass.DATA_RATE,
|
||||
UnitOfDataRate.KIBIBYTES_PER_SECOND,
|
||||
id="throughput",
|
||||
),
|
||||
pytest.param(
|
||||
SensorType.TIMESPAN,
|
||||
"s",
|
||||
SensorDeviceClass.DURATION,
|
||||
UnitOfTime.SECONDS,
|
||||
id="timespan",
|
||||
),
|
||||
pytest.param(
|
||||
SensorType.ENERGY,
|
||||
"mWh",
|
||||
SensorDeviceClass.ENERGY_STORAGE,
|
||||
UnitOfEnergy.MILLIWATT_HOUR,
|
||||
id="energy",
|
||||
),
|
||||
pytest.param(
|
||||
SensorType.NOISE,
|
||||
"dBA",
|
||||
SensorDeviceClass.SOUND_PRESSURE,
|
||||
UnitOfSoundPressure.WEIGHTED_DECIBEL_A,
|
||||
id="noise",
|
||||
),
|
||||
pytest.param(
|
||||
SensorType.CONDUCTIVITY,
|
||||
# LHM sends the micro sign (U+00B5), HA normalizes it to greek mu (U+03BC)
|
||||
"\u00b5S/cm",
|
||||
SensorDeviceClass.CONDUCTIVITY,
|
||||
UnitOfConductivity.MICROSIEMENS_PER_CM,
|
||||
id="conductivity",
|
||||
),
|
||||
pytest.param(
|
||||
SensorType.HUMIDITY,
|
||||
"%",
|
||||
SensorDeviceClass.HUMIDITY,
|
||||
PERCENTAGE,
|
||||
id="humidity",
|
||||
),
|
||||
pytest.param(SensorType.FACTOR, None, None, None, id="factor_unmapped"),
|
||||
pytest.param(None, None, None, None, id="unknown_type"),
|
||||
],
|
||||
)
|
||||
async def test_sensor_device_class_mapping(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
mock_lhm_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
sensor_type: SensorType | None,
|
||||
lhm_unit: str | None,
|
||||
expected_device_class: SensorDeviceClass | None,
|
||||
expected_unit: str | None,
|
||||
) -> None:
|
||||
"""Test every LHM sensor type gets the expected device class and unit."""
|
||||
sensor_id = "gpu-nvidia-0-test-0"
|
||||
mock_lhm_client.get_data.return_value = replace(
|
||||
mock_lhm_client.get_data.return_value,
|
||||
sensor_data=MappingProxyType(
|
||||
{
|
||||
sensor_id: LibreHardwareMonitorSensorData(
|
||||
name="Test",
|
||||
value="42.0",
|
||||
type=sensor_type,
|
||||
min="40.0",
|
||||
max="44.0",
|
||||
unit=lhm_unit,
|
||||
device_id="gpu-nvidia-0",
|
||||
device_name="NVIDIA GeForce RTX 4080 SUPER",
|
||||
device_type="NVIDIA",
|
||||
sensor_id=sensor_id,
|
||||
)
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
await init_integration(hass, mock_config_entry)
|
||||
|
||||
entity_id = entity_registry.async_get_entity_id(
|
||||
"sensor", DOMAIN, f"{mock_config_entry.entry_id}_{sensor_id}"
|
||||
)
|
||||
assert entity_id
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
|
||||
assert state
|
||||
assert state.attributes.get(ATTR_DEVICE_CLASS) == expected_device_class
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == expected_unit
|
||||
|
||||
|
||||
async def test_min_max_follow_selected_conductivity_unit(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
mock_lhm_client: AsyncMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test min and max are converted from the micro sign spelling LHM reports."""
|
||||
sensor_id = "gpu-nvidia-0-conductivity-0"
|
||||
mock_lhm_client.get_data.return_value = replace(
|
||||
mock_lhm_client.get_data.return_value,
|
||||
sensor_data=MappingProxyType(
|
||||
{
|
||||
sensor_id: LibreHardwareMonitorSensorData(
|
||||
name="Coolant",
|
||||
value="42.0",
|
||||
type=SensorType.CONDUCTIVITY,
|
||||
min="40.0",
|
||||
max="44.0",
|
||||
unit="\u00b5S/cm",
|
||||
device_id="gpu-nvidia-0",
|
||||
device_name="NVIDIA GeForce RTX 4080 SUPER",
|
||||
device_type="NVIDIA",
|
||||
sensor_id=sensor_id,
|
||||
)
|
||||
}
|
||||
),
|
||||
)
|
||||
await init_integration(hass, mock_config_entry)
|
||||
|
||||
entity_id = entity_registry.async_get_entity_id(
|
||||
"sensor", DOMAIN, f"{mock_config_entry.entry_id}_{sensor_id}"
|
||||
)
|
||||
assert entity_id
|
||||
|
||||
entity_registry.async_update_entity_options(
|
||||
entity_id,
|
||||
"sensor",
|
||||
{"unit_of_measurement": UnitOfConductivity.MILLISIEMENS_PER_CM},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
|
||||
assert state
|
||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == (
|
||||
UnitOfConductivity.MILLISIEMENS_PER_CM
|
||||
)
|
||||
assert float(state.state) == pytest.approx(0.042)
|
||||
assert state.attributes[STATE_MIN_VALUE] == pytest.approx(0.04)
|
||||
assert state.attributes[STATE_MAX_VALUE] == pytest.approx(0.044)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"error", [LibreHardwareMonitorConnectionError, LibreHardwareMonitorNoDevicesError]
|
||||
)
|
||||
@@ -141,8 +376,8 @@ async def test_sensor_invalid_auth_during_startup(
|
||||
(
|
||||
"gaming_pc_nvidia_geforce_rtx_4080_super_gpu_pcie_tx_throughput",
|
||||
"gpu-nvidia-0-throughput-1",
|
||||
"792150000.0",
|
||||
"773584.0",
|
||||
"811161600.0",
|
||||
"792150.0",
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user