gpu sensors

#6-gpu-reporting
sleevezipper 4 years ago
parent 8a237de0a7
commit cfdf803a7b

@ -90,6 +90,14 @@ This sensor shows if the microphone is currently being used. It uses the Windows
This sensor checks the current CPU load. It averages the load on all logical cores every second and rounds the output to two decimals. This sensor checks the current CPU load. It averages the load on all logical cores every second and rounds the output to two decimals.
### GPULoad
This sensor returns the current GPU load. This should work for both NVidia and AMD GPU's.
### GPUTemperature
This sensor returns the current temperature of the GPU in °C. This should work for both NVidia and AMD GPU's.
### UsedMemory ### UsedMemory
This sensor calculates the percentage of used memory. This sensor calculates the percentage of used memory.

@ -163,6 +163,20 @@ namespace UserInterface.Views
item.ShowWindowNameInput = false; item.ShowWindowNameInput = false;
item.UpdateInterval = 5; item.UpdateInterval = 5;
break; break;
case AvailableSensors.GPUTemperatureSensor:
item.Description = "This sensor returns the current temperature of the GPU in °C.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#gputemperature";
item.ShowQueryInput = false;
item.ShowWindowNameInput = false;
item.UpdateInterval = 5;
break;
case AvailableSensors.GPULoadSensor:
item.Description = "This sensor returns the current GPU load.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#gpuload";
item.ShowQueryInput = false;
item.ShowWindowNameInput = false;
item.UpdateInterval = 5;
break;
default: default:
item.Description = null; item.Description = null;
item.MoreInfoLink = null; item.MoreInfoLink = null;

@ -50,12 +50,17 @@ namespace UserInterface.Views
sensorsNeedToRefresh = false; sensorsNeedToRefresh = false;
List<ConfiguredSensorModel> status = await this.client.InvokeAsync(x => x.GetConfiguredSensors()); List<ConfiguredSensorModel> status = await this.client.InvokeAsync(x => x.GetConfiguredSensors());
((SensorSettingsViewModel)this.DataContext).ConfiguredSensors = status.Select(s => new SensorViewModel() { Name = s.Name, Type = s.Type, Value = s.Value, Id = s.Id , UpdateInterval = s.UpdateInterval, UnitOfMeasurement = s.UnitOfMeasurement}).ToList(); ((SensorSettingsViewModel)this.DataContext).ConfiguredSensors = status.Select(s => new SensorViewModel() { Name = s.Name, Type = s.Type, Value = s.Value, Id = s.Id, UpdateInterval = s.UpdateInterval, UnitOfMeasurement = s.UnitOfMeasurement }).ToList();
while (!sensorsNeedToRefresh) while (!sensorsNeedToRefresh)
{ {
await Task.Delay(1000); await Task.Delay(1000);
List<ConfiguredSensorModel> statusUpdated = await this.client.InvokeAsync(x => x.GetConfiguredSensors()); List<ConfiguredSensorModel> statusUpdated = await this.client.InvokeAsync(x => x.GetConfiguredSensors());
var configuredSensors = ((SensorSettingsViewModel)this.DataContext).ConfiguredSensors; var configuredSensors = ((SensorSettingsViewModel)this.DataContext).ConfiguredSensors;
// this is a workaround for the list showing before it has been completely loaded in the service
if (statusUpdated.Count != configuredSensors.Count) {
sensorsNeedToRefresh = true;
GetConfiguredSensors();
}
statusUpdated.ForEach(s => statusUpdated.ForEach(s =>
{ {
var configuredSensor = configuredSensors.FirstOrDefault(cs => cs.Id == s.Id); var configuredSensor = configuredSensors.FirstOrDefault(cs => cs.Id == s.Id);

@ -73,9 +73,10 @@ namespace hass_workstation_service.Communication.InterProcesCommunication
return this._configurationService.IsAutoStartEnabled(); return this._configurationService.IsAutoStartEnabled();
} }
public List<ConfiguredSensorModel> GetConfiguredSensors() public async Task<List<ConfiguredSensorModel>> GetConfiguredSensors()
{ {
return this._configurationService.ConfiguredSensors.Select(s => new ConfiguredSensorModel() { Name = s.Name, Type = s.GetType().Name, Value = s.PreviousPublishedState, Id = s.Id, UpdateInterval = s.UpdateInterval, UnitOfMeasurement = ((SensorDiscoveryConfigModel)s.GetAutoDiscoveryConfig()).Unit_of_measurement }).ToList(); var sensors = await this._configurationService.GetSensorsAfterLoadingAsync();
return sensors.Select(s => new ConfiguredSensorModel() { Name = s.Name, Type = s.GetType().Name, Value = s.PreviousPublishedState, Id = s.Id, UpdateInterval = s.UpdateInterval, UnitOfMeasurement = ((SensorDiscoveryConfigModel)s.GetAutoDiscoveryConfig()).Unit_of_measurement }).ToList();
} }
public List<ConfiguredCommandModel> GetConfiguredCommands() public List<ConfiguredCommandModel> GetConfiguredCommands()
@ -150,6 +151,12 @@ namespace hass_workstation_service.Communication.InterProcesCommunication
case AvailableSensors.CurrentVolumeSensor: case AvailableSensors.CurrentVolumeSensor:
sensorToCreate = new CurrentVolumeSensor(this._publisher, (int)model.UpdateInterval, model.Name); sensorToCreate = new CurrentVolumeSensor(this._publisher, (int)model.UpdateInterval, model.Name);
break; break;
case AvailableSensors.GPUTemperatureSensor:
sensorToCreate = new GpuTemperatureSensor(this._publisher, (int)model.UpdateInterval, model.Name);
break;
case AvailableSensors.GPULoadSensor:
sensorToCreate = new GpuLoadSensor(this._publisher, (int)model.UpdateInterval, model.Name);
break;
default: default:
Log.Logger.Error("Unknown sensortype"); Log.Logger.Error("Unknown sensortype");
break; break;

@ -14,7 +14,7 @@ namespace hass_workstation_service.Communication.NamedPipe
MqqtClientStatus GetMqqtClientStatus(); MqqtClientStatus GetMqqtClientStatus();
void EnableAutostart(bool enable); void EnableAutostart(bool enable);
bool IsAutoStartEnabled(); bool IsAutoStartEnabled();
List<ConfiguredSensorModel> GetConfiguredSensors(); Task<List<ConfiguredSensorModel>> GetConfiguredSensors();
void RemoveSensorById(Guid id); void RemoveSensorById(Guid id);
void AddSensor(AvailableSensors sensorType, string json); void AddSensor(AvailableSensors sensorType, string json);
void RemoveCommandById(Guid id); void RemoveCommandById(Guid id);

@ -51,7 +51,9 @@ namespace hass_workstation_service.Communication.InterProcesCommunication.Models
LastActiveSensor, LastActiveSensor,
LastBootSensor, LastBootSensor,
SessionStateSensor, SessionStateSensor,
CurrentVolumeSensor CurrentVolumeSensor,
GPUTemperatureSensor,
GPULoadSensor
} }
public enum AvailableCommands public enum AvailableCommands

@ -32,6 +32,7 @@ namespace hass_workstation_service.Data
private bool BrokerSettingsFileLocked { get; set; } private bool BrokerSettingsFileLocked { get; set; }
private bool SensorsSettingsFileLocked { get; set; } private bool SensorsSettingsFileLocked { get; set; }
private bool CommandSettingsFileLocked { get; set; } private bool CommandSettingsFileLocked { get; set; }
private bool _sensorsLoading { get; set; }
private readonly string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Hass Workstation Service"); private readonly string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Hass Workstation Service");
@ -59,6 +60,7 @@ namespace hass_workstation_service.Data
public async void ReadSensorSettings(MqttPublisher publisher) public async void ReadSensorSettings(MqttPublisher publisher)
{ {
this._sensorsLoading = true;
while (this.SensorsSettingsFileLocked) while (this.SensorsSettingsFileLocked)
{ {
await Task.Delay(500); await Task.Delay(500);
@ -123,6 +125,12 @@ namespace hass_workstation_service.Data
case "CurrentVolumeSensor": case "CurrentVolumeSensor":
sensor = new CurrentVolumeSensor(publisher, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id); sensor = new CurrentVolumeSensor(publisher, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id);
break; break;
case "GpuTemperatureSensor":
sensor = new GpuTemperatureSensor(publisher, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id);
break;
case "GpuLoadSensor":
sensor = new GpuLoadSensor(publisher, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id);
break;
// keep this one last! // keep this one last!
case "WMIQuerySensor": case "WMIQuerySensor":
sensor = new WMIQuerySensor(publisher, configuredSensor.Query, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id); sensor = new WMIQuerySensor(publisher, configuredSensor.Query, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id);
@ -135,6 +143,7 @@ namespace hass_workstation_service.Data
{ {
this.ConfiguredSensors.Add(sensor); this.ConfiguredSensors.Add(sensor);
} }
this._sensorsLoading = false;
} }
} }
@ -474,5 +483,14 @@ namespace hass_workstation_service.Data
RegistryKey rkApp = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true); RegistryKey rkApp = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
return rkApp.GetValue("hass-workstation-service") != null; return rkApp.GetValue("hass-workstation-service") != null;
} }
public async Task<ICollection<AbstractSensor>> GetSensorsAfterLoadingAsync()
{
while (this._sensorsLoading)
{
await Task.Delay(500);
}
return this.ConfiguredSensors;
}
} }
} }

@ -31,5 +31,6 @@ namespace hass_workstation_service.Data
void DeleteConfiguredCommand(Guid id); void DeleteConfiguredCommand(Guid id);
void WriteCommandSettingsAsync(); void WriteCommandSettingsAsync();
void ReadCommandSettings(MqttPublisher publisher); void ReadCommandSettings(MqttPublisher publisher);
Task<ICollection<AbstractSensor>> GetSensorsAfterLoadingAsync();
} }
} }

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using hass_workstation_service.Communication;
using LibreHardwareMonitor.Hardware;
namespace hass_workstation_service.Domain.Sensors
{
public class GpuLoadSensor : AbstractSensor
{
private Computer _computer;
private IHardware _gpu;
public GpuLoadSensor(MqttPublisher publisher, int? updateInterval = null, string name = "GPULoad", Guid id = default(Guid)) : base(publisher, name ?? "GPULoad", updateInterval ?? 10, id)
{
_computer = new Computer
{
IsCpuEnabled = true,
IsGpuEnabled = true,
IsMemoryEnabled = true,
IsMotherboardEnabled = true,
IsControllerEnabled = true,
IsNetworkEnabled = true,
IsStorageEnabled = true
};
_computer.Open();
this._gpu = _computer.Hardware.FirstOrDefault(h => h.HardwareType == HardwareType.GpuAmd || h.HardwareType == HardwareType.GpuNvidia);
}
public override DiscoveryConfigModel GetAutoDiscoveryConfig()
{
return this._autoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel()
{
Name = this.Name,
Unique_id = this.Id.ToString(),
Device = this.Publisher.DeviceConfigModel,
State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/state",
Unit_of_measurement = "%",
Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability"
});
}
public override string GetState()
{
if (_gpu == null)
{
return "NotSupported";
}
_gpu.Update();
var sensor = _gpu.Sensors.FirstOrDefault(s => s.SensorType == SensorType.Load);
if (sensor == null)
{
return "NotSupported";
}
return sensor.Value.HasValue ? sensor.Value.Value.ToString("#.##", CultureInfo.InvariantCulture) : "Unknown";
}
}
}

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using hass_workstation_service.Communication;
using LibreHardwareMonitor.Hardware;
namespace hass_workstation_service.Domain.Sensors
{
public class GpuTemperatureSensor : AbstractSensor
{
private Computer _computer;
private IHardware _gpu;
public GpuTemperatureSensor(MqttPublisher publisher, int? updateInterval = null, string name = "GPUTemperature", Guid id = default(Guid)) : base(publisher, name ?? "GPUTemperature", updateInterval ?? 10, id)
{
_computer = new Computer
{
IsCpuEnabled = true,
IsGpuEnabled = true,
IsMemoryEnabled = true,
IsMotherboardEnabled = true,
IsControllerEnabled = true,
IsNetworkEnabled = true,
IsStorageEnabled = true
};
_computer.Open();
this._gpu = _computer.Hardware.FirstOrDefault(h => h.HardwareType == HardwareType.GpuAmd || h.HardwareType == HardwareType.GpuNvidia);
}
public override DiscoveryConfigModel GetAutoDiscoveryConfig()
{
return this._autoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel()
{
Name = this.Name,
Unique_id = this.Id.ToString(),
Device = this.Publisher.DeviceConfigModel,
State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/state",
Device_class = "temperature",
Unit_of_measurement = "°C",
Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability"
});
}
public override string GetState()
{
if (_gpu == null)
{
return "NotSupported";
}
_gpu.Update();
var sensor = _gpu.Sensors.FirstOrDefault(s => s.SensorType == SensorType.Temperature);
if (sensor == null)
{
return "NotSupported";
}
return sensor.Value.HasValue ? sensor.Value.Value.ToString("#.##", CultureInfo.InvariantCulture) : "Unknown";
}
}
}

@ -43,6 +43,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="JKang.IpcServiceFramework.Hosting.NamedPipe" Version="3.1.0" /> <PackageReference Include="JKang.IpcServiceFramework.Hosting.NamedPipe" Version="3.1.0" />
<PackageReference Include="LibreHardwareMonitorLib" Version="0.8.7" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" /> <PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="MQTTnet" Version="3.0.13" /> <PackageReference Include="MQTTnet" Version="3.0.13" />

Loading…
Cancel
Save