feat(essentials): #912 Updates to GenericCommunicationMonitor to better monitor socket status

This commit is contained in:
Neil Dorin
2022-03-03 14:39:54 -07:00
parent 787c8eb954
commit 89dd098ea6
2 changed files with 131 additions and 25 deletions

View File

@@ -16,11 +16,28 @@ namespace PepperDash.Essentials.Core
/// <summary> /// <summary>
/// Used for monitoring comms that are IBasicCommunication. Will send a poll string and provide an event when /// Used for monitoring comms that are IBasicCommunication. Will send a poll string and provide an event when
/// statuses change. /// statuses change.
/// Default monitoring uses TextReceived event on Client.
/// </summary> /// </summary>
public class GenericCommunicationMonitor : StatusMonitorBase public class GenericCommunicationMonitor : StatusMonitorBase
{ {
public IBasicCommunication Client { get; private set; } public IBasicCommunication Client { get; private set; }
/// <summary>
/// Will monitor Client.BytesReceived if set to true. Otherwise the default is to monitor Client.TextReceived
/// </summary>
public bool MonitorBytesReceived { get; private set; }
/// <summary>
/// Return true if the Client is ISocketStatus
/// </summary>
public bool IsSocket
{
get
{
return Client is ISocketStatus;
}
}
long PollTime; long PollTime;
CTimer PollTimer; CTimer PollTimer;
string PollString; string PollString;
@@ -46,8 +63,20 @@ namespace PepperDash.Essentials.Core
Client = client; Client = client;
PollTime = pollTime; PollTime = pollTime;
PollString = pollString; PollString = pollString;
if (IsSocket)
{
(Client as ISocketStatus).ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
}
} }
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);
}
/// <summary> /// <summary>
/// Poll is a provided action instead of string /// Poll is a provided action instead of string
/// </summary> /// </summary>
@@ -69,6 +98,19 @@ namespace PepperDash.Essentials.Core
Client = client; Client = client;
PollTime = pollTime; PollTime = pollTime;
PollAction = pollAction; PollAction = pollAction;
if (IsSocket)
{
(Client as ISocketStatus).ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
}
}
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);
} }
@@ -79,23 +121,96 @@ namespace PepperDash.Essentials.Core
CommunicationMonitorConfig props) : CommunicationMonitorConfig props) :
this(parent, client, props.PollInterval, props.TimeToWarning, props.TimeToError, props.PollString) this(parent, client, props.PollInterval, props.TimeToWarning, props.TimeToError, props.PollString)
{ {
if (IsSocket)
{
(Client as ISocketStatus).ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
}
} }
/// <summary>
/// Builds the monitor from a config object and takes a bool to specify whether to monitor BytesReceived
/// Default is to monitor TextReceived
/// </summary>
/// <param name="parent"></param>
/// <param name="client"></param>
/// <param name="props"></param>
/// <param name="monitorBytesReceived"></param>
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;
}
public override void Start() public override void Start()
{ {
Client.BytesReceived += Client_BytesReceived; if (MonitorBytesReceived)
Poll(); {
PollTimer = new CTimer(o => Poll(), null, PollTime, PollTime); Client.BytesReceived += Client_BytesReceived;
}
else
{
Client.TextReceived += Client_TextReceived;
}
if (!IsSocket)
{
BeginPolling();
}
} }
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
{
if (!e.Client.IsConnected)
{
// Immediately stop polling and notify that device is offline
Stop();
Status = MonitorStatus.InError;
ResetErrorTimers();
}
else
{
// 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();
}
}
void BeginPolling()
{
Poll();
PollTimer = new CTimer(o => Poll(), null, PollTime, PollTime);
}
public override void Stop() public override void Stop()
{ {
Client.BytesReceived -= this.Client_BytesReceived; if(MonitorBytesReceived)
PollTimer.Stop(); {
PollTimer = null; Client.BytesReceived -= this.Client_BytesReceived;
StopErrorTimers(); }
else
{
Client.TextReceived -= Client_TextReceived;
}
if (PollTimer != null)
{
PollTimer.Stop();
PollTimer = null;
StopErrorTimers();
}
} }
void Client_TextReceived(object sender, GenericCommMethodReceiveTextArgs e)
{
DataReceived();
}
/// <summary> /// <summary>
/// Upon any receipt of data, set everything to ok! /// Upon any receipt of data, set everything to ok!
/// </summary> /// </summary>
@@ -103,10 +218,14 @@ namespace PepperDash.Essentials.Core
/// <param name="e"></param> /// <param name="e"></param>
void Client_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e) void Client_BytesReceived(object sender, GenericCommMethodReceiveBytesArgs e)
{ {
Status = MonitorStatus.IsOk; DataReceived();
ResetErrorTimers(); }
//
} void DataReceived()
{
Status = MonitorStatus.IsOk;
ResetErrorTimers();
}
void Poll() void Poll()
{ {
@@ -124,19 +243,6 @@ namespace PepperDash.Essentials.Core
Debug.Console(2, this, "Comm not connected"); Debug.Console(2, this, "Comm not connected");
} }
} }
/// <summary>
/// When the client connects, and we're waiting for it, respond and disconect from event
/// </summary>
void OneTimeConnectHandler(object o, EventArgs a)
{
if (Client.IsConnected)
{
//Client.IsConnected -= OneTimeConnectHandler;
Debug.Console(2, this, "Comm connected");
Poll();
}
}
} }

View File

@@ -99,7 +99,7 @@ namespace PepperDash.Essentials.Devices.Displays
WarmupTime = 10000; WarmupTime = 10000;
CooldownTime = 8000; CooldownTime = 8000;
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 2000, 120000, 300000, StatusGet); CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 2000, 120000, 300000, StatusGet, true);
DeviceManager.AddDevice(CommunicationMonitor); DeviceManager.AddDevice(CommunicationMonitor);
VolumeIncrementer = new ActionIncrementer(655, 0, 65535, 800, 80, VolumeIncrementer = new ActionIncrementer(655, 0, 65535, 800, 80,