using System; using System.Collections; using System.Collections.Generic; using System.Configuration; using System.Data; using System.IO; using System.Linq; using NLog; namespace MTC { public class baseUtils { /// /// classe logger /// public static Logger lg; /// /// legge conf in formato char /// /// /// public static char CRC(string key) { char answ = '-'; try { answ = ConfigurationManager.AppSettings[key].ToCharArray()[0]; } catch { } return answ; } /// /// legge conf in formato stringa /// /// /// public static string CRS(string key) { string answ = ""; try { answ = ConfigurationManager.AppSettings[key].ToString(); } catch { } return answ; } /// /// legge conf in formato INT /// /// /// public static Int32 CRI(string key) { int answ = 0; try { answ = Convert.ToInt32(CRS(key)); } catch { } return answ; } /// /// legge conf in formato BOOLean /// /// /// public static bool CRB(string key) { bool answ = false; try { answ = Convert.ToBoolean(CRS(key)); } catch { } return answ; } /// /// verifica se un dato bit sia alzato (come flag di strobe) /// /// valore da testare /// valore cercato, può essere un singolo valore o un insieme in modalità AND /// public static bool IsSetAll(Strobe value, Strobe flag) { return ((value & flag) == flag); } /// /// verifica se un dato bit sia alzato (come flag di strobe) /// /// valore da testare /// valore cercato, può essere un singolo valore o un insieme in modalità OR /// public static bool IsSetAny(Strobe value, Strobe flag) { return ((value & flag) != 0); } /// /// verifica se un dato bit sia alzato (come flag di strobe) /// /// valore da testare /// valore cercato, può essere un singolo valore o un insieme in modalità AND /// public static bool IsSetAll(StatusBitMap value, StatusBitMap flag) { return ((value & flag) == flag); } /// /// verifica se un dato bit sia alzato (come flag di strobe) /// /// valore da testare /// valore cercato, può essere un singolo valore o un insieme in modalità OR /// public static bool IsSetAny(StatusBitMap value, StatusBitMap flag) { return ((value & flag) != 0); } /// /// formatta un numero in forma binaria 0/1 /// /// /// public static string binaryForm(int valore) { string answ = ""; try { answ = string.Format(new BinaryFormatter(), "{0:B}", valore); } catch { } return answ; } /// /// imposta un bit al valore richiesto duplicando il valore IN come OUT /// /// valore originale da aggiornare /// valore richiesto x il bit (0/1) /// indice bit, 0 based (es: 0..31 per 32bit) /// 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; } /// /// Converte un bitarray a byte[] /// /// /// 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; } /// /// Scrittura dictionary su file /// /// /// public static void WriteBin(Dictionary 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); } } } /// /// Lettura dictionary da file /// /// /// public static Dictionary ReadBin(string file) { var result = new Dictionary(); // 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; } /// /// Scrittura dictionary su file /// /// /// public static void WritePlain(Dictionary 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) { lg.Info(exc, string.Format("Errore in scrittura file {0}", file)); } } /// /// Lettura dictionary da file /// /// /// public static Dictionary ReadPlain(string file) { // inizializzo num righe lette... int numRow = 0; var result = new Dictionary(); // 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(); } return result; } } /// /// Oggetto timing x archiviazione dati perfomances /// public class TimeRec { /// /// Codice univoco chiamata: tipo R4 (read 4 byte), W2 (write 2 Byte) /// public string codCall; /// /// Num chiamate totale /// public int numCall; /// /// Tempo medio chiamata /// public double avgMsec { get { return totMsec.TotalMilliseconds / numCall; } } /// /// Totale Msec accumulati /// public TimeSpan totMsec; /// /// Classe record timing /// public TimeRec() { codCall = ""; numCall = 0; totMsec = new TimeSpan(0); } /// /// Classe record timing /// /// /// public TimeRec(string codice, long nTicks) { codCall = codice; numCall = 1; totMsec = new TimeSpan(nTicks); } } public static class TimingData { public static List results = new List(); /// /// aggiorno vettore aggiungendo risultato /// /// /// public static void addResult(string codice, long ticks) { if (results.Count == 0) { results.Add(new TimeRec(codice, ticks)); } int indice = -1; for (int i = 0; i < results.Count; i++) { // se il codice è quello cercato... if (results[i].codCall == codice) 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(codice, ticks)); } } /// /// Resetta i dati registrati (ad avvio adapter...) /// public static void resetData() { results = new List(); } } public enum tipoAdapter { /// /// Adapter DB /// DB, /// /// Adapter generico/demo /// DEMO, /// /// Adapter ESAGV (SCM) /// ESAGV, /// /// adapter FANUC (CMS) /// FANUC, /// /// Adapter non specificato /// ND, /// /// Adapter OSAI /// OSAI, /// /// Adapter SIEMENS (CMS) /// SIEMENS } public enum gatherCycle { /// /// lettura dati ad alta frequenza /// HF, /// /// lettura dati standard /// MF, /// /// lettura dati bassa freq /// LF, /// /// lettura dati bassissima priorità (re-sync stato allarmi) /// VLF } /// /// informazioni di produzione /// 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; } /// /// Vettore completo posizione (X-Y-Z con versori i-j-k) /// 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; } } /// /// Dati Prod SCM (per decodifica) /// 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); } /// /// crea un nuovo oggetto a partire da un array di stringhe /// /// 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 { } } } /// /// Allarme (per decodifica) /// 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; } } /// /// Dato generico (per decodifica) /// 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; } } /// /// Strobe: contiene il set di strobe di comunicazione /// /// rif: http://stackoverflow.com/questions/17209054/parse-bits-in-a-byte-to-enum /// [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 } /// /// StFlag8: set di 8 bit (1 word) contente semaforo di variabili /// [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 } /// /// StFlag32: set di 32 bit (4 word) contente semaforo di variabili /// [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 } /// /// StatusBitMap: contiene il set di semafori/flag x status + allarmi (x classi) /// [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 } }