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 /// /// Estende l'init della classe base /// /// /// 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 /// /// metodo controllo ping lento, override AutoODL /// 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; } } } /// /// Effettua lettura semafori principale Parametri da /// aggiornare x display in form /// 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(); } /// /// Override connessione /// 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"); } } } } /// /// Override disconnessione /// public override void tryDisconnect() { lgInfo("Richiesta disconnessione adapter PING!"); connectionOk = false; queueInEnabCurr = false; } #endregion Public Methods #region Protected Fields /// /// Dimensione coda di ping x valutazione /// protected int maxQueuePing = 11; /// /// Coda degli esiti di ping x calcolo stato macchina /// protected DataQueue PingQueue = new DataQueue("000", "PingQueue", false); protected int PoweroffTimeoutSec = 100; /// /// Veto controllo status x log... /// 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); } } /// /// Calcola status ping: /// - se ha ‹ 50% coda richiesta --› true /// - se ha › 50% coda richiesta --› true se è maggior parte a 1 (true) /// /// 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 } }