using IOB_UT_NEXT.Config; using NLog; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net.NetworkInformation; using System.Threading; using System.Threading.Tasks; using static IOB_UT_NEXT.BaseAlarmConf; namespace IOB_UT_NEXT.Iob { /// /// Classe di base per IOB /// public class BaseObj { #region Public Fields /// /// valore booleano di check se sia stato AVVIATO l'adapter (Running) /// public bool adpRunning = false; /// /// valore booleano di check se l'adapter STIA SALVANDO /// public bool adpSaving = false; /// /// valore booleano (richiesta di riavvio automatico) /// public bool adpTryRestart; /// /// Livello minimo allarmi da considerare x invio /// public AlarmLevel alarmLevelMin = AlarmLevel.Alarm; /// /// Struttura allarmi mappati /// public List alarmMaps = new List(); /// /// Tipo di allarmi gestiti /// rif: BaseAlarmConf.AlarmBlockType.[Bitmap/ActiveList] /// public AlarmBlockType alarmType = AlarmBlockType.Bitmap; #if false /// /// Conf adapter corrente /// public IobConfiguration cIobConf; #endif /// /// Conteggio ATTUALE ore macchina IN LAVORO /// public double contOreMaccLav; /// /// Conteggio ATTUALE ore macchina ON /// public double contOreMaccOn; /// /// contatore x simulazione valori input /// public int countSim = 0; /// /// ODL attualmente sulla macchina /// public Int32 currIdxODL = 0; /// /// Modo corrente (da classe ENUM) /// public CNC_MODE currMode; /// /// ODL corrente caricato sulla macchina (stringa, da chiamata MP/IO) /// public string currODL = ""; /// /// Indica se sia richiesto campionamento memoria PERIODICO /// public bool doSampleMemory; /// /// Indica se si debba leggere e fare DUMP delle aree di memoria (1 volta solo all'avvio x debug...) /// public bool doStartMemDump; /// /// Data/ora ultimo avvio adapter /// public DateTime dtAvvioAdp = DateTime.Now; /// /// Data/ora ultimo spegnimento adapter /// public DateTime dtStopAdp = DateTime.Now; /// /// Indicazione VETO check status IOB x evitare loop troppo stretti... /// public DateTime dtVetoCheckIOB = DateTime.Now.AddDays(-1); /// /// Indicazione VETO check sync ricette x evitare loop troppo stretti... /// public DateTime dtVetoCheckSyncRecipe = DateTime.Now.AddHours(-1); /// /// Abilitazione lettura PrgName /// public bool enablePrgName = true; /// /// Abilitazione invio pezzi "in blocco" per recupero contapezzi /// public bool enableSendPzCountBlock = false; /// /// Determina se sia encessario convertire valori little/big endian (SIEMENS=true, OSAI=FALSE) /// public bool hasBigEndian = false; /// /// Configurazione gerarchica completa (v 4.x.x.x) /// public IobConfTree IOBConfFull; /// /// dataOra ultima verifica CNC disconnesso... /// public DateTime lastDisconnCheck; /// /// Data/ora ultima volta che IOB è stato dichiarato online /// public DateTime lastIobOnline = DateTime.Now.AddHours(-1); /// /// dataOra ultimo log periodico... /// public DateTime lastPeriodicLog; /// /// dataOra ultimo PING inviato verso il PLC... /// public DateTime lastPING = DateTime.Now.AddHours(-1); /// /// DataOra ultima lettura da PLC /// public DateTime lastReadPLC; /// /// ULtimo valore inviato (in caso di disconnessione lo reinvia x garantire watchdog...) /// public string lastSignInVal = ""; /// /// DateTime Ultimo valore simulazione generato /// public DateTime lastSim; /// /// dataOra ultimo segnale inviato al SERVER... /// public DateTime lastWatchDog; /// /// dataOra ultimo segnale inviato a macchina/PLC... /// public DateTime lastWatchDogPLC = DateTime.Now; /// /// Massimo numero di px da inviare in blocco /// public int maxSendPzCountBlock = 10; /// /// Struttura memoria PLC x lettura/scrittura da JSON file /// public plcMemMapExt memMap; /// /// Minimo numero di px da inviare in blocco /// public int minSendPzCountBlock = 1; /// /// Variabile booleana che indica se sia necessario fare refresh del contapezzi /// public bool needRefreshPzCount = true; /// /// Coda degli esiti di ping x calcolo stato macchina /// public DataQueue QueuePing; /// /// Determina se utilizzare blocchi di memoria IOT contigui (e quindi processing /// "monoblocco" semplificato"= /// public bool procIotMem = false; /// /// Coda valori ALLARMI ove gestiti... /// public DataQueue QueueAlarm;// = new DataQueue("000", "QueueAlarm", false); /// /// Oggetto della coda degli elementi letti di tipo FluxLog (e non ancora trasmessi) /// public DataQueue QueueFLog;// = new DataQueue("000", "QueueFLog", false); /// /// Oggetto della coda degli elementi letti (e non ancora trasmessi) /// public DataQueue QueueIN;// = new DataQueue("000", "QueueIN", false); /// /// Coda valori MESSAGGI/EVENTI (da non sottocampionare come samples)... /// public DataQueue QueueMessages;// = new DataQueue("000", "QueueMessages", false); /// /// Oggetto della coda degli elementi di tipo RawTransf (e non ancora trasmessi) /// NB: sono salvati serializzati come stringhe /// public DataQueue QueueRawTransf;// = new DataQueue("000", "QueueRawTransf", false); /// /// Coda valori LOG UTENTE (da non sottocampionare come samples)... /// public DataQueue QueueULog;// = new DataQueue("000", "QueueULog", false); /// /// alias booleano false = R /// public bool R = false; /// /// 32 byte input base (es strobe, 8 word da 32 bit di flags...) /// public byte[] RawInput = new byte[32]; /// /// 32 byte output base (es ack, 8 word da 32 bit di flags...) /// public byte[] RawOutput = new byte[32]; /// /// Oggetto connessione REDIS /// public RedisIobCache redisMan; /// /// Oggetto cronometro x campionamento durate chiamate /// public Stopwatch sw = new Stopwatch(); /// /// Oggetto gestione TempiCiclo e contapezzi /// public TCMan tcMan = new TCMan(0.5, 1.3, 5); /// /// Imposta veto lettura dati (es per DB a 2 sec) /// public DateTime vetoDataRead = DateTime.Now; /// /// Imposta veto SYNC dati (es per DB 2 DB a 10 sec) /// public DateTime vetoDataSync = DateTime.Now; /// /// Veto (in sec) a nuovi ping (x IOB PING, FTP...) /// public int vetoPingSec = 1; /// /// Imposta veto chiamata split (durante chiamata, per 60 sec) /// public DateTime vetoSplit = DateTime.Now.AddMinutes(1); /// /// alias booleano true = W /// public bool W = true; #endregion Public Fields #region Public Properties /// /// Verifica se sia in modalità DEMO avanzata (campionamento da set di valori ammessi...) /// public static bool DemoInSample { get { return baseUtils.CRB("DemoInSample"); } } /// /// Verifica se sia in modalità DEMO x dati OUTPUT /// public static bool DemoOut { get { return utils.CRB("DemoOut"); } } /// /// Indicazione VETO PING a server sino alla data-ora indicata /// public static DateTime dtVetoPing { get { return utils.dtVetoPing; } set { utils.dtVetoPing = value; } } /// /// Indicazione VETO accodamento valori INGRESSI/EVENTI sino alla data-ora indicata /// public static DateTime dtVetoQueueIN { get { return utils.dtVetoQueueIN; } set { utils.dtVetoQueueIN = value; } } /// /// Indicazione VETO invio a server sino alla data-ora indicata /// public static DateTime dtVetoSend { get { return utils.dtVetoSend; } set { utils.dtVetoSend = value; } } /// /// Verifica se sia abilitato test lettura blocchi memoria all'avvio /// public static bool EnableTest { get { return baseUtils.CRB("enableTest"); } } /// /// stato Online/Offline del server MP IO (su REDIS) /// public static bool MPOnline { get { return utils.MPIO_Online; } set { utils.MPIO_Online = value; } } #endregion Public Properties #region Public Methods /// /// Effettua chiamata URL e restituisce risultato /// /// /// invio in modalità async (NON GARANTITO ordine...) /// public static async Task callUrl(string URL, bool doAsync) { string answ = ""; if (doAsync) { answ = await utils.callUrlAsync(URL); } else { answ = await Task.Run(() => utils.callUrl(URL)); } if (urlRandWait > 0) { // NON blocca il thread, libera risorse per le altre 20 istanze await Task.Delay(rnd.Next(urlRandWait / 10, urlRandWait)); } return answ; } /// /// Effettua chiamata URL e restituisce risultato /// /// /// /// invio in modalità async (NON GARANTITO ordine...) /// public static async Task callUrlWithPayloadAsync(string URL, string payload, bool doAsync) { string answ = ""; if (doAsync) { answ = await utils.callUrlAsync(URL, payload); } else { answ = await Task.Run(() => utils.callUrl(URL, payload)); } if (urlRandWait > 0) { // NON blocca il thread, libera risorse per le altre 20 istanze await Task.Delay(rnd.Next(urlRandWait / 10, urlRandWait)); } return answ; } /// /// processa dataLayer e se necessario salva/mostra /// public static void checkSavePersDataLayer() { } public static string GetMACAddress() { NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces(); String sMacAddress = string.Empty; foreach (NetworkInterface adapter in nics) { if (string.IsNullOrEmpty(sMacAddress))// only return MAC Address from first card { IPInterfaceProperties properties = adapter.GetIPProperties(); //sMacAddress = adapter.GetPhysicalAddress().ToString(); sMacAddress = string.Join(":", (from z in adapter.GetPhysicalAddress().GetAddressBytes() select z.ToString("X2")).ToArray()); } } return sMacAddress; } public static void resetDebugConsole() { } /// /// Reset dei webclients /// public static void resetWebClients() { utils.resetWebClients(); } #endregion Public Methods #region Protected Fields /// /// Valore di attesa (random) dopo ogni invio x evitare congestione send... /// protected static int urlRandWait = 0; /// /// Disabilitazione gestione ODL (lettura e gestione) /// protected bool disableOdl = false; //protected static Logger lg = LogManager.GetCurrentClassLogger(); /// /// Abilitazione invio conf macchine /// protected bool enabSendMachineConf = true; /// /// Ultimo LOG registrazione avvio (x ridurre log notturni...) /// protected DateTime lastLogStartup = DateTime.Today.AddHours(-1); /// /// Dimensione coda di ping x valutazione /// protected int maxQueuePing = 11; /// /// Tempo minimo ammissibile di risposta (es x errori ModBus che risponde troppo in fretta) in millisec /// protected int minRespTimeMs = 5; /// /// Indica se resettare allarmi all'avvio e inviare il reset appena parte adapter /// protected bool resetAlarmOnStart = false; /// /// Veto per registrazione completa log di startup (minuti) /// protected int vetoLogStartupDuration = 60; #endregion Protected Fields #region Protected Properties /// /// Dizionario condizioni di veto log x ogni tipo di messaggio (periodo differente secondo livello) /// protected Dictionary VetoLog { get; set; } = new Dictionary(); /// /// Dizionario conteggio numero volte che si fa veto log x ogni tipo di messaggio /// protected Dictionary VetoLogCount { get; set; } = new Dictionary(); #endregion Protected Properties #region Protected Methods /// /// Verifica se ci sia veto log attivo e gestisce casistiche /// /// /// /// protected bool checkLogVeto(int vetoSec, ref string message) { // verifico SE si debba fare log, altrimenti metto in coda... bool doVeto = true; try { DateTime adesso = DateTime.Now; if (VetoLog.ContainsKey(message)) { // conteggio num veto a +1... if (VetoLogCount.ContainsKey(message)) { VetoLogCount[message]++; } else { VetoLogCount.Add(message, 1); } // controllo scadenza, quando superata soglia aggiorno messaggio con {n} x {messaggio} if (adesso.Subtract(VetoLog[message]).TotalSeconds > vetoSec) { doVeto = false; string newMessage = $"{VetoLogCount[message]} x {message}"; VetoLog.Remove(message); VetoLogCount.Remove(message); message = newMessage; } } else { // primo --> loggo doVeto = false; VetoLog.Add(message, adesso.AddSeconds(vetoSec)); if (VetoLogCount.ContainsKey(message)) { VetoLogCount[message]++; } else { VetoLogCount.Add(message, 0); } } } catch (Exception exc) { lg.Error($"Eccezione in checkLogVeto: reset contatori VetoLog/VetoLogCount | message: {message}"); lg.Error($"Raised Exc:{Environment.NewLine}{exc}"); doVeto = false; // svuoto tutti i log veto... VetoLog = new Dictionary(); VetoLogCount = new Dictionary(); lg.Error($"Effettuato reset contatori VetoLog/VetoLogCount"); } // restituisco esito! return doVeto; } /// /// Setup di tutti gli oggetti Queue, ma solo alcuni hanno coda REDIS (quelli senza sono "sacrificabili" /// protected void SetupQueue() { string codIob = IOBConfFull.General.FilenameIOB; bool useRedis = IOBConfFull.General.EnabRedisQue; QueueAlarm = new DataQueue(codIob, "QueueAlarm", false, redisMan); // valutare se portare di nuovo in redis... QueueIN = new DataQueue(codIob, "QueueIN", useRedis, redisMan); // fix a NON redis QueueFLog = new DataQueue(codIob, "QueueFLog", false, redisMan); //QueueFLog = new DataQueue(codIob, "QueueFLog", useRedis, redisMan); QueueMessages = new DataQueue(codIob, "QueueMessages", false, redisMan); QueueRawTransf = new DataQueue(codIob, "QueueRawTransf", false, redisMan); QueueULog = new DataQueue(codIob, "QueueULog", false, redisMan); QueuePing = new DataQueue(codIob, "QueuePing", false, redisMan); } #endregion Protected Methods #region Private Fields /// /// wrapper di log /// private static readonly Logger lg = LogManager.GetCurrentClassLogger(); private static Random rnd = new Random(); #endregion Private Fields } }