Files
Samuele Locatelli 95f2b208c9 WS:
- inizio modifica x inclusione calcolo MD5 e import DB Ricette
2025-07-16 16:28:05 +02:00

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 &gt; 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 --&gt; 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;
}
}