Files
Mapo-IOB-WIN/IOB-WIN-NEXT/IobNet/Ping.cs
T
2023-09-08 18:45:45 +02:00

241 lines
7.9 KiB
C#

using IOB_UT_NEXT;
using MapoSDK;
using System;
using System.Linq;
using System.Net.NetworkInformation;
namespace IOB_WIN_NEXT.IobNet
{
public class Ping : Iob.Generic
{
#region Public Constructors
/// <summary> Estende l'init della classe base <param name="caller"></param> <param name="IOBConf"></param>
public Ping(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf)
{
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;
var POWEROFF_TIMEOUT_SEC = getOptPar("POWEROFF_TIMEOUT_SEC");
if (!string.IsNullOrEmpty(POWEROFF_TIMEOUT_SEC))
{
int.TryParse(POWEROFF_TIMEOUT_SEC, out PoweroffTimeoutSec);
}
// fix coda ping
PingQueue = new DataQueue("000", "PingQueue", false);
lgDebug($"L'adapter effettuera' PING di controllo all'indirizzo {cIobConf.cncPingAddr} 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;
if (adesso.Subtract(lastPING).TotalSeconds >= PoweroffTimeoutSec)
{
// invio poweroff!
newDisplayData currDispData = new newDisplayData();
readSemafori(ref currDispData);
// SOLO SE ho poweroff da inviare...
if (B_output == 0)
{
accodaSigIN(ref currDispData);
// reset last ping...
lastPING = 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)
{
byte[] MemBlock = new byte[2];
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 = 1;
}
else
{
B_input = 0;
}
// annullo lettura bit signal IN pre/post x evitare invio automatico...
B_output = B_input;
B_previous = B_input;
}
catch
{
currDispData.semIn = Semaforo.SR;
}
}
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;
//lastPING = 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...
//PingQueue = new DataQueue("000", "PingQueue", 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 PingQueue");
bool pingOK = testPingMachine == IPStatus.Success;
addTest(pingOK);
// 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");
}
}
}
}
/// <summary>
/// Override disconnessione
/// </summary>
public override void tryDisconnect()
{
lgInfo("Richiesta disconnessione adapter PING!");
connectionOk = false;
queueInEnabCurr = false;
}
#endregion Public Methods
#region Protected Fields
/// <summary>
/// Dimensione coda di ping x valutazione
/// </summary>
protected int maxQueuePing = 11;
/// <summary>
/// Coda degli esiti di ping x calcolo stato macchina
/// </summary>
protected DataQueue PingQueue = new DataQueue("000", "PingQueue", false);
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;
PingQueue = new DataQueue("000", "PingQueue", false);
lgTrace($"PingQueue resetted on addTest");
}
PingQueue.Enqueue($"{score}");
while (PingQueue.Count > maxQueuePing)
{
string res = "";
PingQueue.TryDequeue(out res);
}
}
/// <summary> calcola status ping:
/// - se ha < 50% coda richiesta --> true
/// - se ha > 50% del max coda --> true se èmaggior parte a 1 (true) </summary> <returns></returns>
protected bool pingStatusOk()
{
bool answ = true;
int numVal = PingQueue.Count;
if (numVal > maxQueuePing / 2)
{
var listaValori = PingQueue.ToList();
int numOk = listaValori.Where(x => x == "1").Count();
int numKo = numVal - numOk;
answ = numOk >= numKo;
lgTrace($"PING ok per: {numOk} > {numKo}");
}
else
{
lgTrace("PING ok per mancanza dati minimi test");
}
return answ;
}
#endregion Protected Methods
}
}