wip namedWindow sensor

pull/9/head
Sleevezipper 4 years ago
parent 6a122e3337
commit 95d4c8aad5

@ -14,9 +14,11 @@ namespace UserInterface.ViewModels
public string Description { get => description; set => this.RaiseAndSetIfChanged(ref description, value); } public string Description { get => description; set => this.RaiseAndSetIfChanged(ref description, value); }
public bool ShowQueryInput { get => showQueryInput; set => this.RaiseAndSetIfChanged(ref showQueryInput, value); } public bool ShowQueryInput { get => showQueryInput; set => this.RaiseAndSetIfChanged(ref showQueryInput, value); }
public bool ShowWindowNameInput { get => showWindowNameInput; set => this.RaiseAndSetIfChanged(ref showWindowNameInput, value); }
private string moreInfoLink; private string moreInfoLink;
private int updateInterval; private int updateInterval;
private bool showWindowNameInput;
public string MoreInfoLink public string MoreInfoLink
{ {
@ -28,6 +30,7 @@ namespace UserInterface.ViewModels
public AvailableSensors SelectedType { get => selectedType; set => this.RaiseAndSetIfChanged(ref selectedType, value); } public AvailableSensors SelectedType { get => selectedType; set => this.RaiseAndSetIfChanged(ref selectedType, value); }
public string Name { get; set; } public string Name { get; set; }
public string Query { get; set; } public string Query { get; set; }
public string WindowName { get; set; }
public int UpdateInterval { get => updateInterval; set => this.RaiseAndSetIfChanged(ref updateInterval, value); } public int UpdateInterval { get => updateInterval; set => this.RaiseAndSetIfChanged(ref updateInterval, value); }
} }
} }

@ -23,6 +23,9 @@
<TextBlock Text="{Binding UpdateInterval, StringFormat= Update every {0} seconds}" HorizontalAlignment="Left" MinWidth="150"/> <TextBlock Text="{Binding UpdateInterval, StringFormat= Update every {0} seconds}" HorizontalAlignment="Left" MinWidth="150"/>
<ContentControl IsVisible="{Binding ShowQueryInput}" Margin="0 20 0 10">Query</ContentControl> <ContentControl IsVisible="{Binding ShowQueryInput}" Margin="0 20 0 10">Query</ContentControl>
<TextBox IsVisible="{Binding ShowQueryInput}" Text="{Binding Query}" Watermark="SELECT Name FROM Win32_Processor" HorizontalAlignment="Left" MinWidth="300"/> <TextBox IsVisible="{Binding ShowQueryInput}" Text="{Binding Query}" Watermark="SELECT Name FROM Win32_Processor" HorizontalAlignment="Left" MinWidth="300"/>
<ContentControl IsVisible="{Binding ShowWindowNameInput}" Margin="0 20 0 5">Window name</ContentControl>
<TextBlock TextWrapping="Wrap" MaxWidth="300" FontStyle="Italic" IsVisible="{Binding ShowWindowNameInput}" Margin="0 0 0 10">This is case-insensitive and loosely matched. A window called "Spotify Premium" will match "spotify" or "premium".</TextBlock>
<TextBox IsVisible="{Binding ShowWindowNameInput}" Text="{Binding WindowName}" Watermark="Visual Studio Code" HorizontalAlignment="Left" MinWidth="300"/>
<Button Width="75" HorizontalAlignment="Right" Margin="0 40 0 10" Click="Save">Save</Button> <Button Width="75" HorizontalAlignment="Right" Margin="0 40 0 10" Click="Save">Save</Button>
</StackPanel> </StackPanel>
</Window> </Window>

@ -47,7 +47,7 @@ namespace UserInterface.Views
public async void Save(object sender, RoutedEventArgs args) public async void Save(object sender, RoutedEventArgs args)
{ {
var item = ((AddSensorViewModel)this.DataContext); var item = ((AddSensorViewModel)this.DataContext);
dynamic model = new { Name = item.Name, Query = item.Query, UpdateInterval = item.UpdateInterval }; dynamic model = new { item.Name, item.Query, item.UpdateInterval, item.WindowName };
string json = JsonSerializer.Serialize(model); string json = JsonSerializer.Serialize(model);
await this.client.InvokeAsync(x => x.AddSensor(item.SelectedType, json)); await this.client.InvokeAsync(x => x.AddSensor(item.SelectedType, json));
Close(); Close();
@ -62,42 +62,56 @@ namespace UserInterface.Views
item.Description = "This sensor watches the UserNotificationState. This is normally used in applications to determine if it is appropriate to send a notification but we can use it to expose this state. \n "; item.Description = "This sensor watches the UserNotificationState. This is normally used in applications to determine if it is appropriate to send a notification but we can use it to expose this state. \n ";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#usernotificationstate"; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#usernotificationstate";
item.ShowQueryInput = false; item.ShowQueryInput = false;
item.ShowWindowNameInput = false;
item.UpdateInterval = 5; item.UpdateInterval = 5;
break; break;
case AvailableSensors.DummySensor: 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.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#dummy"; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#dummy";
item.ShowQueryInput = false; item.ShowQueryInput = false;
item.ShowWindowNameInput = false;
item.UpdateInterval = 1; item.UpdateInterval = 1;
break; break;
case AvailableSensors.CPULoadSensor: 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.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#cpuload"; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#cpuload";
item.ShowQueryInput = false; item.ShowQueryInput = false;
item.ShowWindowNameInput = false;
item.UpdateInterval = 5; item.UpdateInterval = 5;
break; break;
case AvailableSensors.CurrentClockSpeedSensor: case AvailableSensors.CurrentClockSpeedSensor:
item.Description = "This sensor returns the BIOS configured baseclock for the processor."; item.Description = "This sensor returns the BIOS configured baseclock for the processor.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#currentclockspeed"; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#currentclockspeed";
item.ShowQueryInput = false; item.ShowQueryInput = false;
item.ShowWindowNameInput = false;
item.UpdateInterval = 3600; item.UpdateInterval = 3600;
break; break;
case AvailableSensors.WMIQuerySensor: 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.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/sleevezipper/hass-workstation-service#wmiquerysensor"; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#wmiquerysensor";
item.ShowQueryInput = true; item.ShowQueryInput = true;
item.ShowWindowNameInput = false;
item.UpdateInterval = 10; item.UpdateInterval = 10;
break; break;
case AvailableSensors.MemoryUsageSensor: case AvailableSensors.MemoryUsageSensor:
item.Description = "This sensor calculates the percentage of used memory."; item.Description = "This sensor calculates the percentage of used memory.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#usedmemorysensor"; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#usedmemorysensor";
item.ShowQueryInput = false; item.ShowQueryInput = false;
item.ShowWindowNameInput = false;
item.UpdateInterval = 10; item.UpdateInterval = 10;
break; break;
case AvailableSensors.ActiveWindowSensor: case AvailableSensors.ActiveWindowSensor:
item.Description = "This sensor exposes the name of the currently active window."; item.Description = "This sensor exposes the name of the currently active window.";
item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#activewindow"; item.MoreInfoLink = "https://github.com/sleevezipper/hass-workstation-service#activewindow";
item.ShowQueryInput = false; item.ShowQueryInput = false;
item.ShowWindowNameInput = false;
item.UpdateInterval = 5;
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#namedwindow";
item.ShowQueryInput = false;
item.ShowWindowNameInput = true;
item.UpdateInterval = 5; item.UpdateInterval = 5;
break; break;
default: default:

@ -106,6 +106,9 @@ namespace hass_workstation_service.Communication.InterProcesCommunication
case AvailableSensors.ActiveWindowSensor: case AvailableSensors.ActiveWindowSensor:
sensorToCreate = new ActiveWindowSensor(this._publisher, (int)model.UpdateInterval, model.Name); sensorToCreate = new ActiveWindowSensor(this._publisher, (int)model.UpdateInterval, model.Name);
break; break;
case AvailableSensors.NamedWindowSensor:
sensorToCreate = new NamedWindowSensor(this._publisher, model.WindowName, model.Name, (int)model.UpdateInterval);
break;
default: default:
Log.Logger.Error("Unknown sensortype"); Log.Logger.Error("Unknown sensortype");
break; break;

@ -36,6 +36,7 @@ namespace hass_workstation_service.Communication.InterProcesCommunication.Models
CPULoadSensor, CPULoadSensor,
WMIQuerySensor, WMIQuerySensor,
MemoryUsageSensor, MemoryUsageSensor,
ActiveWindowSensor ActiveWindowSensor,
NamedWindowSensor
} }
} }

@ -88,6 +88,9 @@ namespace hass_workstation_service.Data
case "ActiveWindowSensor": case "ActiveWindowSensor":
sensor = new ActiveWindowSensor(publisher, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id); sensor = new ActiveWindowSensor(publisher, configuredSensor.UpdateInterval, configuredSensor.Name, configuredSensor.Id);
break; break;
case "NamedWindowSensor":
sensor = new NamedWindowSensor(publisher, configuredSensor.WindowName, configuredSensor.Name, configuredSensor.UpdateInterval, configuredSensor.Id);
break;
default: default:
Log.Logger.Error("unsupported sensor type in config"); Log.Logger.Error("unsupported sensor type in config");
break; break;
@ -164,6 +167,11 @@ namespace hass_workstation_service.Data
var wmiSensor = (WMIQuerySensor)sensor; var wmiSensor = (WMIQuerySensor)sensor;
configuredSensorsToSave.Add(new ConfiguredSensor() { Id = wmiSensor.Id, Name = wmiSensor.Name, Type = wmiSensor.GetType().Name, UpdateInterval = wmiSensor.UpdateInterval, Query = wmiSensor.Query }); configuredSensorsToSave.Add(new ConfiguredSensor() { Id = wmiSensor.Id, Name = wmiSensor.Name, Type = wmiSensor.GetType().Name, UpdateInterval = wmiSensor.UpdateInterval, Query = wmiSensor.Query });
} }
if (sensor is NamedWindowSensor)
{
var namedWindowSensor = (NamedWindowSensor)sensor;
configuredSensorsToSave.Add(new ConfiguredSensor() { Id = namedWindowSensor.Id, Name = namedWindowSensor.Name, Type = namedWindowSensor.GetType().Name, UpdateInterval = namedWindowSensor.UpdateInterval, WindowName = namedWindowSensor.WindowName });
}
else else
{ {
configuredSensorsToSave.Add(new ConfiguredSensor() { Id = sensor.Id, Name = sensor.Name, Type = sensor.GetType().Name, UpdateInterval = sensor.UpdateInterval }); configuredSensorsToSave.Add(new ConfiguredSensor() { Id = sensor.Id, Name = sensor.Name, Type = sensor.GetType().Name, UpdateInterval = sensor.UpdateInterval });

@ -9,5 +9,6 @@ namespace hass_workstation_service.Data
public string Name { get; set; } public string Name { get; set; }
public string Query { get; set; } public string Query { get; set; }
public int? UpdateInterval { get; set; } public int? UpdateInterval { get; set; }
public string WindowName { get; set; }
} }
} }

@ -0,0 +1,81 @@
using hass_workstation_service.Communication;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using HWND = System.IntPtr;
namespace hass_workstation_service.Domain.Sensors
{
public class NamedWindowSensor : AbstractSensor
{
public string WindowName { get; protected set; }
public NamedWindowSensor(MqttPublisher publisher, string windowName, string name = "NamedWindow", int? updateInterval = 10, Guid id = default) : base(publisher, name ?? "NamedWindow", updateInterval ?? 10, id)
{
this.WindowName = windowName;
}
public override AutoDiscoveryConfigModel GetAutoDiscoveryConfig()
{
return this._autoDiscoveryConfigModel ?? SetAutoDiscoveryConfigModel(new AutoDiscoveryConfigModel()
{
Name = this.Name,
Unique_id = this.Id.ToString(),
Device = this.Publisher.DeviceConfigModel,
State_topic = $"homeassistant/sensor/{this.Name}/state",
Icon = "mdi:window-maximize",
});
}
public override string GetState()
{
var windowNames = GetOpenWindows().Values;
return windowNames.Any(v => v.Contains(this.WindowName, StringComparison.OrdinalIgnoreCase)) ? "True" : "False";
}
/// <summary>Returns a dictionary that contains the handle and title of all the open windows.</summary>
/// <returns>A dictionary that contains the handle and title of all the open windows.</returns>
public static IDictionary<HWND, string> GetOpenWindows()
{
HWND shellWindow = GetShellWindow();
Dictionary<HWND, string> windows = new Dictionary<HWND, string>();
EnumWindows(delegate (HWND hWnd, int lParam)
{
if (hWnd == shellWindow) return true;
if (!IsWindowVisible(hWnd)) return true;
int length = GetWindowTextLength(hWnd);
if (length == 0) return true;
StringBuilder builder = new StringBuilder(length);
GetWindowText(hWnd, builder, length + 1);
windows[hWnd] = builder.ToString();
return true;
}, 0);
return windows;
}
private delegate bool EnumWindowsProc(HWND hWnd, int lParam);
[DllImport("USER32.DLL")]
private static extern bool EnumWindows(EnumWindowsProc enumFunc, int lParam);
[DllImport("USER32.DLL")]
private static extern int GetWindowText(HWND hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("USER32.DLL")]
private static extern int GetWindowTextLength(HWND hWnd);
[DllImport("USER32.DLL")]
private static extern bool IsWindowVisible(HWND hWnd);
[DllImport("USER32.DLL")]
private static extern IntPtr GetShellWindow();
}
}
Loading…
Cancel
Save