Files
Mapo-IOB-WIN/IOB-UT/baseUtils.cs
T
2019-10-11 12:01:16 +02:00

1548 lines
38 KiB
C#

using NLog;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
namespace IOB_UT
{
/// <summary>
/// Override metodo WebCLient con gesitone TimeOut corto
/// </summary>
public class WebClientWT : WebClient
{
/// <summary>
/// timeout da conf
/// </summary>
protected int urlCallTOut
{
get
{
int answ = 5000;
answ = baseUtils.CRI("urlCallTOut");
if (answ < 0 || answ > 10000)
{
answ = 3000;
}
return answ;
}
}
protected override WebRequest GetWebRequest(Uri address)
{
WebRequest wr = base.GetWebRequest(address);
wr.Timeout = urlCallTOut; // timeout in milliseconds (ms)
return wr;
}
}
public class baseUtils
{
/// <summary>
/// Indicazione VETO invio a server sino alla data-ora indicata
/// </summary>
public static DateTime dtVetoSend = DateTime.Now;
/// <summary>
/// oggetto static x gestione baseUtils
/// </summary>
public static baseUtils mgr = new baseUtils();
/// <summary>
/// Fattore di riduzione dei log
/// </summary>
public static int logReduxFactor = 10;
/// <summary>
/// legge conf in formato char
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static char CRC(string key)
{
char answ = '-';
try
{
answ = ConfigurationManager.AppSettings[key].ToCharArray()[0];
}
catch
{ }
return answ;
}
/// <summary>
/// legge conf in formato stringa
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static string CRS(string key)
{
string answ = "";
try
{
answ = ConfigurationManager.AppSettings[key].ToString();
}
catch
{ }
return answ;
}
/// <summary>
/// legge conf in formato INT
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static Int32 CRI(string key)
{
int answ = 0;
try
{
answ = Convert.ToInt32(CRS(key));
}
catch
{ }
return answ;
}
/// <summary>
/// legge conf in formato BOOLean
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static bool CRB(string key)
{
bool answ = false;
try
{
answ = Convert.ToBoolean(CRS(key));
}
catch
{ }
return answ;
}
/// <summary>
/// verifica se un dato bit sia alzato (come flag di strobe)
/// </summary>
/// <param name="value">valore da testare</param>
/// <param name="flag">valore cercato, può essere un singolo valore o un insieme in modalità AND</param>
/// <returns></returns>
public static bool IsSetAll(Strobe value, Strobe flag)
{
return ((value & flag) == flag);
}
/// <summary>
/// verifica se un dato bit sia alzato (come flag di strobe)
/// </summary>
/// <param name="value">valore da testare</param>
/// <param name="flag">valore cercato, può essere un singolo valore o un insieme in modalità OR</param>
/// <returns></returns>
public static bool IsSetAny(Strobe value, Strobe flag)
{
return ((value & flag) != 0);
}
/// <summary>
/// verifica se un dato bit sia alzato (come flag di strobe)
/// </summary>
/// <param name="value">valore da testare</param>
/// <param name="flag">valore cercato, può essere un singolo valore o un insieme in modalità AND</param>
/// <returns></returns>
public static bool IsSetAll(StatusBitMap value, StatusBitMap flag)
{
return ((value & flag) == flag);
}
/// <summary>
/// verifica se un dato bit sia alzato (come flag di strobe)
/// </summary>
/// <param name="value">valore da testare</param>
/// <param name="flag">valore cercato, può essere un singolo valore o un insieme in modalità OR</param>
/// <returns></returns>
public static bool IsSetAny(StatusBitMap value, StatusBitMap flag)
{
return ((value & flag) != 0);
}
/// <summary>
/// formatta un numero in forma binaria 0/1
/// </summary>
/// <param name="valore"></param>
/// <returns></returns>
public static string binaryForm(int valore)
{
string answ = "";
try
{
answ = string.Format(new BinaryFormatter(), "{0:B}", valore);
}
catch
{ }
return answ;
}
/// <summary>
/// Method to convert an integer to a string containing the number in binary. A negative
/// number will be formatted as a 32-character binary number in two's compliment.
/// </summary>
/// <param name="theNumber">self-explanatory</param>
/// <param name="minimumDigits">if binary number contains fewer characters leading zeros are added</param>
/// <returns>string as described above</returns>
public static string IntToBinStr(int theNumber, int minimumDigits)
{
return Convert.ToString(theNumber, 2).PadLeft(minimumDigits, '0');
}
/// <summary>
/// Effettua reverse delal stringa
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public static string reverseStr(string s)
{
char[] arr = s.ToCharArray();
Array.Reverse(arr);
return new string(arr);
}
/// <summary>
/// imposta un bit al valore richiesto duplicando il valore IN come OUT
/// </summary>
/// <param name="original">valore originale da aggiornare</param>
/// <param name="bitBool">valore richiesto x il bit (0/1)</param>
/// <param name="bitIndex">indice bit, 0 based (es: 0..31 per 32bit)</param>
/// <returns></returns>
public static byte[] setBitOnStFlag(byte[] original, bool bitBool, int bitIndex)
{
int bitVal = 0;
if (bitBool)
{
bitVal = 1;
}
// risposta è identica ad originale...
byte[] answ = original;
// verifico se il bit è 0/1b
if (bitVal <= 1 && bitVal >= 0)
{
// verifico se si possa aggiornare il bit richiesto (<= al totale dei bit...)
if (bitIndex <= original.Length * 8 - 1)
{
// calcolo byte
int byteIndex = bitIndex / 8;
// bit nel byte
int bitInByteIndex = bitIndex % 8;
// bit richiesto
byte mask = (byte)(bitVal << bitInByteIndex);
// imposto!
answ[byteIndex] |= mask;
}
}
return answ;
}
/// <summary>
/// Converte un bitarray a byte[]
/// </summary>
/// <param name="bits"></param>
/// <returns></returns>
public static byte[] ToByteArray(BitArray bits)
{
int numBytes = bits.Count / 8;
if (bits.Count % 8 != 0)
{
numBytes++;
}
byte[] bytes = new byte[numBytes];
int byteIndex = 0, bitIndex = 0;
for (int i = 0; i < bits.Count; i++)
{
if (bits[i])
{
bytes[byteIndex] |= (byte)(1 << (7 - bitIndex));
}
bitIndex++;
if (bitIndex == 8)
{
bitIndex = 0;
byteIndex++;
}
}
return bytes;
}
/// <summary>
/// Scrittura dictionary su file
/// </summary>
/// <param name="dictionary"></param>
/// <param name="file"></param>
public static void WriteBin(Dictionary<string, string> dictionary, string file)
{
using (FileStream fs = File.OpenWrite(file))
using (BinaryWriter writer = new BinaryWriter(fs))
{
// Put count.
writer.Write(dictionary.Count);
// Write pairs.
foreach (var pair in dictionary)
{
writer.Write(pair.Key);
writer.Write(pair.Value);
}
}
}
/// <summary>
/// Lettura dictionary da file
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public static Dictionary<string, string> ReadBin(string file)
{
var result = new Dictionary<string, string>();
// verifico file esista...
if (!File.Exists(file))
{
FileStream fs = File.Create(file);
fs.Close();
}
using (FileStream fs = File.OpenRead(file))
using (BinaryReader reader = new BinaryReader(fs))
{
// Get count.
int count = 0;
try
{
count = reader.ReadInt32();
}
catch
{ }
// Read in all pairs.
for (int i = 0; i < count; i++)
{
string key = reader.ReadString();
string value = reader.ReadString();
result[key] = value;
}
}
return result;
}
/// <summary>
/// Scrittura dictionary su file
/// </summary>
/// <param name="dictionary"></param>
/// <param name="file"></param>
public static void WritePlain(Dictionary<string, string> dictionary, string file)
{
string dirPath = file.Substring(0, file.LastIndexOf('\\'));
// verifico directory
if (!Directory.Exists(dirPath))
{
Directory.CreateDirectory(dirPath);
}
string[] lines = dictionary.OrderBy(i => i.Key).Select(kvp => kvp.Key + ":" + kvp.Value).ToArray();
try
{
File.WriteAllLines(file, lines);
}
catch (Exception exc)
{
Logger lg = LogManager.GetCurrentClassLogger();
lg.Info(exc, string.Format("Errore in scrittura file {0}", file));
}
}
/// <summary>
/// Lettura dictionary da file
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public static Dictionary<string, string> ReadPlain(string file)
{
// inizializzo num righe lette...
int numRow = 0;
var result = new Dictionary<string, string>();
// verifico file esista...
if (!File.Exists(file))
{
FileStream fs = File.Create(file);
fs.Close();
}
try
{
string[] lines = File.ReadAllLines(file);
result = lines.Select(l => l.Split(':')).ToDictionary(a => a[0], a => a[1]);
numRow = result.Count;
}
catch
{ }
// se leggesse un valore NON coerente (senza righe) restituisce un file vuoto...
if (numRow == 0)
{
result = new Dictionary<string, string>();
}
return result;
}
/// <summary>
/// Test ping x indirizzo indicato
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
public static bool pingAddress(IPAddress address)
{
bool answ = false;
Ping pingSender = new Ping();
PingReply reply = pingSender.Send(address, 100);
// se passa il ping do OK...
if (reply.Status == IPStatus.Success)
{
answ = true;
}
return answ;
}
/// <summary>
/// IP della macchina
/// </summary>
/// <returns></returns>
public static string GetIP()
{
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
String sIpAddr = string.Empty;
try
{
foreach (NetworkInterface adapter in nics)
{
if (sIpAddr == String.Empty)// only return IP Address from first card
{
IPInterfaceProperties properties = adapter.GetIPProperties();
foreach (var item in properties.UnicastAddresses)
{
if (item.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
sIpAddr = item.Address.ToString();
}
}
}
}
}
catch (Exception exc)
{
Logger lg = LogManager.GetCurrentClassLogger();
lg.Error(exc);
}
return sIpAddr;
}
/// <summary>
/// Macaddress della macchina
/// </summary>
/// <returns></returns>
public static string GetMACAddress()
{
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
String sMacAddress = string.Empty;
foreach (NetworkInterface adapter in nics)
{
if (sMacAddress == String.Empty)// 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;
}
/// <summary>
/// Effettua chaimata URL e restituisce risultato
/// </summary>
/// <param name="URL"></param>
/// <returns></returns>
public static string callUrl(string URL)
{
string answ = "";
// controllo se ho un VETO all'invio...
if (dtVetoSend < DateTime.Now)
{
var client = new WebClientWT();
//var client = new WebClient();
client.Headers.Add("user-agent", CRS("appName"));
try
{
answ = client.DownloadString(URL);
}
catch (Exception exc)
{
// imposto un veto per pauseSendMSec
int pauseSendMSec = CRI("pauseSendMSec");
// aggiungo NOISE... +/- 33%
Random rnd = new Random();
int noise = rnd.Next(1, pauseSendMSec / 3);
pauseSendMSec += noise - (pauseSendMSec / 6);
// imposto veto
dtVetoSend = DateTime.Now.AddMilliseconds(pauseSendMSec);
// log ogni
Logger lg = LogManager.GetCurrentClassLogger();
lg.Info($"Errore in callURL verso {URL}: impostato attesa di {pauseSendMSec} ms prima della prossima chiamata");
logReduxFactor--;
if (logReduxFactor <= 0)
{
lg.Error("Eccezione in esecuzione callURL: {0}{1}{2}", URL, Environment.NewLine, exc);
logReduxFactor = 10;
}
}
// restituisco valore!
}
return answ;
}
/// <summary>
/// provvede a verificare la dim della cartella dei log e cancella i + vecchi fino a restare a dim inferiori a _logMaxMb
/// </summary>
public static void shrinkDir(string dirPath)
{
Logger lg = LogManager.GetCurrentClassLogger();
// obj filemover...
fileMover.obj.setDirectory(dirPath);
float dirSizeMb = fileMover.obj.totalMb();
lg.Info("Inizio shrinkDir LOG folder: {0} Mb", dirSizeMb);
// ottengo elenco files *.txt
FileInfo[] _fis = fileMover.obj.elencoFiles_FI("*.log");
int numDdMax = 2;
try
{
numDdMax = CRI("zipLogOldDay");
}
catch
{ }
foreach (FileInfo _file in _fis)
{
if (_file.LastWriteTime < DateTime.Now.AddDays(-1)) // zippo files + vecchi di 2 gg...
{
fileMover.obj.zippaSingoloFile(_file);
// cancello l'originale...
fileMover.obj.eliminaFile(_file);
}
}
// ora controllo SE sia superata la dim max della directory --> in tal caso cancello dal + vecchio...
dirSizeMb = fileMover.obj.totalMb();
int maxLogDirSize = CRI("maxLogDirSize");
int maxTry = 100;
// controllo se serva eliminare...
if (dirSizeMb > maxLogDirSize)
{
lg.Info("Continuo shrinkDir LOG folder: {0} Mb --> ELIMINAZIONE FILES", dirSizeMb);
while (dirSizeMb > maxLogDirSize)
{
fileMover.obj.deleteOldest();
maxTry--;
if (maxTry > 0)
{
dirSizeMb = fileMover.obj.totalMb();
}
else
{
// per uscire fingo di aver ridotto...
dirSizeMb = maxLogDirSize - 1;
}
}
dirSizeMb = fileMover.obj.totalMb();
lg.Info("Completata shrinkDir LOG folder: {0} Mb", dirSizeMb);
}
}
}
/// <summary>
/// Oggetto timing x archiviazione dati perfomances
/// </summary>
public class TimeRec
{
/// <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>
/// Tempo medio chiamata
/// </summary>
public double avgMsec
{
get
{
return totMsec.TotalMilliseconds / numCall;
}
}
/// <summary>
/// Totale Msec accumulati
/// </summary>
public TimeSpan totMsec;
/// <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);
}
}
/// <summary>
/// Classe gestione valori campionati su periodo
/// </summary>
public class sampleVect
{
/// <summary>
/// Dimensione finestra di campionamento (secondi)
/// </summary>
protected int windSize;
/// <summary>
/// vettore valori temporali della serie
/// </summary>
protected List<DateTime> lTime;
/// <summary>
/// vettore valoti puntuali della serie
/// </summary>
protected List<int> lVal;
/// <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>();
}
/// <summary>
/// Conteggio elementi
/// </summary>
protected int numElem
{
get
{
int answ = 0;
try
{
answ = lTime.Count;
}
catch
{ }
return answ;
}
}
/// <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>
/// 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;
}
}
/// <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...
}
}
/// <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);
}
}
}
public static class TimingData
{
public static List<TimeRec> results = new List<TimeRec>();
/// <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>();
}
}
/// <summary>
/// Gestione Endianness
/// </summary>
public static class Endian
{
/// <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);
}
}
/// <summary>
/// Tipologie di DUMP memoria
/// </summary>
public enum dumpType
{
/// <summary>
/// Salvataggio all'avvio aree memoria (con sovrascrittura)
/// </summary>
STARTUP,
/// <summary>
/// Campionamento periodico
/// </summary>
SAMPLE
}
public enum tipoAdapter
{
/// <summary>
/// Adapter SIMULAZIONE
/// </summary>
SIMULA,
/// <summary>
/// adapter FANUC
/// </summary>
FANUC,
/// <summary>
/// adapter KAWASAKI e-controller
/// </summary>
KAWASAKI,
/// <summary>
/// Adapter non specificato
/// </summary>
ND,
/// <summary>
/// Adapter OSAI CNDEX (Cndex)
/// </summary>
OSAI_CNDEX,
/// <summary>
/// Adapter OSAI OPEN (ws)
/// </summary>
OSAI_OPEN,
/// <summary>
/// Adapter OSAI VB6
/// </summary>
OSAI_VB6,
/// <summary>
/// Adapter SIEMENS
/// </summary>
SIEMENS,
/// <summary>
/// Adapter SIEMENS, interfaccia versione APROCHIM (filtro liquidi rettifiche)
/// </summary>
SIEMENS_APROCHIM,
/// <summary>
/// Adapter SIEMENS, interfaccia versione VIPA @2001
/// </summary>
SIEMENS_AT2001,
/// <summary>
/// Adapter SIEMENS, interfaccia versione FAPE (punzonatrici)
/// </summary>
SIEMENS_FAPE,
/// <summary>
/// Adapter SIEMENS, interfaccia versione INGENIA (Valvital, Automazione)
/// </summary>
SIEMENS_INGENIA,
/// <summary>
/// Adapter SIEMENS, interfaccia versione LASCO (Valvital, Pressa Bilancere)
/// </summary>
SIEMENS_LASCO,
/// <summary>
/// Adapter SIEMENS, interfaccia versione PRESSOIL + CEI (Valvital, Pressa Idraulica)
/// </summary>
SIEMENS_PRESSOIL_CEI,
/// <summary>
/// Adapter SIEMENS, interfaccia versione SAET (Valvital, forni / tempra)
/// </summary>
SIEMENS_SAET,
/// <summary>
/// Adapter SIEMENS, interfaccia versione Torri
/// </summary>
SIEMENS_TORRI,
/// <summary>
/// Metodi di WPS WebPageScraping (es x compressori Atlas Copco)
/// </summary>
WPS
}
public enum gatherCycle
{
/// <summary>
/// Very High Frequency (solo x invii...)
/// </summary>
VHF,
/// <summary>
/// lettura dati ad alta frequenza
/// </summary>
HF,
/// <summary>
/// lettura dati standard
/// </summary>
MF,
/// <summary>
/// lettura dati bassa freq
/// </summary>
LF,
/// <summary>
/// lettura dati bassissima priorità (re-sync stato allarmi)
/// </summary>
VLF
}
/// <summary>
/// Classe conf x item DynData
/// </summary>
public class DynDataItem
{
public string key { get; set; } = "";
public string name { get; set; } = "";
public string val { get; set; } = "";
public string unit { get; set; } = "";
public string func { get; set; } = "";
public int sPeriod { get; set; } = 60;
/// <summary>
/// Valore effettivo da salvare
/// </summary>
public string actVal { get; set; } = "";
/// <summary>
/// DataOra scadenza invio forzato
/// </summary>
public DateTime DTScad = DateTime.Now;
}
/// <summary>
/// Classe conf x decodifica stsatus
/// </summary>
public class StatusItem : DynDataItem
{
public Dictionary<string, string> codeMapping;
}
/// <summary>
/// Classe conf server html
/// </summary>
public class srvData
{
public string baseUri { get; set; } = "";
public string driverName { get; set; } = "";
}
/// <summary>
/// Elenco oggetti del monitoraggio (DynData, Status)
/// </summary>
public class MonitoredItemsConf
{
public srvData SrvData { get; set; }
public List<DynDataItem> DynData { get; set; }
public List<StatusItem> Status { get; set; }
}
/// <summary>
/// Configurazione per Eventi/Variabili
/// </summary>
public class EVData
{
/// <summary>
/// Unità di misura
/// </summary>
public string UM { get; set; } = "num";
/// <summary>
/// Valore salvato
/// </summary>
public string Val { get; set; } = "";
/// <summary>
/// DataOra scadenza invio forzato
/// </summary>
public DateTime DTScad = DateTime.Now;
}
/// <summary>
/// Configurazione per Variabili Casuali
/// </summary>
public class VCData
{
/// <summary>
/// Periodo di riferimento
/// </summary>
public int Period { get; set; } = 60;
/// <summary>
/// Tipologia di funzione da applicare
/// </summary>
public VC_func Funzione { get; set; } = VC_func.POINT;
/// <summary>
/// DataOra inizio periodo di elaborazione
/// </summary>
public DateTime DTStart;
/// <summary>
/// Array dati per calcolo
/// </summary>
public List<double> dataArray;
}
/// <summary>
/// Tipologia di elaborazione/funzione da applicare a VC
/// </summary>
public enum VC_func
{
/// <summary>
/// Valore puntuale
/// </summary>
POINT = 0,
/// <summary>
/// Valore medio del periodo
/// </summary>
AVG,
/// <summary>
/// Valore massimo del periodo
/// </summary>
MAX,
/// <summary>
/// Valore minimo del periodo
/// </summary>
MIN
}
/// <summary>
/// Elenco task ammessi
/// </summary>
public enum taskType
{
/// <summary>
/// Task nullo / fake
/// </summary>
nihil,
/// <summary>
/// Rimanda a PLC eventuale segnale NON in setup (MA NON RESETTA)
/// </summary>
fixStopSetup,
/// <summary>
/// Indica al PLC di forzare il reset del contapezzi
/// </summary>
forceResetPzCount,
/// <summary>
/// Indica al PLC di forzare il NUOVO valore di contapezzi (impostato come value)
/// </summary>
forceSetPzCount,
/// <summary>
/// Imposta Articolo su PLC
/// </summary>
setArt,
/// <summary>
/// Imposta Commessa su PLC
/// </summary>
setComm,
/// <summary>
/// Set Programma CNC su PLC
/// </summary>
setProg,
/// <summary>
/// Indica al PLC iniziato setup (e secondo casi ferma contapezzi /resetta)
/// </summary>
startSetup,
/// <summary>
/// Indica al PLC finito setup (e secondo casi ferma contapezzi /resetta)
/// </summary>
stopSetup,
/// <summary>
/// Richiesta invio watchdog a PLC
/// </summary>
sendWatchDogMes2Plc
}
/// <summary>
/// informazioni di produzione
/// </summary>
public struct prodData
{
public string Operator;
public bool Status;
public int AccTime;
public int Power;
public string FuncMode;
public bool EmrStop;
public string MessageCode;
public string MessageText;
}
public struct PathData
{
public int PathSel;
public string PathType; // LAVOR/ASSERV
public string RunMode;
public string ExeMode;
public int pzTot;
public string ProgramName;
public string ProgrRow;
public string PartId;
public string ActiveAxes;
public string CodG_Act;
public string SubMode;
public int PathFeedrate;
public int PathFeedrateOver;
public int PathRapidOver;
public int PathJogOver;
public int PathSpindleOver_01;
public int PathSpindleOver_02;
public int PathSpindleOver_03;
public int PathSpindleOver_04;
public position PathPosAct;
}
public struct UnOpData
{
public int UnOpSel;
public int UnOpToolId;
public int UnOpNumCU;
public string UnOpStatus;
public int UnOpVitaRes;
public int UnOpSpeed;
public int UnOpLoad;
public int UnOpAccTime;
}
public struct AxisData
{
public int AxisSel;
public string AxisMainProc;
public bool AxisIsMaster;
public string AxisMastId;
public string AxisType;
public string AxisDir;
public int AxisLoad;
public int AxisPosAct;
public int AxisPosTgt;
public int AxisFeedAct;
public int AxisFeedOver;
public string AxisAccel;
public string AxisAccTime;
public string AxisBattery;
public string DistDone;
public string InvDDone;
}
/// <summary>
/// Vettore completo posizione (X-Y-Z con versori i-j-k)
/// </summary>
public class position
{
public float x;
public float y;
public float z;
public float i;
public float j;
public float k;
public position()
{
x = 0;
y = 0;
z = 0;
i = 0;
j = 0;
k = 0;
}
}
/// <summary>
/// Dati Prod SCM (per decodifica)
/// </summary>
public class datiProdSCM
{
public string area;
public string fileName;
public string dimensioni;
public DateTime start;
public DateTime stop;
public TimeSpan tEff;
public TimeSpan tTot;
public int qta;
public TimeSpan tMed;
public datiProdSCM()
{
area = "";
fileName = "";
dimensioni = "";
start = DateTime.Now;
stop = DateTime.Now;
tEff = new TimeSpan(0);
tTot = new TimeSpan(0);
qta = 0;
tMed = new TimeSpan(0);
}
/// <summary>
/// crea un nuovo oggetto a partire da un array di stringhe
/// </summary>
/// <param name="valori"></param>
public datiProdSCM(string[] valori)
{
try
{
area = valori[0];
fileName = valori[1];
dimensioni = string.Format("{0}x{1}x{2}", valori[3], valori[4], valori[5]);
start = DateTime.Today.AddHours(Convert.ToInt16(valori[6])).AddMinutes(Convert.ToInt16(valori[7])).AddSeconds(Convert.ToInt16(valori[8]));
stop = DateTime.Today.AddHours(Convert.ToInt16(valori[9])).AddMinutes(Convert.ToInt16(valori[10])).AddSeconds(Convert.ToInt16(valori[11]));
// se ore == 0 --> aggiungo 1 gg!!!
if (Convert.ToInt16(valori[9]) == 0)
{
stop.AddDays(1);
}
tEff = new TimeSpan(Convert.ToInt16(valori[12]), Convert.ToInt16(valori[13]), Convert.ToInt16(valori[14]));
tTot = new TimeSpan(Convert.ToInt16(valori[15]), Convert.ToInt16(valori[16]), Convert.ToInt16(valori[17]));
qta = Convert.ToInt16(valori[18]);
tMed = new TimeSpan(Convert.ToInt16(valori[19]), Convert.ToInt16(valori[20]), Convert.ToInt16(valori[22]), Convert.ToInt16(valori[23]));
}
catch
{ }
}
}
/// <summary>
/// Allarme (per decodifica)
/// </summary>
public class allarme
{
public string codNum;
public string gruppo;
public string livello;
public string descrizione;
public allarme()
{
codNum = "";
gruppo = "";
livello = "";
descrizione = "";
}
public allarme(string _codNum, string _gruppo, string _livello, string _descrizione)
{
codNum = _codNum;
gruppo = _gruppo;
livello = _livello;
descrizione = _descrizione;
}
}
/// <summary>
/// Dato generico (per decodifica)
/// </summary>
public class otherData
{
public string codNum;
public string memAddr;
public string varName;
public string dataType;
public otherData()
{
codNum = "";
memAddr = "";
varName = "";
dataType = "";
}
public otherData(string _codNum, string _memAddr, string _varName, string _dataType)
{
codNum = _codNum;
memAddr = _memAddr;
varName = _varName;
dataType = _dataType;
}
}
/// <summary>
/// Strobe: contiene il set di strobe di comunicazione
///
/// rif: http://stackoverflow.com/questions/17209054/parse-bits-in-a-byte-to-enum
/// </summary>
[Flags]
public enum Strobe : int
{
NONE = 0,
M_CODE = 1 << 0,
S_CODE = 1 << 1,
T_CODE = 1 << 2,
PZ_OK = 1 << 3,
PZ_KO = 1 << 4,
FEED_SPEED = 1 << 5,
POS_ACT = 1 << 6,
SP07 = 1 << 7,
SP08 = 1 << 8,
SP09 = 1 << 9,
SP10 = 1 << 10,
SP11 = 1 << 11,
SP12 = 1 << 12,
SP13 = 1 << 13,
SP14 = 1 << 14,
SP15 = 1 << 15,
SP16 = 1 << 16,
SP17 = 1 << 17,
SP18 = 1 << 18,
SP19 = 1 << 19,
SP20 = 1 << 20,
SP21 = 1 << 21,
SP22 = 1 << 22,
SP23 = 1 << 23,
SP24 = 1 << 24,
SP25 = 1 << 25,
SP26 = 1 << 26,
SP27 = 1 << 27,
SP28 = 1 << 28,
SP29 = 1 << 29,
SP30 = 1 << 30,
SP31 = 1 << 31
}
/// <summary>
/// StFlag8: set di 8 bit (1 word) contente semaforo di variabili
/// </summary>
[Flags]
public enum StFlag8 : int
{
NONE = 0,
B0 = 1 << 0,
B1 = 1 << 1,
B2 = 1 << 2,
B3 = 1 << 3,
B4 = 1 << 4,
B5 = 1 << 5,
B6 = 1 << 6,
B7 = 1 << 7
}
/// <summary>
/// StFlag32: set di 32 bit (4 word) contente semaforo di variabili
/// </summary>
[Flags]
public enum StFlag32 : int
{
NONE = 0,
B00 = 1 << 0,
B01 = 1 << 1,
B02 = 1 << 2,
B03 = 1 << 3,
B04 = 1 << 4,
B05 = 1 << 5,
B06 = 1 << 6,
B07 = 1 << 7,
B08 = 1 << 8,
B09 = 1 << 9,
B10 = 1 << 10,
B11 = 1 << 11,
B12 = 1 << 12,
B13 = 1 << 13,
B14 = 1 << 14,
B15 = 1 << 15,
B16 = 1 << 16,
B17 = 1 << 17,
B18 = 1 << 18,
B19 = 1 << 19,
B20 = 1 << 20,
B21 = 1 << 21,
B22 = 1 << 22,
B23 = 1 << 23,
B24 = 1 << 24,
B25 = 1 << 25,
B26 = 1 << 26,
B27 = 1 << 27,
B28 = 1 << 28,
B29 = 1 << 29,
B30 = 1 << 30,
B31 = 1 << 31
}
/// <summary>
/// StatusBitMap: contiene il set di semafori/flag x status + allarmi (x classi)
/// </summary>
[Flags]
public enum StatusBitMap : int
{
NONE = 0,
ESTOP = 1 << 0,
RM_AUTO = 1 << 1,
RM_MANUAL = 1 << 2,
RM_MDI = 1 << 3,
RM_EDIT = 1 << 4,
EM_RUN = 1 << 5,
EM_READY = 1 << 6,
EM_STOP = 1 << 7,
EM_FEEDHOLD = 1 << 8,
HM = 1 << 9,
ST11 = 1 << 10,
ST12 = 1 << 11,
ST13 = 1 << 12,
ST14 = 1 << 13,
ST15 = 1 << 14,
ST16 = 1 << 15,
AL01 = 1 << 16,
AL02 = 1 << 17,
AL03 = 1 << 18,
AL04 = 1 << 19,
AL05 = 1 << 20,
AL06 = 1 << 21,
AL07 = 1 << 22,
AL08 = 1 << 23,
AL09 = 1 << 24,
AL10 = 1 << 25,
AL11 = 1 << 26,
AL12 = 1 << 27,
AL13 = 1 << 28,
AL14 = 1 << 29,
AL15 = 1 << 30,
AL16 = 1 << 31
}
/// <summary>
/// Enumerazione tipi di semaforo
/// </summary>
public enum Semaforo
{
/// <summary>
/// Verde
/// </summary>
SV,
/// <summary>
/// Giallo
/// </summary>
SG,
/// <summary>
/// Rosso
/// </summary>
SR,
/// <summary>
/// Grigio/Spento
/// </summary>
SS
}
/// <summary>
/// Enumerazione tipi di tipi di URL x invio
/// </summary>
public enum urlType
{
/// <summary>
/// Salvataggio FluxLog (valori estesi che non provocano calcoli di macchine a stati, eventi...)
/// </summary>
FLog,
/// <summary>
/// INPUT segnali in ingresso (standard base MAPO)
/// </summary>
SignIN
}
/// <summary>
/// Elenco STATI CNC OSAI
/// </summary>
public enum CNC_STATUS_OSAI
{
IDLE = 1,
CYCLE,
HODA,
RUNH,
HRUN,
ERRO,
WAIT,
RESET,
EMERG,
INPUT
}
/// <summary>
/// Elenco MODI CNC
/// </summary>
public enum CNC_MODE
{
/// <summary>
/// Non definito
/// </summary>
ND = 0,
/// <summary>
/// AUTOMATICO
/// </summary>
AUTO,
/// <summary>
/// EDIT (MEMORY EDIT)
/// </summary>
EDIT,
/// <summary>
/// MEN (MEMORY OPERATION)
/// </summary>
MEN,
/// <summary>
/// MDI (MANUAL DATA INPUT)
/// </summary>
MDI,
/// <summary>
/// HANDLE/INC (MANUAL HANDLE / INCREMENTAL FEED)
/// </summary>
HANDLE_INC,
/// <summary>
/// HOME
/// </summary>
HOME,
/// <summary>
/// JOG (MANUAL CONTINUOUS FEED)
/// </summary>
JOG,
/// <summary>
/// JOG MAN
/// </summary>
JOG_MAN,
/// <summary>
/// JOG_INC
/// </summary>
JOG_INC,
/// <summary>
/// PROFILE
/// </summary>
PROFILE,
/// <summary>
/// SEMI
/// </summary>
SEMI,
/// <summary>
/// THND (TEACH IN HANDLE)
/// </summary>
THND,
/// <summary>
/// TJOG (TEACH IN JOG)
/// </summary>
TJOG,
/// <summary>
/// RMT (DNC OPERATION)
/// </summary>
RMT,
/// <summary>
/// REF (MANUAL REFERENCE POSITION RETURN)
/// </summary>
REF
}
}