diff --git a/UserInterface/Views/AddSensorDialog.axaml.cs b/UserInterface/Views/AddSensorDialog.axaml.cs
index 9ab9bde..b75f2aa 100644
--- a/UserInterface/Views/AddSensorDialog.axaml.cs
+++ b/UserInterface/Views/AddSensorDialog.axaml.cs
@@ -102,7 +102,7 @@ namespace UserInterface.Views
item.ShowWindowNameInput = false;
item.UpdateInterval = 5;
break;
-
+
case AvailableSensors.DummySensor:
item.Description = "This sensor spits out a random number every second. Useful for testing, maybe you'll find some other use for it.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#dummysensor";
@@ -110,7 +110,7 @@ namespace UserInterface.Views
item.ShowWindowNameInput = false;
item.UpdateInterval = 1;
break;
-
+
case AvailableSensors.CPULoadSensor:
item.Description = "This sensor checks the current CPU load. It averages the load on all logical cores every second and rounds the output to two decimals.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#cpuloadsensor";
@@ -118,7 +118,7 @@ namespace UserInterface.Views
item.ShowWindowNameInput = false;
item.UpdateInterval = 5;
break;
-
+
case AvailableSensors.CurrentClockSpeedSensor:
item.Description = "This sensor returns the BIOS configured baseclock for the processor.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#currentclockspeedsensor";
@@ -126,7 +126,7 @@ namespace UserInterface.Views
item.ShowWindowNameInput = false;
item.UpdateInterval = 3600;
break;
-
+
case AvailableSensors.WMIQuerySensor:
item.Description = "This advanced sensor executes a user defined WMI query and exposes the result. The query should return a single value.";
item.MoreInfoLink = "https://github.com/sleevezipperhass-workstation-service/blob/master/documentation/WMIQuery.md#wmiquerysensor";
@@ -134,7 +134,7 @@ namespace UserInterface.Views
item.ShowWindowNameInput = false;
item.UpdateInterval = 10;
break;
-
+
case AvailableSensors.MemoryUsageSensor:
item.Description = "This sensor calculates the percentage of used memory.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#memoryusagesensorsensor";
@@ -142,7 +142,7 @@ namespace UserInterface.Views
item.ShowWindowNameInput = false;
item.UpdateInterval = 10;
break;
-
+
case AvailableSensors.ActiveWindowSensor:
item.Description = "This sensor exposes the name of the currently active window.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#activewindowsensor";
@@ -150,28 +150,35 @@ namespace UserInterface.Views
item.ShowWindowNameInput = false;
item.UpdateInterval = 5;
break;
-
+
case AvailableSensors.WebcamActiveSensor:
item.Description = "This sensor shows if the webcam is currently being used.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#webcamactivesensor";
item.ShowQueryInput = false;
item.UpdateInterval = 10;
break;
-
+
case AvailableSensors.WebcamProcessSensor:
item.Description = "This sensor shows which process is using the webcam.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#webcamprocesssensor";
item.ShowQueryInput = false;
item.UpdateInterval = 10;
break;
-
+
case AvailableSensors.MicrophoneActiveSensor:
item.Description = "This sensor shows if the microphone is currently in use.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#microphoneactivesensor";
item.ShowQueryInput = false;
item.UpdateInterval = 10;
break;
-
+
+ case AvailableSensors.MicrophoneProcessSensor:
+ item.Description = "This sensor shows which process is using the microphone.";
+ item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#microphoneprocesssensor";
+ item.ShowQueryInput = false;
+ item.UpdateInterval = 10;
+ break;
+
case AvailableSensors.NamedWindowSensor:
item.Description = "This sensor returns true if a window was found with the name you search for. ";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#namedwindowsensor";
@@ -179,7 +186,7 @@ namespace UserInterface.Views
item.ShowWindowNameInput = true;
item.UpdateInterval = 5;
break;
-
+
case AvailableSensors.LastActiveSensor:
item.Description = "This sensor returns the date/time that the workstation was last active.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#lastactivesensor";
@@ -187,7 +194,7 @@ namespace UserInterface.Views
item.ShowWindowNameInput = false;
item.UpdateInterval = 5;
break;
-
+
case AvailableSensors.LastBootSensor:
item.Description = "This sensor returns the date/time that Windows was last booted";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#lastbootsensor";
@@ -195,7 +202,7 @@ namespace UserInterface.Views
item.ShowWindowNameInput = false;
item.UpdateInterval = 5;
break;
-
+
case AvailableSensors.SessionStateSensor:
item.Description = "This sensor returns the state of the Windows session.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#sessionstatesensor";
@@ -203,7 +210,7 @@ namespace UserInterface.Views
item.ShowWindowNameInput = false;
item.UpdateInterval = 5;
break;
-
+
case AvailableSensors.CurrentVolumeSensor:
item.Description = "This sensor returns the volume of currently playing audio.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#currentvolumesensor";
@@ -211,7 +218,7 @@ namespace UserInterface.Views
item.ShowWindowNameInput = false;
item.UpdateInterval = 5;
break;
-
+
case AvailableSensors.MasterVolumeSensor:
item.Description = "This sensor returns the master volume of the currently selected default audio device as a percentage value.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/Sensors.md#mastervolumesensor";
@@ -219,7 +226,7 @@ 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/blob/master/documentation/Sensors.md#gputemperaturesensor";
@@ -227,7 +234,7 @@ namespace UserInterface.Views
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/blob/master/documentation/Sensors.md#gpuloadsensor";
@@ -235,7 +242,7 @@ namespace UserInterface.Views
item.ShowWindowNameInput = false;
item.UpdateInterval = 5;
break;
-
+
default:
item.Description = null;
item.MoreInfoLink = null;
diff --git a/documentation/Sensors.md b/documentation/Sensors.md
index 2938c7d..6d35695 100644
--- a/documentation/Sensors.md
+++ b/documentation/Sensors.md
@@ -24,7 +24,7 @@ This sensor returns the current volume of playing audio. **It does not return th
This sensor returns the master volume for the currently selected default audio device.
-### DummySensor
+### DummySensor
This sensor produces a random output every second, and is intended to test latency and connectivity.
@@ -89,6 +89,10 @@ The webcam active sensor returns the status of the webcam.
The webcam process sensor returns the process which is using the webcam.
+### MicrophoneProcessSensor
+
+The microphone process sensor returns the process which is using the microphone.
+
### WMIQuerySensor
Please see the specific documentaion page [here](https://github.com/sleevezipper/hass-workstation-service/blob/master/documentation/WMIQuery.md#wmiquerysensor).
diff --git a/hass-workstation-service/Communication/InterProcesCommunication/InterProcessApi.cs b/hass-workstation-service/Communication/InterProcesCommunication/InterProcessApi.cs
index 9c9824e..bf4b3a4 100644
--- a/hass-workstation-service/Communication/InterProcesCommunication/InterProcessApi.cs
+++ b/hass-workstation-service/Communication/InterProcesCommunication/InterProcessApi.cs
@@ -30,7 +30,7 @@ namespace hass_workstation_service.Communication.InterProcesCommunication
///
/// You can use this to check if the application responds.
- ///
+ ///
///
///
public string Ping(string str) => str == "ping" ? "pong" : "what?";
@@ -44,7 +44,7 @@ namespace hass_workstation_service.Communication.InterProcesCommunication
public void WriteMqttBrokerSettingsAsync(MqttSettings settings) => _configurationService.WriteMqttBrokerSettingsAsync(settings);
///
- /// Enables or disables autostart.
+ /// Enables or disables autostart.
///
///
public void EnableAutostart(bool enable) => _configurationService.EnableAutoStart(enable);
@@ -108,7 +108,7 @@ namespace hass_workstation_service.Communication.InterProcesCommunication
public void RemoveCommandById(Guid id) => _configurationService.DeleteConfiguredCommand(id);
///
- /// Adds a command to the configured commands. This properly initializes the class and writes it to the config file.
+ /// Adds a command to the configured commands. This properly initializes the class and writes it to the config file.
///
///
///
@@ -123,7 +123,7 @@ namespace hass_workstation_service.Communication.InterProcesCommunication
}
///
- /// Adds a command to the configured commands. This properly initializes the class, subscribes to the command topic and writes it to the config file.
+ /// Adds a command to the configured commands. This properly initializes the class, subscribes to the command topic and writes it to the config file.
///
///
///
@@ -179,6 +179,7 @@ namespace hass_workstation_service.Communication.InterProcesCommunication
AvailableSensors.WebcamActiveSensor => new WebcamActiveSensor(_publisher, (int)model.UpdateInterval, model.Name),
AvailableSensors.WebcamProcessSensor => new WebcamProcessSensor(_publisher, (int)model.UpdateInterval, model.Name),
AvailableSensors.MicrophoneActiveSensor => new MicrophoneActiveSensor(_publisher, (int)model.UpdateInterval, model.Name),
+ AvailableSensors.MicrophoneProcessSensor => new MicrophoneProcessSensor(_publisher, (int)model.UpdateInterval, model.Name),
AvailableSensors.NamedWindowSensor => new NamedWindowSensor(_publisher, model.WindowName, model.Name, (int)model.UpdateInterval),
AvailableSensors.LastActiveSensor => new LastActiveSensor(_publisher, (int)model.UpdateInterval, model.Name),
AvailableSensors.LastBootSensor => new LastBootSensor(_publisher, (int)model.UpdateInterval, model.Name),
diff --git a/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractModels.cs b/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractModels.cs
index fafa58d..86f7065 100644
--- a/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractModels.cs
+++ b/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractModels.cs
@@ -45,7 +45,7 @@ namespace hass_workstation_service.Communication.InterProcesCommunication.Models
{
this.WindowName = namedWindowSensor.WindowName;
}
- this.UpdateInterval = sensor.UpdateInterval;
+ this.UpdateInterval = sensor.UpdateInterval;
this.UnitOfMeasurement = ((SensorDiscoveryConfigModel)sensor.GetAutoDiscoveryConfig()).Unit_of_measurement;
}
public ConfiguredSensorModel()
@@ -95,6 +95,7 @@ namespace hass_workstation_service.Communication.InterProcesCommunication.Models
WebcamActiveSensor,
WebcamProcessSensor,
MicrophoneActiveSensor,
+ MicrophoneProcessSensor,
ActiveWindowSensor,
NamedWindowSensor,
LastActiveSensor,
diff --git a/hass-workstation-service/Data/ConfigurationService.cs b/hass-workstation-service/Data/ConfigurationService.cs
index 3ef2a15..f00bb3c 100644
--- a/hass-workstation-service/Data/ConfigurationService.cs
+++ b/hass-workstation-service/Data/ConfigurationService.cs
@@ -135,6 +135,9 @@ namespace hass_workstation_service.Data
case "MicrophoneActiveSensor":
sensor = new MicrophoneActiveSensor(publisher, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id);
break;
+ case "MicrophoneProcessSensor":
+ sensor = new MicrophoneProcessSensor(publisher, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id);
+ break;
case "SessionStateSensor":
sensor = new SessionStateSensor(publisher, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id);
break;
@@ -462,7 +465,7 @@ namespace hass_workstation_service.Data
}
///
- ///
+ ///
///
/// The Id of the sensor to replace
/// The new sensor
diff --git a/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs b/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs
new file mode 100644
index 0000000..17ec875
--- /dev/null
+++ b/hass-workstation-service/Domain/Sensors/MicrophoneProcessSensor.cs
@@ -0,0 +1,130 @@
+using hass_workstation_service.Communication;
+using Microsoft.Win32;
+using System;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace hass_workstation_service.Domain.Sensors
+{
+ public class MicrophoneProcessSensor : AbstractSensor
+ {
+ public MicrophoneProcessSensor(MqttPublisher publisher, int? updateInterval = null, string name = "MicrophoneProcess", Guid id = default) : base(publisher, name ?? "MicrophoneProcess", updateInterval ?? 10, id)
+ {
+ }
+
+ public override string GetState()
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ return IsMicrophoneInUseRegistry();
+ }
+ else
+ {
+ return "unsupported";
+ }
+ }
+ public override SensorDiscoveryConfigModel GetAutoDiscoveryConfig()
+ {
+ return this._autoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new SensorDiscoveryConfigModel()
+ {
+ Name = this.Name,
+ NamePrefix = Publisher.NamePrefix,
+ Unique_id = this.Id.ToString(),
+ Device = this.Publisher.DeviceConfigModel,
+ State_topic = $"homeassistant/{this.Domain}/{Publisher.DeviceConfigModel.Name}/{DiscoveryConfigModel.GetNameWithPrefix(Publisher.NamePrefix, this.ObjectId)}/state",
+ Availability_topic = $"homeassistant/sensor/{Publisher.DeviceConfigModel.Name}/availability"
+ });
+ }
+
+ [SupportedOSPlatform("windows")]
+ private string IsMicrophoneInUseRegistry()
+ {
+ using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\microphone"))
+ {
+ foreach (var subKeyName in key.GetSubKeyNames())
+ {
+ // NonPackaged has multiple subkeys
+ if (subKeyName == "NonPackaged")
+ {
+ using (var nonpackagedkey = key.OpenSubKey(subKeyName))
+ {
+ foreach (var nonpackagedSubKeyName in nonpackagedkey.GetSubKeyNames())
+ {
+ using (var subKey = nonpackagedkey.OpenSubKey(nonpackagedSubKeyName))
+ {
+ if (subKey.GetValueNames().Contains("LastUsedTimeStop"))
+ {
+ var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1;
+ if (endTime <= 0)
+ {
+ return nonpackagedSubKeyName;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ using (var subKey = key.OpenSubKey(subKeyName))
+ {
+ if (subKey.GetValueNames().Contains("LastUsedTimeStop"))
+ {
+ var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1;
+ if (endTime <= 0)
+ {
+ return subKeyName;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ using (var key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\microphone"))
+ {
+ foreach (var subKeyName in key.GetSubKeyNames())
+ {
+ // NonPackaged has multiple subkeys
+ if (subKeyName == "NonPackaged")
+ {
+ using (var nonpackagedkey = key.OpenSubKey(subKeyName))
+ {
+ foreach (var nonpackagedSubKeyName in nonpackagedkey.GetSubKeyNames())
+ {
+ using (var subKey = nonpackagedkey.OpenSubKey(nonpackagedSubKeyName))
+ {
+ if (subKey.GetValueNames().Contains("LastUsedTimeStop"))
+ {
+ var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1;
+ if (endTime <= 0)
+ {
+ return nonpackagedSubKeyName;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ using (var subKey = key.OpenSubKey(subKeyName))
+ {
+ if (subKey.GetValueNames().Contains("LastUsedTimeStop"))
+ {
+ var endTime = subKey.GetValue("LastUsedTimeStop") is long ? (long)subKey.GetValue("LastUsedTimeStop") : -1;
+ if (endTime <= 0)
+ {
+ return subKeyName;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return "off";
+ }
+ }
+}