mirror of
https://github.com/ckaczor/HomeStatusWindow.git
synced 2026-01-13 17:22:55 -05:00
Fixes for new service
This commit is contained in:
29
App.config
29
App.config
@@ -1,12 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<section name="HomeStatusWindow.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
|
||||
</sectionGroup>
|
||||
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
||||
<section name="HomeStatusWindow.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
|
||||
</startup>
|
||||
<userSettings>
|
||||
<HomeStatusWindow.Properties.Settings>
|
||||
@@ -16,9 +19,25 @@
|
||||
<setting name="WindowSettings" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="ServerAddress" serializeAs="String">
|
||||
<value>http://chip</value>
|
||||
</setting>
|
||||
</HomeStatusWindow.Properties.Settings>
|
||||
</userSettings>
|
||||
<applicationSettings>
|
||||
<HomeStatusWindow.Properties.Settings>
|
||||
<setting name="ReconnectTimerInterval" serializeAs="String">
|
||||
<value>00:00:30</value>
|
||||
</setting>
|
||||
<setting name="ReconnectTimeout" serializeAs="String">
|
||||
<value>00:01:00</value>
|
||||
</setting>
|
||||
<setting name="ServerUri" serializeAs="String">
|
||||
<value>http://{0}:{1}/api/hub/device-status</value>
|
||||
</setting>
|
||||
<setting name="ServerName" serializeAs="String">
|
||||
<value>172.23.10.3</value>
|
||||
</setting>
|
||||
<setting name="ServerPort" serializeAs="String">
|
||||
<value>80</value>
|
||||
</setting>
|
||||
</HomeStatusWindow.Properties.Settings>
|
||||
</applicationSettings>
|
||||
</configuration>
|
||||
@@ -9,11 +9,12 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>HomeStatusWindow</RootNamespace>
|
||||
<AssemblyName>HomeStatusWindow</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
@@ -53,6 +54,7 @@
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="Status.cs" />
|
||||
<Compile Include="StatusMessage.cs" />
|
||||
<Compile Include="WindowSource.cs" />
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
@@ -98,8 +100,11 @@
|
||||
<PackageReference Include="FloatingStatusWindow">
|
||||
<Version>1.0.0.9</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="SocketIoClientDotNet">
|
||||
<Version>1.0.5</Version>
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client">
|
||||
<Version>6.0.8</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json">
|
||||
<Version>13.0.1</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
2
Properties/Resources.Designer.cs
generated
2
Properties/Resources.Designer.cs
generated
@@ -19,7 +19,7 @@ namespace HomeStatusWindow.Properties {
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
47
Properties/Settings.Designer.cs
generated
47
Properties/Settings.Designer.cs
generated
@@ -12,7 +12,7 @@ namespace HomeStatusWindow.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.3.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
@@ -47,15 +47,48 @@ namespace HomeStatusWindow.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("http://chip")]
|
||||
public string ServerAddress {
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("00:00:30")]
|
||||
public global::System.TimeSpan ReconnectTimerInterval {
|
||||
get {
|
||||
return ((string)(this["ServerAddress"]));
|
||||
return ((global::System.TimeSpan)(this["ReconnectTimerInterval"]));
|
||||
}
|
||||
set {
|
||||
this["ServerAddress"] = value;
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("00:01:00")]
|
||||
public global::System.TimeSpan ReconnectTimeout {
|
||||
get {
|
||||
return ((global::System.TimeSpan)(this["ReconnectTimeout"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("http://{0}:{1}/api/hub/device-status")]
|
||||
public string ServerUri {
|
||||
get {
|
||||
return ((string)(this["ServerUri"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("172.23.10.3")]
|
||||
public string ServerName {
|
||||
get {
|
||||
return ((string)(this["ServerName"]));
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("80")]
|
||||
public int ServerPort {
|
||||
get {
|
||||
return ((int)(this["ServerPort"]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,20 @@
|
||||
<Setting Name="WindowSettings" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
<Setting Name="ServerAddress" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)">http://chip</Value>
|
||||
<Setting Name="ReconnectTimerInterval" Type="System.TimeSpan" Scope="Application">
|
||||
<Value Profile="(Default)">00:00:30</Value>
|
||||
</Setting>
|
||||
<Setting Name="ReconnectTimeout" Type="System.TimeSpan" Scope="Application">
|
||||
<Value Profile="(Default)">00:01:00</Value>
|
||||
</Setting>
|
||||
<Setting Name="ServerUri" Type="System.String" Scope="Application">
|
||||
<Value Profile="(Default)">http://{0}:{1}/api/hub/device-status</Value>
|
||||
</Setting>
|
||||
<Setting Name="ServerName" Type="System.String" Scope="Application">
|
||||
<Value Profile="(Default)">172.23.10.3</Value>
|
||||
</Setting>
|
||||
<Setting Name="ServerPort" Type="System.Int32" Scope="Application">
|
||||
<Value Profile="(Default)">80</Value>
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
@@ -4,9 +4,9 @@
|
||||
public class Status
|
||||
{
|
||||
// ReSharper disable once UnusedAutoPropertyAccessor.Global
|
||||
public bool? Washer { get; set; }
|
||||
public bool Washer { get; set; }
|
||||
|
||||
// ReSharper disable once UnusedAutoPropertyAccessor.Global
|
||||
public bool? Dryer { get; set; }
|
||||
public bool Dryer { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
8
StatusMessage.cs
Normal file
8
StatusMessage.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace HomeStatusWindow
|
||||
{
|
||||
public class StatusMessage
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public bool Status { get; set; }
|
||||
}
|
||||
}
|
||||
173
WindowSource.cs
173
WindowSource.cs
@@ -1,10 +1,11 @@
|
||||
using FloatingStatusWindowLibrary;
|
||||
using HomeStatusWindow.Properties;
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
using Newtonsoft.Json;
|
||||
using Quobject.SocketIoClientDotNet.Client;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace HomeStatusWindow
|
||||
@@ -14,21 +15,30 @@ namespace HomeStatusWindow
|
||||
private readonly FloatingStatusWindow _floatingStatusWindow;
|
||||
private readonly Dispatcher _dispatcher;
|
||||
|
||||
private Socket _socket;
|
||||
private HubConnection _hubConnection;
|
||||
private DateTime _lastUpdate;
|
||||
private Timer _reconnectTimer;
|
||||
|
||||
private readonly Status _lastStatus = new Status();
|
||||
|
||||
internal WindowSource()
|
||||
{
|
||||
_dispatcher = Dispatcher.CurrentDispatcher;
|
||||
|
||||
_floatingStatusWindow = new FloatingStatusWindow(this);
|
||||
_floatingStatusWindow.SetText(Resources.Loading);
|
||||
UpdateText(Resources.Loading);
|
||||
|
||||
Task.Factory.StartNew(Initialize);
|
||||
// Initialize the connection
|
||||
Task.Factory.StartNew(InitializeConnection);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
public async void Dispose()
|
||||
{
|
||||
Terminate();
|
||||
// Stop the reconnection timer (if any)
|
||||
StopReconnectionTimer();
|
||||
|
||||
// Terminate the connection
|
||||
await TerminateConnection();
|
||||
|
||||
_floatingStatusWindow.Save();
|
||||
_floatingStatusWindow.Dispose();
|
||||
@@ -48,12 +58,14 @@ namespace HomeStatusWindow
|
||||
|
||||
public string Name => Resources.Name;
|
||||
|
||||
public bool HasSettingsMenu => false;
|
||||
public bool HasRefreshMenu => false;
|
||||
public bool HasAboutMenu => false;
|
||||
|
||||
public System.Drawing.Icon Icon => Resources.ApplicationIcon;
|
||||
|
||||
public bool HasSettingsMenu => false;
|
||||
|
||||
public bool HasRefreshMenu => false;
|
||||
|
||||
public bool HasAboutMenu => false;
|
||||
|
||||
public string WindowSettings
|
||||
{
|
||||
get => Settings.Default.WindowSettings;
|
||||
@@ -64,64 +76,121 @@ namespace HomeStatusWindow
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Status _fullStatus = new Status();
|
||||
|
||||
private void Initialize()
|
||||
private void StartReconnectionTimer()
|
||||
{
|
||||
// Create the socket
|
||||
_socket = IO.Socket(Settings.Default.ServerAddress);
|
||||
// Stop the current timer (if any)
|
||||
StopReconnectionTimer();
|
||||
|
||||
// Setup for status events
|
||||
_socket.On("status", UpdateText);
|
||||
|
||||
_socket.On(Socket.EVENT_CONNECT, () => _socket.Emit("getStatus"));
|
||||
_socket.On(Socket.EVENT_DISCONNECT, () => SetText(Resources.Disconnected));
|
||||
// Create and start the reconnection timer
|
||||
_reconnectTimer = new Timer(Settings.Default.ReconnectTimerInterval.TotalMilliseconds);
|
||||
_reconnectTimer.Elapsed += HandleReconnectTimerElapsed;
|
||||
_reconnectTimer.Start();
|
||||
}
|
||||
|
||||
private void Terminate()
|
||||
private void StopReconnectionTimer()
|
||||
{
|
||||
_socket?.Disconnect();
|
||||
// Get rid of the reconnection timer
|
||||
_reconnectTimer?.Dispose();
|
||||
_reconnectTimer = null;
|
||||
}
|
||||
|
||||
private void UpdateText(object data)
|
||||
private void HandleReconnectTimerElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
var json = (string)data;
|
||||
|
||||
var status = JsonConvert.DeserializeObject<Status>(json);
|
||||
|
||||
if (status.Dryer.HasValue)
|
||||
_fullStatus.Dryer = status.Dryer;
|
||||
|
||||
if (status.Washer.HasValue)
|
||||
_fullStatus.Washer = status.Washer;
|
||||
|
||||
var text = GetText(_fullStatus);
|
||||
|
||||
SetText(text);
|
||||
// See if we haven't heard from the server within the timeout and reconnect if needed
|
||||
if (DateTime.Now - _lastUpdate >= Settings.Default.ReconnectTimeout)
|
||||
InitializeConnection();
|
||||
}
|
||||
|
||||
private void SetText(string text)
|
||||
{
|
||||
// Update the window on the main thread
|
||||
_dispatcher.Invoke(() => _floatingStatusWindow.SetText(text));
|
||||
}
|
||||
|
||||
private static string GetText(Status status)
|
||||
private void InitializeConnection()
|
||||
{
|
||||
try
|
||||
{
|
||||
var output = new StringBuilder();
|
||||
// Stop the reconnection timer (if any)
|
||||
StopReconnectionTimer();
|
||||
|
||||
output.AppendFormat(Resources.DryerStatus, status.Dryer.GetValueOrDefault() ? Resources.On : Resources.Off);
|
||||
output.AppendLine();
|
||||
output.AppendFormat(Resources.WasherStatus, status.Washer.GetValueOrDefault() ? Resources.On : Resources.Off);
|
||||
// Create the URI for the server
|
||||
var serverUri = string.Format(Settings.Default.ServerUri, Settings.Default.ServerName, Settings.Default.ServerPort);
|
||||
|
||||
return output.ToString();
|
||||
}
|
||||
catch (Exception ex)
|
||||
_hubConnection = new HubConnectionBuilder()
|
||||
.WithUrl(serverUri)
|
||||
.Build();
|
||||
|
||||
_hubConnection.Closed += error =>
|
||||
{
|
||||
return ex.Message;
|
||||
}
|
||||
StartReconnectionTimer();
|
||||
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
_hubConnection.On<string>("LatestStatus", (message) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var statusMessage = JsonConvert.DeserializeObject<StatusMessage>(message);
|
||||
|
||||
switch (statusMessage?.Name)
|
||||
{
|
||||
case "washer":
|
||||
_lastStatus.Washer = statusMessage.Status;
|
||||
break;
|
||||
case "dryer":
|
||||
_lastStatus.Dryer = statusMessage.Status;
|
||||
break;
|
||||
}
|
||||
|
||||
UpdateDisplay(_lastStatus);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
});
|
||||
|
||||
// Open the connection
|
||||
_hubConnection.StartAsync().Wait();
|
||||
|
||||
_hubConnection.InvokeAsync("RequestLatestStatus").Wait();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
UpdateText($"Connection error: {exception.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Start the reconnection check timer
|
||||
StartReconnectionTimer();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task TerminateConnection()
|
||||
{
|
||||
// If the client doesn't exist or isn't open then there's nothing to do
|
||||
if (_hubConnection == null || _hubConnection.State != HubConnectionState.Connected)
|
||||
return;
|
||||
|
||||
// Close the connection
|
||||
await _hubConnection.DisposeAsync();
|
||||
}
|
||||
|
||||
private void UpdateDisplay(Status status)
|
||||
{
|
||||
// Last update was now
|
||||
_lastUpdate = DateTime.Now;
|
||||
|
||||
// Create a string builder
|
||||
var text = new StringBuilder();
|
||||
|
||||
text.AppendFormat(Resources.DryerStatus, status.Dryer ? Resources.On : Resources.Off);
|
||||
text.AppendLine();
|
||||
text.AppendFormat(Resources.WasherStatus, status.Washer ? Resources.On : Resources.Off);
|
||||
|
||||
// Set the text
|
||||
UpdateText(text.ToString());
|
||||
}
|
||||
|
||||
private void UpdateText(string text)
|
||||
{
|
||||
_dispatcher.InvokeAsync(() => _floatingStatusWindow.SetText(text));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user