diff --git a/UserInterface/Views/AddSensorDialog.axaml.cs b/UserInterface/Views/AddSensorDialog.axaml.cs
index 5d83bd7..9ab9bde 100644
--- a/UserInterface/Views/AddSensorDialog.axaml.cs
+++ b/UserInterface/Views/AddSensorDialog.axaml.cs
@@ -158,6 +158,13 @@ namespace UserInterface.Views
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";
diff --git a/UserInterface/Views/BackgroundServiceSettings.axaml b/UserInterface/Views/BackgroundServiceSettings.axaml
index 4b7baed..eadbee8 100644
--- a/UserInterface/Views/BackgroundServiceSettings.axaml
+++ b/UserInterface/Views/BackgroundServiceSettings.axaml
@@ -9,10 +9,7 @@
Background service
-
-
-
-
+
Autostart
diff --git a/UserInterface/Views/BrokerSettings.axaml b/UserInterface/Views/BrokerSettings.axaml
index d583039..b23b798 100644
--- a/UserInterface/Views/BrokerSettings.axaml
+++ b/UserInterface/Views/BrokerSettings.axaml
@@ -4,7 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="450"
x:Class="UserInterface.Views.BrokerSettings">
-
+
MQTT Broker
diff --git a/UserInterface/Views/MainWindow.axaml b/UserInterface/Views/MainWindow.axaml
index d559359..31d7da7 100644
--- a/UserInterface/Views/MainWindow.axaml
+++ b/UserInterface/Views/MainWindow.axaml
@@ -1,4 +1,4 @@
-
-
-
+
+
+
+
+
+
-
\ No newline at end of file
diff --git a/documentation/Sensors.md b/documentation/Sensors.md
index 958efa8..2938c7d 100644
--- a/documentation/Sensors.md
+++ b/documentation/Sensors.md
@@ -85,6 +85,10 @@ This sensor watches the UserNotificationState. This is normally used in applicat
The webcam active sensor returns the status of the webcam.
+### WebcamProcessSensor
+
+The webcam process sensor returns the process which is using the webcam.
+
### 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 0a53b1a..9c9824e 100644
--- a/hass-workstation-service/Communication/InterProcesCommunication/InterProcessApi.cs
+++ b/hass-workstation-service/Communication/InterProcesCommunication/InterProcessApi.cs
@@ -177,6 +177,7 @@ namespace hass_workstation_service.Communication.InterProcesCommunication
AvailableSensors.MemoryUsageSensor => new MemoryUsageSensor(_publisher, (int)model.UpdateInterval, model.Name),
AvailableSensors.ActiveWindowSensor => new ActiveWindowSensor(_publisher, (int)model.UpdateInterval, model.Name),
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.NamedWindowSensor => new NamedWindowSensor(_publisher, model.WindowName, model.Name, (int)model.UpdateInterval),
AvailableSensors.LastActiveSensor => new LastActiveSensor(_publisher, (int)model.UpdateInterval, model.Name),
@@ -221,4 +222,4 @@ namespace hass_workstation_service.Communication.InterProcesCommunication
public void WriteGeneralSettings(GeneralSettings settings) => _configurationService.WriteGeneralSettingsAsync(settings);
}
-}
\ No newline at end of file
+}
diff --git a/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractModels.cs b/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractModels.cs
index 0507e5e..fafa58d 100644
--- a/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractModels.cs
+++ b/hass-workstation-service/Communication/InterProcesCommunication/ServiceContractModels.cs
@@ -93,6 +93,7 @@ namespace hass_workstation_service.Communication.InterProcesCommunication.Models
WMIQuerySensor,
MemoryUsageSensor,
WebcamActiveSensor,
+ WebcamProcessSensor,
MicrophoneActiveSensor,
ActiveWindowSensor,
NamedWindowSensor,
@@ -120,4 +121,4 @@ namespace hass_workstation_service.Communication.InterProcesCommunication.Models
VolumeDownCommand,
MuteCommand
}
-}
\ No newline at end of file
+}
diff --git a/hass-workstation-service/Data/ConfigurationService.cs b/hass-workstation-service/Data/ConfigurationService.cs
index dc8e12f..3ef2a15 100644
--- a/hass-workstation-service/Data/ConfigurationService.cs
+++ b/hass-workstation-service/Data/ConfigurationService.cs
@@ -129,6 +129,9 @@ namespace hass_workstation_service.Data
case "WebcamActiveSensor":
sensor = new WebcamActiveSensor(publisher, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id);
break;
+ case "WebcamProcessSensor":
+ sensor = new WebcamProcessSensor(publisher, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id);
+ break;
case "MicrophoneActiveSensor":
sensor = new MicrophoneActiveSensor(publisher, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id);
break;
@@ -619,4 +622,4 @@ namespace hass_workstation_service.Data
return this.ConfiguredSensors;
}
}
-}
\ No newline at end of file
+}
diff --git a/hass-workstation-service/Domain/Sensors/LastActiveSensor.cs b/hass-workstation-service/Domain/Sensors/LastActiveSensor.cs
index 9aa38bc..9eba3b8 100644
--- a/hass-workstation-service/Domain/Sensors/LastActiveSensor.cs
+++ b/hass-workstation-service/Domain/Sensors/LastActiveSensor.cs
@@ -25,7 +25,7 @@ namespace hass_workstation_service.Domain.Sensors
public override string GetState()
{
- return GetLastInputTime().ToString("s");
+ return GetLastInputTime().ToString("o", System.Globalization.CultureInfo.InvariantCulture);
}
diff --git a/hass-workstation-service/Domain/Sensors/LastBootSensor.cs b/hass-workstation-service/Domain/Sensors/LastBootSensor.cs
index fda171c..26b4896 100644
--- a/hass-workstation-service/Domain/Sensors/LastBootSensor.cs
+++ b/hass-workstation-service/Domain/Sensors/LastBootSensor.cs
@@ -29,10 +29,10 @@ namespace hass_workstation_service.Domain.Sensors
public override string GetState()
{
- return (DateTime.Now - TimeSpan.FromMilliseconds(GetTickCount64())).ToString("s");
+ return (DateTime.Now - TimeSpan.FromMilliseconds(GetTickCount64())).ToString("o", System.Globalization.CultureInfo.InvariantCulture);
}
[DllImport("kernel32")]
extern static UInt64 GetTickCount64();
}
-}
+}
\ No newline at end of file
diff --git a/hass-workstation-service/Domain/Sensors/WebcamProcessSensor.cs b/hass-workstation-service/Domain/Sensors/WebcamProcessSensor.cs
new file mode 100644
index 0000000..9210654
--- /dev/null
+++ b/hass-workstation-service/Domain/Sensors/WebcamProcessSensor.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 WebcamProcessSensor : AbstractSensor
+ {
+ public WebcamProcessSensor(MqttPublisher publisher, int? updateInterval = null, string name = "WebcamProcess", Guid id = default) : base(publisher, name ?? "WebcamProcess", updateInterval ?? 10, id)
+ {
+ }
+
+ public override string GetState()
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ return IsWebCamInUseRegistry();
+ }
+ 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 IsWebCamInUseRegistry()
+ {
+ using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\CapabilityAccessManager\ConsentStore\webcam"))
+ {
+ 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\webcam"))
+ {
+ 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";
+ }
+ }
+}
diff --git a/hass-workstation-service/Properties/PublishProfiles/AzureHosted.pubxml b/hass-workstation-service/Properties/PublishProfiles/AzureHosted.pubxml
index 64dd310..cb38d89 100644
--- a/hass-workstation-service/Properties/PublishProfiles/AzureHosted.pubxml
+++ b/hass-workstation-service/Properties/PublishProfiles/AzureHosted.pubxml
@@ -4,7 +4,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
-->
- 55
+ 57
1.0.0.*
True
Release
diff --git a/hass-workstation-service/UserInterface.exe b/hass-workstation-service/UserInterface.exe
index a34952d..1633afc 100644
Binary files a/hass-workstation-service/UserInterface.exe and b/hass-workstation-service/UserInterface.exe differ
diff --git a/hass-workstation-service/hass-workstation-service.exe b/hass-workstation-service/hass-workstation-service.exe
index 8c8bd7b..64b88d0 100644
Binary files a/hass-workstation-service/hass-workstation-service.exe and b/hass-workstation-service/hass-workstation-service.exe differ