Add GPU sensor to Glances (#106322)

* feat: add GPU sensor to Glances

* Add translations to Glances GPU sensor

* Fix translations of GPU processor and memory usage

* PR feedback: move icons to icons.json

thanks to @wittypluck

* Update glances snapshot with added GPU

* Remove JSON trailing comma

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* Limit precision of Glance GPU mem usage sensor

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* Clean up outdated snapshots

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
pull/114546/head
fhoekstra 2024-04-07 15:05:22 +02:00 committed by GitHub
parent 1b07d3ecfa
commit e4fbe539aa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 255 additions and 1 deletions

View File

@ -54,6 +54,12 @@
},
"uptime": {
"default": "mdi:clock-time-eight-outline"
},
"gpu_processor_usage": {
"default": "mdi:expansion-card"
},
"gpu_memory_usage": {
"default": "mdi:memory"
}
}
}

View File

@ -235,6 +235,36 @@ SENSOR_TYPES = {
translation_key="uptime",
device_class=SensorDeviceClass.TIMESTAMP,
),
("gpu", "mem"): GlancesSensorEntityDescription(
key="mem",
type="gpu",
translation_key="gpu_memory_usage",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
("gpu", "proc"): GlancesSensorEntityDescription(
key="proc",
type="gpu",
translation_key="gpu_processor_usage",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=1,
),
("gpu", "temperature"): GlancesSensorEntityDescription(
key="temperature",
type="gpu",
translation_key="temperature",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
),
("gpu", "fan_speed"): GlancesSensorEntityDescription(
key="fan_speed",
type="gpu",
translation_key="fan_speed",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
}
@ -249,7 +279,7 @@ async def async_setup_entry(
entities: list[GlancesSensor] = []
for sensor_type, sensors in coordinator.data.items():
if sensor_type in ["fs", "diskio", "sensors", "raid"]:
if sensor_type in ["fs", "diskio", "sensors", "raid", "gpu"]:
entities.extend(
GlancesSensor(
coordinator,

View File

@ -109,6 +109,12 @@
},
"uptime": {
"name": "Uptime"
},
"gpu_memory_usage": {
"name": "{sensor_label} memory usage"
},
"gpu_processor_usage": {
"name": "{sensor_label} processor usage"
}
}
},

View File

@ -215,4 +215,12 @@ HA_SENSOR_DATA: dict[str, Any] = {
},
},
"uptime": "3 days, 10:25:20",
"gpu": {
"NVIDIA GeForce RTX 3080 (GPU 0)": {
"temperature": 51,
"mem": 8.41064453125,
"proc": 26,
"fan_speed": 0,
}
},
}

View File

@ -802,6 +802,210 @@
'state': 'unavailable',
})
# ---
# name: test_sensor_states[sensor.0_0_0_0_nvidia_geforce_rtx_3080_gpu_0_fan_speed-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.0_0_0_0_nvidia_geforce_rtx_3080_gpu_0_fan_speed',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'NVIDIA GeForce RTX 3080 (GPU 0) fan speed',
'platform': 'glances',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'fan_speed',
'unique_id': 'test-NVIDIA GeForce RTX 3080 (GPU 0)-fan_speed',
'unit_of_measurement': '%',
})
# ---
# name: test_sensor_states[sensor.0_0_0_0_nvidia_geforce_rtx_3080_gpu_0_fan_speed-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': '0.0.0.0 NVIDIA GeForce RTX 3080 (GPU 0) fan speed',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': '%',
}),
'context': <ANY>,
'entity_id': 'sensor.0_0_0_0_nvidia_geforce_rtx_3080_gpu_0_fan_speed',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '0',
})
# ---
# name: test_sensor_states[sensor.0_0_0_0_nvidia_geforce_rtx_3080_gpu_0_memory_usage-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.0_0_0_0_nvidia_geforce_rtx_3080_gpu_0_memory_usage',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'NVIDIA GeForce RTX 3080 (GPU 0) memory usage',
'platform': 'glances',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'gpu_memory_usage',
'unique_id': 'test-NVIDIA GeForce RTX 3080 (GPU 0)-mem',
'unit_of_measurement': '%',
})
# ---
# name: test_sensor_states[sensor.0_0_0_0_nvidia_geforce_rtx_3080_gpu_0_memory_usage-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': '0.0.0.0 NVIDIA GeForce RTX 3080 (GPU 0) memory usage',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': '%',
}),
'context': <ANY>,
'entity_id': 'sensor.0_0_0_0_nvidia_geforce_rtx_3080_gpu_0_memory_usage',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '8.41064453125',
})
# ---
# name: test_sensor_states[sensor.0_0_0_0_nvidia_geforce_rtx_3080_gpu_0_processor_usage-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.0_0_0_0_nvidia_geforce_rtx_3080_gpu_0_processor_usage',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
'sensor': dict({
'suggested_display_precision': 1,
}),
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'NVIDIA GeForce RTX 3080 (GPU 0) processor usage',
'platform': 'glances',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'gpu_processor_usage',
'unique_id': 'test-NVIDIA GeForce RTX 3080 (GPU 0)-proc',
'unit_of_measurement': '%',
})
# ---
# name: test_sensor_states[sensor.0_0_0_0_nvidia_geforce_rtx_3080_gpu_0_processor_usage-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': '0.0.0.0 NVIDIA GeForce RTX 3080 (GPU 0) processor usage',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': '%',
}),
'context': <ANY>,
'entity_id': 'sensor.0_0_0_0_nvidia_geforce_rtx_3080_gpu_0_processor_usage',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '26',
})
# ---
# name: test_sensor_states[sensor.0_0_0_0_nvidia_geforce_rtx_3080_gpu_0_temperature-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': None,
'entity_id': 'sensor.0_0_0_0_nvidia_geforce_rtx_3080_gpu_0_temperature',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.TEMPERATURE: 'temperature'>,
'original_icon': None,
'original_name': 'NVIDIA GeForce RTX 3080 (GPU 0) temperature',
'platform': 'glances',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'temperature',
'unique_id': 'test-NVIDIA GeForce RTX 3080 (GPU 0)-temperature',
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
})
# ---
# name: test_sensor_states[sensor.0_0_0_0_nvidia_geforce_rtx_3080_gpu_0_temperature-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'temperature',
'friendly_name': '0.0.0.0 NVIDIA GeForce RTX 3080 (GPU 0) temperature',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
}),
'context': <ANY>,
'entity_id': 'sensor.0_0_0_0_nvidia_geforce_rtx_3080_gpu_0_temperature',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '51',
})
# ---
# name: test_sensor_states[sensor.0_0_0_0_nvme0n1_disk_read-entry]
EntityRegistryEntrySnapshot({
'aliases': set({