diff --git a/README.md b/README.md index d2a95dc..18577e5 100644 --- a/README.md +++ b/README.md @@ -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. +### 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 This sensor calculates the percentage of used memory. @@ -196,7 +204,7 @@ Sends a keystroke with the specified key. You can pick [any of these](https://do ### Media Commands -There's several media commands available which are very self exlanatory. +There's several media commands available which are very self exlanatory. - Play/Pause - Next @@ -211,4 +219,8 @@ This project depends on work done by others and they should at least get a menti ### [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. diff --git a/UserInterface/Views/AddSensorDialog.axaml.cs b/UserInterface/Views/AddSensorDialog.axaml.cs index 1f0f785..e51a34e 100644 --- a/UserInterface/Views/AddSensorDialog.axaml.cs +++ b/UserInterface/Views/AddSensorDialog.axaml.cs @@ -163,6 +163,20 @@ namespace UserInterface.Views item.ShowWindowNameInput = false; item.UpdateInterval = 5; 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: item.Description = null; item.MoreInfoLink = null; diff --git a/UserInterface/Views/SensorSettings.axaml.cs b/UserInterface/Views/SensorSettings.axaml.cs index 6619e06..532006c 100644 --- a/UserInterface/Views/SensorSettings.axaml.cs +++ b/UserInterface/Views/SensorSettings.axaml.cs @@ -50,12 +50,17 @@ namespace UserInterface.Views sensorsNeedToRefresh = false; List 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) { await Task.Delay(1000); List statusUpdated = await this.client.InvokeAsync(x => x.GetConfiguredSensors()); 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 => { var configuredSensor = configuredSensors.FirstOrDefault(cs => cs.Id == s.Id); diff --git a/hass-workstation-service/Communication/InterProcesCommunication/InterProcessApi.cs b/hass-workstation-service/Communication/InterProcesCommunication/InterProcessApi.cs index 25eff46..e78985b 100644 --- a/hass-workstation-service/Communication/InterProcesCommunication/InterProcessApi.cs +++ b/hass-workstation-service/Communication/InterProcesCommunication/InterProcessApi.cs @@ -73,9 +73,10 @@ namespace hass_workstation_service.Communication.InterProcesCommunication return this._configurationService.IsAutoStartEnabled(); } - public List GetConfiguredSensors() + public async Task> 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 GetConfiguredCommands() @@ -150,6 +151,12 @@ namespace hass_workstation_service.Communication.InterProcesCommunication case AvailableSensors.CurrentVolumeSensor: sensorToCreate = new CurrentVolumeSensor(this._publisher, (int)model.UpdateInterval, model.Name); 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: Log.Logger.Error("Unknown sensortype"); break; diff --git a/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractInterfaces.cs b/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractInterfaces.cs index 189bd5c..b7f9dc3 100644 --- a/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractInterfaces.cs +++ b/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractInterfaces.cs @@ -14,7 +14,7 @@ namespace hass_workstation_service.Communication.NamedPipe MqqtClientStatus GetMqqtClientStatus(); void EnableAutostart(bool enable); bool IsAutoStartEnabled(); - List GetConfiguredSensors(); + Task> GetConfiguredSensors(); void RemoveSensorById(Guid id); void AddSensor(AvailableSensors sensorType, string json); void RemoveCommandById(Guid id); diff --git a/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractModels.cs b/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractModels.cs index 768f5e8..1f87979 100644 --- a/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractModels.cs +++ b/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractModels.cs @@ -51,7 +51,9 @@ namespace hass_workstation_service.Communication.InterProcesCommunication.Models LastActiveSensor, LastBootSensor, SessionStateSensor, - CurrentVolumeSensor + CurrentVolumeSensor, + GPUTemperatureSensor, + GPULoadSensor } public enum AvailableCommands diff --git a/hass-workstation-service/Data/ConfigurationService.cs b/hass-workstation-service/Data/ConfigurationService.cs index e58d95e..db11c32 100644 --- a/hass-workstation-service/Data/ConfigurationService.cs +++ b/hass-workstation-service/Data/ConfigurationService.cs @@ -32,6 +32,7 @@ namespace hass_workstation_service.Data private bool BrokerSettingsFileLocked { get; set; } private bool SensorsSettingsFileLocked { 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"); @@ -59,6 +60,7 @@ namespace hass_workstation_service.Data public async void ReadSensorSettings(MqttPublisher publisher) { + this._sensorsLoading = true; while (this.SensorsSettingsFileLocked) { await Task.Delay(500); @@ -123,6 +125,12 @@ namespace hass_workstation_service.Data case "CurrentVolumeSensor": sensor = new CurrentVolumeSensor(publisher, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id); 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! case "WMIQuerySensor": 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._sensorsLoading = false; } } @@ -474,5 +483,14 @@ namespace hass_workstation_service.Data RegistryKey rkApp = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true); return rkApp.GetValue("hass-workstation-service") != null; } + + public async Task> GetSensorsAfterLoadingAsync() + { + while (this._sensorsLoading) + { + await Task.Delay(500); + } + return this.ConfiguredSensors; + } } } \ No newline at end of file diff --git a/hass-workstation-service/Data/IConfigurationService.cs b/hass-workstation-service/Data/IConfigurationService.cs index ba0d4d7..43d81dc 100644 --- a/hass-workstation-service/Data/IConfigurationService.cs +++ b/hass-workstation-service/Data/IConfigurationService.cs @@ -31,5 +31,6 @@ namespace hass_workstation_service.Data void DeleteConfiguredCommand(Guid id); void WriteCommandSettingsAsync(); void ReadCommandSettings(MqttPublisher publisher); + Task> GetSensorsAfterLoadingAsync(); } } \ No newline at end of file diff --git a/hass-workstation-service/Domain/Commands/CustomCommand.cs b/hass-workstation-service/Domain/Commands/CustomCommand.cs index 6a62b53..2cc1a9a 100644 --- a/hass-workstation-service/Domain/Commands/CustomCommand.cs +++ b/hass-workstation-service/Domain/Commands/CustomCommand.cs @@ -56,8 +56,8 @@ namespace hass_workstation_service.Domain.Commands Name = this.Name, Unique_id = this.Id.ToString(), Availability_topic = $"homeassistant/sensor/{Publisher.DeviceConfigModel.Name}/availability", - Command_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/set", - State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/state", + Command_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/set", + State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/state", Device = this.Publisher.DeviceConfigModel, }; } diff --git a/hass-workstation-service/Domain/Commands/KeyCommand.cs b/hass-workstation-service/Domain/Commands/KeyCommand.cs index 93c636d..bf66e9e 100644 --- a/hass-workstation-service/Domain/Commands/KeyCommand.cs +++ b/hass-workstation-service/Domain/Commands/KeyCommand.cs @@ -32,8 +32,8 @@ namespace hass_workstation_service.Domain.Commands Name = this.Name, Unique_id = this.Id.ToString(), Availability_topic = $"homeassistant/sensor/{Publisher.DeviceConfigModel.Name}/availability", - Command_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/set", - State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.Name}/state", + Command_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/set", + State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{this.ObjectId}/state", Device = this.Publisher.DeviceConfigModel, }; } diff --git a/hass-workstation-service/Domain/Sensors/ActiveWindowSensor.cs b/hass-workstation-service/Domain/Sensors/ActiveWindowSensor.cs index b9fb58b..2ab6f2c 100644 --- a/hass-workstation-service/Domain/Sensors/ActiveWindowSensor.cs +++ b/hass-workstation-service/Domain/Sensors/ActiveWindowSensor.cs @@ -16,7 +16,7 @@ namespace hass_workstation_service.Domain.Sensors Name = this.Name, Unique_id = this.Id.ToString(), 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", Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability" }); diff --git a/hass-workstation-service/Domain/Sensors/CPULoadSensor.cs b/hass-workstation-service/Domain/Sensors/CPULoadSensor.cs index d84fe1f..c5fcf7e 100644 --- a/hass-workstation-service/Domain/Sensors/CPULoadSensor.cs +++ b/hass-workstation-service/Domain/Sensors/CPULoadSensor.cs @@ -24,7 +24,7 @@ namespace hass_workstation_service.Domain.Sensors Name = this.Name, Unique_id = this.Id.ToString(), 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", Unit_of_measurement = "%", Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability" @@ -34,17 +34,20 @@ namespace hass_workstation_service.Domain.Sensors [SupportedOSPlatform("windows")] public override string GetState() { - ManagementObjectCollection collection = _searcher.Get(); - List processorLoadPercentages = new List(); - foreach (ManagementObject mo in collection) + using (ManagementObjectCollection collection = _searcher.Get()) { - foreach (PropertyData property in mo.Properties) + List processorLoadPercentages = new List(); + foreach (ManagementObject mo in collection) { - processorLoadPercentages.Add(int.Parse(property.Value.ToString())); + foreach (PropertyData property in mo.Properties) + { + processorLoadPercentages.Add(int.Parse(property.Value.ToString())); + } } + double average = processorLoadPercentages.Count > 0 ? processorLoadPercentages.Average() : 0.0; + return average.ToString("#.##", CultureInfo.InvariantCulture); } - double average = processorLoadPercentages.Count > 0 ? processorLoadPercentages.Average() : 0.0; - return average.ToString("#.##", CultureInfo.InvariantCulture); + } } } diff --git a/hass-workstation-service/Domain/Sensors/CurrentClockSpeedSensor.cs b/hass-workstation-service/Domain/Sensors/CurrentClockSpeedSensor.cs index 523fe30..56754cc 100644 --- a/hass-workstation-service/Domain/Sensors/CurrentClockSpeedSensor.cs +++ b/hass-workstation-service/Domain/Sensors/CurrentClockSpeedSensor.cs @@ -16,7 +16,7 @@ namespace hass_workstation_service.Domain.Sensors Name = this.Name, Unique_id = this.Id.ToString(), 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", Unit_of_measurement = "MHz", Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability" diff --git a/hass-workstation-service/Domain/Sensors/CurrentVolumeSensor.cs b/hass-workstation-service/Domain/Sensors/CurrentVolumeSensor.cs index aa5d33d..6a46bde 100644 --- a/hass-workstation-service/Domain/Sensors/CurrentVolumeSensor.cs +++ b/hass-workstation-service/Domain/Sensors/CurrentVolumeSensor.cs @@ -12,9 +12,11 @@ namespace hass_workstation_service.Domain.Sensors { 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) { - this.DevEnum = new MMDeviceEnumerator(); + this.deviceEnumerator = new MMDeviceEnumerator(); + this.devices = deviceEnumerator.EnumerateAudioEndPoints(EDataFlow.eRender, DEVICE_STATE.DEVICE_STATE_ACTIVE); } public override SensorDiscoveryConfigModel GetAutoDiscoveryConfig() { @@ -23,24 +25,18 @@ namespace hass_workstation_service.Domain.Sensors Name = this.Name, Unique_id = this.Id.ToString(), 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", Unit_of_measurement = "%", 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() { - var collection = DevEnum.EnumerateAudioEndPoints(EDataFlow.eRender, DEVICE_STATE.DEVICE_STATE_ACTIVE); - List peaks = new List(); - - foreach (MMDevice device in collection) + foreach (MMDevice device in devices) { peaks.Add(device.AudioMeterInformation.PeakValues[0]); } diff --git a/hass-workstation-service/Domain/Sensors/GpuLoadSensor.cs b/hass-workstation-service/Domain/Sensors/GpuLoadSensor.cs new file mode 100644 index 0000000..5120b6f --- /dev/null +++ b/hass-workstation-service/Domain/Sensors/GpuLoadSensor.cs @@ -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"; + } + } +} diff --git a/hass-workstation-service/Domain/Sensors/GpuTemperatureSensor.cs b/hass-workstation-service/Domain/Sensors/GpuTemperatureSensor.cs new file mode 100644 index 0000000..44c157c --- /dev/null +++ b/hass-workstation-service/Domain/Sensors/GpuTemperatureSensor.cs @@ -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"; + } + } +} diff --git a/hass-workstation-service/Domain/Sensors/LastActiveSensor.cs b/hass-workstation-service/Domain/Sensors/LastActiveSensor.cs index ac1acdf..a6555a7 100644 --- a/hass-workstation-service/Domain/Sensors/LastActiveSensor.cs +++ b/hass-workstation-service/Domain/Sensors/LastActiveSensor.cs @@ -16,7 +16,7 @@ namespace hass_workstation_service.Domain.Sensors Name = this.Name, Unique_id = this.Id.ToString(), 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", Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability", Device_class = "timestamp" diff --git a/hass-workstation-service/Domain/Sensors/LastBootSensor.cs b/hass-workstation-service/Domain/Sensors/LastBootSensor.cs index 464fdd4..7d2230a 100644 --- a/hass-workstation-service/Domain/Sensors/LastBootSensor.cs +++ b/hass-workstation-service/Domain/Sensors/LastBootSensor.cs @@ -20,7 +20,7 @@ namespace hass_workstation_service.Domain.Sensors Name = this.Name, Unique_id = this.Id.ToString(), 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", Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability", Device_class = "timestamp" diff --git a/hass-workstation-service/Domain/Sensors/MemoryUsageSensor.cs b/hass-workstation-service/Domain/Sensors/MemoryUsageSensor.cs index 6893d0a..9b666ed 100644 --- a/hass-workstation-service/Domain/Sensors/MemoryUsageSensor.cs +++ b/hass-workstation-service/Domain/Sensors/MemoryUsageSensor.cs @@ -17,22 +17,25 @@ namespace hass_workstation_service.Domain.Sensors } public override string GetState() { - ManagementObjectCollection collection = _searcher.Get(); - UInt64? totalMemory = null; - UInt64? freeMemory = null; - foreach (ManagementObject mo in collection) + using (ManagementObjectCollection collection = _searcher.Get()) { - totalMemory = (UInt64)mo.Properties["TotalVisibleMemorySize"]?.Value; - freeMemory = (UInt64)mo.Properties["FreePhysicalMemory"]?.Value; + UInt64? totalMemory = null; + UInt64? freeMemory = null; + foreach (ManagementObject mo in collection) + { + totalMemory = (UInt64)mo.Properties["TotalVisibleMemorySize"]?.Value; + freeMemory = (UInt64)mo.Properties["FreePhysicalMemory"]?.Value; + } + if (totalMemory != null && freeMemory != null) + { + decimal totalMemoryDec = totalMemory.Value; + decimal freeMemoryDec = freeMemory.Value; + decimal precentageUsed = 100 - (freeMemoryDec / totalMemoryDec) * 100; + return precentageUsed.ToString("#.##", CultureInfo.InvariantCulture); + } + return ""; } - if (totalMemory != null && freeMemory != null) - { - decimal totalMemoryDec = totalMemory.Value; - decimal freeMemoryDec = freeMemory.Value; - decimal precentageUsed = 100 - (freeMemoryDec / totalMemoryDec) * 100; - return precentageUsed.ToString("#.##", CultureInfo.InvariantCulture); - } - return ""; + } public override SensorDiscoveryConfigModel GetAutoDiscoveryConfig() { @@ -41,7 +44,7 @@ namespace hass_workstation_service.Domain.Sensors Name = this.Name, Unique_id = this.Id.ToString(), 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", Unit_of_measurement = "%", Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability" diff --git a/hass-workstation-service/Domain/Sensors/MicrophoneActiveSensor.cs b/hass-workstation-service/Domain/Sensors/MicrophoneActiveSensor.cs index 1a79238..1b46811 100644 --- a/hass-workstation-service/Domain/Sensors/MicrophoneActiveSensor.cs +++ b/hass-workstation-service/Domain/Sensors/MicrophoneActiveSensor.cs @@ -29,7 +29,7 @@ namespace hass_workstation_service.Domain.Sensors Name = this.Name, Unique_id = this.Id.ToString(), 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" }); } diff --git a/hass-workstation-service/Domain/Sensors/NamedWindowSensor.cs b/hass-workstation-service/Domain/Sensors/NamedWindowSensor.cs index 4577584..095b5bd 100644 --- a/hass-workstation-service/Domain/Sensors/NamedWindowSensor.cs +++ b/hass-workstation-service/Domain/Sensors/NamedWindowSensor.cs @@ -24,7 +24,7 @@ namespace hass_workstation_service.Domain.Sensors Name = this.Name, Unique_id = this.Id.ToString(), 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" }); } diff --git a/hass-workstation-service/Domain/Sensors/SessionStateSensor.cs b/hass-workstation-service/Domain/Sensors/SessionStateSensor.cs index 882cbd7..650de5f 100644 --- a/hass-workstation-service/Domain/Sensors/SessionStateSensor.cs +++ b/hass-workstation-service/Domain/Sensors/SessionStateSensor.cs @@ -44,7 +44,7 @@ namespace hass_workstation_service.Domain.Sensors Name = this.Name, Unique_id = this.Id.ToString(), 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", Availability_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/availability" }); @@ -73,25 +73,34 @@ namespace hass_workstation_service.Domain.Sensors .Select(p => p.Id.ToString()) .ToHashSet(); var REprocessid = new Regex(@"(?<=Handle="").*?(?="")", RegexOptions.Compiled); - - var numberOfLogonSessionsWithExplorer = new ManagementObjectSearcher(scope, new SelectQuery("SELECT * FROM Win32_SessionProcess")).Get() - .Cast() - .Where(mo => explorerProcesses.Contains(REprocessid.Match(mo["Dependent"].ToString()).Value)) - .Select(mo => mo["Antecedent"].ToString()) - .Distinct() - .Count(); + int numberOfLogonSessionsWithExplorer = 1; + using (var managemntObjectSearcher = new ManagementObjectSearcher(scope, new SelectQuery("SELECT * FROM Win32_SessionProcess"))) + { + numberOfLogonSessionsWithExplorer = managemntObjectSearcher.Get() + .Cast() + .Where(mo => explorerProcesses.Contains(REprocessid.Match(mo["Dependent"].ToString()).Value)) + .Select(mo => mo["Antecedent"].ToString()) + .Distinct() + .Count(); + } int numberOfUserDesktops = 1; // this can fail sometimes, that's why we set numberOfUserDesktops to 1 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 { - + } + + var numberOflogonUIProcesses = Process.GetProcessesByName("LogonUI").Length; if (numberOflogonUIProcesses >= numberOfUserDesktops) @@ -102,7 +111,9 @@ namespace hass_workstation_service.Domain.Sensors return PCUserStatuses.LoggedOff; } else + { return PCUserStatuses.InUse; + } } catch (Exception e) { diff --git a/hass-workstation-service/Domain/Sensors/WMIQuerySensor.cs b/hass-workstation-service/Domain/Sensors/WMIQuerySensor.cs index 6304389..d2601b6 100644 --- a/hass-workstation-service/Domain/Sensors/WMIQuerySensor.cs +++ b/hass-workstation-service/Domain/Sensors/WMIQuerySensor.cs @@ -34,16 +34,17 @@ namespace hass_workstation_service.Domain.Sensors public override string GetState() { - ManagementObjectCollection collection = _searcher.Get(); - - foreach (ManagementObject mo in collection) + using (ManagementObjectCollection collection = _searcher.Get()) { - foreach (PropertyData property in mo.Properties) + foreach (ManagementObject mo in collection) { - return property.Value.ToString(); + foreach (PropertyData property in mo.Properties) + { + return property.Value.ToString(); + } } + return ""; } - return ""; } } diff --git a/hass-workstation-service/hass-workstation-service.csproj b/hass-workstation-service/hass-workstation-service.csproj index 675b076..3dc5f99 100644 --- a/hass-workstation-service/hass-workstation-service.csproj +++ b/hass-workstation-service/hass-workstation-service.csproj @@ -43,6 +43,7 @@ +