95f2b208c9
- inizio modifica x inclusione calcolo MD5 e import DB Ricette
699 lines
18 KiB
C#
699 lines
18 KiB
C#
using MapoSDK;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace IOB_UT_NEXT
|
|
{
|
|
/// <summary>
|
|
/// informazioni di produzione
|
|
/// </summary>
|
|
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
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gestione Endianness
|
|
/// </summary>
|
|
public static class Endian
|
|
{
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Scambia MSB/LSB per 16bit
|
|
/// </summary>
|
|
/// <param name="inValue"></param>
|
|
/// <returns></returns>
|
|
public static UInt16 SwapUInt16(UInt16 inValue)
|
|
{
|
|
return (UInt16)(((inValue & 0xff00) >> 8) |
|
|
((inValue & 0x00ff) << 8));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Scambia MSB/LSB per 32bit
|
|
/// </summary>
|
|
/// <param name="inValue"></param>
|
|
/// <returns></returns>
|
|
public static UInt32 SwapUInt32(UInt32 inValue)
|
|
{
|
|
return ((inValue & 0xff000000) >> 24) |
|
|
((inValue & 0x00ff0000) >> 8) |
|
|
((inValue & 0x0000ff00) << 8) |
|
|
((inValue & 0x000000ff) << 24);
|
|
}
|
|
|
|
#endregion Public Methods
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco task di tipo FTP
|
|
/// </summary>
|
|
public class FtpTaskList
|
|
{
|
|
public List<FtpActConf> ListTask { get; set; } = new List<FtpActConf>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco task generici
|
|
/// </summary>
|
|
public class GenTaskList
|
|
{
|
|
public List<GenActConf> ListTask { get; set; } = new List<GenActConf>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gestione dati di timing
|
|
/// </summary>
|
|
public static class TimingData
|
|
{
|
|
#region Public Fields
|
|
|
|
public static List<TimeRec> results = new List<TimeRec>();
|
|
|
|
#endregion Public Fields
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// aggiorno vettore aggiungendo risultato
|
|
/// </summary>
|
|
/// <param name="caller">Codice chiamante</param>
|
|
/// <param name="codice">Codice da registrare (univoco con chiamante)</param>
|
|
/// <param name="ticks">Tempo esecuzione in ticks</param>
|
|
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));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resetta i dati registrati (ad avvio adapter...)
|
|
/// </summary>
|
|
public static void resetData()
|
|
{
|
|
results = new List<TimeRec>();
|
|
}
|
|
|
|
#endregion Public Methods
|
|
}
|
|
|
|
/// <summary>
|
|
/// Cache a tempo valori INT
|
|
/// </summary>
|
|
public class CachedInt
|
|
{
|
|
#region Public Properties
|
|
|
|
public DateTime ValidUntil { get; set; } = DateTime.Now;
|
|
public int Value { get; set; } = 0;
|
|
|
|
#endregion Public Properties
|
|
}
|
|
|
|
/// <summary>
|
|
/// Cache a tempo valori String
|
|
/// </summary>
|
|
public class CachedString
|
|
{
|
|
#region Public Properties
|
|
|
|
public DateTime ValidUntil { get; set; } = DateTime.Now;
|
|
public string Value { get; set; } = "";
|
|
|
|
#endregion Public Properties
|
|
}
|
|
|
|
/// <summary>
|
|
/// Classe conf x item DynData
|
|
/// </summary>
|
|
public class DynDataItem
|
|
{
|
|
#region Public Fields
|
|
|
|
/// <summary>
|
|
/// DataOra scadenza invio forzato
|
|
/// </summary>
|
|
public DateTime DTScad = DateTime.Now;
|
|
|
|
#endregion Public Fields
|
|
|
|
#region Public Properties
|
|
|
|
/// <summary>
|
|
/// Valore effettivo da salvare
|
|
/// </summary>
|
|
public string actVal { get; set; } = "";
|
|
|
|
public string func { get; set; } = "";
|
|
public string key { get; set; } = "";
|
|
public int maxVal { get; set; }
|
|
public int minVal { 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
|
|
}
|
|
|
|
/// <summary>
|
|
/// Configurazione per Eventi/Variabili
|
|
/// </summary>
|
|
public class EVData
|
|
{
|
|
#region Public Fields
|
|
|
|
/// <summary>
|
|
/// DataOra scadenza invio forzato
|
|
/// </summary>
|
|
public DateTime DTScad = DateTime.Now;
|
|
|
|
#endregion Public Fields
|
|
|
|
#region Public Properties
|
|
|
|
/// <summary>
|
|
/// Unità di misura
|
|
/// </summary>
|
|
public string UM { get; set; } = "num";
|
|
|
|
/// <summary>
|
|
/// Valore salvato
|
|
/// </summary>
|
|
public string Val { get; set; } = "";
|
|
|
|
#endregion Public Properties
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco oggetti del monitoraggio (DynData, Status) per WPS
|
|
/// </summary>
|
|
public class MonitoredItemsConf
|
|
{
|
|
#region Public Properties
|
|
|
|
public List<DynDataItem> DynData { get; set; }
|
|
public srvData SrvData { get; set; }
|
|
public List<StatusItem> Status { get; set; }
|
|
|
|
#endregion Public Properties
|
|
}
|
|
|
|
/// <summary>
|
|
/// Classe che contiene tutte le NUOVE informazioni da aggiornare sulla form
|
|
/// </summary>
|
|
public class newDisplayData
|
|
{
|
|
#region Public Properties
|
|
|
|
/// <summary>
|
|
/// Oggetto COUTNER generico (pezzi, portata...)
|
|
/// </summary>
|
|
public int counter { get; set; } = -9999;
|
|
|
|
/// <summary>
|
|
/// Bitmap attuale segnali letti
|
|
/// </summary>
|
|
public string currBitmap { get; set; } = "";
|
|
|
|
/// <summary>
|
|
/// Verifica se contenga valori (NON default/empty)
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dati tipo FluxLog
|
|
/// </summary>
|
|
public string newFLogData { get; set; } = "";
|
|
|
|
/// <summary>
|
|
/// Dati tipo IN (RAW)
|
|
/// </summary>
|
|
public string newInData { get; set; } = "";
|
|
|
|
/// <summary>
|
|
/// Dati tipo LiveLog
|
|
/// </summary>
|
|
public string newLiveLogData { get; set; } = "";
|
|
|
|
/// <summary>
|
|
/// Dati tipo Signal
|
|
/// </summary>
|
|
public string newSignalData { get; set; } = "";
|
|
|
|
/// <summary>
|
|
/// Dati tipo UrlCall
|
|
/// </summary>
|
|
public string newUrlCallData { get; set; } = "";
|
|
|
|
/// <summary>
|
|
/// Stato semaforo IN verso PLC
|
|
/// </summary>
|
|
public Semaforo semIn { get; set; } = Semaforo.ND;
|
|
|
|
/// <summary>
|
|
/// Stato semaforo OUT verso MES
|
|
/// </summary>
|
|
public Semaforo semOut { get; set; } = Semaforo.ND;
|
|
|
|
#endregion Public Properties
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dato generico (per decodifica)
|
|
/// </summary>
|
|
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
|
|
}
|
|
|
|
/// <summary>
|
|
/// Classe gestione valori campionati su periodo
|
|
/// </summary>
|
|
public class sampleVect
|
|
{
|
|
#region Public Constructors
|
|
|
|
/// <summary>
|
|
/// Inizializzo l'oggetto
|
|
/// </summary>
|
|
public sampleVect()
|
|
{
|
|
// init valori default...
|
|
windSize = baseUtils.CRI("countWindSize") > 0 ? baseUtils.CRI("countWindSize") : 60;
|
|
lTime = new List<DateTime>();
|
|
lVal = new List<int>();
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Properties
|
|
|
|
/// <summary>
|
|
/// Calcola il valore mediano...
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifica se la vc sia valida (ovvero almeno 2 valori e intervallo > window richiesta)
|
|
/// </summary>
|
|
public bool vcValid
|
|
{
|
|
get
|
|
{
|
|
return (flWindSize > windSize && numElem > 1);
|
|
}
|
|
}
|
|
|
|
#endregion Public Properties
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Aggiunge un valore alla serie ed eventualmente elimina i valori superflui a garantirne
|
|
/// una finestra temporale valida
|
|
/// </summary>
|
|
/// <param name="tempo"></param>
|
|
/// <param name="valore"></param>
|
|
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
|
|
|
|
#region Protected Fields
|
|
|
|
/// <summary>
|
|
/// vettore valori temporali della serie
|
|
/// </summary>
|
|
protected List<DateTime> lTime;
|
|
|
|
/// <summary>
|
|
/// vettore valori puntuali della serie
|
|
/// </summary>
|
|
protected List<int> lVal;
|
|
|
|
/// <summary>
|
|
/// Dimensione finestra di campionamento (secondi)
|
|
/// </summary>
|
|
protected int windSize;
|
|
|
|
#endregion Protected Fields
|
|
|
|
#region Protected Properties
|
|
|
|
/// <summary>
|
|
/// Verifica ampiezza finestra valori First-Last
|
|
/// </summary>
|
|
protected double flWindSize
|
|
{
|
|
get
|
|
{
|
|
double answ = 0;
|
|
if (numElem > 1)
|
|
{
|
|
answ = lTime.Last().Subtract(lTime[0]).TotalSeconds;
|
|
}
|
|
return answ;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Conteggio elementi
|
|
/// </summary>
|
|
protected int numElem
|
|
{
|
|
get
|
|
{
|
|
int answ = 0;
|
|
try
|
|
{
|
|
answ = lTime.Count;
|
|
}
|
|
catch
|
|
{ }
|
|
return answ;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifica ampiezza finestra valori Second-Last
|
|
/// </summary>
|
|
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
|
|
}
|
|
|
|
/// <summary>
|
|
/// Classe x descrivere status server MP
|
|
/// </summary>
|
|
public class ServerMpStatus
|
|
{
|
|
#region Public Properties
|
|
|
|
/// <summary>
|
|
/// IP server
|
|
/// </summary>
|
|
public string IP { get; set; }
|
|
|
|
/// <summary>
|
|
/// DataOra ultima comunicazione OUT (con MP Server)
|
|
/// </summary>
|
|
public DateTime lastUpdate { get; set; } = DateTime.Now.AddDays(-1);
|
|
|
|
/// <summary>
|
|
/// Status del server
|
|
/// </summary>
|
|
public bool online { get; set; } = false;
|
|
|
|
#endregion Public Properties
|
|
}
|
|
|
|
/// <summary>
|
|
/// Classe conf server html
|
|
/// </summary>
|
|
public class srvData
|
|
{
|
|
#region Public Properties
|
|
|
|
public string baseUri { get; set; } = "";
|
|
public string driverName { get; set; } = "";
|
|
|
|
#endregion Public Properties
|
|
}
|
|
|
|
/// <summary>
|
|
/// Classe conf x decodifica status
|
|
/// </summary>
|
|
public class StatusItem : DynDataItem
|
|
{
|
|
#region Public Fields
|
|
|
|
public Dictionary<string, string> codeMapping;
|
|
|
|
#endregion Public Fields
|
|
}
|
|
|
|
/// <summary>
|
|
/// Oggetto timing x archiviazione dati perfomances
|
|
/// </summary>
|
|
public class TimeRec
|
|
{
|
|
#region Public Fields
|
|
|
|
/// <summary>
|
|
/// Classe chiamante della funzione (es codice univoco IOB)
|
|
/// </summary>
|
|
public string classCall;
|
|
|
|
/// <summary>
|
|
/// Codice univoco chiamata: tipo R4 (read 4 byte), W2 (write 2 Byte)
|
|
/// </summary>
|
|
public string codCall;
|
|
|
|
/// <summary>
|
|
/// Num chiamate totale
|
|
/// </summary>
|
|
public int numCall;
|
|
|
|
/// <summary>
|
|
/// Totale Msec accumulati
|
|
/// </summary>
|
|
public TimeSpan totMsec;
|
|
|
|
#endregion Public Fields
|
|
|
|
#region Public Constructors
|
|
|
|
/// <summary>
|
|
/// Classe record timing
|
|
/// </summary>
|
|
public TimeRec()
|
|
{
|
|
codCall = "";
|
|
numCall = 0;
|
|
totMsec = new TimeSpan(0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Classe record timing
|
|
/// </summary>
|
|
/// <param name="caller"></param>
|
|
/// <param name="codice"></param>
|
|
/// <param name="ticks"></param>
|
|
public TimeRec(string caller, string codice, long nTicks)
|
|
{
|
|
classCall = caller;
|
|
codCall = codice;
|
|
numCall = 1;
|
|
totMsec = new TimeSpan(nTicks);
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Properties
|
|
|
|
/// <summary>
|
|
/// Tempo medio chiamata
|
|
/// </summary>
|
|
public double avgMsec
|
|
{
|
|
get
|
|
{
|
|
return totMsec.TotalMilliseconds / numCall;
|
|
}
|
|
}
|
|
|
|
#endregion Public Properties
|
|
}
|
|
|
|
/// <summary>
|
|
/// Configurazione per Variabili Casuali
|
|
/// </summary>
|
|
public class VCData
|
|
{
|
|
#region Public Fields
|
|
|
|
/// <summary>
|
|
/// Array dati per calcolo
|
|
/// </summary>
|
|
public List<double> dataArray;
|
|
|
|
/// <summary>
|
|
/// DataOra inizio periodo di elaborazione
|
|
/// </summary>
|
|
public DateTime DTStart;
|
|
|
|
#endregion Public Fields
|
|
|
|
#region Public Properties
|
|
|
|
/// <summary>
|
|
/// Tipologia di funzione da applicare
|
|
/// </summary>
|
|
public VC_func Funzione { get; set; } = VC_func.POINT;
|
|
|
|
/// <summary>
|
|
/// Periodo di riferimento
|
|
/// </summary>
|
|
public int Period { get; set; } = 60;
|
|
|
|
/// <summary>
|
|
/// UM parametro, impiegato anche x conversione (es epoch --> datetime)
|
|
/// </summary>
|
|
public string UM { get; set; } = "";
|
|
|
|
#endregion Public Properties
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generico evento log
|
|
/// </summary>
|
|
public class GenLogRow
|
|
{
|
|
public DateTime dtRif { get; set; } = DateTime.Now;
|
|
|
|
public string valString { get; set; } = "";
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Informazioni generiche su batch produzione rilevati
|
|
/// </summary>
|
|
public class ProdBatchData
|
|
{
|
|
public DateTime dtStart { get; set; } = DateTime.Now;
|
|
public DateTime? dtEnd { get; set; } = null;
|
|
|
|
public string codArt { get; set; } = "";
|
|
public int numPz { get; set; } = 0;
|
|
}
|
|
} |