using MapoSDK; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace IOB_UT { /// /// informazioni di produzione /// public struct prodData { #region Public Fields public int AccTime; public bool EmrStop; public string FuncMode; public string MessageCode; public string MessageText; public string Operator; public int Power; public bool Status; #endregion Public Fields } /// /// Gestione Endianness /// public static class Endian { #region Public Methods /// /// Scambia MSB/LSB per 16bit /// /// /// public static UInt16 SwapUInt16(UInt16 inValue) { return (UInt16)(((inValue & 0xff00) >> 8) | ((inValue & 0x00ff) << 8)); } /// /// Scambia MSB/LSB per 32bit /// /// /// public static UInt32 SwapUInt32(UInt32 inValue) { return ((inValue & 0xff000000) >> 24) | ((inValue & 0x00ff0000) >> 8) | ((inValue & 0x0000ff00) << 8) | ((inValue & 0x000000ff) << 24); } #endregion Public Methods } /// /// GEstione dati di timing /// public static class TimingData { #region Public Fields public static List results = new List(); #endregion Public Fields #region Public Methods /// /// aggiorno vettore aggiungendo risultato /// /// Codice chiamante /// Codice da registrare (univoco con chiamante) /// Tempo esecuzione in ticks public static void addResult(string caller, string codice, long ticks) { if (results.Count == 0) { results.Add(new TimeRec(caller, codice, ticks)); } int indice = -1; for (int i = 0; i < results.Count; i++) { // se il codice è quello cercato... if (results[i].codCall == codice && results[i].classCall == caller) { indice = i; } } // se c'è aggiorno... if (indice >= 0) { results[indice].numCall++; results[indice].totMsec = results[indice].totMsec.Add(new TimeSpan(ticks)); } // altrimenti aggiungo... else { results.Add(new TimeRec(caller, codice, ticks)); } } /// /// Resetta i dati registrati (ad avvio adapter...) /// public static void resetData() { results = new List(); } #endregion Public Methods } /// /// Cache a tempo valori INT /// public class CachedInt { #region Public Properties public DateTime ValidUntil { get; set; } = DateTime.Now; public int Value { get; set; } = 0; #endregion Public Properties } /// /// Cache a tempo valori String /// public class CachedString { #region Public Properties public DateTime ValidUntil { get; set; } = DateTime.Now; public string Value { get; set; } = ""; #endregion Public Properties } /// /// Classe conf x item DynData /// public class DynDataItem { #region Public Fields /// /// DataOra scadenza invio forzato /// public DateTime DTScad = DateTime.Now; #endregion Public Fields #region Public Properties /// /// Valore effettivo da salvare /// public string actVal { get; set; } = ""; public string func { get; set; } = ""; public string key { get; set; } = ""; public string name { get; set; } = ""; public int sPeriod { get; set; } = 60; public string unit { get; set; } = ""; public string val { get; set; } = ""; #endregion Public Properties } /// /// Configurazione per Eventi/Variabili /// public class EVData { #region Public Fields /// /// DataOra scadenza invio forzato /// public DateTime DTScad = DateTime.Now; #endregion Public Fields #region Public Properties /// /// Unità di misura /// public string UM { get; set; } = "num"; /// /// Valore salvato /// public string Val { get; set; } = ""; #endregion Public Properties } /// /// Rappresentazione dello stato corrente dell'IOB /// public class IobWinStatus { #region Public Properties /// /// ID univoco /// public string CodIob { get; set; } = "0"; /// /// Contatore IOB /// public float counterIOB { get; set; } = 0; /// /// Contatore Macchina /// public float counterMAC { get; set; } = 0; /// /// DataOra ultima comunicazione IN (con PLC) /// public DateTime lastDataIn { get; set; } = DateTime.Now.AddMinutes(-1); /// /// DataOra ultima comunicazione OUT (con MP Server) /// public DateTime lastUpdate { get; set; } = DateTime.Now.AddDays(-1); /// /// Status del SINGOLO IOB /// public bool online { get; set; } = false; #if false /// /// Indica se sia correntemente in setup /// public bool inSetup { get; set; } = false; /// /// Semaforo IN (IOB-PLC) /// public Semaforo SemIn { get; set; } = Semaforo.ND; /// /// Semaforo OUT (IOB-MPserver) /// public Semaforo SemOut { get; set; } = Semaforo.ND; #endif /// /// Lungh coda ALLARMI in uscita /// public int queueAlLen { get; set; } = 0; /// /// Lunghezza coda EVENTI in uscita /// public int queueEvLen { get; set; } = 0; /// /// Lunghezza coda FluxLog in uscita /// public int queueFlLen { get; set; } = 0; /// /// Lungh coda MESSAGGI in uscita /// public int queueMsLen { get; set; } = 0; #endregion Public Properties #if false /// /// DataOra ultima comunicazione OUT (con MP Server) /// public DateTime lastDataOut { get; set; } = DateTime.Now.AddDays(-1); /// /// Ultimo stato noto dei parametri in memoria letti da PLC /// public Dictionary currParams { get; set; } = null; #endif } /// /// Elenco oggetti del monitoraggio (DynData, Status) per WPS /// public class MonitoredItemsConf { #region Public Properties public List DynData { get; set; } public srvData SrvData { get; set; } public List Status { get; set; } #endregion Public Properties } /// /// Classe che contiene tutte le NUOVE informazioni da aggiornare sulla form /// public class newDisplayData { #region Public Properties /// /// Oggetto COUTNER generico (pezzi, portata...) /// public int counter { get; set; } = -9999; /// /// Bitmap attuale segnali letti /// public string currBitmap { get; set; } = ""; /// /// Verifica se contenga valori (NON default/empty) /// public bool hasData { get { bool answ = false; // true se qualcosa NON E' come default if (!string.IsNullOrWhiteSpace(newInData) || !string.IsNullOrWhiteSpace(newSignalData) || !string.IsNullOrWhiteSpace(newFLogData) || !string.IsNullOrWhiteSpace(newUrlCallData) || !string.IsNullOrWhiteSpace(newLiveLogData) || counter > -9999 || !string.IsNullOrWhiteSpace(currBitmap) || semIn != Semaforo.ND || semOut != Semaforo.ND) { answ = true; } return answ; } } /// /// Dati tipo FluxLog /// public string newFLogData { get; set; } = ""; /// /// Dati tipo IN (RAW) /// public string newInData { get; set; } = ""; /// /// Dati tipo LiveLog /// public string newLiveLogData { get; set; } = ""; /// /// Dati tipo Signal /// public string newSignalData { get; set; } = ""; /// /// Dati tipo UrlCall /// public string newUrlCallData { get; set; } = ""; /// /// Stato semaforo IN verso PLC /// public Semaforo semIn { get; set; } = Semaforo.ND; /// /// Stato semaforo OUT verso MES /// public Semaforo semOut { get; set; } = Semaforo.ND; #endregion Public Properties } /// /// Dato generico (per decodifica) /// public class otherData { #region Public Fields public string codNum; public string dataType; public string memAddr; public string varName; #endregion Public Fields #region Public Constructors public otherData() { codNum = ""; memAddr = ""; varName = ""; dataType = ""; } public otherData(string _codNum, string _memAddr, string _varName, string _dataType) { codNum = _codNum; memAddr = _memAddr; varName = _varName; dataType = _dataType; } #endregion Public Constructors } /// /// Classe gestione valori campionati su periodo /// public class sampleVect { #region Protected Fields /// /// vettore valori temporali della serie /// protected List lTime; /// /// vettore valoti puntuali della serie /// protected List lVal; /// /// Dimensione finestra di campionamento (secondi) /// protected int windSize; #endregion Protected Fields #region Public Constructors /// /// Inizializzo l'oggetto /// public sampleVect() { // init valori default... windSize = baseUtils.CRI("countWindSize") > 0 ? baseUtils.CRI("countWindSize") : 60; lTime = new List(); lVal = new List(); } #endregion Public Constructors #region Protected Properties /// /// Verifica ampiezza finestra valori First-Last /// protected double flWindSize { get { double answ = 0; if (numElem > 1) { answ = lTime.Last().Subtract(lTime[0]).TotalSeconds; } return answ; } } /// /// Conteggio elementi /// protected int numElem { get { int answ = 0; try { answ = lTime.Count; } catch { } return answ; } } /// /// Verifica ampiezza finestra valori Second-Last /// protected double slWindSize { get { double answ = 0; if (numElem > 2) // altrimenti SE non ne ho almeno 3 NON posso avere secondo/ultimo... { answ = lTime.Last().Subtract(lTime[1]).TotalSeconds; } return answ; } } #endregion Protected Properties #region Public Properties /// /// Calcola il valore mediano... /// public double vcMedian { get { double answ = 0; // restituisce la mediana SE valida, altrimenti null... if (numElem > 2 && flWindSize > windSize) { try { // calcolo mediana! //answ = Statistics.Median(lVal.ToArray()); // rif: https://blogs.msmvps.com/deborahk/linq-mean-median-and-mode/ var sortedNumbers = lVal.OrderBy(n => n); int numCount = lVal.Count; int indice50 = lVal.Count / 2; if ((numCount % 2) == 0) { answ = ((sortedNumbers.ElementAt(indice50) + sortedNumbers.ElementAt(indice50 - 1)) / 2); } else { answ = sortedNumbers.ElementAt(indice50); } } catch { } } return answ; } } /// /// Verifica se la vc sia valida (ovvero almeno 2 valori e intervallo > window richiesta) /// public bool vcValid { get { return (flWindSize > windSize && numElem > 1); } } #endregion Public Properties #region Public Methods /// /// Aggiunge un valore alla serie ed eventualmente elimina i valori superflui a garantirne una finestra temporale valida /// /// /// public void addValue(DateTime tempo, int valore) { lTime.Add(tempo); lVal.Add(valore); // verifico se siano da accorciare le serie... ovvero i 2 intervalli ENTRAMBI sono superiori al periodo minimo (in tal caso riduco.. while (flWindSize > windSize && slWindSize > windSize) { // elimino i 2 valori + vecchi lTime.RemoveAt(0); lVal.RemoveAt(0); // ora ricontrollo... } } #endregion Public Methods } /// /// Classe x descrivere status server MP /// public class ServerMpStatus { #region Public Properties /// /// IP server /// public string IP { get; set; } /// /// DataOra ultima comunicazione OUT (con MP Server) /// public DateTime lastUpdate { get; set; } = DateTime.Now.AddDays(-1); /// /// Status del server /// public bool online { get; set; } = false; #endregion Public Properties } /// /// Classe conf server html /// public class srvData { #region Public Properties public string baseUri { get; set; } = ""; public string driverName { get; set; } = ""; #endregion Public Properties } /// /// Classe conf x decodifica stsatus /// public class StatusItem : DynDataItem { #region Public Fields public Dictionary codeMapping; #endregion Public Fields } /// /// Oggetto timing x archiviazione dati perfomances /// public class TimeRec { #region Public Fields /// /// Classe chiamante della funzione (es codice univoco IOB) /// public string classCall; /// /// Codice univoco chiamata: tipo R4 (read 4 byte), W2 (write 2 Byte) /// public string codCall; /// /// Num chiamate totale /// public int numCall; /// /// Totale Msec accumulati /// public TimeSpan totMsec; #endregion Public Fields #region Public Constructors /// /// Classe record timing /// public TimeRec() { codCall = ""; numCall = 0; totMsec = new TimeSpan(0); } /// /// Classe record timing /// /// /// /// public TimeRec(string caller, string codice, long nTicks) { classCall = caller; codCall = codice; numCall = 1; totMsec = new TimeSpan(nTicks); } #endregion Public Constructors #region Public Properties /// /// Tempo medio chiamata /// public double avgMsec { get { return totMsec.TotalMilliseconds / numCall; } } #endregion Public Properties } /// /// Configurazione per Variabili Casuali /// public class VCData { #region Public Fields /// /// Array dati per calcolo /// public List dataArray; /// /// DataOra inizio periodo di elaborazione /// public DateTime DTStart; #endregion Public Fields #region Public Properties /// /// Tipologia di funzione da applicare /// public VC_func Funzione { get; set; } = VC_func.POINT; /// /// Periodo di riferimento /// public int Period { get; set; } = 60; #endregion Public Properties } }