Files
Mapo-IOB-WIN/IOB-WIN-FORM/Iob/PingWatchDog.cs
T
Samuele Locatelli 46d4eade14 Update ping adapter
2026-05-19 12:41:56 +02:00

282 lines
9.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using IOB_UT_NEXT;
using IOB_UT_NEXT.Config;
using MapoSDK;
using System;
using System.Diagnostics;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading;
using System.Threading.Tasks;
namespace IOB_WIN_FORM.Iob
{
public class PingWatchDog : Generic
{
#region Public Constructors
private int bInOff = 0;
private int bInOn = 1;
private int vetoCheckSec = 5;
/// <summary>
/// Estende l'init della classe base
/// </summary>
/// <param name="caller">Form chiamante</param>
/// <param name="IobConfFull">Configurazione (v 4.x)</param>
public PingWatchDog(AdapterForm caller, IobConfTree IobConfFull) : base(caller, IobConfFull)
{
lgInfo("NEW IobPing (WatchDog)");
// init datetime counters
DateTime adesso = DateTime.Now;
lastPzCountSend = adesso;
lastWarnODL = adesso;
vetoCheckStatus = adesso;
// 2023.09.05 imposto anche primo ping e check disconnected...
lastPING = adesso;
lastDisconnCheck = adesso;
PoweroffTimeoutSec = IOBConfFull.Device.PoweroffTimeOutSec;
// imposto i valori da inviare al controllo stato...
bInOff = IOBConfFull.Special.PingConf.B_PowerOff;
bInOn = IOBConfFull.Special.PingConf.B_PowerOn;
vetoCheckSec = IOBConfFull.Special.PingConf.VetoCheckSec;
// fix coda ping
QueuePing = new DataQueue(IOBConfFull.General.FilenameIOB, "QueuePing", false, redisMan);
lgDebug($"L'adapter effettuera' PING di controllo all'indirizzo {IOBConfFull.Device.Connect.IpAddr} per forzare stato poweroff dopo {PoweroffTimeoutSec} sec");
}
#endregion Public Constructors
#region Public Methods
/// <summary>
/// metodo controllo ping lento, override AutoODL
/// </summary>
public override void processDisconnectedTask()
{
// effettuo check ping!
DateTime adesso = DateTime.Now;
var lastCheck = lastPING < lastReadPLC ? lastReadPLC : lastReadPLC;
if (adesso.Subtract(lastCheck).TotalSeconds >= PoweroffTimeoutSec)
{
// gestione invio anche in caso di disconnessione
// invio poweroff!
newDisplayData currDispData = new newDisplayData();
try
{
readSemafori(ref currDispData);
}
catch(Exception exc)
{
lgError($"Eccezione in processDisconnectedTask{Environment.NewLine}{exc}");
}
lgDebug($"processDisconnectedTask | B_output: {B_output}");
// SOLO SE ho poweroff da inviare...
if (B_output == 0)
{
accodaSigIN(ref currDispData);
// reset last ping...
lastPING = DateTime.Now;
lastReadPLC = DateTime.Now;
}
}
}
/// <summary>
/// Effettua lettura semafori principale <paramref name="currDispData">Parametri da
/// aggiornare x display in form</paramref>
/// </summary>
public override void readSemafori(ref newDisplayData currDispData)
{
Stopwatch sw = new Stopwatch();
DateTime adesso = DateTime.Now;
//lgInfo($"readSemafori | {adesso}");
sw.Start();
byte[] MemBlock = new byte[2];
// faccio comunque ping se non ne ho collezionati a sufficienza...
if (QueuePing.Count < maxQueuePing)
{
// in primis salvo data ping comunque...
lastPING = DateTime.Now;
// salvo esito ping
bool pingOK = testPingMachine == IPStatus.Success;
addTest(pingOK);
}
if (adesso.Subtract(lastPING).TotalSeconds >= vetoCheckSec)
{
try
{
currDispData.semIn = Semaforo.SV;
// in primis salvo data ping comunque...
lastPING = DateTime.Now;
// salvo esito ping
bool pingOK = testPingMachine == IPStatus.Success;
addTest(pingOK);
// se passa il ping faccio il resto...
if (pingStatusOk())
{
connectionOk = true;
lastReadPLC = DateTime.Now;
lastWatchDog = DateTime.Now;
}
else
{
connectionOk = false;
}
if (connectionOk)
{
B_input = bInOn;
}
else
{
B_input = bInOff;
}
// annullo lettura bit signal IN pre/post x evitare invio automatico...
B_output = B_input;
B_previous = B_input;
}
catch
{
currDispData.semIn = Semaforo.SR;
}
}
sw.Stop();
// fermo per una quota del tempo di attesa previsto
Task.Delay(vetoCheckSec - (int)sw.ElapsedMilliseconds + 20);
}
public override void startAdapter(bool resetQueue)
{
base.startAdapter(resetQueue);
// 2023.09.05 imposto anche primo ping e check disconnected...
DateTime adesso = DateTime.Now;
lastWatchDog = adesso;
lastReadPLC = adesso;
lastDisconnCheck = adesso;
// faccio un primo check POST ritardo
tryConnect();
}
/// <summary>
/// Override connessione
/// </summary>
public override void tryConnect()
{
bool doLog = (verboseLog || periodicLog);
lgDebug($"PING: tryConnect step 01 | connectionOk: {connectionOk}");
if (!connectionOk)
{
//// resetto coda...
//QueuePing = new DataQueue("000", "QueuePing", false);
// controllo che il ping sia stato tentato almeno pingTestSec fa...
if (DateTime.Now.Subtract(lastPING).TotalSeconds > utils.CRI("pingTestSec"))
{
if (doLog)
{
lgInfo("PING: ConnKO - tryConnect");
}
lgDebug("PING: tryConnect step 04");
lgDebug("PING: Reset QueuePing");
Stopwatch sw = new Stopwatch();
sw.Start();
bool pingOK = testPingMachine == IPStatus.Success;
addTest(pingOK);
sw.Stop();
trackReadData(4, sw.Elapsed.TotalSeconds);
// se passa il ping faccio il resto...
if (pingStatusOk())
{
// in primis salvo data ping...
lastPING = DateTime.Now;
connectionOk = true;
queueInEnabCurr = true;
lgInfo("PING OK");
}
else
{
// loggo no risposta ping ...
lgError("PING KO");
queueInEnabCurr = true;
processDisconnectedTask();
queueInEnabCurr = false;
}
}
}
}
/// <summary>
/// Override disconnessione
/// </summary>
public override void tryDisconnect()
{
lgInfo("Richiesta disconnessione adapter PING!");
connectionOk = false;
queueInEnabCurr = false;
}
#endregion Public Methods
#region Protected Fields
protected int PoweroffTimeoutSec = 100;
/// <summary>
/// Veto controllo status x log...
/// </summary>
protected DateTime vetoCheckStatus = DateTime.Now;
#endregion Protected Fields
#region Protected Methods
protected void addTest(bool pingOk)
{
int score = pingOk ? 1 : 0;
// controllo: se era spenta e risulta ping ok --> reset coda!
if (B_input == 0 && pingOk)
{
B_input = 1;
QueuePing = new DataQueue(IOBConfFull.General.FilenameIOB, "QueuePing", false, redisMan);
lgTrace($"QueuePing resetted on addTest");
}
QueuePing.Enqueue($"{score}");
while (QueuePing.Count > maxQueuePing)
{
string res = "";
QueuePing.TryDequeue(out res);
}
}
/// <summary>
/// Calcola status ping:
/// - se ha 50% coda richiesta -- true
/// - se ha 50% coda richiesta -- true se è maggior parte a 1 (true)
/// </summary>
/// <returns></returns>
protected bool pingStatusOk()
{
bool answ = true;
long numVal = QueuePing.Count;
if (numVal > maxQueuePing / 2)
{
var listaValori = QueuePing.ToList();
long numOk = listaValori.Where(x => x == "1").Count();
long numKo = numVal - numOk;
answ = numOk >= numKo;
lgTrace($"PING | numOK:{numOk} | numKO: {numKo}");
}
else
{
lgTrace("PING ok per mancanza dati minimi test");
}
return answ;
}
#endregion Protected Methods
}
}