Merge branch '#6-gpu-reporting' into develop

pull/56/head
sleevezipper 4 years ago
commit bbf23a04c6

@ -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.
@ -212,3 +220,7 @@ This project depends on work done by others and they should at least get a menti
### [CoreAudio](https://github.com/morphx666/CoreAudio) ### [CoreAudio](https://github.com/morphx666/CoreAudio)
CoreAudio was used to check the current volume of playing audio. CoreAudio was used to check the current volume of playing audio.
### [LibreHardwareMonitor](https://github.com/LibreHardwareMonitor/LibreHardwareMonitor)
We use this for our GPU sensors.

@ -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();
} }
} }

@ -56,8 +56,8 @@ namespace hass_workstation_service.Domain.Commands
Name = this.Name, Name = this.Name,
Unique_id = this.Id.ToString(), Unique_id = this.Id.ToString(),
Availability_topic = $"homeassistant/sensor/{Publisher.DeviceConfigModel.Name}/availability", Availability_topic = $"homeassistant/sensor/{Publisher.DeviceConfigModel.Name}/availability",
Command_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/set", Command_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/set",
State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/state", State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/state",
Device = this.Publisher.DeviceConfigModel, Device = this.Publisher.DeviceConfigModel,
}; };
} }

@ -32,8 +32,8 @@ namespace hass_workstation_service.Domain.Commands
Name = this.Name, Name = this.Name,
Unique_id = this.Id.ToString(), Unique_id = this.Id.ToString(),
Availability_topic = $"homeassistant/sensor/{Publisher.DeviceConfigModel.Name}/availability", Availability_topic = $"homeassistant/sensor/{Publisher.DeviceConfigModel.Name}/availability",
Command_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/set", Command_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/set",
State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/state", State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/state",
Device = this.Publisher.DeviceConfigModel, Device = this.Publisher.DeviceConfigModel,
}; };
} }

@ -16,7 +16,7 @@ namespace hass_workstation_service.Domain.Sensors
Name = this.Name, Name = this.Name,
Unique_id = this.Id.ToString(), Unique_id = this.Id.ToString(),
Device = this.Publisher.DeviceConfigModel, Device = this.Publisher.DeviceConfigModel,
State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/state", State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/state",
Icon = "mdi:window-maximize", Icon = "mdi:window-maximize",
Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability" Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability"
}); });

@ -24,7 +24,7 @@ namespace hass_workstation_service.Domain.Sensors
Name = this.Name, Name = this.Name,
Unique_id = this.Id.ToString(), Unique_id = this.Id.ToString(),
Device = this.Publisher.DeviceConfigModel, Device = this.Publisher.DeviceConfigModel,
State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/state", State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/state",
Icon = "mdi:chart-areaspline", Icon = "mdi:chart-areaspline",
Unit_of_measurement = "%", Unit_of_measurement = "%",
Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability" Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability"
@ -34,7 +34,8 @@ namespace hass_workstation_service.Domain.Sensors
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
public override string GetState() public override string GetState()
{ {
ManagementObjectCollection collection = _searcher.Get(); using (ManagementObjectCollection collection = _searcher.Get())
{
List<int> processorLoadPercentages = new List<int>(); List<int> processorLoadPercentages = new List<int>();
foreach (ManagementObject mo in collection) foreach (ManagementObject mo in collection)
{ {
@ -46,5 +47,7 @@ namespace hass_workstation_service.Domain.Sensors
double average = processorLoadPercentages.Count > 0 ? processorLoadPercentages.Average() : 0.0; double average = processorLoadPercentages.Count > 0 ? processorLoadPercentages.Average() : 0.0;
return average.ToString("#.##", CultureInfo.InvariantCulture); return average.ToString("#.##", CultureInfo.InvariantCulture);
} }
}
} }
} }

@ -16,7 +16,7 @@ namespace hass_workstation_service.Domain.Sensors
Name = this.Name, Name = this.Name,
Unique_id = this.Id.ToString(), Unique_id = this.Id.ToString(),
Device = this.Publisher.DeviceConfigModel, Device = this.Publisher.DeviceConfigModel,
State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/state", State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/state",
Icon = "mdi:speedometer", Icon = "mdi:speedometer",
Unit_of_measurement = "MHz", Unit_of_measurement = "MHz",
Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability" Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability"

@ -12,9 +12,11 @@ namespace hass_workstation_service.Domain.Sensors
{ {
public class CurrentVolumeSensor : AbstractSensor public class CurrentVolumeSensor : AbstractSensor
{ {
private MMDeviceEnumerator DevEnum; private MMDeviceEnumerator deviceEnumerator;
private MMDeviceCollection devices;
public CurrentVolumeSensor(MqttPublisher publisher, int? updateInterval = null, string name = "CurrentVolume", Guid id = default(Guid)) : base(publisher, name ?? "CurrentVolume", updateInterval ?? 10, id) { public CurrentVolumeSensor(MqttPublisher publisher, int? updateInterval = null, string name = "CurrentVolume", Guid id = default(Guid)) : base(publisher, name ?? "CurrentVolume", updateInterval ?? 10, id) {
this.DevEnum = new MMDeviceEnumerator(); this.deviceEnumerator = new MMDeviceEnumerator();
this.devices = deviceEnumerator.EnumerateAudioEndPoints(EDataFlow.eRender, DEVICE_STATE.DEVICE_STATE_ACTIVE);
} }
public override SensorDiscoveryConfigModel GetAutoDiscoveryConfig() public override SensorDiscoveryConfigModel GetAutoDiscoveryConfig()
{ {
@ -23,24 +25,18 @@ namespace hass_workstation_service.Domain.Sensors
Name = this.Name, Name = this.Name,
Unique_id = this.Id.ToString(), Unique_id = this.Id.ToString(),
Device = this.Publisher.DeviceConfigModel, Device = this.Publisher.DeviceConfigModel,
State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/state", State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/state",
Icon = "mdi:volume-medium", Icon = "mdi:volume-medium",
Unit_of_measurement = "%", Unit_of_measurement = "%",
Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability" Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability"
}); });
} }
[DllImport("winmm.dll")]
public static extern int waveOutGetVolume(IntPtr hwo, out uint dwVolume);
public override string GetState() public override string GetState()
{ {
var collection = DevEnum.EnumerateAudioEndPoints(EDataFlow.eRender, DEVICE_STATE.DEVICE_STATE_ACTIVE);
List<float> peaks = new List<float>(); List<float> peaks = new List<float>();
foreach (MMDevice device in devices)
foreach (MMDevice device in collection)
{ {
peaks.Add(device.AudioMeterInformation.PeakValues[0]); peaks.Add(device.AudioMeterInformation.PeakValues[0]);
} }

@ -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.ObjectId}/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.ObjectId}/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";
}
}
}

@ -16,7 +16,7 @@ namespace hass_workstation_service.Domain.Sensors
Name = this.Name, Name = this.Name,
Unique_id = this.Id.ToString(), Unique_id = this.Id.ToString(),
Device = this.Publisher.DeviceConfigModel, Device = this.Publisher.DeviceConfigModel,
State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/state", State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/state",
Icon = "mdi:clock-time-three-outline", Icon = "mdi:clock-time-three-outline",
Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability", Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability",
Device_class = "timestamp" Device_class = "timestamp"

@ -20,7 +20,7 @@ namespace hass_workstation_service.Domain.Sensors
Name = this.Name, Name = this.Name,
Unique_id = this.Id.ToString(), Unique_id = this.Id.ToString(),
Device = this.Publisher.DeviceConfigModel, Device = this.Publisher.DeviceConfigModel,
State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/state", State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/state",
Icon = "mdi:clock-time-three-outline", Icon = "mdi:clock-time-three-outline",
Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability", Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability",
Device_class = "timestamp" Device_class = "timestamp"

@ -17,7 +17,8 @@ namespace hass_workstation_service.Domain.Sensors
} }
public override string GetState() public override string GetState()
{ {
ManagementObjectCollection collection = _searcher.Get(); using (ManagementObjectCollection collection = _searcher.Get())
{
UInt64? totalMemory = null; UInt64? totalMemory = null;
UInt64? freeMemory = null; UInt64? freeMemory = null;
foreach (ManagementObject mo in collection) foreach (ManagementObject mo in collection)
@ -34,6 +35,8 @@ namespace hass_workstation_service.Domain.Sensors
} }
return ""; return "";
} }
}
public override SensorDiscoveryConfigModel GetAutoDiscoveryConfig() public override SensorDiscoveryConfigModel GetAutoDiscoveryConfig()
{ {
return this._autoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel() return this._autoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel()
@ -41,7 +44,7 @@ namespace hass_workstation_service.Domain.Sensors
Name = this.Name, Name = this.Name,
Unique_id = this.Id.ToString(), Unique_id = this.Id.ToString(),
Device = this.Publisher.DeviceConfigModel, Device = this.Publisher.DeviceConfigModel,
State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/state", State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/state",
Icon = "mdi:memory", Icon = "mdi:memory",
Unit_of_measurement = "%", Unit_of_measurement = "%",
Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability" Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability"

@ -29,7 +29,7 @@ namespace hass_workstation_service.Domain.Sensors
Name = this.Name, Name = this.Name,
Unique_id = this.Id.ToString(), Unique_id = this.Id.ToString(),
Device = this.Publisher.DeviceConfigModel, Device = this.Publisher.DeviceConfigModel,
State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/state", State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/state",
Availability_topic = $"homeassistant/sensor/{Publisher.DeviceConfigModel.Name}/availability" Availability_topic = $"homeassistant/sensor/{Publisher.DeviceConfigModel.Name}/availability"
}); });
} }

@ -24,7 +24,7 @@ namespace hass_workstation_service.Domain.Sensors
Name = this.Name, Name = this.Name,
Unique_id = this.Id.ToString(), Unique_id = this.Id.ToString(),
Device = this.Publisher.DeviceConfigModel, Device = this.Publisher.DeviceConfigModel,
State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/state", State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/state",
Availability_topic = $"homeassistant/sensor/{Publisher.DeviceConfigModel.Name}/availability" Availability_topic = $"homeassistant/sensor/{Publisher.DeviceConfigModel.Name}/availability"
}); });
} }

@ -44,7 +44,7 @@ namespace hass_workstation_service.Domain.Sensors
Name = this.Name, Name = this.Name,
Unique_id = this.Id.ToString(), Unique_id = this.Id.ToString(),
Device = this.Publisher.DeviceConfigModel, Device = this.Publisher.DeviceConfigModel,
State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/state", State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/state",
Icon = "mdi:lock", Icon = "mdi:lock",
Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability" Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability"
}); });
@ -73,25 +73,34 @@ namespace hass_workstation_service.Domain.Sensors
.Select(p => p.Id.ToString()) .Select(p => p.Id.ToString())
.ToHashSet(); .ToHashSet();
var REprocessid = new Regex(@"(?<=Handle="").*?(?="")", RegexOptions.Compiled); var REprocessid = new Regex(@"(?<=Handle="").*?(?="")", RegexOptions.Compiled);
int numberOfLogonSessionsWithExplorer = 1;
var numberOfLogonSessionsWithExplorer = new ManagementObjectSearcher(scope, new SelectQuery("SELECT * FROM Win32_SessionProcess")).Get() using (var managemntObjectSearcher = new ManagementObjectSearcher(scope, new SelectQuery("SELECT * FROM Win32_SessionProcess")))
{
numberOfLogonSessionsWithExplorer = managemntObjectSearcher.Get()
.Cast<ManagementObject>() .Cast<ManagementObject>()
.Where(mo => explorerProcesses.Contains(REprocessid.Match(mo["Dependent"].ToString()).Value)) .Where(mo => explorerProcesses.Contains(REprocessid.Match(mo["Dependent"].ToString()).Value))
.Select(mo => mo["Antecedent"].ToString()) .Select(mo => mo["Antecedent"].ToString())
.Distinct() .Distinct()
.Count(); .Count();
}
int numberOfUserDesktops = 1; int numberOfUserDesktops = 1;
// this can fail sometimes, that's why we set numberOfUserDesktops to 1 // this can fail sometimes, that's why we set numberOfUserDesktops to 1
try try
{ {
numberOfUserDesktops = new ManagementObjectSearcher(scope, new SelectQuery("select * from win32_Perfrawdata_TermService_TerminalServicesSession")).Get().Count - 1; // don't count Service desktop using (var managementObjectSearcher = new ManagementObjectSearcher(scope, new SelectQuery("select * from win32_Perfrawdata_TermService_TerminalServicesSession")))
{
numberOfUserDesktops = managementObjectSearcher.Get().Count - 1; // don't count Service desktop
}
} }
catch catch
{ {
} }
var numberOflogonUIProcesses = Process.GetProcessesByName("LogonUI").Length; var numberOflogonUIProcesses = Process.GetProcessesByName("LogonUI").Length;
if (numberOflogonUIProcesses >= numberOfUserDesktops) if (numberOflogonUIProcesses >= numberOfUserDesktops)
@ -102,8 +111,10 @@ namespace hass_workstation_service.Domain.Sensors
return PCUserStatuses.LoggedOff; return PCUserStatuses.LoggedOff;
} }
else else
{
return PCUserStatuses.InUse; return PCUserStatuses.InUse;
} }
}
catch (Exception e) catch (Exception e)
{ {
Log.Logger.Error(e, "Exception in SessionStateSensor"); Log.Logger.Error(e, "Exception in SessionStateSensor");

@ -34,8 +34,8 @@ namespace hass_workstation_service.Domain.Sensors
public override string GetState() public override string GetState()
{ {
ManagementObjectCollection collection = _searcher.Get(); using (ManagementObjectCollection collection = _searcher.Get())
{
foreach (ManagementObject mo in collection) foreach (ManagementObject mo in collection)
{ {
foreach (PropertyData property in mo.Properties) foreach (PropertyData property in mo.Properties)
@ -45,6 +45,7 @@ namespace hass_workstation_service.Domain.Sensors
} }
return ""; return "";
} }
}
} }
} }

@ -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