diff --git a/src/PepperDash.Essentials.Core/Monitoring/GenericCommunicationMonitor.cs b/src/PepperDash.Essentials.Core/Monitoring/GenericCommunicationMonitor.cs index 094cdb22..5bc505e2 100644 --- a/src/PepperDash.Essentials.Core/Monitoring/GenericCommunicationMonitor.cs +++ b/src/PepperDash.Essentials.Core/Monitoring/GenericCommunicationMonitor.cs @@ -1,16 +1,7 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; -using Crestron.SimplSharpPro.DeviceSupport; - -using System.ComponentModel; - using PepperDash.Core; -using Serilog.Events; - +using System.Threading; +using PepperDash.Core.Logging; namespace PepperDash.Essentials.Core { @@ -31,35 +22,32 @@ namespace PepperDash.Essentials.Core /// /// Return true if the Client is ISocketStatus /// - public bool IsSocket - { - get - { - return Client is ISocketStatus; - } - } + public bool IsSocket => Client is ISocketStatus; - long PollTime; - CTimer PollTimer; - string PollString; - Action PollAction; - - /// - /// - /// - /// - /// in MS, >= 5000 - /// in MS, >= 5000 - /// in MS, >= 5000 - /// String to send to comm - public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime, + private readonly string PollString; + private readonly Action PollAction; + private readonly long PollTime; + + private Timer PollTimer; + + /// + /// GenericCommunicationMonitor constructor + /// + /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected + /// + /// Parent device + /// Communications Client + /// Time in MS for polling + /// Warning time in MS. If a message is not received before this elapsed time the status will be Warning + /// Error time in MS. If a message is not received before this elapsed time the status will be Error + /// string to send for polling + /// Poll time must be less than warning and error time + public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime, long warningTime, long errorTime, string pollString) : base(parent, warningTime, errorTime) { if (pollTime > warningTime || pollTime > errorTime) throw new ArgumentException("pollTime must be less than warning or errorTime"); - //if (pollTime < 5000) - // throw new ArgumentException("pollTime cannot be less than 5000 ms"); Client = client; PollTime = pollTime; @@ -67,26 +55,41 @@ namespace PepperDash.Essentials.Core if (IsSocket) { - (Client as ISocketStatus).ConnectionChange += new EventHandler(socket_ConnectionChange); + (Client as ISocketStatus).ConnectionChange += Socket_ConnectionChange; } } + /// + /// GenericCommunicationMonitor constructor with a bool to specify whether to monitor BytesReceived + /// + /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected + /// + /// Parent device + /// Communications Client + /// Time in MS for polling + /// Warning time in MS. If a message is not received before this elapsed time the status will be Warning + /// Error time in MS. If a message is not received before this elapsed time the status will be Error + /// string to send for polling + /// Use bytesReceived event instead of textReceived when true public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime, long warningTime, long errorTime, string pollString, bool monitorBytesReceived) : this(parent, client, pollTime, warningTime, errorTime, pollString) { - SetMonitorBytesReceived(monitorBytesReceived); + MonitorBytesReceived = monitorBytesReceived; } /// - /// Poll is a provided action instead of string + /// GenericCommunicationMonitor constructor with a poll action instead of a poll string + /// + /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected /// - /// - /// - /// - /// - /// - /// + /// Parent device + /// Communications Client + /// Time in MS for polling + /// Warning time in MS. If a message is not received before this elapsed time the status will be Warning + /// Error time in MS. If a message is not received before this elapsed time the status will be Error + /// Action to execute for polling + /// Poll time must be less than warning and error time public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime, long warningTime, long errorTime, Action pollAction) : base(parent, warningTime, errorTime) @@ -102,51 +105,67 @@ namespace PepperDash.Essentials.Core if (IsSocket) { - (Client as ISocketStatus).ConnectionChange += new EventHandler(socket_ConnectionChange); + (Client as ISocketStatus).ConnectionChange += Socket_ConnectionChange; } } + /// + /// GenericCommunicationMonitor constructor with a poll action instead of a poll string and a bool to specify whether to monitor BytesReceived + /// + /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected + /// + /// Parent device + /// Communications Client + /// Time in MS for polling + /// Warning time in MS. If a message is not received before this elapsed time the status will be Warning + /// Error time in MS. If a message is not received before this elapsed time the status will be Error + /// Action to execute for polling + /// Use bytesReceived event instead of textReceived when true public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, long pollTime, long warningTime, long errorTime, Action pollAction, bool monitorBytesReceived) : this(parent, client, pollTime, warningTime, errorTime, pollAction) { - SetMonitorBytesReceived(monitorBytesReceived); + MonitorBytesReceived = monitorBytesReceived; } - /// - /// Build the monitor from a config object - /// - public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, + /// + /// GenericCommunicationMonitor constructor with a config object + /// + /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected + /// + /// Parent Device + /// Communications Client + /// Communication Monitor Config object + public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, CommunicationMonitorConfig props) : this(parent, client, props.PollInterval, props.TimeToWarning, props.TimeToError, props.PollString) { if (IsSocket) { - (Client as ISocketStatus).ConnectionChange += new EventHandler(socket_ConnectionChange); + (Client as ISocketStatus).ConnectionChange += Socket_ConnectionChange; } } /// - /// Builds the monitor from a config object and takes a bool to specify whether to monitor BytesReceived - /// Default is to monitor TextReceived + /// GenericCommunicationMonitor constructor with a config object and a bool to specify whether to monitor BytesReceived + /// + /// Note: If the client is a socket, the connection status will be monitored and the PollTimer will be started automatically when the client is connected /// - /// - /// - /// - /// + /// Parent Device + /// Communications Client + /// Communication Monitor Config object + /// Use bytesReceived event instead of textReceived when true public GenericCommunicationMonitor(IKeyed parent, IBasicCommunication client, CommunicationMonitorConfig props, bool monitorBytesReceived) : this(parent, client, props.PollInterval, props.TimeToWarning, props.TimeToError, props.PollString) - { - SetMonitorBytesReceived(monitorBytesReceived); - } - - void SetMonitorBytesReceived(bool monitorBytesReceived) { MonitorBytesReceived = monitorBytesReceived; } + /// + /// Start the poll cycle + /// public override void Start() { if (MonitorBytesReceived) @@ -163,7 +182,7 @@ namespace PepperDash.Essentials.Core BeginPolling(); } - void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e) + private void Socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e) { if (!e.Client.IsConnected) { @@ -176,58 +195,62 @@ namespace PepperDash.Essentials.Core { // Start polling and set status to unknow and let poll result update the status to IsOk when a response is received Status = MonitorStatus.StatusUnknown; - Start(); - BeginPolling(); + Start(); } } - void BeginPolling() + private void BeginPolling() { - Poll(); - PollTimer = new CTimer(o => Poll(), null, PollTime, PollTime); + if(PollTimer != null) + { + return; + } + + PollTimer = new Timer(o => Poll(), null, 0, PollTime); } + /// + /// Stop the poll cycle + /// public override void Stop() { if(MonitorBytesReceived) { - Client.BytesReceived -= this.Client_BytesReceived; + Client.BytesReceived -= Client_BytesReceived; } else { Client.TextReceived -= Client_TextReceived; } - if (PollTimer != null) + StopErrorTimers(); + + if (PollTimer == null) { - PollTimer.Stop(); - PollTimer = null; - StopErrorTimers(); + return; } + + PollTimer.Dispose(); + PollTimer = null; } - void Client_TextReceived(object sender, GenericCommMethodReceiveTextArgs e) + private void Client_TextReceived(object sender, GenericCommMethodReceiveTextArgs e) { DataReceived(); } - /// - /// Upon any receipt of data, set everything to ok! - /// - /// - /// - void Client_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e) + private void Client_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e) { DataReceived(); } - void DataReceived() + private void DataReceived() { Status = MonitorStatus.IsOk; ResetErrorTimers(); } - void Poll() + private void Poll() { StartErrorTimers(); if (Client.IsConnected) @@ -240,12 +263,14 @@ namespace PepperDash.Essentials.Core } else { - Debug.LogMessage(LogEventLevel.Verbose, this, "Comm not connected"); + this.LogVerbose("Comm not connected"); } } } - + /// + /// Communication Monitor Configuration from Essentials Configuration + /// public class CommunicationMonitorConfig { public int PollInterval { get; set; } @@ -253,6 +278,9 @@ namespace PepperDash.Essentials.Core public int TimeToError { get; set; } public string PollString { get; set; } + /// + /// Default constructor. Sets pollInterval to 30s, TimeToWarning to 120s, and TimeToError to 300s + /// public CommunicationMonitorConfig() { PollInterval = 30000;