223 lines
5.8 KiB
C#
223 lines
5.8 KiB
C#
#nullable enable
|
||
|
||
using System;
|
||
using System.Globalization;
|
||
using LibreHardwareMonitor.Hardware;
|
||
|
||
public class Telemetry : IDisposable
|
||
{
|
||
private const int UpdateRateDefaultMs = 1000;
|
||
public int UpdateRateMs => UpdateRateDefaultMs;
|
||
|
||
private readonly UdpSender udp = new UdpSender();
|
||
private readonly Computer computer = new Computer();
|
||
|
||
private IHardware? cpuHw;
|
||
private IHardware? gpuHw;
|
||
private IHardware? memHw;
|
||
|
||
private ISensor[] cpuLoadSensors = Array.Empty<ISensor>();
|
||
private ISensor? cpuTempSensor;
|
||
|
||
private ISensor? gpu3DLoadSensor;
|
||
private ISensor? gpuTempSensor;
|
||
private ISensor? gpuVramUsedSensor;
|
||
private ISensor? gpuVramTotalSensor;
|
||
|
||
private ISensor? memUsedSensor;
|
||
private ISensor? memAvailSensor;
|
||
|
||
private static readonly CultureInfo CI = CultureInfo.InvariantCulture;
|
||
|
||
public void Initialize()
|
||
{
|
||
computer.IsCpuEnabled = true;
|
||
computer.IsGpuEnabled = true;
|
||
computer.IsMemoryEnabled = true;
|
||
|
||
computer.Open();
|
||
CacheHardwareAndSensors();
|
||
}
|
||
|
||
private void CacheHardwareAndSensors()
|
||
{
|
||
foreach (var hw in computer.Hardware)
|
||
{
|
||
hw.Update();
|
||
|
||
switch (hw.HardwareType)
|
||
{
|
||
case HardwareType.Cpu:
|
||
cpuHw = hw;
|
||
CacheCpuSensors(hw);
|
||
break;
|
||
|
||
case HardwareType.GpuNvidia:
|
||
case HardwareType.GpuAmd:
|
||
case HardwareType.GpuIntel:
|
||
gpuHw = hw;
|
||
CacheGpuSensors(hw);
|
||
break;
|
||
|
||
case HardwareType.Memory:
|
||
memHw = hw;
|
||
CacheMemorySensors(hw);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
private void CacheCpuSensors(IHardware hw)
|
||
{
|
||
var loads = new System.Collections.Generic.List<ISensor>();
|
||
|
||
foreach (var s in hw.Sensors)
|
||
{
|
||
if (s.SensorType == SensorType.Load &&
|
||
s.Name.Contains("CPU Core"))
|
||
loads.Add(s);
|
||
|
||
if (s.SensorType == SensorType.Temperature)
|
||
{
|
||
if (s.Name == "Core (Tctl/Tdie)")
|
||
cpuTempSensor = s;
|
||
else if (cpuTempSensor == null)
|
||
cpuTempSensor = s;
|
||
}
|
||
}
|
||
|
||
cpuLoadSensors = loads.ToArray();
|
||
}
|
||
|
||
private void CacheGpuSensors(IHardware hw)
|
||
{
|
||
foreach (var s in hw.Sensors)
|
||
{
|
||
if (s.SensorType == SensorType.Load)
|
||
{
|
||
if (s.Name == "D3D 3D")
|
||
gpu3DLoadSensor = s;
|
||
else if (gpu3DLoadSensor == null && s.Name == "GPU Core")
|
||
gpu3DLoadSensor = s;
|
||
}
|
||
|
||
if (s.SensorType == SensorType.Temperature)
|
||
{
|
||
if (s.Name == "GPU Core")
|
||
gpuTempSensor = s;
|
||
else if (gpuTempSensor == null)
|
||
gpuTempSensor = s;
|
||
}
|
||
|
||
if (s.SensorType == SensorType.SmallData)
|
||
{
|
||
if (s.Name == "GPU Memory Used")
|
||
gpuVramUsedSensor = s;
|
||
|
||
if (s.Name == "GPU Memory Total")
|
||
gpuVramTotalSensor = s;
|
||
}
|
||
}
|
||
}
|
||
|
||
private void CacheMemorySensors(IHardware hw)
|
||
{
|
||
foreach (var s in hw.Sensors)
|
||
{
|
||
if (s.SensorType == SensorType.Data && s.Name == "Memory Used")
|
||
memUsedSensor = s;
|
||
|
||
if (s.SensorType == SensorType.Data && s.Name == "Memory Available")
|
||
memAvailSensor = s;
|
||
}
|
||
}
|
||
|
||
public void UpdateAndSend()
|
||
{
|
||
cpuHw?.Update();
|
||
gpuHw?.Update();
|
||
memHw?.Update();
|
||
|
||
float cpu = GetCpuLoadPercent();
|
||
float cpuTemp = GetCpuTemperaturePercent();
|
||
float mem = GetMemoryUsagePercent();
|
||
float gpu3d = GetGpu3DLoad();
|
||
float gpuTemp = GetGpuTemperaturePercent();
|
||
float vram = GetGpuVramPercent();
|
||
|
||
// Prepare 8 floats (future‑proof)
|
||
float[] packet =
|
||
{
|
||
cpu,
|
||
cpuTemp,
|
||
mem,
|
||
gpu3d,
|
||
gpuTemp,
|
||
vram,
|
||
0f, // reserved for future use
|
||
0f // reserved for future use
|
||
};
|
||
|
||
udp.SendFloats(packet);
|
||
}
|
||
|
||
private float GetCpuLoadPercent()
|
||
{
|
||
if (cpuLoadSensors.Length == 0) return 0;
|
||
|
||
float total = 0;
|
||
int count = 0;
|
||
|
||
foreach (var s in cpuLoadSensors)
|
||
{
|
||
total += s.Value ?? 0;
|
||
count++;
|
||
}
|
||
|
||
return count == 0 ? 0 : total / count;
|
||
}
|
||
|
||
private float GetCpuTemperaturePercent()
|
||
{
|
||
float t = cpuTempSensor?.Value ?? 0;
|
||
return Math.Clamp(t, 0, 100);
|
||
}
|
||
|
||
private float GetGpu3DLoad()
|
||
{
|
||
return gpu3DLoadSensor?.Value ?? 0;
|
||
}
|
||
|
||
private float GetGpuTemperaturePercent()
|
||
{
|
||
float t = gpuTempSensor?.Value ?? 0;
|
||
return Math.Clamp(t, 0, 100);
|
||
}
|
||
|
||
private float GetGpuVramPercent()
|
||
{
|
||
float used = gpuVramUsedSensor?.Value ?? 0;
|
||
float total = gpuVramTotalSensor?.Value ?? 0;
|
||
|
||
if (total <= 0) return 0;
|
||
return (used / total) * 100f;
|
||
}
|
||
|
||
private float GetMemoryUsagePercent()
|
||
{
|
||
float used = memUsedSensor?.Value ?? 0;
|
||
float avail = memAvailSensor?.Value ?? 0;
|
||
|
||
float total = used + avail;
|
||
if (total <= 0) return 0;
|
||
|
||
return (used / total) * 100f;
|
||
}
|
||
|
||
public void Dispose()
|
||
{
|
||
udp.Dispose();
|
||
computer.Close();
|
||
}
|
||
}
|