using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using NLog; namespace SCMA.AdapterPLC { using AdapterCom; using MTC; using OPC_UA_REDIS; #region macro oggetti da istanziare a blocchi da configurazione XML /// /// Singola pompa da vuoto, 0..n /// public class VacuumPump : element { /// /// Stato: ACTIVE/INACTIVE /// public string statusKey { get { return string.Format("{0}_Status", ident); } } /// /// Valore work time della pompa vuoto /// public string workTimeKey { get { return string.Format("{0}_WrkTime", ident); } } /// /// Classe Vacuum Pump (pompa) /// /// element base contenente parametri (da XML) public VacuumPump(element baseElem) { ident = baseElem.ident; dataRefList = baseElem.dataRefList; } } /// /// Singolo attuatore vuoto, 0..n /// public class VacuumAct : element { /// /// valore contatore azioni /// public string countKey { get { return string.Format("{0}_Count", ident); } } /// /// Classe Vacuum Actuator (valvola) /// /// element base contenente parametri (da XML) public VacuumAct(element baseElem) { ident = baseElem.ident; dataRefList = baseElem.dataRefList; } } /// /// Singolo attuatore per lubrificazione, 0..n /// public class Lubro : element { /// /// Stato: ACTIVE/INACTIVE /// public string statusKey { get { return string.Format("{0}_Status", ident); } } /// /// valore contatore (numero pompate necessarie per far scattare sensore) /// public string countKey { get { return string.Format("{0}_Count", ident); } } /// /// Classe Lubrorefrigerante /// /// element base contenente parametri (da XML) public Lubro(element baseElem) { ident = baseElem.ident; dataRefList = baseElem.dataRefList; } } /// /// Singola Slitta Mag, 0..n /// public class SlittaMag : element { /// /// valore contatore (numero attivazioni/disattivazioni slitta magazzino) /// public string countKey { get { return string.Format("{0}_Count", ident); } } /// /// Classe Slitta Magazzino /// /// element base contenente parametri (da XML) public SlittaMag(element baseElem) { ident = baseElem.ident; dataRefList = baseElem.dataRefList; } } /// /// Singolo attuatore Protezione Magazzino, 0..n /// public class ProtMag : element { /// /// valore contatore (numero attivazioni/disattivazioni valvola) /// public string countKey { get { return string.Format("{0}_Count", ident); } } /// /// Classe Protezione Magazzino /// /// element base contenente parametri (da XML) public ProtMag(element baseElem) { ident = baseElem.ident; dataRefList = baseElem.dataRefList; } } /// /// Singolo refrigeratore, 0..n /// public class Cooler : element { /// /// Stato: ACTIVE/INACTIVE /// public string statusKey { get { return string.Format("{0}_Status", ident); } } /// /// Classe refrigeratore /// /// element base contenente parametri (da XML) public Cooler(element baseElem) { ident = baseElem.ident; dataRefList = baseElem.dataRefList; } } /// /// Singola Pressione rilevata, 0..n /// public class Press : element { /// /// valore variabile (valore pressione istantaneo) /// public string valueKey { get { return string.Format("{0}_Value", ident); } } /// /// Classe pressione con Idx e descrizione /// /// element base contenente parametri (da XML) public Press(element baseElem) { ident = baseElem.ident; dataRefList = baseElem.dataRefList; } } /// /// Singola temperatura rilevata, 0..n /// public class Tempe : element { /// /// valore variabile (valore temperatura istantaneo) /// public string valueKey { get { return string.Format("{0}_Value", ident); } } /// /// Classe temperatura con Idx e descrizione /// /// element base contenente parametri (da XML) public Tempe(element baseElem) { ident = baseElem.ident; dataRefList = baseElem.dataRefList; } } /// /// Singola Area Memoria (Kvara 1..4) /// public class MemArea : element { /// /// Programma caricato /// public string prgNameKey { get { return string.Format("{0}_PROG_NAME", ident); } } /// /// Programma caricato /// public string prgRunningKey { get { return string.Format("{0}_RUNNING", ident); } } /// /// Programma caricato /// public string numExeKey { get { return string.Format("{0}_NUM_EXE", ident); } } /// /// Programma caricato /// public string numRepKey { get { return string.Format("{0}_NUM_REP", ident); } } /// /// INIT Classe Memory Area /// /// element base contenente parametri (da XML) public MemArea(element baseElem) { ident = baseElem.ident; dataRefList = baseElem.dataRefList; } } /// /// Singolo path, da 1..20 /// public class Path : element { /// /// Tipo Path (LAVOR/ASSERV) /// public string pathTypeKey { get { return string.Format("{0}_Type", ident); } } /// /// Cod Particolare su Path /// public string partIdKey { get { return string.Format("{0}_PartId", ident); } } /// /// Contapezzi x PATH /// public string partCountKey { get { return string.Format("{0}_PZ_TOT", ident); } } /// /// Codici M sul PATH /// public string pathCodMKey { get { return string.Format("{0}_Cod_M", ident); } } /// /// Codici S sul PATH /// public string pathCodSKey { get { return string.Format("{0}_Cod_S", ident); } } /// /// Codici T sul PATH /// public string pathCodTKey { get { return string.Format("{0}_Cod_T", ident); } } /// /// Modalità RUN del PATH: AUTO/EDIT/MDI/JOG/JOGINC/REF/HANDLE /// public string runModeKey { get { return string.Format("{0}_RUN_MODE", ident); } } /// /// Modalità execution del path: RUN/HOLD/FEED_HOLD/... /// public string exeModeKey { get { return string.Format("{0}_EXE_MODE", ident); } } /// /// Programma corrente /// public string currProgKey { get { return string.Format("{0}_CurrProg", ident); } } /// /// Area Programma corrente/selezionata /// public string currAreaKey { get { return string.Format("{0}_CurrArea", ident); } } /// /// num riga corrente /// public string currProgRowNumKey { get { return string.Format("{0}_CurrProg_RowNum", ident); } } /// /// Assi attivi per path /// public string activeAxesKey { get { return string.Format("{0}_ActiveAxes", ident); } } /// /// Feedrate /// public string feedKey { get { return string.Format("{0}_FeedRate", ident); } } /// /// Override feed /// public string feedOverKey { get { return string.Format("{0}_FeedOverr", ident); } } /// /// Override speed /// public string rapidOverKey { get { return string.Format("{0}_RapidOverr", ident); } } /// /// Override Jog /// public string jogOverKey { get { return string.Format("{0}_JogOverr", ident); } } /// /// Override Spindle_01 /// public string spindleOver_01_Key { get { return string.Format("{0}_SpindleOver_01", ident); } } /// /// Override Spindle_02 /// public string spindleOver_02_Key { get { return string.Format("{0}_SpindleOver_02", ident); } } /// /// Override Spindle_03 /// public string spindleOver_03_Key { get { return string.Format("{0}_SpindleOver_03", ident); } } /// /// Override Spindle_04 /// public string spindleOver_04_Key { get { return string.Format("{0}_SpindleOver_04", ident); } } /// /// Posizione X /// public string posAct_X_Key { get { return string.Format("{0}_PosActX", ident); } } /// /// Posizione Y /// public string posAct_Y_Key { get { return string.Format("{0}_PosActY", ident); } } /// /// Posizione Z /// public string posAct_Z_Key { get { return string.Format("{0}_PosActZ", ident); } } /// /// Angolo I /// public string posAct_I_Key { get { return string.Format("{0}_PosActI", ident); } } /// /// Angolo J /// public string posAct_J_Key { get { return string.Format("{0}_PosActJ", ident); } } /// /// Angolo K /// public string posAct_K_Key { get { return string.Format("{0}_PosActK", ident); } } /// /// Stato dei codici G attivi /// public string gCodeAct_Key { get { return string.Format("{0}_CodG_Act", ident); } } /// /// Stato dei SubMode attivi /// public string subModeKey { get { return string.Format("{0}_SubMode", ident); } } /// /// Allarmi CNC del PATH /// public string alarmCncKey { get { return string.Format("{0}_AlarmCNC", ident); } } /// /// Allarmi PCL del PATH /// public string alarmPlcKey { get { return string.Format("{0}_AlarmPLC", ident); } } /// /// Classe Path con Idx e descrizione /// /// element base contenente parametri (da XML) public Path(element baseElem) { ident = baseElem.ident; dataRefList = baseElem.dataRefList; } } /// /// Singolo mandrino, 1..n /// public class UnOp : element { /// /// ToolID /// public string toolIdKey { get { return string.Format("{0}_ToolId", ident); } } /// /// valore numero Cambi Utensili effettuato /// public string numCUKey { get { return string.Format("{0}_NumCU", ident); } } /// /// status utensili /// public string statusKey { get { return string.Format("{0}_Status", ident); } } /// /// valore vita residua utensile /// public string vitaResKey { get { return string.Format("{0}_VitaRes", ident); } } /// /// tipologia di vita residua utensile: /// 0 : "ND" (famiglia senza gestione vitautensili) /// 1 : "Time [s]" /// 2 : "Stroke [n]" /// 3 : "Distance [m]" ([ft] se la macchina è impostata in pollici) /// public string vitaResTypeKey { get { return string.Format("{0}_VitaResType", ident); } } /// /// valore speed /// public string speedKey { get { return string.Format("{0}_Speed", ident); } } /// /// valore speed override /// public string speedOverKey { get { return string.Format("{0}_SpeedOverr", ident); } } /// /// valore load /// public string loadKey { get { return string.Format("{0}_Load", ident); } } /// /// valore tempo cumulato di impiego /// public string accTimeKey { get { return string.Format("{0}_AccTime", ident); } } /// /// contatore cumulato di giri mandrino (migliaia) /// public string kRevKey { get { return string.Format("{0}_KRev", ident); } } /// /// contatore cumulato di apertura testa /// public string countKey { get { return string.Format("{0}_Count", ident); } } /// /// Classe Unita Operatrice (Mandrino) con Idx e descrizione /// /// element base contenente parametri (da XML) public UnOp(element baseElem) { ident = baseElem.ident; dataRefList = baseElem.dataRefList; } } /// /// Asse singolo, 1..n /// public class Axis : element { /// /// Descrizione asse (nome assegnato) /// public string descriptionKey { get { return string.Format("{0}_Descr", ident); } } /// /// Processo di appartenenza /// public string mainProcKey { get { return string.Format("{0}_MainProc", ident); } } /// /// Bit se sia master (=1) o slave (=0) /// public string isMastKey { get { return string.Format("{0}_IsMast", ident); } } /// /// ID del master /// public string mastIdKey { get { return string.Format("{0}_MastId", ident); } } /// /// Gruppo di appartenenza dell'asse /// public string groupKey { get { return string.Format("{0}_Grp", ident); } } /// /// Tipo asse: lineare, rotazionale... /// public string typeKey { get { return string.Format("{0}_Type", ident); } } /// /// Bit direzione: 1 = avanti/clockwise, 0 indietro/counterclockwise /// public string directionKey { get { return string.Format("{0}_Dir", ident); } } /// /// load /// public string loadKey { get { return string.Format("{0}_Load", ident); } } /// /// posizione attuale /// public string posActKey { get { return string.Format("{0}_PosAct", ident); } } /// /// posizione target /// public string posTgtKey { get { return string.Format("{0}_PosTgt", ident); } } /// /// feed attuale /// public string feedrateKey { get { return string.Format("{0}_FeedAct", ident); } } /// /// Feed Override /// public string feedOverKey { get { return string.Format("{0}_FeedOver", ident); } } /// /// Accelerazione Attuale /// public string accelActKey { get { return string.Format("{0}_AccelAct", ident); } } /// /// Tempo Lavoro cumulato /// public string accTimeKey { get { return string.Format("{0}_AccTime", ident); } } /// /// Carica batteria /// public string batteryKey { get { return string.Format("{0}_Battery", ident); } } /// /// Distanza compiuta nell'intervallo di tempo /// public string distDoneKey { get { return string.Format("{0}_DistDone", ident); } } /// /// numero di inversioni di direzione fatte nell'intervallo di tempo /// public string invDDoneKey { get { return string.Format("{0}_InvDDone", ident); } } /// /// Allarmi CNC del PATH /// public string alarmCncKey { get { return string.Format("{0}_AlarmCNC", ident); } } /// /// Allarmi PCL del PATH /// public string alarmPlcKey { get { return string.Format("{0}_AlarmPLC", ident); } } /// /// Classe Asse con relativo ID UNIVOCO /// /// element base contenente parametri (da XML) public Axis(element baseElem) { ident = baseElem.ident; // valori da conf esplicita dataRefList = baseElem.dataRefList; } } #endregion macro oggetti da istanziare a blocchi da configurazione XML public class Generic { /// /// inizializzo l'oggetto sulla form SULLA BASE DEL FILE DI CONFIGURAZIONE letto /// /// FORM chaimante /// CONFIGURAZIONE adapter /// OGGETTO gestione comunicazione OUT (tipologia e metodi) public Generic(MainForm caller, AdapterConf adpConf, Gateway gatewayObj) { lg = LogManager.GetCurrentClassLogger(); lg.Info("Avvio preliminare AdapterGeneric"); currGateway = gatewayObj; lg.Info(string.Format("Impostato protocollo di comunicazione {0}", currGateway.protocollo)); procIotMem = utils.CRB("procIotMem"); currAdpConf = adpConf; // inizializzo vettore gruppi assi, MAX 20!!! FeedRateGrp = new int[20]; // inizializzo FeedRatePath... FeedRatePath = new int[adpConf.nPath]; // init override path... FeedRateOverPath = new int[adpConf.nPath]; RapidOverPath = new int[adpConf.nPath]; SpeedRateOverPath = new int[adpConf.nPath]; // salvo il form chiamante parentForm = caller; addItemsToGateway(adpConf); // inizializzo vettori code MST x num path... codaM = new List[adpConf.nPath]; codaS = new List[adpConf.nPath]; codaT = new List[adpConf.nPath]; for (int i = 0; i < adpConf.nPath; i++) { codaM[i] = new List(); codaS[i] = new List(); codaT[i] = new List(); } // concluso! lg.Info("Istanziata classe preliminare AdapterGeneric"); } /// /// Effettua aggiunta items a Gateway... /// /// private void addItemsToGateway(AdapterConf adpConf) { // solo se sono in modalità SOUR aggiungo item cablati... if (currGateway.protocollo == gwProtocol.SOURS) { currGateway.addItemNodeAndSet("Alarm", itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet("Emergency", itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); } // solo se sono in modalità MTC aggiungo item cablati... else { // item disponibilità currGateway.addItemNodeAndSet("AVAIL", itemType.Event, availStatus.AVAILABLE.ToString()); currGateway.addItemNodeAndSet("MESSAGE", itemType.Message, ""); // assets currGateway.addItemNodeAndSet("MTC_asset_chg", itemType.Event, ""); currGateway.addItemNodeAndSet("MTC_asset_rem", itemType.Event, ""); // modalità esecutiva e funzionale currGateway.addItemNodeAndSet("FUNCT_MODE", itemType.Message, ""); // dati utente currGateway.addItemNodeAndSet("OperatorId", itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet("CLOCK", itemType.Sample, DateTime.Now.Date.ToFileTimeUtc()); currGateway.addItemNodeAndSet("SlittaTastatore_Count", itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); } // status, clock, emergency stop currGateway.addItemNodeAndSet("E_STOP", itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet("STATUS", itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); // tempi, potenza, processo, counters vari ACC_TIME_WORK currGateway.addItemNodeAndSet("ACC_TIME", itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet("ACC_TIME_WORK", itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet("POWER", itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); // testing e autodiagnostica currGateway.addItemNodeAndSet("TESTING_DATA", itemType.Message, ""); // strobe/status non riconosciuti currGateway.addItemNodeAndSet("UNK_STATUS", itemType.Message, ""); currGateway.addItemNodeAndSet("UNK_STROBE", itemType.Message, ""); // Aree memoria vettMemArea = new MemArea[adpConf.nMemArea]; for (int i = 0; i < adpConf.nMemArea; i++) { vettMemArea[i] = new MemArea(adpConf.MemArea[i]); currGateway.addItemNodeAndSet(vettMemArea[i].prgNameKey, itemType.Message, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettMemArea[i].prgRunningKey, itemType.Message, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettMemArea[i].numExeKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettMemArea[i].numRepKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); } // Pompe vuoto vettVacPump = new VacuumPump[adpConf.nVacuumPump]; for (int i = 0; i < adpConf.nVacuumPump; i++) { vettVacPump[i] = new VacuumPump(adpConf.VacuumPump[i]); currGateway.addItemNodeAndSet(vettVacPump[i].statusKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettVacPump[i].workTimeKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); } // Attuatori vuoto vettVacAct = new VacuumAct[adpConf.nVacuumAct]; for (int i = 0; i < adpConf.nVacuumAct; i++) { vettVacAct[i] = new VacuumAct(adpConf.VacuumAct[i]); currGateway.addItemNodeAndSet(vettVacAct[i].countKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); } // Lubrorefrigeranti vettLubro = new Lubro[adpConf.nLubro]; for (int i = 0; i < adpConf.nLubro; i++) { vettLubro[i] = new Lubro(adpConf.Lubro[i]); currGateway.addItemNodeAndSet(vettLubro[i].countKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); if (currGateway.protocollo != gwProtocol.SOURS) { currGateway.addItemNodeAndSet(vettLubro[i].statusKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); } } // Slitta Mag vettSlittaMag = new SlittaMag[adpConf.nSlittaMag]; for (int i = 0; i < adpConf.nSlittaMag; i++) { vettSlittaMag[i] = new SlittaMag(adpConf.SlittaMag[i]); currGateway.addItemNodeAndSet(vettSlittaMag[i].countKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); } // Protezione Mag vettProtMag = new ProtMag[adpConf.nProtMag]; for (int i = 0; i < adpConf.nProtMag; i++) { vettProtMag[i] = new ProtMag(adpConf.ProtMag[i]); currGateway.addItemNodeAndSet(vettProtMag[i].countKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); } // Cooler vettCooler = new Cooler[adpConf.nCooler]; for (int i = 0; i < adpConf.nCooler; i++) { vettCooler[i] = new Cooler(adpConf.Cooler[i]); currGateway.addItemNodeAndSet(vettCooler[i].statusKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); } // Press vettPress = new Press[adpConf.nPress]; for (int i = 0; i < adpConf.nPress; i++) { vettPress[i] = new Press(adpConf.Press[i]); currGateway.addItemNodeAndSet(vettPress[i].valueKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); } // Temp vettTempe = new Tempe[adpConf.nTemp]; for (int i = 0; i < adpConf.nTemp; i++) { vettTempe[i] = new Tempe(adpConf.Temp[i]); currGateway.addItemNodeAndSet(vettTempe[i].valueKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); } // 2019.08.28 RIMETTO GESTIONE PROCESSO SEL! //// lo riporto SOLO SE HO almeno 2 processi AND protocollo NON OPC-UA //if (currGateway.protocollo != gwProtocol.SOURS && currAdpConf.nPath > 1) //{ currGateway.addItemNodeAndSet("PROC_SEL", itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); //} vettPath = new Path[adpConf.nPath]; for (int i = 0; i < adpConf.nPath; i++) { vettPath[i] = new Path(adpConf.Path[i]); //samples currGateway.addItemNodeAndSet(vettPath[i].feedKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].feedOverKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].rapidOverKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); // SOLO SE NON sono SOUR... if (currGateway.protocollo != gwProtocol.SOURS) { currGateway.addItemNodeAndSet(vettPath[i].spindleOver_01_Key, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].spindleOver_02_Key, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].spindleOver_03_Key, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].spindleOver_04_Key, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].jogOverKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].posAct_X_Key, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].posAct_Y_Key, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].posAct_Z_Key, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].posAct_I_Key, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].posAct_J_Key, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].posAct_K_Key, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].partIdKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].partCountKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].currProgKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].currProgRowNumKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].currAreaKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); // conditions... currGateway.addItemNodeAndSet(vettPath[i].alarmCncKey, itemType.Condition, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].alarmPlcKey, itemType.Condition, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].activeAxesKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); } // messages & events currGateway.addItemNodeAndSet(vettPath[i].pathTypeKey, itemType.Message, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].pathCodMKey, itemType.Message, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].pathCodSKey, itemType.Message, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].pathCodTKey, itemType.Message, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].runModeKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].exeModeKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].gCodeAct_Key, itemType.Message, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettPath[i].subModeKey, itemType.Message, availStatus.UNAVAILABLE.ToString().ToLower()); } // UnOp vettUnOp = new UnOp[adpConf.nUnOp]; for (int i = 0; i < adpConf.nUnOp; i++) { vettUnOp[i] = new UnOp(adpConf.UnOp[i]); currGateway.addItemNodeAndSet(vettUnOp[i].toolIdKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettUnOp[i].numCUKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettUnOp[i].statusKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettUnOp[i].vitaResKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettUnOp[i].vitaResTypeKey, itemType.Message, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettUnOp[i].speedKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettUnOp[i].speedOverKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettUnOp[i].loadKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettUnOp[i].accTimeKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettUnOp[i].countKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); // SOLO SE NON sono SOUR... if (currGateway.protocollo != gwProtocol.SOURS) { currGateway.addItemNodeAndSet(vettUnOp[i].kRevKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); } } // Assi vettAxis = new Axis[adpConf.nAxis]; for (int i = 0; i < adpConf.nAxis; i++) { vettAxis[i] = new Axis(adpConf.Axis[i]); // SOLO SE NON sono SOUR... if (currGateway.protocollo != gwProtocol.SOURS) { currGateway.addItemNodeAndSet(vettAxis[i].batteryKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettAxis[i].groupKey, itemType.Message, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettAxis[i].accelActKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettAxis[i].isMastKey, itemType.Message, availStatus.UNAVAILABLE.ToString().ToLower()); // conditions... currGateway.addItemNodeAndSet(vettAxis[i].alarmCncKey, itemType.Condition, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettAxis[i].alarmPlcKey, itemType.Condition, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettAxis[i].mastIdKey, itemType.Message, availStatus.UNAVAILABLE.ToString().ToLower()); } currGateway.addItemNodeAndSet(vettAxis[i].descriptionKey, itemType.Message, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettAxis[i].mainProcKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettAxis[i].directionKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettAxis[i].loadKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettAxis[i].posActKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettAxis[i].posTgtKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettAxis[i].feedrateKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettAxis[i].feedOverKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettAxis[i].accTimeKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettAxis[i].distDoneKey, itemType.Sample, availStatus.UNAVAILABLE.ToString().ToLower()); currGateway.addItemNodeAndSet(vettAxis[i].invDDoneKey, itemType.Event, availStatus.UNAVAILABLE.ToString().ToLower()); } // allarmi "base" currGateway.addAlarmNodes(); // 2019.07.22 NON RIPORTO USER_ACTION x SOUR if (currGateway.protocollo != gwProtocol.SOURS) { // azioni utente currGateway.addItemNodeAndSet("USER_ACTION", itemType.Message, ""); } } /// /// alias booleano false = R /// public bool R = false; /// /// alias booleano true = W /// public bool W = true; /// /// wrapper di log /// public static Logger lg; /// /// valore booleano di check se sia in fase di COMUNICAZIONE ATTIVA con il PLC/NC /// protected bool adpCommAct; /// /// valore booleano di check se sia stato AVVIATO l'adapter (Running) /// public bool adpRunning = false; /// /// valore booleano di check se l'adapter STIA SALVANDO /// public bool adpSaving = false; /// /// valore booleano (richiesta di riavvio automatico) /// public bool adpTryRestart; /// /// Ultimo valore watchdog rilevato /// public bool lastWatchDog = false; /// /// Determina se utilizzare blocchi di memoria IOT contigui (e quindi processing "monoblocco" semplificato"= /// public bool procIotMem = false; /// /// porta x adapter (x restart) /// protected int adpPortNum; /// /// DataOra ultimo avvio adapter x watchdog /// protected DateTime adpStartRun; /// /// Data/ora ultimo avvio adapter /// public DateTime dtAvvioAdp = DateTime.Now; /// /// Data/ora ultimo spegnimento adapter /// public DateTime dtStopAdp = DateTime.Now; /// /// vettore gestione cronometraggi /// public DateTime inizio; /// /// Conteggio ATTUALE ore macchina ON /// public double contOreMaccOn; /// /// Conteggio ATTUALE ore macchina IN LAVORO /// public double contOreMaccLav; /// /// Conteggio ATTUALE numero movimenti Slitta Tastatore /// public double contSlittaTast; /// /// Vettore ATTUALE dei contatori giri cumulati elettromandrino (migliaia) /// public uint[] contGiriElettrom; /// /// Vettore ATTUALE dei contatori ore lavorate elettromandrino /// public uint[] contOreElettrom; /// /// Vettore ATTUALE dei contatori del movimento degli assi /// public double[] contDistMovAssi; /// /// Vettore ATTUALE dei contatori del tempo cumulato degli assi /// public double[] contAccTimeAssi; /// /// Vettore ATTUALE dei contatori del num inv degli assi /// public uint[] contNumInvAssi; /// /// vettore dei ProgramName dei path ATTIVI /// public string[] currPathProgrName; /// /// vettore dei PartId dei path ATTIVI /// public string[] currPathPartId; /// /// Vettore ATTUALE dei contatori del num pezzi fatti x PartId /// public uint[] currPathPartCount; /// /// Vettore ATTUALE dei contatori del work time x VacPump /// public uint[] currVacPumpWrkTime; /// /// Vettore ATTUALE dei contatori del numero impieghi VacAct /// public uint[] currVacActCount; /// /// Vettore ATTUALE dei contatori del Lubro /// public uint[] currLubroCount; /// /// Vettore ATTUALE dei contatori del numero cambi utensili x UnOp /// public uint[] currNumCambiUt; /// /// Vettore ATTUALE dei contatori del numero cambi utensili x UnOp /// public uint[] currRepetitionUnOp; /// /// Vettore ATTUALE dei contatori GENERICI MONOTONI CRESCENTI /// public uint[] currCounters; /// /// Vettore ATTUALE dei contatori GENERICI LIBERI /// public uint[] currRTCounters; /// /// Vettore ATTUALE dei contatori x VALORI GENERICI /// public int[] currRTVCount; /// /// Vettore ATTUALE dei contatori del numero movimenti Slitta Magazzino /// public uint[] currSlittaMag; /// /// Vettore ATTUALE dei contatori del numero movimenti Protezione Magazzino /// public uint[] currProtMag; /// /// Conteggio ISTANTANEO ore macchina ON /// public sampleVect istOreMaccOn; /// /// isteggio ISTANTANEO ore macchina IN LAVORO /// public sampleVect istOreMaccLav; /// /// Conteggio ISTANTANEO contatore del numero movimenti Slitta Tastatore /// public sampleVect istSlittaTast; /// /// Vettore ISTANTANEO dei contatori giri cumulati elettromandrino (migliaia) /// public sampleVect[] istGiriElettrom; /// /// Vettore ISTANTANEO dei contatori Apertura teste /// public sampleVect[] istRepetitionUnOp; /// /// Vettore ISTANTANEO dei contatori ORE LAVORATE elettromandrino /// public sampleVect[] istOreElettrom; /// /// Vettore ISTANTANEO dei contatori del movimento degli assi /// public sampleVect[] istDistMovAssi; /// /// Vettore ISTANTANEO dei contatori del LOAD degli assi /// public sampleVect[] istLoadAssi; /// /// Vettore ISTANTANEO dei contatori del tempo cumulato degli assi /// public sampleVect[] istAccTimeAssi; /// /// Vettore ISTANTANEO dei contatori del num inv degli assi /// public sampleVect[] istNumInvAssi; /// /// vettore dei Program Name dei path ISTANTANEI (nuovi/letti) /// public string[] istPathProgrName; /// /// vettore dei PartId dei path ISTANTANEI (nuovi/letti) /// public string[] istPathPartId; /// /// Vettore ISTANTANEO dei contatori del num pezzi fatti x PartId /// public sampleVect[] istPathPartCount; /// /// Vettore ISTANTANEO dei contatori del work time x VacPump /// public sampleVect[] istVacPumpWrkTime; /// /// Vettore ISTANTANEO dei contatori del numero impieghi VacAct /// public sampleVect[] istVacActCount; /// /// Vettore ISTANTANEO dei contatori del Lubro /// public sampleVect[] istLubroCount; /// /// Vettore ISTANTANEO dei contatori del numero cambi utensili x UnOp /// public sampleVect[] istNumCambiUt; /// /// Vettore ISTANTANEO dei contatori generici MONOTONI CRESCENTI /// public sampleVect[] istCounters; /// /// Vettore ISTANTANEO dei contatori generici LIBERI /// public sampleVect[] istRTCounters; /// /// Vettore ISTANTANEO dei contatori generici LIBERI x VALORI /// public sampleVect[] istRTVCount; /// /// Vettore ISTANTANEO dei contatori del numero movimenti Slitta Magazzino /// public sampleVect[] istSlittaMag; /// /// Vettore ISTANTANEO dei contatori del numero movimenti Protezione Magazzino /// public sampleVect[] istProtMag; /// /// vettore valori in file interscambio /// public Dictionary generalStatus; /// /// Contenuto valori contatori manutenzione da PLC /// public otherData[] maintData; /// /// Contenuto valori variabili analogiche da PLC /// public otherData[] analogData; /// /// Contenuto valori variabili stringa da PLC /// public otherData[] stringData; /// /// Contenuto valori status data da PLC /// public otherData[] statusData; /// /// data-ora ultimo controllo movimento assi /// public DateTime lastChekAccumTimeAxis; /// /// posizione precedente assi per calcolo distanze... /// public double[] prevPosAxis; /// /// direzione precedente assi per calcolo inversioni... /// public int[] prevDirAxis; /// /// blocco memoria BYTE x lettura TUTTI i dati di buffer M/S/T /// public byte[] MemBlock_MST; /// /// Indica se sia necessario il salto x array codici MST (OSAI = 1, FANUC/SIEMENS=0) /// public int saltoMST = 0; /// /// Determina se sia encessario convertire valori little/big endian (SIEMENS=true, OSAI=FALSE) /// public bool hasBigEndian = false; /// /// Verifica se siano stati già mostrati gli allarmi x debug... /// public bool alarmMsgDispl = true; /// /// dimensione massima vettore memorie UT /// public short numMemUt = 200; /// /// Processo selezionato /// public string procSel = ""; /// /// Modo del processo selezionato /// public int procMode = 0; /// /// Form chiamante /// protected MainForm parentForm; /// /// Conf adapter corrente /// public AdapterConf currAdpConf; /// /// Obj gestione la comunicazione a valle (secondo standard LOGFILE / MTC / SOURS) /// public Gateway currGateway; #region altri oggetti /// /// 16 byte di strobe (4 word da 32 bit di flags...) /// public byte[] Strobes = new byte[16]; /// /// 16 byte di strobe in risposta (4 word da 32 bit di flags...) /// public byte[] Acknowl = new byte[16]; public Dictionary elencoSubMode; /// /// Prima word di strobe da array flag completo /// public StFlag32 STRB_DW0 { get { return (StFlag32)BitConverter.ToUInt32(Strobes, 0); } } /// /// Seconda word di strobe da array flag completo /// public StFlag32 STRB_DW1 { get { return (StFlag32)BitConverter.ToUInt32(Strobes, 4); } } /// /// Terza word di strobe da array flag completo /// public StFlag32 STRB_DW2 { get { return (StFlag32)BitConverter.ToUInt32(Strobes, 8); } } /// /// Valore statud x standard OPC-UA (da valorizzare in adapter specifico) /// valore default a -1 --> SE NON VALORIZZATO NON LO USA:.. /// public int ouStatus = -1; /// /// Quarta word di strobe da array flag completo /// public StFlag32 STRB_DW3 { get { return (StFlag32)BitConverter.ToUInt32(Strobes, 12); } } /// /// PRIMO BYTE della Quarta word di strobe /// public byte ACK_DW3_B0 { get { return Acknowl[12]; } } /// /// Quarta word di strobe da array flag completo /// public StFlag32 STRB_DW4 { get { return (StFlag32)BitConverter.ToUInt32(Strobes, 16); } } /// /// Prima word di ACKnowledgment da array flag completo /// public StFlag32 ACK_DW0 { get { return (StFlag32)BitConverter.ToUInt32(Acknowl, 0); } } /// /// Seconda word di ACKnowledgment da array flag completo /// public StFlag32 ACK_DW1 { get { return (StFlag32)BitConverter.ToUInt32(Acknowl, 4); } } /// /// Terza word di ACKnowledgment da array flag completo /// public StFlag32 ACK_DW2 { get { return (StFlag32)BitConverter.ToUInt32(Acknowl, 8); } } /// /// Quarta word di ACKnowledgment da array flag completo /// public StFlag32 ACK_DW3 { get { return (StFlag32)BitConverter.ToUInt32(Acknowl, 12); } } /// /// Strobe mask PLC /// public Strobe STROBE_PLC = 0; /// /// Strobe mask adapter /// public Strobe STROBE_ADP = 0; /// /// Status flag /// public StatusBitMap STATUS_FLAG = 0; /// /// Variabili stato macchina principali /// public StFlag8 ST_MACCH = 0; public List[] codaM; public List[] codaS; public List[] codaT; /// /// Verifica se los tatus sia recuperabile dal PLC ( oppure da calcolare) /// public bool ouStatusByPlc { get { return utils.CRB("ouStatusByPlc"); } } #endregion altri oggetti #region Gestione contatori & obj specifici (Events & Samples) /// /// Vettore conters monotoni crescenti - EVENT /// public List elCounter; /// /// Vettore conters realtime (liberi) - EVENT /// public List elRTCounter; /// /// Vettore conters realtime value GENERICI comprensivo di indice - EVENT /// public Dictionary elRTVCount; /// /// Vettore status (EVENT) /// public List elStatus; /// /// Vettore analog data (SAMPLE) /// public List elAnalogData; /// /// Vettore string data (SAMPLE) /// public List elStringData; #endregion Gestione contatori & obj specifici (Events & Samples) #region oggetti complessi/completi public VacuumPump[] vettVacPump; public VacuumAct[] vettVacAct; public Lubro[] vettLubro; public SlittaMag[] vettSlittaMag; public ProtMag[] vettProtMag; public Cooler[] vettCooler; public Press[] vettPress; public Tempe[] vettTempe; public Path[] vettPath; public UnOp[] vettUnOp; public Axis[] vettAxis; public MemArea[] vettMemArea; public Dictionary DirectMem = new Dictionary(); #endregion oggetti complessi/completi public event EventHandler eh_refreshed; /// /// caricamento allarmi da file /// protected void loadAllarmi() { if (utils.CRB("verbose")) { lg.Info("Inizio caricamento vettore allarmi"); } int totRighe = 0; string fileName = string.Format(@"{0}\{1}", utils.confDir, utils.CRS("AlarmList")); string linea; totRighe = File.ReadLines(fileName).Count(); // creo un vettore della dimensione corretta... conta anche commenti tanto poi riduco... currGateway.elencoAllarmi = new allarme[File.ReadLines(fileName).Count()]; // carica da file... StreamReader file = new StreamReader(fileName); // leggo 1 linea alla volta... int numRiga = 0; while ((linea = file.ReadLine()) != null) { // SE non è un commento... if (linea.Substring(0, 1) != "#") { //elencoAllarmi[rumRiga] = decodeAlarmLine(linea, ':'); currGateway.elencoAllarmi[numRiga] = decodeAlarmLine(linea, utils.CRC("testCharSep")); numRiga++; } } // chiudo file file.Close(); // ora trimmo vettore al solo numero VERO degli allarmi caricati... Array.Resize(ref currGateway.elencoAllarmi, numRiga); // inizializzo a zero il vettore allarmi... int numByte = (int)Math.Ceiling(Convert.ToDecimal(numRiga) / 8); // 2016.07.20: dimensione AlarmFlags è la MAX tra quella del numero allarmi ed il numero allarmi standard dalla memoria... if (numByte < 32) { numByte = 32; } currGateway.AlarmFlags = new byte[numByte]; if (utils.CRB("verbose")) { lg.Info(string.Format("Fine caricamento vettore allarmi: {0} allarmi caricati!", numRiga)); } } /// /// Caricamento file rimappatura naming (per evitare uso improprio di "_" che porta a "split") /// impiega il file delle sostituzioni "inizio/fine/contenuto/tutto" (NameRepRolesList) /// protected void loadNameRepRoles() { if (utils.CRB("verbose")) { lg.Info("Inizio caricamento dizionario remapping nomi variabili"); } try { // PRIMA leggo il file GENERATO di replacement... NON dando per scontato ci sia... if (File.Exists(utils.nameRepRoleFileSOUR)) { importFile(utils.nameRepRoleFileSOUR); } // processo file pre REPLACE parziale (con like) - file DI BASE ESPLICITO importFile(utils.nameRepRoleFile); } catch { } } private void importFile(string fileName) { // init variabili string linea; int rumRiga = 0; string valSost = ""; string valTrad; string sMode = ""; string sSearch = ""; string[] dictSubst; subsMode modoSearch; substSearch tipoCerca; StreamReader file; replDict replacement; // carica da file... file = new StreamReader(fileName); // leggo 1 linea alla volta while ((linea = file.ReadLine()) != null) { linea = linea.Trim(); // se HA CONTENUTO if (linea != "") { // SE non è un commento... if (linea.Substring(0, 1) != "#") { dictSubst = linea.Split(utils.CRC("testCharSep")); // recupero valori inseriti sMode = dictSubst[0].Trim(); sSearch = dictSubst[1].Trim(); valSost = dictSubst[2].Trim(); valTrad = dictSubst[3].Trim(); switch (sMode) { case "X": modoSearch = subsMode.X; break; default: case "A": modoSearch = subsMode.A; break; } switch (sSearch) { case "B": tipoCerca = substSearch.B; break; case "C": tipoCerca = substSearch.C; break; case "E": tipoCerca = substSearch.E; break; default: case "I": tipoCerca = substSearch.I; break; } replacement = new replDict { modo = modoSearch, search = tipoCerca, tradz = valTrad }; // 3 oggetti: tipo ricerca | valOriginale | valTradotto if (currGateway.nameRepRoles != null && currGateway.nameRepRoles.ContainsKey(valSost)) { currGateway.nameRepRoles.Remove(valSost); } currGateway.nameRepRoles.Add(valSost, replacement); rumRiga++; } } } // chiudo file file.Close(); // registro chiusura if (utils.CRB("verbose")) { lg.Info(string.Format("Fine caricamento file {0} con dizionario traduzioni nomi: {1} regole caricate", fileName, rumRiga)); } } /// /// Caricamento file rimappatura naming (per evitare uso improprio di "_" che porta a "split") /// impiega il file delle sostituzioni "inizio/fine/contenuto/tutto" (NameRepRolesList) /// protected void loadMemCopyList() { if (utils.CRB("verbose")) { lg.Info("Inizio caricamento dizionario copia variabili REDIS"); } string linea; string fileName = ""; int rumRiga = 0; string valSost = ""; string valTrad; string[] dictSubst; StreamReader file; try { // processo file pre REPLACE parziale (con like) fileName = string.Format(@"{0}\{1}", utils.confDir, utils.CRS("MemCopyList")); // carica da file... file = new StreamReader(fileName); // leggo 1 linea alla volta... while ((linea = file.ReadLine()) != null) { linea = linea.Trim(); // se HA CONTENUTO if (linea != "") { // SE non è un commento... if (linea.Substring(0, 1) != "#") { dictSubst = linea.Split(utils.CRC("testCharSep")); // recupero valori inseriti valSost = dictSubst[0].Trim(); valTrad = dictSubst[1].Trim(); // 3 oggetti: tipo ricerca | valOriginale | valTradotto if (currGateway.memCopyList != null && currGateway.memCopyList.ContainsKey(valSost)) { currGateway.nameRepRoles.Remove(valSost); } currGateway.memCopyList.Add(valSost, valTrad); rumRiga++; } } } // chiudo file file.Close(); // registro chiusura if (utils.CRB("verbose")) { lg.Info(string.Format("Fine caricamento dizionario copia variabili MemCopy: {0} righe caricate", rumRiga)); } } catch { } } /// /// Caricamento altri file necessari epr adapter all'avvio /// protected virtual void loadOtherFile() { // se è SOURS --> leggo datamodel... if (currGateway.protocollo == gwProtocol.SOURS) { if (utils.CRB("verbose")) { lg.Info("Inizio caricamento DataModel per OPC-UA REDIS server"); } string fileName = ""; int rumRiga = 0; StreamReader file; // processo file pre REPLACE parziale (con like) fileName = string.Format(@"{0}\{1}", utils.confDir, utils.CRS("DataModel")); // carica da file... file = new StreamReader(fileName); // leggo file... string rawDataModel = file.ReadToEnd(); // pre-processo datamodel... currGateway.DataModel = utils.xmlSanitize(rawDataModel); // chiudo file file.Close(); // secondo metodo x deserializzare... DataModel dm = new DataModel(); var currMachine2 = dm.Deserialize(currGateway.DataModel); // registro chiusura if (utils.CRB("verbose")) { lg.Info(string.Format("Fine caricamento DataModel XML: {0} righe caricate", rumRiga)); } } } /// /// Lettura file gestione dati manutenzione da PLC /// /// /// /// public void loadMaintData(string memPre, int baseAddr, int memSize) { // carico dati x Maintenance if (utils.CRB("verbose")) { lg.Info("Inizio caricamento vettore variabili manutenzione gestite"); } int totRighe = 0; int numCounters = 0; int numRTCounters = 0; int numRTVCount = 0; string fileName = utils.CounterListFile; if (currGateway.protocollo == gwProtocol.SOURS) { fileName = utils.CounterListFileSOUR; } string linea; totRighe = File.ReadLines(fileName).Count(); // creo un vettore della dimensione corretta... conta anche commenti tanto poi riduco... maintData = new otherData[File.ReadLines(fileName).Count()]; // carica da file... StreamReader file = new StreamReader(fileName); // leggo 1 linea alla volta... int numRiga = 0; while ((linea = file.ReadLine()) != null) { // se NON VUOTA... if (linea != "") { // SE non è un commento... if (linea.Substring(0, 1) != "#") { maintData[numRiga] = decodeOtherData(linea, utils.CRC("testCharSep"), memPre, baseAddr, memSize); // se è un counter lo processo come tale.. if (maintData[numRiga].varName.StartsWith("Counter_")) { numCounters++; } else if (maintData[numRiga].varName.StartsWith("RTCounter_")) { numRTCounters++; } else if (maintData[numRiga].dataType == "RTV") { numRTVCount++; } numRiga++; } } } // chiudo file file.Close(); // ora trimmo vettore al solo numero VERO dei valori caricati... Array.Resize(ref maintData, numRiga); if (utils.CRB("verbose")) { lg.Info(string.Format("Fine caricamento vettore di {0} variabili manutenzione gestite", numRiga)); } // se log verboso 10+ --> scrivo tutti! if (utils.CRI("loglevel") > 9) { foreach (var item in maintData) { lg.Info($"VarName: {item.varName} | dataType: {item.dataType} | codNum: {item.codNum} | memAddr: {item.memAddr}"); } } elCounter = new List(); elRTCounter = new List(); elRTVCount = new Dictionary(); currCounters = new uint[numCounters]; currRTCounters = new uint[numRTCounters]; currRTVCount = new int[numRTVCount]; istCounters = new sampleVect[numCounters]; istRTCounters = new sampleVect[numRTCounters]; istRTVCount = new sampleVect[numRTVCount]; int idx = 0; int idxRT = 0; int idxRTV = 0; foreach (otherData item in maintData) { if (item.varName.StartsWith("Counter_")) { elCounter.Add(item.varName); currGateway.addItemNodeByType(item.varName, itemType.Event); istCounters[idx] = new sampleVect(); idx++; } else if (item.varName.StartsWith("RTCounter_")) { elRTCounter.Add(item.varName); currGateway.addItemNodeByType(item.varName, itemType.Event); istRTCounters[idxRT] = new sampleVect(); idxRT++; } else if (item.dataType == "RTV") { elRTVCount.Add(item.varName, idxRTV); currGateway.addItemNodeByType(item.varName, itemType.Event); istRTVCount[idxRTV] = new sampleVect(); idxRTV++; } else { currGateway.addItemNodeByType(item.varName, itemType.Event); } } if (utils.CRB("verbose")) { lg.Info(string.Format("inizializzato vettore di {0} MTC.EVENTS delle variabili CONTATORI generiche", numRiga)); } } /// /// Lettura file gestione dati analogici da PLC /// /// /// /// public void loadAnalogData(string memPre, int baseAddr, int memSize) { // carico dati x Maintenance if (utils.CRB("verbose")) { lg.Info("Inizio caricamento vettore variabili analogiche gestite"); } int totRighe = 0; string fileName = utils.AnalogListFile; if (currGateway.protocollo == gwProtocol.SOURS) { fileName = utils.AnalogListFileSOUR; } string linea; totRighe = File.ReadLines(fileName).Count(); // creo un vettore della dimensione corretta... conta anche commenti tanto poi riduco... analogData = new otherData[File.ReadLines(fileName).Count()]; // carica da file... StreamReader file = new StreamReader(fileName); // leggo 1 linea alla volta... int numRiga = 0; while ((linea = file.ReadLine()) != null) { // se NON VUOTA... if (linea != "") { // SE non è un commento... if (linea.Substring(0, 1) != "#") { analogData[numRiga] = decodeOtherData(linea, utils.CRC("testCharSep"), memPre, baseAddr, memSize); numRiga++; } } } // chiudo file file.Close(); // ora trimmo vettore al solo numero VERO dei valori caricati... Array.Resize(ref analogData, numRiga); if (utils.CRB("verbose")) { lg.Info(string.Format("Fine caricamento vettore di {0} variabili analogiche gestite", numRiga)); } // ora inizializzo l'insieme dei Samples delle var analogiche elAnalogData = new List(); string varName = ""; for (int i = 0; i < numRiga; i++) { varName = analogData[i].varName; if (currGateway.protocollo != gwProtocol.SOURS) { varName = string.Format("AV_" + analogData[i].varName); } elAnalogData.Add(varName); currGateway.addItemNodeByType(varName, itemType.Sample); } if (utils.CRB("verbose")) { lg.Info(string.Format("inizializzato vettore di {0} MTC.SAMPLES delle variabili analogiche", numRiga)); } } /// /// Lettura file gestione dati status da PLC /// /// /// /// public void loadStatusData(string memPre, int baseAddr, int memSize) { // carico dati x Maintenance if (utils.CRB("verbose")) { lg.Info("Inizio caricamento vettore variabili status gestite"); } int totRighe = 0; // secondo protocollo scelgo quale file... string fileName = utils.StatusListFile; if (currGateway.protocollo == gwProtocol.SOURS) { fileName = utils.StatusListFileSOUR; } string linea; totRighe = File.ReadLines(fileName).Count(); // creo un vettore della dimensione corretta... conta anche commenti tanto poi riduco... statusData = new otherData[File.ReadLines(fileName).Count()]; // carica da file... StreamReader file = new StreamReader(fileName); // leggo 1 linea alla volta... int numRiga = 0; while ((linea = file.ReadLine()) != null) { // se NON VUOTA... if (linea != "") { // SE non è un commento... if (linea.Substring(0, 1) != "#") { statusData[numRiga] = decodeBitData(linea, utils.CRC("testCharSep"), memPre, baseAddr, memSize); numRiga++; } } } // chiudo file file.Close(); // ora trimmo vettore al solo numero VERO dei valori caricati... Array.Resize(ref statusData, numRiga); if (utils.CRB("verbose")) { lg.Info(string.Format("Fine caricamento vettore di {0} variabili status gestite", numRiga)); } // ora inizializzo l'insieme degli Eventi di status elStatus = new List(); string varName = ""; for (int i = 0; i < numRiga; i++) { varName = statusData[i].varName; if (currGateway.protocollo != gwProtocol.SOURS) { varName = string.Format("ST_" + statusData[i].varName); } elStatus.Add(varName); currGateway.addItemNodeByType(varName, itemType.Event); } if (utils.CRB("verbose")) { lg.Info(string.Format("inizializzato vettore di {0} MTC.EVENTS di status", numRiga)); } } /// /// Lettura file gestione dati stringa da PLC /// /// /// /// public void loadStringData(string memPre, int baseAddr, int memSize) { // carico dati x Maintenance if (utils.CRB("verbose")) { lg.Info("Inizio caricamento vettore variabili stringa gestite"); } int totRighe = 0; string fileName = utils.StringListFile; if (currGateway.protocollo == gwProtocol.SOURS) { fileName = utils.StringListFileSOUR; } string linea; totRighe = File.ReadLines(fileName).Count(); // creo un vettore della dimensione corretta... conta anche commenti tanto poi riduco... stringData = new otherData[File.ReadLines(fileName).Count()]; // carica da file... StreamReader file = new StreamReader(fileName); // leggo 1 linea alla volta... int numRiga = 0; while ((linea = file.ReadLine()) != null) { // se NON VUOTA... if (linea != "") { // SE non è un commento... if (linea.Substring(0, 1) != "#") { stringData[numRiga] = decodeOtherData(linea, utils.CRC("testCharSep"), memPre, baseAddr, memSize); numRiga++; } } } // chiudo file file.Close(); // ora trimmo vettore al solo numero VERO dei valori caricati... Array.Resize(ref stringData, numRiga); if (utils.CRB("verbose")) { lg.Info(string.Format("Fine caricamento vettore di {0} variabili stringa gestite", numRiga)); } // ora inizializzo l'insieme dei Samples delle var analogiche elStringData = new List(); string varName = ""; for (int i = 0; i < numRiga; i++) { varName = stringData[i].varName; if (currGateway.protocollo != gwProtocol.SOURS) { varName = string.Format("STR_" + stringData[i].varName); } elStringData.Add(varName); currGateway.addItemNodeByType(varName, itemType.Sample); } if (utils.CRB("verbose")) { lg.Info(string.Format("inizializzato vettore di {0} MTC.SAMPLES delle variabili string", numRiga)); } } /// /// caricamento allarmi da file /// protected void loadSubMode() { try { if (utils.CRB("verbose")) { lg.Info("Inizio caricamento vettore SubMode"); } int totRighe = 0; string fileName = string.Format(@"{0}\{1}", utils.confDir, utils.CRS("SubModeListFilePath")); string linea; totRighe = File.ReadLines(fileName).Count(); // inizializzo elencoSubMode = new Dictionary(); // carica da file... StreamReader file = new StreamReader(fileName); // leggo 1 linea alla volta... string[] valori; while ((linea = file.ReadLine()) != null) { // SE non è un commento... if (linea.Substring(0, 1) != "#") { valori = linea.Split(':'); elencoSubMode.Add(valori[0], valori[1]); } } // chiudo file file.Close(); if (utils.CRB("verbose")) { lg.Info("Fine caricamento vettore SubMode"); } } catch (Exception exc) { lg.Error(exc, "Eccezione in caricamento SubMode"); } } /// /// Decodifica file allarme, con linee allarme composte come di seguito /// LEGACY: CodAllarme | Gruppo | Livello | Descrizione (verrà poi replicata in IT e EN) /// v1811: CodAllarme | Gruppo | Livello | Descrizione (lingua corrente) | Descrizione IT (italiano) | Descrizione EN (inglese) /// /// Allarme in formato tutto su 1 linea /// Tipicamente | /// protected allarme decodeAlarmLine(string linea, char separator) { string[] valori = linea.Split(separator); allarme answ = new allarme(); // in base a quanti oggetti ho uso tutti i valori indicati singolarmente if (valori.Length == 6) { answ = new allarme(valori[0], valori[1], valori[2], valori[3], valori[4], valori[5]); } else // oppure decido di replicare lingua corrente --> IT / EN { answ = new allarme(valori[0], valori[1], valori[2], valori[3]); } return answ; } /// /// Recupera il numero (iniziale) da una stringa prendendo la aprte sino al separatore... /// /// /// /// protected int startNumb(string linea, char separator) { int answ = 0; try { answ = Convert.ToInt32(linea.Substring(0, linea.IndexOf(separator))); } catch { } return answ; } /// /// Decodifica file datiProdSCM /// /// /// /// protected datiProdSCM decodeScmProdLine(string linea, char separator) { string[] valori = linea.Split(separator); datiProdSCM answ = null; if (valori.Length == 23) { answ = new datiProdSCM(valori); } return answ; } /// /// Decodifica file allarme /// /// /// /// tipo memoria (R/D/...) /// indirizzo di partenza memoria /// dimensione singolo slot in byte /// protected otherData decodeOtherData(string linea, char separator, string memPre, int baseAddr, int memSize) { string[] valori = linea.Split(separator); int shift = 0; try { shift = Convert.ToInt32(valori[0]) - 1; } catch { } string memAddr = string.Format("{0}{1}", memPre, baseAddr + shift * memSize); int scale = 1; if (valori.Length > 3) { int.TryParse(valori[3].Trim(), out scale); } return new otherData(valori[0], memAddr, valori[1].Trim(), valori[2].Trim(), scale); } /// /// Decodifica file MAP (caso ESA/IOT) /// /// /// /// indirizzo Byte: indirizzo di partenza memoria /// dimensione singolo slot in byte /// indirizzo bit: numero riga x calcolo indice bit /// protected otherData decodeBitData(string linea, char separator, int ByteNum, int memSize, int BitNum) { string[] valori = linea.Split(separator); int shift = 0; try { shift = Convert.ToInt32(valori[0]) - 1; } catch { } int resto = 0; Math.DivRem(BitNum, 8, out resto); string memAddr = string.Format("{0}.{1}", ByteNum + shift * memSize, resto); return new otherData(valori[0], memAddr, valori[1].Trim(), valori[2].Trim()); } /// /// Decodifica file MAP (caso FANUC/OSAI/...) /// /// /// /// tipo memoria (R/D/...) /// indirizzo Byte: indirizzo di partenza memoria /// dimensione singolo slot in byte /// protected otherData decodeBitData(string linea, char separator, string memPre, int baseAddr, int memSize) { string[] valori = linea.Split(separator); int shift = 0; //indirizzo bit: numero riga x calcolo indice bit (base 0!!!) int numRiga = 0; int.TryParse(valori[0], out numRiga); numRiga--; try { shift = (numRiga) / (8 * memSize); } catch { } int resto = 0; Math.DivRem(numRiga, 8 * memSize, out resto); string memAddr = string.Format("{0}{1}.{2}", memPre, baseAddr + shift, resto); return new otherData(valori[0], memAddr, valori[1].Trim(), valori[2].Trim()); } #region metodi adapter /// /// lettura file di persistenza /// public void loadPersData() { try { // nuova lettura valori da file persistenza... contOreMaccOn = getStoredValDouble("ACC_TIME"); contOreMaccLav = getStoredValDouble("ACC_TIME_WORK"); contSlittaTast = getStoredValDouble("SlittaTastatore_Count"); for (int i = 0; i < currAdpConf.nUnOp; i++) { contGiriElettrom[i] = getStoredValUInt(string.Format("UnOp_{0:00}_AccTime", i + 1)); contOreElettrom[i] = getStoredValUInt(string.Format("UnOp_{0:00}_KRev", i + 1)); currNumCambiUt[i] = getStoredValUInt(string.Format("UnOp_{0:00}_NumCU", i + 1)); currRepetitionUnOp[i] = getStoredValUInt(string.Format("UnOp_{0:00}_Count", i + 1)); } for (int i = 0; i < currAdpConf.nAxis; i++) { contDistMovAssi[i] = getStoredValUInt(string.Format("Axis_{0:00}_DistDone", i + 1)); contNumInvAssi[i] = getStoredValUInt(string.Format("Axis_{0:00}_InvDDone", i + 1)); contAccTimeAssi[i] = getStoredValDouble(string.Format("Axis_{0:00}_AccTime", i + 1)); } for (int i = 0; i < currAdpConf.nVacuumPump; i++) { currVacPumpWrkTime[i] = getStoredValUInt(string.Format("VacPump_{0:00}_WrkTime", i + 1)); } for (int i = 0; i < currAdpConf.nVacuumAct; i++) { currVacActCount[i] = getStoredValUInt(string.Format("VacAct_{0:00}_Count", i + 1)); } for (int i = 0; i < currAdpConf.nLubro; i++) { currLubroCount[i] = getStoredValUInt(string.Format("Lubro_{0:00}_Count", i + 1)); } for (int i = 0; i < currAdpConf.nSlittaMag; i++) { currSlittaMag[i] = getStoredValUInt(string.Format("SlittaMagazzino_{0:00}_Count", i + 1)); } if (elCounter != null) { for (int i = 0; i < elCounter.Count; i++) { currCounters[i] = getStoredValUInt(string.Format("Counter_{0:000}", i + 1)); } } for (int i = 0; i < currAdpConf.nProtMag; i++) { currProtMag[i] = getStoredValUInt(string.Format("ProtMagazzino_{0:00}_Count", i + 1)); } } catch (Exception exc) { lg.Error(string.Format("Eccezione in decodifica valori PersLayer: {0}{1}", Environment.NewLine, exc)); } } /// /// Avvia l'adapter secondo parametri app.config /// public virtual void startAdapter() { lg.Info("Starting adapter..."); // leggo parametri da app.config int port = 0; if (currGateway.protocollo == gwProtocol.MTC) { port = utils.CRI("MTC_port"); } else if (currGateway.protocollo == gwProtocol.SOURS) { port = utils.CRI("SOURS_port"); } // continuo parentForm.commPlcActive = false; adpRunning = true; dtAvvioAdp = DateTime.Now; TimingData.resetData(); // inizializzo vettori di utility.. loadAllarmi(); loadNameRepRoles(); loadSubMode(); loadOtherFile(); // salvo porta! adpPortNum = port; currGateway.port = port; // avvio currGateway.start(); // setto status a ACTIV, SOLO SE è MTC if (currGateway.protocollo == gwProtocol.MTC) { currGateway.updateItemNodeValue("STATUS", actStatus.ACTIVE.ToString()); } // resetto running flag... adpCommAct = false; // avvio i Sample vectors... istOreMaccOn = new sampleVect(); istOreMaccLav = new sampleVect(); istSlittaTast = new sampleVect(); // carico valori da adapter x i conteggi contOreMaccOn = currAdpConf.ContOreMaccOn; contOreMaccLav = currAdpConf.ContOreMaccLav; contSlittaTast = currAdpConf.ContSlittaTast; // UnOp contGiriElettrom = new uint[currAdpConf.nUnOp]; contOreElettrom = new uint[currAdpConf.nUnOp]; istGiriElettrom = new sampleVect[currAdpConf.nUnOp]; istRepetitionUnOp = new sampleVect[currAdpConf.nUnOp]; istOreElettrom = new sampleVect[currAdpConf.nUnOp]; currNumCambiUt = new uint[currAdpConf.nUnOp]; currRepetitionUnOp = new uint[currAdpConf.nUnOp]; istNumCambiUt = new sampleVect[currAdpConf.nUnOp]; for (int i = 0; i < currAdpConf.nUnOp; i++) { // leggo tutti i dati... List> listaDR = currAdpConf.UnOp[i].dataRefList; // punto all'item DataRefItem riContKRev = listaDR.Find(x => x.Key == string.Format("UnOp_{0:00}_KRev", i + 1)); DataRefItem riContOre = listaDR.Find(x => x.Key == string.Format("UnOp_{0:00}_AccTime", i + 1)); DataRefItem riContNumCU = listaDR.Find(x => x.Key == string.Format("UnOp_{0:00}_NumCU", i + 1)); DataRefItem riRepUO = listaDR.Find(x => x.Key == string.Format("UnOp_{0:00}_Count", i + 1)); // recupero valore giri... UInt32 contTotGiri = Convert.ToUInt32(riContKRev.Value); // recupero valore ore... UInt32 contTotOre = Convert.ToUInt32(riContOre.Value); // recupero valore num cambi ut... UInt32 contNumCU = Convert.ToUInt32(riContNumCU.Value); UInt32 contRepUO = Convert.ToUInt32(riRepUO.Value); // salvo valore letto contGiriElettrom[i] = contTotGiri; contOreElettrom[i] = contTotOre; currNumCambiUt[i] = contNumCU; currRepetitionUnOp[i] = contRepUO; istGiriElettrom[i] = new sampleVect(); istRepetitionUnOp[i] = new sampleVect(); istOreElettrom[i] = new sampleVect(); istNumCambiUt[i] = new sampleVect(); } // imposto num assi e leggo valori salvati... contDistMovAssi = new double[currAdpConf.nAxis]; istDistMovAssi = new sampleVect[currAdpConf.nAxis]; istLoadAssi = new sampleVect[currAdpConf.nAxis]; contNumInvAssi = new uint[currAdpConf.nAxis]; istAccTimeAssi = new sampleVect[currAdpConf.nAxis]; contAccTimeAssi = new double[currAdpConf.nAxis]; istNumInvAssi = new sampleVect[currAdpConf.nAxis]; lastChekAccumTimeAxis = DateTime.Now; for (int i = 0; i < currAdpConf.nAxis; i++) { // leggo tutti i dati... List> listaDR = currAdpConf.Axis[i].dataRefList; // punto all'item DataRefItem riContDist = listaDR.Find(x => x.Key == string.Format("Axis_{0:00}_DistDone", i + 1)); DataRefItem riNumInv = listaDR.Find(x => x.Key == string.Format("Axis_{0:00}_Invers", i + 1)); DataRefItem riAccTime = listaDR.Find(x => x.Key == string.Format("Axis_{0:00}_AccTime", i + 1)); // recupero valori... contDistMovAssi[i] = Convert.ToUInt32(riContDist.Value); contNumInvAssi[i] = Convert.ToUInt32(riNumInv.Value); contAccTimeAssi[i] = Convert.ToDouble(riAccTime.Value); // nons erve init generale allarmi finale istDistMovAssi[i] = new sampleVect(); istLoadAssi[i] = new sampleVect(); istAccTimeAssi[i] = new sampleVect(); istNumInvAssi[i] = new sampleVect(); } currPathPartId = new string[currAdpConf.nPath]; istPathPartId = new string[currAdpConf.nPath]; currPathProgrName = new string[currAdpConf.nPath]; istPathProgrName = new string[currAdpConf.nPath]; currPathPartCount = new uint[currAdpConf.nPath]; istPathPartCount = new sampleVect[currAdpConf.nPath]; for (int i = 0; i < currAdpConf.nPath; i++) { // leggo tutti i dati... List> listaDR = currAdpConf.Path[i].dataRefList; // punto all'item DataRefItem riPathProgr = listaDR.Find(x => x.Key == string.Format("Path_{0:00}_PartId", i + 1)); DataRefItem riPathPzTot = listaDR.Find(x => x.Key == string.Format("Path_{0:00}_PZ_TOT", i + 1)); // recupero valori... currPathPartId[i] = riPathProgr.Value; currPathPartCount[i] = Convert.ToUInt32(riPathPzTot.Value); currPathProgrName[i] = ""; if (currGateway.protocollo != gwProtocol.SOURS) { currGateway.initAlarm(currGateway.conditionNodes[vettPath[i].alarmCncKey]); currGateway.initAlarm(currGateway.conditionNodes[vettPath[i].alarmPlcKey]); } istPathPartCount[i] = new sampleVect(); } currVacPumpWrkTime = new uint[currAdpConf.nVacuumPump]; istVacPumpWrkTime = new sampleVect[currAdpConf.nVacuumPump]; for (int i = 0; i < currAdpConf.nVacuumPump; i++) { // leggo tutti i dati... List> listaDR = currAdpConf.VacuumPump[i].dataRefList; // punto all'item DataRefItem riVacPumpWrk = listaDR.Find(x => x.Key == string.Format("VacPump_{0:00}_WrkTime", i + 1)); // recupero valori... currVacPumpWrkTime[i] = Convert.ToUInt32(riVacPumpWrk.Value); istVacPumpWrkTime[i] = new sampleVect(); } currVacActCount = new uint[currAdpConf.nVacuumAct]; istVacActCount = new sampleVect[currAdpConf.nVacuumAct]; for (int i = 0; i < currAdpConf.nVacuumAct; i++) { // leggo tutti i dati... List> listaDR = currAdpConf.VacuumAct[i].dataRefList; // punto all'item DataRefItem riVacActCount = listaDR.Find(x => x.Key == string.Format("VacAct_{0:00}_Count", i + 1)); // recupero valori... currVacActCount[i] = Convert.ToUInt32(riVacActCount.Value); istVacActCount[i] = new sampleVect(); } currLubroCount = new uint[currAdpConf.nLubro]; istLubroCount = new sampleVect[currAdpConf.nLubro]; for (int i = 0; i < currAdpConf.nLubro; i++) { // leggo tutti i dati... List> listaDR = currAdpConf.Lubro[i].dataRefList; // punto all'item DataRefItem riLubro = listaDR.Find(x => x.Key == string.Format("Lubro_{0:00}_Count", i + 1)); // recupero valori... currLubroCount[i] = Convert.ToUInt32(riLubro.Value); istLubroCount[i] = new sampleVect(); } currSlittaMag = new uint[currAdpConf.nSlittaMag]; istSlittaMag = new sampleVect[currAdpConf.nSlittaMag]; for (int i = 0; i < currAdpConf.nSlittaMag; i++) { // leggo tutti i dati... List> listaDR = currAdpConf.SlittaMag[i].dataRefList; // punto all'item DataRefItem riSlittaMag = listaDR.Find(x => x.Key == string.Format("SlittaMagazzino_{0:00}_Count", i + 1)); // recupero valori... currSlittaMag[i] = Convert.ToUInt32(riSlittaMag.Value); istSlittaMag[i] = new sampleVect(); } currProtMag = new uint[currAdpConf.nProtMag]; istProtMag = new sampleVect[currAdpConf.nProtMag]; for (int i = 0; i < currAdpConf.nProtMag; i++) { // leggo tutti i dati... List> listaDR = currAdpConf.ProtMag[i].dataRefList; // punto all'item DataRefItem riProtMag = listaDR.Find(x => x.Key == string.Format("ProtMagazzino_{0:00}_Count", i + 1)); // recupero valori... currProtMag[i] = Convert.ToUInt32(riProtMag.Value); istProtMag[i] = new sampleVect(); } // inizializzo TUTTI gli alarms currGateway.initAlarms(); adpTryRestart = true; parentForm.displayTaskAndWait("Adapter Started!"); } /// /// ferma l'adapter... /// /// indica se si debba tentare di riavviare l'adapter (con caduta connessione viene fermato in automatico) public void stopAdapter(bool tryRestart) { parentForm.displayTaskAndWait("Stopping adapter..."); adpTryRestart = false; if (currGateway.protocollo == gwProtocol.MTC) { currGateway.updateItemNodeValue("STATUS", actStatus.INACTIVE.ToString()); } // faccio una chiamata extra ad ogni metodo di check... gaterAndSend(gatherCycle.HF); gaterAndSend(gatherCycle.MF); gaterAndSend(gatherCycle.LF); gaterAndSend(gatherCycle.VLF); parentForm.displayTaskAndWait("Stopping adapter - last periodic data read..."); // chiudo la connessione all'adapter... tryDisconnect(); // Stop everything... try { currGateway.stop(); } catch (Exception exc) { lg.Error(exc, "Eccezione in chiusura Adapter:{0}{1}", Environment.NewLine, exc); } dtStopAdp = DateTime.Now; adpPortNum = currGateway.port; adpTryRestart = tryRestart; adpRunning = false; // chiudo! parentForm.resetProgBar(); parentForm.dataMonitor_1 = "... not connected, waiting for data ..."; parentForm.dataMonitor_2 = ""; parentForm.dataMonitor_3 = ""; parentForm.displayTaskAndWait("Adapter Stopped."); parentForm.commPlcActive = false; } /// /// effettua recupero dati ed invio valori modificati... /// /// public void gaterAndSend(gatherCycle ciclo) { // controllo connessione/connettività if (connectionOk) { // controllo non sia già in esecuzione... if (!adpCommAct) { // provo ad avviare try { // avvio fase raccolta dati currGateway.beginDataCollect(); // imposto flag adapter running.. adpCommAct = true; adpStartRun = DateTime.Now; } catch (Exception exc) { parentForm.displayTaskAndWait(string.Format("Adapter NOT STARTED!!!{0}{1}", Environment.NewLine, exc)); adpCommAct = false; adpStartRun = DateTime.Now; } if (adpCommAct) { // try / catch generale altrimenti segno che è disconnesso... try { // processing degli strobes di allarme (da ULTIMA rappresentazione vettore dell'ADP) processAlarm(); // se sono in debug testo invio vario dati che ho generalizzato da MTC... #if DEBUG testData(); #endif bool showDebugData = false; // verifico se processare tutto "in un colpo solo" if (procIotMem) { processAllMemory(); // ciclo lento x log... if (ciclo == gatherCycle.LF) { // Eventuale log! if (utils.CRB("recTime")) { logTimeResults(); } } } // oppure in "modalità classica" con multistep... else { // ciclo VHF x invii... if (ciclo == gatherCycle.VHF) { // processo e svuoto Eventuali code di invio per Codici M/S/T trySendCodMST(); } // POI CONTROLLO cicli + lenti di lettura... // ciclo HF: recupero update status & strobes vari if (ciclo == gatherCycle.HF) { // parte che eseguo SEMPRE: RECUPERO stato di tutti gli strobe/status e degli ack attualmente noti getStrobeAndAckStatus(); // faccio refresh degli allarmi segnalati (da strobe su vettore locale) refreshAlarmState(STRB_DW0, true); // acquisizione degli status processStatus(); // processing degli strobes processStrobe(); } else if (ciclo == gatherCycle.MF) { resetDebugConsole(); // leggo parametri a media freq (dati globali, path, assi, Unità Operatrice) getGlobalData(); getUnOp(); getPath(); getAxis(); // se NON in modalità PROD eseguo chiamate "extra" x allarmi if (utils.CRS("mode") == "debug") { // SOLO in modalità testing forzo il controllo continuo allarmi... forceAlarmCheck(); } // salva richiesta update x dati debug showDebugData = true; } // ciclo lento else if (ciclo == gatherCycle.LF) { // leggo EVENTUALI parametri da config file getConfigParam(); ///acquisisco dati su programma in esecuzione e dati generali (stato, orologio, power...) getSlowChangingData(); // Eventuale log! if (utils.CRB("recTime")) { logTimeResults(); } } // ciclo lentissimo else if (ciclo == gatherCycle.VLF) { lg.Info("Richiesta lettura completa allarmi attivi"); // faccio comunque rilettura completa allarmi... forceAlarmCheck(); } } if (showDebugData) { // verifica se debba salvare e mostrare dati checkSavePersDataLayer(); } // INVIO dati variati! currGateway.sendChanged(); } catch (Exception exc) { // segnalo eccezione e indico disconnesso... lg.Error(exc, string.Format("Errore in gestione ciclo principale ADP, fermo adapter{0}{1}", Environment.NewLine, exc)); parentForm.fermaAdapter(true); } // tolgo flag running adpCommAct = false; } else { lg.Info("ADP not running..."); } } else { // log ADP running lg.Error("Non eseguo chiamata: ADP ancora in running"); // se è bloccato da oltre maxSec lo sblocco... if (DateTime.Now.Subtract(adpStartRun).TotalSeconds > utils.CRI("maxAdapterLockSec")) { // tolgo flag running adpCommAct = false; adpStartRun = DateTime.Now; } } } else { // log connessione KO lg.Error("CicloMF - Connessione non disponibile, provo a riconnettere"); // provo a riconnettere SE abilitato tryRestart... if (adpTryRestart && !connectionOk) { lg.Info("ConnKO - tryConnect"); tryConnect(); } } if (eh_refreshed != null) { eh_refreshed(this, new EventArgs()); } } /// /// Effettua verifica direzione asse /// /// /// protected string calculateDirection(int newDir, int i) { string tipoAsse = ""; string direzione = ""; try { tipoAsse = currGateway.getItemNode(vettAxis[i].typeKey).ToString(); if (tipoAsse.EndsWith("UNAVAILABLE")) { tipoAsse = "LINEAR"; } } catch { } if (tipoAsse == "" || tipoAsse == "OPC_UA_REDIS.DataItemRed") { // recupero info TIPO ASSE List> drl = vettAxis[i].dataRefList; foreach (var item in drl) { if (item.Key == vettAxis[i].typeKey) { tipoAsse = item.Value; } } } // verifico tipo direzione da tipo asse... if (tipoAsse == "LINEAR") { if (currGateway.protocollo == gwProtocol.SOURS) { direzione = (newDir > 0) ? "POS" : "NEG"; } else { // ?: conditional operator. direzione = (newDir > 0) ? "POSITIVE" : "NEGATIVE"; } } else if (tipoAsse == "ROTATIONAL") { if (currGateway.protocollo == gwProtocol.SOURS) { direzione = (newDir > 0) ? "CW" : "CCW"; } else { direzione = (newDir > 0) ? "CLOCKWISE" : "COUNTER_CLOCKWISE"; } } return direzione; } /// /// Area per effettuazione test (tipicamente variabili scambiate da MTC --> generali... /// private void testData() { // imposto continuamente valore assetChange/removal x TESGING !!!FARE!!! togliere int sCount = DateTime.Now.Second; } public void resetDebugConsole() { // resetto console debug... parentForm.dataMonitor_1 = ""; parentForm.dataMonitor_2 = ""; parentForm.dataMonitor_3 = ""; // indico msg allarme NON inviati alarmMsgDispl = false; } /// /// recupero dati globali (e comuni) /// public virtual void getGlobalData() { // accodo dati path in DataMonitor...... StringBuilder sb1 = new StringBuilder(); StringBuilder sb2 = new StringBuilder(); // dati base... string currProc = ""; // 2019.08.28 RIMETTO GESTIONE PROCESSO SEL! //if (currGateway.protocollo != gwProtocol.SOURS || currAdpConf.nPath > 1) //{ try { currProc = currGateway.getItemNode("PROC_SEL").ToString(); } catch (Exception exc) { lg.Error($"Eccezione in recupero PROC_SEL:{Environment.NewLine}{exc}"); } //} sb1.AppendLine(string.Format("POWER {0}: | EmStop:{1} | ProcSel: {2}", currGateway.getItemNode("POWER"), currGateway.getItemNode("E_STOP"), currProc)); try { // leggo dati globali... readGlobalData(); } catch (Exception exc) { lg.Error($"Eccezione in readGlobalData:{Environment.NewLine}{exc}"); } // legge overrides... try { readOverrides(ref sb1); } catch (Exception exc) { lg.Error($"Eccezione in readOverrides:{Environment.NewLine}{exc}"); } // processo allarmi CNC try { procCncAlarm(); } catch (Exception exc) { lg.Error($"Eccezione in procCncAlarm:{Environment.NewLine}{exc}"); } // accodo dati base! try { parentForm.dataMonitor_1 += sb1.ToString(); // accodo dati UT... for (int i = 0; i < currAdpConf.nUnOp; i++) { sb2.AppendLine(string.Format("UT: ToolId {0} | VitaRes {1} | TipoVita {2} ", currGateway.getItemNode(vettUnOp[i].toolIdKey), currGateway.getItemNode(vettUnOp[i].vitaResKey), currGateway.getItemNode(vettUnOp[i].vitaResTypeKey))); } parentForm.dataMonitor_2 = sb2.ToString(); } catch (Exception exc) { lg.Error($"Eccezione in accodamento a parentForm:{Environment.NewLine}{exc}"); } // gestisco lettura dati manutenzione da PLC... try { getMtzDataFromPlc(); } catch (Exception exc) { lg.Error($"Eccezione in getMtzDataFromPlc:{Environment.NewLine}{exc}"); } // gestisco lettura dati status da PLC... try { getStatusDataFromPlc(); } catch (Exception exc) { lg.Error($"Eccezione in getStatusDataFromPlc:{Environment.NewLine}{exc}"); } // gestisco lettura dati analogici da PLC... try { getAnalogDataFromPlc(); } catch (Exception exc) { lg.Error($"Eccezione in getAnalogDataFromPlc:{Environment.NewLine}{exc}"); } // gestisco lettura dati stringa da PLC... try { getStringDataFromPlc(); } catch (Exception exc) { lg.Error($"Eccezione in getStringDataFromPlc:{Environment.NewLine}{exc}"); } } /// /// Legge dati globali... /// public virtual void readGlobalData() { } /// /// legge dati override... /// /// /// public virtual bool readOverrides(ref StringBuilder sb1) { bool fatto = false; return fatto; } /// /// processa allarmi CNC... /// public virtual bool procCncAlarm() { bool fatto = false; return fatto; } /// /// Gestione lettura dati manutenzione /// public virtual bool getMtzDataFromPlc() { bool fatto = false; return fatto; } /// /// Gestione lettura dati analogici /// public virtual bool getAnalogDataFromPlc() { bool fatto = false; return fatto; } /// /// Gestione lettura dati stringa /// public virtual bool getStringDataFromPlc() { bool fatto = false; return fatto; } /// /// Gestione lettura dati status da PLC /// public virtual bool getStatusDataFromPlc() { bool fatto = false; return fatto; } /// /// Processa i dati di override di un path /// /// idx path (zero based) /// vettore 7 valori dei dati (valori int16 jog/feed/rapid/spindle[1..4]) /// StringBuilder da aggiornare public bool procPathOverride(int currIdx, ushort[] dataVector, ref StringBuilder sb) { bool fatto = false; // 2019.09.20: provo a salvare i 3 override... try { FeedRateOverPath[currIdx] = dataVector[1]; RapidOverPath[currIdx] = dataVector[2]; SpeedRateOverPath[currIdx] = dataVector[3]; } catch (Exception exc) { lg.Error(exc, $"Errore in processing override per path {currIdx}"); } // altro processing try { // SOLO SE NON sono SOUR... if (currGateway.protocollo != gwProtocol.SOURS) { currGateway.updateItemNodeValue(vettPath[currIdx].jogOverKey, dataVector[0] / 100); } // se ho + di 1 path prendo la sua... if (FeedRatePath.Length > 1) { currGateway.updateItemNodeValue(vettPath[currIdx].feedKey, FeedRatePath[currIdx]); } else { // prendo quella GLOBALE... currGateway.updateItemNodeValue(vettPath[currIdx].feedKey, FeedRate); } // leggo da vettore... CABLATO DIVISO PER 100!!! currGateway.updateItemNodeValue(vettPath[currIdx].feedOverKey, dataVector[1] / 100); currGateway.updateItemNodeValue(vettPath[currIdx].rapidOverKey, dataVector[2] / 100); if (currGateway.protocollo != gwProtocol.SOURS) { currGateway.updateItemNodeValue(vettPath[currIdx].spindleOver_01_Key, dataVector[3] / 100); currGateway.updateItemNodeValue(vettPath[currIdx].spindleOver_02_Key, dataVector[4] / 100); currGateway.updateItemNodeValue(vettPath[currIdx].spindleOver_03_Key, dataVector[5] / 100); currGateway.updateItemNodeValue(vettPath[currIdx].spindleOver_04_Key, dataVector[6] / 100); } // SE il processo è quello corrente... string processo = string.Format("P{0}", currIdx + 1); bool doProc = false; if (currGateway.protocollo != gwProtocol.SOURS) { doProc = currGateway.getItemNode("PROC_SEL").ToString() == processo; } else { doProc = (((DataItemRed)currGateway.getItemNode("PROC_SEL")).Value.ToString() == processo); } if (doProc) { // se da conf richeisto salvo override globale come max tra i 4 letti... if (utils.CRB("getMaxSpOver")) { int maxSpeedOver = 0; maxSpeedOver = ((dataVector[3] / 100) > maxSpeedOver) ? dataVector[3] / 100 : maxSpeedOver; maxSpeedOver = ((dataVector[4] / 100) > maxSpeedOver) ? dataVector[4] / 100 : maxSpeedOver; maxSpeedOver = ((dataVector[5] / 100) > maxSpeedOver) ? dataVector[5] / 100 : maxSpeedOver; maxSpeedOver = ((dataVector[6] / 100) > maxSpeedOver) ? dataVector[6] / 100 : maxSpeedOver; // includo lettura override spindle... è la massima tra quelle che ho letto (dai path) SpeedRateOver = maxSpeedOver; } } // salvo stringa! sb.AppendLine(string.Format("P{0} - Override % Jog | Feed | Rapid: {1} | {2} | {3}", currIdx + 1, dataVector[0] / 100, dataVector[1] / 100, dataVector[2] / 100)); sb.AppendLine(string.Format("P{0} - Override % Spindle 1 | 2 | 3 | 4: {1} | {2} | {3} | {4}", currIdx + 1, dataVector[3] / 100, dataVector[4] / 100, dataVector[5] / 100, dataVector[6] / 100)); fatto = true; } catch { } return fatto; } /// /// riporta il log di tutti i dati di results temporali registrati /// public void logTimeResults() { if (TimingData.results.Count > 0) { lg.Info("{0}--------------- START TIMING DATA ---------------", Environment.NewLine); int globNumCall = 0; TimeSpan globAvgMsec = new TimeSpan(0); foreach (TimeRec item in TimingData.results) { lg.Info("Chiamate {0}: effettuate {1}, tempo medio {2:N2} msec | impegno canale {3:P3}", item.codCall, item.numCall, item.avgMsec, item.totMsec.TotalSeconds / DateTime.Now.Subtract(dtAvvioAdp).TotalSeconds); globNumCall += item.numCall; globAvgMsec += item.totMsec; } // riporto conteggio medio al secondo... lg.Info("Chiamate GLOBALI: {0}, periodo: {1:N2} minuti.cent, tempo medio {2:N2} msec | impegno canale {3:P3}", globNumCall, DateTime.Now.Subtract(dtAvvioAdp).TotalMinutes, globAvgMsec.TotalMilliseconds / globNumCall, globAvgMsec.TotalSeconds / DateTime.Now.Subtract(dtAvvioAdp).TotalSeconds); lg.Info("{0}--------------- STOP TIMING DATA ---------------{0}", Environment.NewLine); // mostro in form statistiche globali! parentForm.updateComStats(string.Format("Periodo: {0:N2}min | {1} x {2:N2}ms | canale {3:P3}", DateTime.Now.Subtract(dtAvvioAdp).TotalMinutes, globNumCall, globAvgMsec.TotalMilliseconds / globNumCall, globAvgMsec.TotalSeconds / DateTime.Now.Subtract(dtAvvioAdp).TotalSeconds)); } } /// /// verifico se ho dati M/S/T e li invio nel caso /// public virtual void trySendCodMST() { // ciclo su + path for (int i = 0; i < currAdpConf.nPath; i++) { // verifico SE ho codici M/S/T da inviare... string codiceM = getNextMCode(i); string codiceS = getNextSCode(i); string codiceT = getNextTCode(i); if (codiceM != "") { currGateway.updateItemNodeValue(vettPath[i].pathCodMKey, string.Format("[M{0}]", codiceM)); } if (codiceS != "") { currGateway.updateItemNodeValue(vettPath[i].pathCodSKey, string.Format("[S{0}]", codiceS)); } if (codiceT != "") { currGateway.updateItemNodeValue(vettPath[i].pathCodTKey, string.Format("[T{0}]", codiceT)); } } } /// /// Metodo base connessione... /// public virtual void tryConnect() { } /// /// Metodo base disconnessione... /// public virtual void tryDisconnect() { } protected bool _connOk = false; /// /// Salva verifica stato connessione OK /// /// public virtual bool connectionOk { get { return _connOk; } set { _connOk = value; } } #region gestione allarmi /// /// effettua ogni log period una rilettura di TUTTI gli allarmi... /// public virtual void forceAlarmCheck() { // carico status allarmi (completo) StFlag32 forceAlarm = (StFlag32)unchecked((int)UInt32.MaxValue); try { refreshAlarmState(forceAlarm, false); } catch { lg.Error("Errore in fase di esecuzione di forceAlarmCheck"); } if (utils.CRB("recTime")) { logTimeResults(); } } /// /// Effettua refresh del vettore privato degli allarmi attivi /// /// flag mask degli allarmi da aggiornare /// boolean: se si debba tornare ACK public virtual void refreshAlarmState(StFlag32 Alarm2Refresh, bool giveAck) { // log bitmap se verboso attivo + ho allarmi da refreshare if ((Alarm2Refresh != StFlag32.NONE) && utils.CRB("verbose")) { lg.Info("AG-RAS | Richiesto refresh allarmi x bitmask: {0}", utils.binaryForm((int)Alarm2Refresh)); } bool ackReturned = false; // byte di acknowledge... byte[] retACK_DW0 = new byte[4]; // inizio impostando una bitmap x ACK che abbia i bit abbassati se lo strobe è disattivo: AND logico tra STR e ACK retACK_DW0 = BitConverter.GetBytes(Convert.ToUInt32(STRB_DW0 & ACK_DW0)); inizio = DateTime.Now; uint[] MemBlock; // controllo, SE devo leggere tutto uso un unico accesso ai 128byte, altrimenti leggo a blocchi di 32bit... if (Alarm2Refresh == (StFlag32)unchecked((int)UInt32.MaxValue)) { // blocco memoria x lettura dati COMPLETO (4Byte*32 = 128Byte) MemBlock = new uint[32]; // recupero tutti i 32 bit del blocco inizio = DateTime.Now; readAllAlarms(ref MemBlock); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("R{0}-STRB_DW0", MemBlock.Length * 4), DateTime.Now.Subtract(inizio).Ticks); } if (currGateway.AlarmFlags != null) { try { // aggiorno vettore allarmi x intero! size del vettore di destinazione (in byte!!!!) Buffer.BlockCopy(MemBlock, 0, currGateway.AlarmFlags, 0, currGateway.AlarmFlags.Length); } catch (Exception exc) { lg.Error(string.Format("Errore in BLOCKCOPY{0}{1}", Environment.NewLine, exc)); } } } else { if (Alarm2Refresh != StFlag32.NONE) { // blocco memoria x lettura dati MemBlock = new uint[1]; // verifico gli allarmi di tutti i bit alzati... for (int i = 0; i < 32; i++) { if (Alarm2Refresh.HasFlag((StFlag32)Math.Pow(2, i))) { // recupero tutti i 32 bit del blocco inizio = DateTime.Now; readAlarmBlock(ref MemBlock, i); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("R{0}-STRB_DW0", MemBlock.Length * 4), DateTime.Now.Subtract(inizio).Ticks); } try { // aggiorno vettore allarmi x intero! Buffer.BlockCopy(MemBlock, 0, currGateway.AlarmFlags, i * 4, 4); } catch (Exception exc) { lg.Error(string.Format("Errore in BLOCKCOPY per indice i = {2},{0}{1}", Environment.NewLine, exc, i)); } if (utils.CRI("loglevel") > 5) { lg.Info("Bit {0}, MemBlock: {1}", i, MemBlock[0]); } // segnalo allarme letto! memorizzo allarme nel vettore ack.... retACK_DW0 = utils.setBitOnStFlag(retACK_DW0, true, i); } } // scrivo ack se richiesto!!! if (giveAck) { // scrivo update ad ack!!! inizio = DateTime.Now; writeAlarmAck(ref retACK_DW0); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("W{0}-ACK_DW0", retACK_DW0.Length), DateTime.Now.Subtract(inizio).Ticks); } ackReturned = true; } } } // SE non ho già tornato un ACK... if (!ackReturned) { // se è diverso il vettori degli ACK in memoria da quello PLC... if (ACK_DW0 != (StFlag32)BitConverter.ToUInt32(retACK_DW0, 0)) { // invio INTERO set ACK_DW0 con bit abbassati... retACK_DW0 = BitConverter.GetBytes(Convert.ToUInt32(STRB_DW0 & ACK_DW0)); inizio = DateTime.Now; writeAlarmAck(ref retACK_DW0); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("W{0}-ACK_DW0", retACK_DW0.Length), DateTime.Now.Subtract(inizio).Ticks); } } } } /// /// Scrive vettore ACK degli allarmi /// /// /// public virtual bool writeAlarmAck(ref byte[] retACK_DW0) { return false; } /// /// Legge vettore di TUTTE memorie tipo DWord dato vettore memorie (completo) /// /// /// public virtual bool readAllAlarms(ref uint[] MemBlock) { return false; } /// /// Legge vettore di TUTTE memorie tipo DWord dato indice di partenza e vettore memorie /// /// /// /// public virtual bool readAlarmBlock(ref uint[] MemBlock, int blockIndex) { return false; } #endregion gestione allarmi #region gestione altri strobe/ack /// /// Invia (se necessario) il watchdog di stato in vita... blink 0/1 ogni secondo /// public void sendWatchDog() { bool setFlag = false; // 2017.07.24 gestisco 32 bit perché c'è la parte finale del doppio watchdog incrociato... byte[] retACK_DW = new byte[4]; // gestione su ultimi 2 bit della DW2 STR/ACK: il PRIMO bit è gestito in master da ADAPTER, il secondo da PLC; in primis io COPIO il valore del bit finale (di cui è slave...) retACK_DW = utils.setBitOnStFlag(retACK_DW, STRB_DW2.HasFlag(StFlag32.B31), 31); // ...poi gestisco il penultimo bit di cui è master... ogni 2 secondi... int restoB30 = 0; Math.DivRem(DateTime.Now.Second, 2, out restoB30); // i secondi dispari controllo... if (restoB30 > 0) { if (STRB_DW2.HasFlag(StFlag32.B30) == ACK_DW2.HasFlag(StFlag32.B30)) { // ... SE in ingresso ho strobe uguale lo cambio!!! retACK_DW = utils.setBitOnStFlag(retACK_DW, !ACK_DW2.HasFlag(StFlag32.B30), 30); } else { retACK_DW = utils.setBitOnStFlag(retACK_DW, ACK_DW2.HasFlag(StFlag32.B30), 30); } } // 2018.10.01 gestione bit status dei check ULTERIORI... SE abilitato if (utils.CRB("stChkEnabled")) { if (currGateway.protocollo == gwProtocol.SOURS) { bool rOK = false; // imposto bit controllo servizio REDIS attivo rOK = currGateway.checkStatus(1); retACK_DW = utils.setBitOnStFlag(retACK_DW, rOK, 16); // controllo catena REDIS | OPC-UA | Gateway | Internet // !!!FARE!!! // verifico se ci siano messaggi da recapitare (MConnect --> GateWay --> macchina) // !!!FARE!!! } else if (currGateway.protocollo == gwProtocol.MTC) { bool agentOk = false; // imposto bit controllo AGENT attivo agentOk = currGateway.checkStatus(1); retACK_DW = utils.setBitOnStFlag(retACK_DW, agentOk, 24); // imposto bit controllo AGENT valido agentOk = currGateway.checkStatus(2); retACK_DW = utils.setBitOnStFlag(retACK_DW, agentOk, 25); // imposto bit controllo CURRENT valido agentOk = currGateway.checkStatus(3); retACK_DW = utils.setBitOnStFlag(retACK_DW, agentOk, 26); } } // 2016.10.18 aggiungo scrittura del bit di "watchdog" al primo bit della DW2... come resto tra secondi / 2 if (utils.CRB("sendWatchDog")) { int resto = 0; Math.DivRem(DateTime.Now.Second / utils.CRI("cycleWatchDog"), 2, out resto); setFlag = resto != 0; // se watchdog è cambiato lo invio, altrimenti lascio come è... if (setFlag != lastWatchDog) { lastWatchDog = setFlag; } retACK_DW = utils.setBitOnStFlag(retACK_DW, setFlag, 0); // imposto primo bit!!! // scrivo su area PLC SE variato if (ACK_DW2 != (StFlag32)BitConverter.ToUInt32(retACK_DW, 0)) { inizio = DateTime.Now; writeWatchDog(ref retACK_DW); if (utils.CRB("recTime")) { TimingData.addResult(string.Format("W{0}-WatchDog", retACK_DW.Length), DateTime.Now.Subtract(inizio).Ticks); } } } } /// /// Scrive watchdog /// /// /// public virtual bool writeWatchDog(ref byte[] retACK_DW) { return false; } #endregion gestione altri strobe/ack /// /// recupero dati PATH /// public virtual void getPath() { // SE presente recupero dati path checkPath(); // dati BASE, ciclando su path for (int i = 0; i < currAdpConf.nPath; i++) { // se ho + di 1 path prendo la sua... if (FeedRatePath.Length > 1) { currGateway.updateItemNodeValue(vettPath[i].feedKey, FeedRatePath[i]); } else { currGateway.updateItemNodeValue(vettPath[i].feedKey, FeedRate); } } } /// /// Recupero dati Unità Operatrici / Mandrini /// public virtual void getUnOp() { } /// /// Processing dati UnOp /// /// public void procUnOp(byte[] unOpSpeedMem) { StringBuilder sb = new StringBuilder(); int numUnOp = currAdpConf.nUnOp; int locSpeedRate = 0; // cicl su path x leggere le velocità dell'UnOp for (int i = 0; i < numUnOp; i++) { // leggo valore Codice locSpeedRate = BitConverter.ToUInt16(unOpSpeedMem, 2 * i); // leggo 41° byte = indice 40 + 2*i x le var del carico UnOp UnOpLoad = unOpSpeedMem[40 + i]; // Eventuale fix bigEndian... if (hasBigEndian) { locSpeedRate = Endian.SwapUInt16((ushort)locSpeedRate); } currGateway.updateItemNodeValue(vettUnOp[i].speedKey, locSpeedRate); currGateway.updateItemNodeValue(vettUnOp[i].loadKey, UnOpLoad); currGateway.updateItemNodeValue(vettUnOp[i].speedOverKey, SpeedRateOver); sb.AppendLine(string.Format("UnOp_{0}: SpeedRate {1} rpm | Load {2} | SpOv: {3}", i + 1, locSpeedRate, UnOpLoad, SpeedRateOver)); } parentForm.dataMonitor_2 += sb.ToString(); } /// /// recupero dati ASSI /// public virtual void getAxis() { } /// /// Gestione STROBE --> ACK per codici M/S/T /// /// byte di strobe corrente /// 0/1/2 /// vettore da restituire di ACK /// shift memoria x buffer dati da leggere /// Vettore completo dei valori + buffer code M/S/T /// Quale coda: M/S/T /// Path (0,1,...) public void gestStrobeCodMST(StFlag8 currStrobe, int bitNum, ref byte[] retACK_DW1, int memShift, byte[] MemBlock, string Coda, int idxPath) { UInt16 numEv = 0; UInt16 codEv = 0; if (currStrobe.HasFlag((StFlag8)Math.Pow(2, bitNum))) { try { // verifico sia > 0 il numero di valori da leggere - indice 0 sull'area... numEv = BitConverter.ToUInt16(MemBlock, 2 * memShift); } catch (Exception exc) { lg.Error(exc, "Errore in gestStrobeCodMST --> BitConverter 01"); } // se è bigEndian devo swappare! if (hasBigEndian) { numEv = Endian.SwapUInt16(numEv); } if (numEv > 0) { // il num ev rappresenta quanti slot 16bit (da 2 byte) sono stati valorizzati, VA FATTO CICLO E LETTI TUTTI for (int i = 0; i < numEv; i++) { try { // leggo valore Codice codEv = BitConverter.ToUInt16(MemBlock, 2 * (1 + saltoMST + i + memShift)); } catch (Exception exc) { lg.Error(exc, "Errore in gestStrobeCodMST --> BitConverter 02"); } if (hasBigEndian) { codEv = Endian.SwapUInt16(codEv); } // accodo Evento Codice appendCodeMST(Coda, codEv.ToString(), idxPath); } } // memorizzo allarme nel vettore ack.... retACK_DW1 = utils.setBitOnStFlag(retACK_DW1, true, bitNum); } } /// /// Gestione strobe UserAction: salva dati e gestione ACK /// /// /// /// /// /// public void gestStrobeUserAction(int idxPath, int bitNum, ref byte[] retACK_DW1, ref string UserAction, string azione) { if (STRB_DW1.HasFlag((StFlag32)Math.Pow(2, bitNum + 16 * idxPath))) { // salvo Evento UserAction in variabile... UserAction += azione; // memorizzo allarme nel vettore ack.... retACK_DW1 = utils.setBitOnStFlag(retACK_DW1, true, bitNum); } } /// /// Ricarica dati da file di scambio con CMSConnect /// public void reloadDataFromFile() { if (currGateway.protocollo == gwProtocol.MTC) { if (utils.CRB("verbose")) { lg.Info("Inizio lettura dati da file"); } int totRighe = 0; // da rivedere: se sono N+1 file (N=path + generale) deve essere ad esempio nomeComune_*.mtc --> ciclo per leggerne N string fileName = string.Format(@"{0}\{1}", utils.dataDir, utils.CRS("GeneralStatusFilePath")); string linea; // creo un vettore della dimensione corretta... conta anche commenti tanto poi riduco... generalStatus = new Dictionary(); try { totRighe = File.ReadLines(fileName).Count(); // carica da file... System.IO.StreamReader file = new System.IO.StreamReader(fileName); if (file != null) { // leggo 1 linea alla volta... string[] valori; while ((linea = file.ReadLine()) != null) { // SE non è un commento... if (linea.Substring(0, 1) != "#") { valori = linea.Split(utils.CRC("testCharSep")); generalStatus.Add(valori[0], valori[1]); } } // chiudo file file.Close(); if (utils.CRB("verbose")) { lg.Info("Fine lettura dati da file scambio CMS"); } } } catch (Exception exc) { lg.Error(exc, "Errore in lettura dati da file scambio CMS"); } // ora salvo valori letti... foreach (KeyValuePair item in generalStatus) { // verifico la chiave e nel caso aggiorno... switch (item.Key) { case "OperatorId": currGateway.updateItemNodeValue("OperatorId", item.Value); break; case "Path_01_CurrProg": istPathProgrName[0] = item.Value; break; case "Path_02_CurrProg": istPathProgrName[1] = item.Value; break; case "Path_03_CurrProg": istPathProgrName[2] = item.Value; break; case "Path_04_CurrProg": istPathProgrName[3] = item.Value; break; case "Path_05_CurrProg": istPathProgrName[4] = item.Value; break; case "Path_06_CurrProg": istPathProgrName[5] = item.Value; break; case "Path_01_PartId": istPathPartId[0] = item.Value; break; case "Path_02_PartId": istPathPartId[1] = item.Value; break; case "Path_03_PartId": istPathPartId[2] = item.Value; break; case "Path_04_PartId": istPathPartId[3] = item.Value; break; case "Path_05_PartId": istPathPartId[4] = item.Value; break; case "Path_06_PartId": istPathPartId[5] = item.Value; break; default: break; } } } } /// /// verifica gli status attivi /// public virtual void processStatus() { // status macchina (SOUR) string sourStatus = "UNDEFINED"; if (currGateway.protocollo == gwProtocol.SOURS) { // recupero byte dello status! ouStatus = ACK_DW3_B0; // recupero valore PUNTUALE status da apposita area memoria... se ha valore >=0... if (ouStatusByPlc && ouStatus >= 0) { sourStatus = ((macState)ouStatus).ToString(); } // calcolo status da ALTRE info (vs leggo variabile...) else { // calcolo lo status... if (!STRB_DW2.HasFlag(StFlag32.B01)) { sourStatus = macState.POWER_OFF.ToString(); } else if (STRB_DW2.HasFlag(StFlag32.B11)) { sourStatus = macState.FAIL.ToString(); } else if (STRB_DW2.HasFlag(StFlag32.B04) && STRB_DW2.HasFlag(StFlag32.B09)) { sourStatus = macState.EXE.ToString(); } else { sourStatus = macState.READY.ToString(); } } currGateway.updateItemNodeValue("STATUS", sourStatus); } // update status da DW2/ DW3 // EMstop: verifico BIT e di conseguenza imposto if (STRB_DW2.HasFlag(StFlag32.B00)) { if (currGateway.protocollo == gwProtocol.SOURS) { currGateway.updateItemNodeValue("E_STOP", true); } else { currGateway.updateItemNodeValue("E_STOP", emStatus.TRIGGERED.ToString()); } } else { if (currGateway.protocollo == gwProtocol.SOURS) { currGateway.updateItemNodeValue("E_STOP", false); } else { currGateway.updateItemNodeValue("E_STOP", emStatus.ARMED.ToString()); } } // verifico POWER ON... if (STRB_DW2.HasFlag(StFlag32.B01)) { if (currGateway.protocollo == gwProtocol.SOURS) { currGateway.updateItemNodeValue("POWER", true); } else { currGateway.updateItemNodeValue("POWER", onOffStatus.ON.ToString()); } } else { if (currGateway.protocollo == gwProtocol.SOURS) { currGateway.updateItemNodeValue("POWER", false); } else { currGateway.updateItemNodeValue("POWER", onOffStatus.OFF.ToString()); } } // Processo selezionato 0=P1, 1=P2 if (STRB_DW2.HasFlag(StFlag32.B02)) { procSel = "P2"; } else { procSel = "P1"; } // 2019.08.28 RIMETTO GESTIONE PROCESSO SEL! //// lo riporto SOLO SE HO almeno 2 processi oppure protocollo NON OPC-UA //if (currGateway.protocollo != gwProtocol.SOURS || currAdpConf.nPath > 1) //{ if (currGateway.getItemNode("PROC_SEL").ToString() != procSel) { currGateway.updateItemNodeValue("PROC_SEL", procSel); } //} // processo ora i dai dei path... di sicuro il primo procPath01_Status(); //...e se c'è pure il secondo... if (currAdpConf.nPath > 1) { // anche il secondo! procPath02_Status(); } // cerco status allarmi presenti if (STRB_DW2.HasFlag(StFlag32.B29)) { currGateway.alarmPresent = true; } else { currGateway.alarmPresent = false; } } /// /// Processa status del path 01... /// public void procPath01_Status() { // HARD CODE: forzo path 1 (indice 0...) x iniziare... int idxPath = 0; string pathType = ""; // verifico tipo processo path... if (STRB_DW2.HasFlag(StFlag32.B03)) { if (currGateway.protocollo == gwProtocol.SOURS) { pathType = "LAV"; } else { pathType = "LAVORO"; } } else { if (currGateway.protocollo == gwProtocol.SOURS) { pathType = "ASS"; } else { pathType = "ASSERV"; } } // switch su RUN mode... string runMode = ""; int currRunMode = 0; if (STRB_DW2.HasFlag(StFlag32.B04)) { currRunMode = (int)MtcRunMode.AUTOMATIC; } else if (STRB_DW2.HasFlag(StFlag32.B05)) { currRunMode = (int)MtcRunMode.EDIT; } else if (STRB_DW2.HasFlag(StFlag32.B06)) { currRunMode = (int)MtcRunMode.MANUAL_DATA_INPUT; } else if (STRB_DW2.HasFlag(StFlag32.B07)) { currRunMode = (int)MtcRunMode.MANUAL; } else if (STRB_DW2.HasFlag(StFlag32.B08)) { currRunMode = (int)MtcRunMode.SEMI_AUTO; } // traduco... if (currGateway.protocollo == gwProtocol.SOURS) { runMode = ((OpcUaPathMode)currRunMode).ToString(); } else { runMode = ((MtcRunMode)currRunMode).ToString(); } // se proc corrente --> salvo if (procSel == "P1") { procMode = currRunMode; } // switch su EXE mode... string exeMode = ""; int currExeMode = 0; if (STRB_DW2.HasFlag(StFlag32.B09)) { currExeMode = (int)MtcExeMode.ACTIVE; } else if (STRB_DW2.HasFlag(StFlag32.B10)) { currExeMode = (int)MtcExeMode.READY; } else if (STRB_DW2.HasFlag(StFlag32.B11)) { currExeMode = (int)MtcExeMode.STOPPED; } else if (STRB_DW2.HasFlag(StFlag32.B12)) { currExeMode = (int)MtcExeMode.FEED_HOLD; } else if (STRB_DW2.HasFlag(StFlag32.B13)) { currExeMode = (int)MtcExeMode.OPTIONAL_STOP; } else if (STRB_DW2.HasFlag(StFlag32.B14)) { currExeMode = (int)MtcExeMode.PROGRAM_STOPPED; } else if (STRB_DW2.HasFlag(StFlag32.B15)) { currExeMode = (int)MtcExeMode.PROGRAM_COMPLETED; } // traduco... if (currGateway.protocollo == gwProtocol.SOURS) { exeMode = ((OpcUaPathStatus)currExeMode).ToString(); } else { exeMode = ((MtcExeMode)currExeMode).ToString(); } // inizializzo SEMPRE a vuoto... string SubMode = ""; // verifico sulla STRB_DW3 i submode che POTREBBERO tutti sovrapposti... if (STRB_DW3 != StFlag32.NONE) { // cerco i bit alzati --> aggiungo relativo submode! for (int i = 0; i < 32; i++) { // converto! e aggiungo allarmi sollevati al corretto controller allarmi... if (STRB_DW3.HasFlag((StFlag32)Math.Pow(2, i))) { SubMode += string.Format(" [P{0:00}_{1}]", idxPath + 1, elencoSubMode[i.ToString()]); } } } // salvo in blocco le info ricostruite x path! savePathData(idxPath, pathType, runMode, exeMode, SubMode.Trim()); } /// /// Processa status del path 02... /// public void procPath02_Status() { // HARD CODE: forzo path 2 (indice 1)... int idxPath = 1; string pathType = ""; // verifico tipo processo path... if (STRB_DW1.HasFlag(StFlag32.B16)) { if (currGateway.protocollo == gwProtocol.SOURS) { pathType = "LAV"; } else { pathType = "LAVORO"; } } else { if (currGateway.protocollo == gwProtocol.SOURS) { pathType = "ASS"; } else { pathType = "ASSERV"; } } // switch su RUN mode... string runMode = ""; int currRunMode = 0; if (STRB_DW2.HasFlag(StFlag32.B17)) { currRunMode = (int)MtcRunMode.AUTOMATIC; } else if (STRB_DW2.HasFlag(StFlag32.B18)) { currRunMode = (int)MtcRunMode.EDIT; } else if (STRB_DW2.HasFlag(StFlag32.B19)) { currRunMode = (int)MtcRunMode.MANUAL_DATA_INPUT; } else if (STRB_DW2.HasFlag(StFlag32.B20)) { currRunMode = (int)MtcRunMode.MANUAL; } else if (STRB_DW2.HasFlag(StFlag32.B21)) { currRunMode = (int)MtcRunMode.SEMI_AUTO; } // traduco... if (currGateway.protocollo == gwProtocol.SOURS) { runMode = ((OpcUaPathMode)currRunMode).ToString(); } else { runMode = ((MtcRunMode)currRunMode).ToString(); } // se proc corrente --> salvo if (procSel == "P2") { procMode = currRunMode; } // switch su EXE mode... string exeMode = ""; int currExeMode = 0; if (STRB_DW2.HasFlag(StFlag32.B22)) { currExeMode = (int)MtcExeMode.ACTIVE; } else if (STRB_DW2.HasFlag(StFlag32.B23)) { currExeMode = (int)MtcExeMode.READY; } else if (STRB_DW2.HasFlag(StFlag32.B24)) { currExeMode = (int)MtcExeMode.STOPPED; } else if (STRB_DW2.HasFlag(StFlag32.B25)) { currExeMode = (int)MtcExeMode.FEED_HOLD; } else if (STRB_DW2.HasFlag(StFlag32.B26)) { currExeMode = (int)MtcExeMode.OPTIONAL_STOP; } else if (STRB_DW2.HasFlag(StFlag32.B27)) { currExeMode = (int)MtcExeMode.PROGRAM_STOPPED; } else if (STRB_DW2.HasFlag(StFlag32.B28)) { currExeMode = (int)MtcExeMode.PROGRAM_COMPLETED; } // traduco... if (currGateway.protocollo == gwProtocol.SOURS) { exeMode = ((OpcUaPathStatus)currExeMode).ToString(); } else { exeMode = ((MtcExeMode)currExeMode).ToString(); } // inizializzo SEMPRE a vuoto... string SubMode = ""; // verifico sulla STRB_DW3 i submode che POTREBBERO tutti sovrapposti... if (STRB_DW4 != StFlag32.NONE) { // cerco i bit alzati --> aggiungo relativo submode! for (int i = 0; i < 32; i++) { // converto! e aggiungo allarmi sollevati al corretto controller allarmi... if (STRB_DW4.HasFlag((StFlag32)Math.Pow(2, i))) { SubMode += string.Format(" [P{0:00}_{1}]", idxPath + 1, elencoSubMode[i.ToString()]); } } } // salvo in blocco le info ricostruite x path! savePathData(idxPath, pathType, runMode, exeMode, SubMode.Trim()); } /// /// Salva i valori per il path indicato SE variati... /// /// /// /// /// /// public void savePathData(int idxPath, string pathType, string pathRunMode, string pathExeMode, string pathSubMode) { // salvo type if (currGateway.getItemNode(vettPath[idxPath].pathTypeKey).ToString() != pathType) { currGateway.updateItemNodeValue(vettPath[idxPath].pathTypeKey, pathType); } // salvo RUN mode if (currGateway.getItemNode(vettPath[idxPath].runModeKey).ToString() != pathRunMode) { currGateway.updateItemNodeValue(vettPath[idxPath].runModeKey, pathRunMode); } // salvo EXE mode if (currGateway.getItemNode(vettPath[idxPath].exeModeKey).ToString() != pathExeMode) { currGateway.updateItemNodeValue(vettPath[idxPath].exeModeKey, pathExeMode); } // salvo i submode.. if (currGateway.getItemNode(vettPath[idxPath].subModeKey).ToString() != pathSubMode) { currGateway.updateItemNodeValue(vettPath[idxPath].subModeKey, pathSubMode); } } /// /// processo tutti gli strobe attivi /// public virtual void processStrobe() { // ...da gestire su ogni adapter... } /// /// Processa strobe x un dato path /// /// path corrente /// Byte di strobe del path corrente /// Byte di strobe del path corrente /// indice x lettura memoria MST del path /// indice x scrittura ACK x path /// stringa COMPLESSIVA azioni utente public void procPathStrobes(int idxPath, StFlag8 currStrobe, StFlag8 currAck, int memIndexMST, int memIndexAck, ref string UserAction) { // byte di strobe e di acknowledge... inizializzo!!! byte[] currACK_DW = new byte[1]; // altre variabili int bitNum = 0; inizio = DateTime.Now; // incomincio vera e propria gestione... try { // controllo TUTTI i flag: se ce ne sono di alzati DEVO processare... if (currStrobe != StFlag8.NONE) { // se ho un M/S/T leggo area... if (currStrobe.HasFlag(StFlag8.B0) || currStrobe.HasFlag(StFlag8.B1) || currStrobe.HasFlag(StFlag8.B2)) { // leggo memoria (direttamente a Byte...)! readMST_data(idxPath, memIndexMST, ref MemBlock_MST); // check COD_M bitNum = 0; gestStrobeCodMST(currStrobe, bitNum, ref currACK_DW, 0, MemBlock_MST, "M", idxPath); // check COD_S bitNum = 1; gestStrobeCodMST(currStrobe, bitNum, ref currACK_DW, 11 + saltoMST, MemBlock_MST, "S", idxPath); // check COD_T bitNum = 2; gestStrobeCodMST(currStrobe, bitNum, ref currACK_DW, 17 + 2 * saltoMST, MemBlock_MST, "T", idxPath); } // check FILE DATI MODIFICATO: ricaricare... bitNum = 3; if (STRB_DW1.HasFlag((StFlag32)Math.Pow(2, bitNum))) { lg.Info("Notifica file modificato"); try { // reload dati da file... reloadDataFromFile(); // memorizzo allarme nel vettore ack.... currACK_DW = utils.setBitOnStFlag(currACK_DW, true, bitNum); } catch { lg.Info("Errore lettura dati da file"); } } // AREA strobe USER ACTION // chiamato Start... bitNum = 4; gestStrobeUserAction(idxPath, bitNum, ref currACK_DW, ref UserAction, string.Format(" (P{0:00} START) ", idxPath + 1)); // chiamato Stop... bitNum = 5; gestStrobeUserAction(idxPath, bitNum, ref currACK_DW, ref UserAction, string.Format(" (P{0:00} STOP) ", idxPath + 1)); // chiamato Reset... bitNum = 6; gestStrobeUserAction(idxPath, bitNum, ref currACK_DW, ref UserAction, string.Format(" (P{0:00} RESET) ", idxPath + 1)); } else { // inizializzo 4 byte a zero!!! currACK_DW = new byte[1]; } } catch (Exception exc) { lg.Error(string.Format("Errore in strobe:{0}{1}", Environment.NewLine, exc)); } // scrivo update ad ack SE VARIATO!!! if (currAck != (StFlag8)currACK_DW[0]) { writeMST_ACK(memIndexAck, ref currACK_DW); } } /// /// Verifica strobe autotest /// /// /// /// /// public void processTestStrobe(StFlag8 currStrobe, StFlag8 currAck, int memIndexAck, int memOrderStart) { // byte di strobe e di acknowledge... inizializzo!!! byte[] currACK_DW = new byte[1]; string TestingData = ""; // INIZIO TEST... int bitNum = 6; if (currStrobe.HasFlag((StFlag8)Math.Pow(2, bitNum))) { // formatto stringa risultato TestingData = string.Format("START TEST{0}", getTestData(utils.CRS("testCharSep"))); // memorizzo allarme nel vettore ack.... currACK_DW = utils.setBitOnStFlag(currACK_DW, true, bitNum); } // FINE TEST... bitNum = 7; if (currStrobe.HasFlag((StFlag8)Math.Pow(2, bitNum))) { // formatto stringa risultato TestingData = string.Format("STOP TEST{0}", getTestData(utils.CRS("testCharSep"))); // memorizzo allarme nel vettore ack.... currACK_DW = utils.setBitOnStFlag(currACK_DW, true, bitNum); } // INVIO stato test... if (currGateway.getItemNode("TESTING_DATA").ToString() != TestingData.Trim()) { currGateway.updateItemNodeValue("TESTING_DATA", TestingData.Trim()); } // scrivo update ad ack SE VARIATO!!! if (currAck != (StFlag8)currACK_DW[0]) { writeMST_ACK(memIndexAck, ref currACK_DW); } } /// /// Recupero info su test: numero + elenco parametri IN/OUT /// /// /// public string getTestData(string charSep) { string answ = ""; // Area di memoria x test... (64 DWord) (la prima va splittata) UInt32[] MemBlockTestData = new UInt32[64]; // variabili numero test e num parametri impiegati int testNum = 0; int numPar = 0; // variabile dove parcheggiare conversione codici dei parametri del test (IN o OUT) UInt32 testParam = 0; readTestData(ref MemBlockTestData); // recupero cod univoco test e numero parametri impiegati testNum = BitConverter.ToUInt16(BitConverter.GetBytes(MemBlockTestData[0]), 0); numPar = BitConverter.ToUInt16(BitConverter.GetBytes(MemBlockTestData[0]), 2); // riporto separatore + numero test + num parametri answ = string.Format("{0}TN:{1}{0}NP:{2}", charSep, testNum, numPar); // se ci sono parametri da accodare li recupero! if (numPar > 0) { for (int i = 0; i < numPar; i++) { testParam = MemBlockTestData[1 + i]; answ += string.Format("{0}{1}", charSep, testParam); } } return answ; } /// /// Effettua lettura dati TESTING /// /// /// public virtual bool readTestData(ref uint[] MemBlockTestData) { bool fatto = false; return fatto; } /// /// Legge area memoria dati MST /// /// /// /// /// public virtual bool readMST_data(int idxPath, int memIndexMST, ref byte[] MemBlock_MST) { bool fatto = false; return fatto; } /// /// Scrive ACK x dati MST /// /// /// /// /// public virtual bool writeMST_ACK(int memIndexAck, ref byte[] currACK_DW) { bool fatto = false; return fatto; } /// /// processo il vettore LOCALE degli allarmi /// public virtual void processAlarm() { currGateway.processAlarm(); } /// /// Classe fittizia in caso di processing GLOBALE di tutto in 1 solo colpo... /// public virtual void processAllMemory() { } /// /// metodo di recupero dei dati di identificativo macchina - DA CONF!!! /// public virtual void getConfigParam() { } /// /// dati "lenti" relativi al device /// public virtual void getSlowChangingData() { if (currGateway.protocollo == gwProtocol.MTC) { // dati da PC currGateway.updateItemNodeValue("CLOCK", DateTime.Now); // reload dati da file... reloadDataFromFile(); } // area gestione dati utensili... in base al num max di UnOp recupero i dati utensile... PROCEDURA AD HOC!!! getDatiUt(currAdpConf.nUnOp); } /// /// recupero di TUTTI gli strobes/status attivi /// public virtual void getStrobeAndAckStatus() { // da gestire su ogni adapter... legge tutto array STROBE!!! } /// /// Effettua decodifica a ritroso della key SOUR /// /// /// /// protected string getOrigName(string varName) { string answ = varName; // se il gateway è sour DEVO FARE CONTROLLO con fix... if (utils.CRS("adpProto") == "SOURS") { GatewaySOURS gSour = (GatewaySOURS)currGateway; answ = gSour.mAdapter.getOrigKey(varName); } // return! return answ; } /// /// Numero massimo (indice) valori maintData (privato) /// protected int _maintDataMaxNum = 0; /// /// Numero massimo (indice) valori maintData (calcolato) /// public int maintDataMaxNum { get { if (_maintDataMaxNum == 0) { if (maintData != null) { // prima stima int idx = maintData.Length; // ora ciclo... foreach (var item in maintData) { int.TryParse(item.codNum, out idx); _maintDataMaxNum = idx > _maintDataMaxNum ? idx : _maintDataMaxNum; } } } return _maintDataMaxNum; } } /// /// Processa la tabella di memoria dei dati di manutenzione /// /// /// public void processMaintData(uint[] tabDatiMtz, otherData[] maintData) { // uno ad uno vado a inserirli nella mappa dei dati dell'adapter... int numero = 0; int idxTab = 0; int valRead = 0; string origName = ""; for (int i = 0; i < maintData.Length; i++) { numero = 0; valRead = 0; // calcolo idx a indice 0... int.TryParse(maintData[i].codNum, out idxTab); idxTab--; origName = getOrigName(maintData[i].varName); // 2020.04.30: inizio TENTANDO di calcolare valRead con suo fattore di scala try { valRead = (int) (tabDatiMtz[idxTab]); // se c'è fatt scala --> divido if (maintData[i].scale != 0 && maintData[i].scale != 1) { // scalo! valRead = valRead / maintData[i].scale; } } catch { } // decodifico... if (origName == "ACC_TIME") { istOreMaccOn.addValue(DateTime.Now, (int)valRead); //istOreMaccOn.addValue(DateTime.Now, Convert.ToInt32(tabDatiMtz[idxTab])); } else if (origName == "ACC_TIME_WORK") { istOreMaccLav.addValue(DateTime.Now, (int)valRead); } else if (origName == "SlittaTastatore_Count") { istSlittaTast.addValue(DateTime.Now, (int)valRead); } // DA RIVEDERE x check traduzione... else if (origName.StartsWith("Counter_")) { try { numero = Convert.ToInt32(origName.Replace("Counter_", "")); } catch { } if (numero > 0 && istCounters.Length >= numero) { istCounters[numero - 1].addValue(DateTime.Now, (int)valRead); } } else if (origName.StartsWith("RTCounter_")) { try { numero = Convert.ToInt32(origName.Replace("RTCounter_", "")); } catch { } if (numero > 0 && istRTCounters.Length >= numero) { istRTCounters[numero - 1].addValue(DateTime.Now, (int)valRead); } } else if (elRTVCount.ContainsKey(origName)) { // recupero da dictionary! try { // numero base 0 --> +1!!! numero = elRTVCount[origName] + 1; } catch { numero = 0; } if (numero > 0 && istRTVCount.Length >= numero) { istRTVCount[numero - 1].addValue(DateTime.Now, (int)valRead); } } else if (origName.StartsWith("Path_")) { if (origName.EndsWith("_PZ_TOT")) { try { numero = Convert.ToInt32(origName.Replace("Path_", "").Replace("_PZ_TOT", "")); } catch { } if (numero > 0 && vettPath.Length >= numero) { // SE NON E' SOUR... if (currGateway.protocollo != gwProtocol.SOURS) { currGateway.updateItemNodeValue(vettPath[numero - 1].partCountKey, valRead); } } } } else if (origName.StartsWith("Axis_")) { if (origName.EndsWith("_DistDone")) { try { numero = Convert.ToInt32(origName.Replace("Axis_", "").Replace("_DistDone", "")); } catch { } if (numero > 0 && istDistMovAssi.Length >= numero) { istDistMovAssi[numero - 1].addValue(DateTime.Now, (int)valRead); } } else if (origName.EndsWith("_InvDDone") || origName.EndsWith("_Invers")) { try { numero = Convert.ToInt32(origName.Replace("Axis_", "").Replace("_InvDDone", "").Replace("_Invers", "")); } catch { } if (numero > 0 && istNumInvAssi.Length >= numero) { // 2016.07.06 debug di valori che potrebbero essere nulli... try { valRead = (int) tabDatiMtz[idxTab]; } catch (Exception exc) { valRead = 0; lg.Error(string.Format("Errore in recupero num inversioni:{0}parametro: {1}{0}i: {2}{0}Exc: {3}", Environment.NewLine, maintData[i].varName, i, exc)); } istNumInvAssi[numero - 1].addValue(DateTime.Now, Convert.ToInt32(valRead)); } } else if (origName.EndsWith("_AccTime")) { try { numero = Convert.ToInt32(origName.Replace("Axis_", "").Replace("_AccTime", "")); } catch { } if (numero > 0 && istAccTimeAssi.Length >= numero) { // 2016.07.06 debug di valori che potrebbero essere nulli... try { valRead = (int) tabDatiMtz[idxTab]; } catch (Exception exc) { valRead = 0; lg.Error(string.Format("Errore in recupero num AccTime:{0}parametro: {1}{0}i: {2}{0}Exc: {3}", Environment.NewLine, maintData[i].varName, i, exc)); } istAccTimeAssi[numero - 1].addValue(DateTime.Now, Convert.ToInt32(valRead)); } } } else if (origName.StartsWith("UnOp_") || origName.StartsWith("OperatingGroups:")) { if (origName.EndsWith("_AccTime") || origName.EndsWith("ActiveTime")) { try { numero = Convert.ToInt32(origName.Replace("UnOp_", "").Replace("_AccTime", "")); } catch { } if (numero > 0 && istOreElettrom.Length >= numero) { istOreElettrom[numero - 1].addValue(DateTime.Now, (int)valRead); } } else if (origName.EndsWith("_KRev") || origName.EndsWith("Distance")) { try { numero = Convert.ToInt32(origName.Replace("UnOp_", "").Replace("_KRev", "")); } catch { } if (numero > 0 && istGiriElettrom.Length >= numero) { istGiriElettrom[numero - 1].addValue(DateTime.Now, (int)valRead); } } else if (origName.EndsWith("_NumCambiUT")) { try { numero = Convert.ToInt32(origName.Replace("UnOp_", "").Replace("_NumCambiUT", "")); } catch { } if (numero > 0 && istNumCambiUt.Length >= numero) { istNumCambiUt[numero - 1].addValue(DateTime.Now, (int)valRead); } } else if (origName.EndsWith("_NumCU")) { try { numero = Convert.ToInt32(origName.Replace("UnOp_", "").Replace("_NumCU", "")); } catch { } if (numero > 0 && istNumCambiUt.Length >= numero) { istNumCambiUt[numero - 1].addValue(DateTime.Now, (int)valRead); } } else if (origName.EndsWith("_Count")) { try { numero = Convert.ToInt32(origName.Replace("UnOp_", "").Replace("_Count", "")); } catch { } if (numero > 0 && istRepetitionUnOp.Length >= numero) { istRepetitionUnOp[numero - 1].addValue(DateTime.Now, (int)valRead); } } } else if (origName.StartsWith("VacPump_")) { if (origName.EndsWith("_WrkTime")) { try { numero = Convert.ToInt32(origName.Replace("VacPump_", "").Replace("_WrkTime", "")); } catch { } if (numero > 0 && istVacPumpWrkTime.Length >= numero) { istVacPumpWrkTime[numero - 1].addValue(DateTime.Now, (int)valRead); } } } else if (origName.StartsWith("VacAct_")) { if (origName.EndsWith("_Count")) { try { numero = Convert.ToInt32(origName.Replace("VacAct_", "").Replace("_Count", "")); } catch { } if (numero > 0 && istVacActCount.Length >= numero) { istVacActCount[numero - 1].addValue(DateTime.Now, (int)valRead); } } } else if (origName.StartsWith("Lubro_")) { if (origName.EndsWith("_Num") || origName.EndsWith("_Count")) { try { numero = Convert.ToInt32(origName.Replace("Lubro_", "").Replace("_Num", "").Replace("_Count", "")); } catch { } if (numero > 0 && istLubroCount.Length >= numero) { istLubroCount[numero - 1].addValue(DateTime.Now, (int)valRead); } } } else if (origName.StartsWith("SlittaMagazzino_")) { if (origName.EndsWith("_Count")) { try { numero = Convert.ToInt32(origName.Replace("SlittaMagazzino_", "").Replace("_Count", "")); } catch { } if (numero > 0 && istSlittaMag.Length >= numero) { istSlittaMag[numero - 1].addValue(DateTime.Now, (int)valRead); } } } else if (origName.StartsWith("ProtMagazzino_")) { if (origName.EndsWith("_Count")) { try { numero = Convert.ToInt32(origName.Replace("ProtMagazzino_", "").Replace("_Count", "")); } catch { } if (numero > 0 && istProtMag.Length >= numero) { istProtMag[numero - 1].addValue(DateTime.Now, (int)valRead); } } } else if (origName.StartsWith("AuxiliaryGroups")) { try { currGateway.updateItemNodeValue(origName, valRead); } catch (Exception exc) { } } else //if (origName.StartsWith("ProtMagazzino_")) { try { currGateway.updateItemNodeValue(origName, valRead); } catch (Exception exc) { } } // !!!FIXME!!! verificare SE si vuole reinserire gestione contapezzi e/o variabili "freepass" qui... } } /// /// Numero massimo (indice) valori analogData (privato) /// protected int _analogDataMaxNum = 0; /// /// Numero massimo (indice) valori analogData (calcolato) /// public int analogDataMaxNum { get { if (_analogDataMaxNum == 0) { if (analogData != null) { // prima stima int idx = analogData.Length; // ora ciclo... foreach (var item in analogData) { int.TryParse(item.codNum, out idx); _analogDataMaxNum = idx > _analogDataMaxNum ? idx : _analogDataMaxNum; } } } return _analogDataMaxNum; } } /// /// Numero massimo (indice) valori string (privato) /// protected int _stringDataMaxNum = 0; /// /// Numero massimo (indice) valori string (calcolato) /// public int stringDataMaxNum { get { if (_stringDataMaxNum == 0) { if (stringData != null) { // prima stima int idx = stringData.Length; // ora ciclo... foreach (var item in stringData) { int.TryParse(item.codNum, out idx); _stringDataMaxNum = idx > _stringDataMaxNum ? idx : _stringDataMaxNum; } } } return _stringDataMaxNum; } } /// /// Processa la tabella di memoria dei dati analogici /// /// /// public void processAnalogData(int[] tabDatiAnag, otherData[] analogData) { // uno ad uno vado a inserirli nella mappa dei dati dell'adapter... StringBuilder sb = new StringBuilder(); double analogVal = 0; int idxTab = 0; string origName = ""; for (int i = 0; i < analogData.Length; i++) { // calcolo idx a indice 0... int.TryParse(analogData[i].codNum, out idxTab); idxTab--; origName = getOrigName(analogData[i].varName); // gestisco in modalità "lazy" qualsiasi variabile (dividendo x opportuno fattore conversione...) try { analogVal = (double)tabDatiAnag[idxTab] / (double)utils.CRI("fattDecVA"); } catch (Exception exc) { analogVal = 0; lg.Error(string.Format("Errore in recupero valore analogico:{0}parametro: {1}{0}i: {2}{0}Exc: {3}", Environment.NewLine, analogData[i].varName, i, exc)); } // salvo vettore Eventi... currGateway.updateItemNodeValue(elAnalogData[i], analogVal); //currGateway.updateItemNodeValue(elAnalogData[idxTab], analogVal); // accodo ultimi codici in visualizzazione... sb.AppendLine(currGateway.getItemNode(elAnalogData[i]).ToString().Replace("|", " | ")); } // aggiungo i vari analogici rilevati parentForm.dataMonitor_3 += sb.ToString(); } /// /// Processa la tabella di memoria dei dati analogici /// /// /// public void processAnalogData(uint[] tabDatiAnag, otherData[] analogData) { // uno ad uno vado a inserirli nella mappa dei dati dell'adapter... StringBuilder sb = new StringBuilder(); double analogVal = 0; int idxTab = 0; string origName = ""; for (int i = 0; i < analogData.Length; i++) { // calcolo idx a indice 0... int.TryParse(analogData[i].codNum, out idxTab); idxTab--; origName = getOrigName(analogData[i].varName); // gestisco in modalità "lazy" qualsiasi variabile (dividendo x opportuno fattore conversione...) try { analogVal = (double)tabDatiAnag[idxTab] / (double)utils.CRI("fattDecVA"); } catch (Exception exc) { analogVal = 0; lg.Error(string.Format("Errore in recupero valore analogico:{0}parametro: {1}{0}i: {2}{0}Exc: {3}", Environment.NewLine, analogData[i].varName, i, exc)); } // salvo vettore Eventi... currGateway.updateItemNodeValue(elAnalogData[idxTab], analogVal); // accodo ultimi codici in visualizzazione... sb.AppendLine(currGateway.getItemNode(elAnalogData[idxTab]).ToString().Replace("|", " | ")); } // aggiungo i vari analogici rilevati parentForm.dataMonitor_3 += sb.ToString(); } /// /// Processa la tabella di memoria dei dati stringa /// /// /// public void processStringData(string[] tabDatiString, otherData[] stringData) { // uno ad uno vado a inserirli nella mappa dei dati dell'adapter... StringBuilder sb = new StringBuilder(); int idxTab = 0; string origName = ""; for (int i = 0; i < stringData.Length; i++) { // calcolo idx a indice 0... int.TryParse(stringData[i].codNum, out idxTab); idxTab--; origName = getOrigName(stringData[i].varName); // salvo vettore... currGateway.updateItemNodeValue(elStringData[idxTab], tabDatiString[idxTab]); // accodo ultimi codici in visualizzazione... sb.AppendLine(currGateway.getItemNode(elStringData[idxTab]).ToString().Replace("|", " | ")); } // aggiungo i vari analogici rilevati parentForm.dataMonitor_3 += sb.ToString(); } /// /// processa dataLayer e se necessario salva/mostra /// public void checkSavePersDataLayer() { // aggiungo dettaglio valori ultimi codici MST StringBuilder sb = new StringBuilder(); string codM = ""; string codS = ""; string codT = ""; for (int i = 0; i < currAdpConf.nPath; i++) { codM = currGateway.getItemNode(vettPath[i].pathCodMKey).ToString().Replace("NULL", "n.d.").Replace("UNAVAILABLE", "n.d."); codS = currGateway.getItemNode(vettPath[i].pathCodSKey).ToString().Replace("NULL", "n.d.").Replace("UNAVAILABLE", "n.d."); codT = currGateway.getItemNode(vettPath[i].pathCodTKey).ToString().Replace("NULL", "n.d.").Replace("UNAVAILABLE", "n.d."); // accodo ultimi codici in visualizzazione... sb.AppendLine(string.Format("P{0} last MST: {1} | {2} | {3}", i + 1, codM, codS, codT)); } parentForm.dataMonitor_1 += sb.ToString(); if (persistenceLayer != null) { bool needSave = false; // verifica se si debba aggiornare XML (e salva in adapter dati vari) needSave = procOreMaccOn(needSave); needSave = procOreMaccLav(needSave); needSave = procProgrName(needSave); needSave = procPartId(needSave); needSave = procPzProd(needSave); needSave = procGiriTotUnOp(needSave); needSave = procNumCU(needSave); needSave = procRepetitions(needSave); needSave = procCounters(needSave); needSave = procMovTotAssi(needSave); needSave = procAccTimeAssi(needSave); needSave = procNumInvAssi(needSave); needSave = procVacPump(needSave); needSave = procVacAct(needSave); needSave = procLubro(needSave); needSave = procSlittaMag(needSave); needSave = procProtMag(needSave); // salvo se necessario! if (needSave) { parentForm.persistData(); } // ------------------------------------------- } } /// /// Numero massimo (indice) valori analogData (privato) /// protected int _statusDataMaxNum = 0; /// /// Numero massimo (indice) valori analogData (calcolato) /// public int statusDataMaxNum { get { if (_statusDataMaxNum == 0) { if (statusData != null) { // prima stima int idx = statusData.Length; // ora ciclo... foreach (var item in statusData) { int.TryParse(item.codNum, out idx); _statusDataMaxNum = idx > _statusDataMaxNum ? idx : _statusDataMaxNum; } } } return _statusDataMaxNum; } } /// /// Processa la tabella di memoria degli status di manutenzione /// /// /// public void processStatusData(byte[] tabDatiStatus, otherData[] statusData) { int bitNum = 0; int byteNum = 0; byte byteVal; StringBuilder sb = new StringBuilder(); // uno ad uno vado a inserirli nella mappa dei dati dell'adapter... int numero = 0; string status = ""; int idxTab = 0; string origName = ""; for (int i = 0; i < statusData.Length; i++) { numero = 0; status = ""; // calcolo idx a indice 0... int.TryParse(statusData[i].codNum, out idxTab); idxTab--; origName = getOrigName(statusData[i].varName); // calcolo quale byte e quale bit devo leggere.. byteNum = idxTab / 8; // indice zero dei bit nel byte ( da cui -1 ) bitNum = idxTab - (8 * byteNum); // faccio vera lettura byteVal = tabDatiStatus[byteNum]; // leggo bit come ACTIVE/INACTIVE if (((StFlag8)byteVal).HasFlag((StFlag8)Math.Pow(2, bitNum))) { if (currGateway.protocollo == gwProtocol.SOURS) { status = "EXE"; } else { status = "ACTIVE"; } } else { if (currGateway.protocollo == gwProtocol.SOURS) { status = "READY"; } else { status = "INACTIVE"; } } // gestione AGGIUNTIVA vettori memorie "vecchie" per retrocompatibilità... if (origName.StartsWith("VacPump_")) { if (origName.EndsWith("_Status")) { try { numero = Convert.ToInt32(origName.Replace("VacPump_", "").Replace("_Status", "")); } catch { } if (numero > 0) { currGateway.updateItemNodeValue(vettVacPump[numero - 1].statusKey, status); } } } else if (origName.StartsWith("Cooler_")) { if (origName.EndsWith("_Status")) { try { numero = Convert.ToInt32(origName.Replace("Cooler_", "").Replace("_Status", "")); } catch { } if (numero > 0) { currGateway.updateItemNodeValue(vettCooler[numero - 1].statusKey, status); } } } else if (origName.StartsWith("UnOp_")) { if (origName.EndsWith("_Status")) { try { numero = Convert.ToInt32(origName.Replace("UnOp_", "").Replace("_Status", "")); } catch { } if (numero > 0) { currGateway.updateItemNodeValue(vettUnOp[numero - 1].statusKey, status); } } } // salvo vettore Eventi... currGateway.updateItemNodeValue(elStatus[i], status); // accodo ultimi codici in visualizzazione... if (currGateway.protocollo == gwProtocol.MTC) { sb.AppendLine(currGateway.getItemNode(elStatus[i]).ToString().Replace("|", " | ")); } else if (currGateway.protocollo == gwProtocol.SOURS) { DataItemRed redDI = (DataItemRed)currGateway.getItemNode(elStatus[i]); sb.AppendLine(string.Format("{0} | {1}", redDI.Name, redDI.Value)); } } // aggiungo i vari status rilevati parentForm.dataMonitor_2 += sb.ToString(); } /// /// procedura di lettura (multistep) dati da memoria x caricare dati utensile /// /// num max di teste da recuperare public virtual void getDatiUt(int maxNumOp) { // variabili "Indice" utensile e famiglia da decodificare + utils int maxMemAddr = numMemUt; byte[] elencoUtMem = new byte[2 * 20]; byte[] tabUt_UT = new byte[2 * maxMemAddr]; byte[] tabFam_FamUt = new byte[2 * maxMemAddr]; // altre variabili ushort[] idUtMontato = new ushort[maxNumOp]; ushort[] idFamUt = new ushort[maxNumOp]; int[] idTipoVitaUt = new int[maxNumOp]; uint[] valVitaUtRes = new uint[maxNumOp]; ushort[] tabUt = new ushort[maxMemAddr]; ushort[] tabFamUt = new ushort[maxMemAddr]; int memIndex = 0; byte[] int32Mem = new byte[4]; byte[] int16Mem = new byte[2]; byte int8Mem = new byte(); bool found = false; // step 1: lettura ID dell'utensile x ogni testa... leggo area memoria degli UT montati memIndex = getDatiUt_step1(ref elencoUtMem); // decodifica da byte a int16 dell'ID Utensile for (int i = 0; i < maxNumOp; i++) { idUtMontato[i] = BitConverter.ToUInt16(elencoUtMem, 2 * i); } // step 2a: leggo vettore memoria dei maxMemAddr(200) UT in Tabella Utensili memIndex = getDatiUt_step2a(ref tabUt_UT); // decodifico TUTTI i maxMemAddr utensili for (int i = 0; i < maxMemAddr; i++) { tabUt[i] = BitConverter.ToUInt16(tabUt_UT, 2 * i); } // step 2b: devo cercare l'UT di ogni UnOp nella Tabella Utensili for (int i = 0; i < maxNumOp; i++) { // poiché potrei trovarlo replicato dopo la prima volta che lo trovo evito di ricontrollare... found = false; // spazzo la tab Utensili x cercare quelli delle UnOp... for (int j = 0; j < maxMemAddr; j++) { // controllo, se l'id utensile è quello dell'attuale UnOp... if (tabUt[j] == idUtMontato[i] && !found) { // leggo FamUt puntuale.. memIndex = getDatiUt_step2b(ref int16Mem, j); // step 2b: leggo puntualmente la FamUt dal suo indice... idFamUt[i] = BitConverter.ToUInt16(int16Mem, 0); found = true; } } } // step 3a: leggo vettore memoria dei maxMemAddr(200) FamUT in Tabella Famiglie Utensili (x ricavare unità misura vita) memIndex = getDatiUt_step3a(ref tabFam_FamUt); // decodifico TUTTI i maxMemAddr utensili for (int i = 0; i < maxMemAddr; i++) { tabFamUt[i] = BitConverter.ToUInt16(tabFam_FamUt, 2 * i); } // step 3b: devo cercare la famiglia dell'UT di ogni UnOp nella Tabella Famiglie for (int i = 0; i < maxNumOp; i++) { // poiché potrei trovarlo replicato dopo la prima volta che lo trovo evito di ricontrollare... found = false; // spazzo la tab Utensili x cercare quelli delle UnOp... for (int j = 0; j < maxMemAddr; j++) { // controllo, se l'id utensile è quello dell'attuale UnOp... if (tabFamUt[j] == idFamUt[i] && !found) { // leggo FamUt puntuale.. memIndex = getDatiUt_step3b(ref int8Mem, j); // step 3b: leggo puntualmente il TIPO DI vita UT dal suo indice... idTipoVitaUt[i] = int8Mem; found = true; } } } // step 4: recupero la vita residua dell'utensile for (int i = 0; i < maxNumOp; i++) { // poiché potrei trovarlo replicato dopo la prima volta che lo trovo evito di ricontrollare... found = false; // spazzo la tab Utensili x cercare quelli delle UnOp... for (int j = 0; j < maxMemAddr; j++) { // controllo, se l'id utensile è quello dell'attuale UnOp... if (tabUt[j] == idUtMontato[i] && !found) { // leggo FamUt puntuale.. memIndex = getDatiUt_step4(ref int32Mem, j); // leggo puntualmente valore della vita ut residua da indice utensile... valVitaUtRes[i] = BitConverter.ToUInt32(int32Mem, 0); found = true; } } } // salvo in adapter vita UT residua... for (int i = 0; i < maxNumOp; i++) { currGateway.updateItemNodeValue(vettUnOp[i].toolIdKey, idUtMontato[i]); currGateway.updateItemNodeValue(vettUnOp[i].vitaResKey, valVitaUtRes[i]); // decodifico valore tipo VitaRes... string tipoVitaRes = "ND"; switch (idTipoVitaUt[i]) { case 1: tipoVitaRes = "Time"; break; case 2: tipoVitaRes = "Stroke"; break; case 3: tipoVitaRes = "Distance"; break; default: break; } currGateway.updateItemNodeValue(vettUnOp[i].vitaResTypeKey, tipoVitaRes); } } /// /// Procedura di processing lettura memoria x DatiUt - Step 4 /// /// /// /// public virtual int getDatiUt_step4(ref byte[] int32Mem, int j) { int memIndex = 13100 + 4 * j; //inizio = DateTime.Now; //OsaiMemRW(R, FANUC.MemType.D, memIndex, ref int32Mem); //if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabUT-VitaRes", int32Mem.Length), DateTime.Now.Subtract(inizio).Ticks); return memIndex; } /// /// Procedura di processing lettura memoria x DatiUt - Step 3b /// /// /// /// public virtual int getDatiUt_step3b(ref byte int8Mem, int j) { int memIndex = 10700 + 1 * j; //inizio = DateTime.Now; //OsaiMemRW(R, FANUC.MemType.D, memIndex, ref int8Mem); //if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabUT-FamUT", 8), DateTime.Now.Subtract(inizio).Ticks); return memIndex; } /// /// Procedura di processing lettura memoria x DatiUt - Step 3a /// /// /// public virtual int getDatiUt_step3a(ref byte[] tabFam_FamUt) { int memIndex = 8900; //inizio = DateTime.Now; //OsaiMemRW(R, FANUC.MemType.D, memIndex, ref tabFam_FamUt); //if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabFamUT-FamUT", tabFam_FamUt.Length), DateTime.Now.Subtract(inizio).Ticks); return memIndex; } /// /// Procedura di processing lettura memoria x DatiUt - Step 2b /// /// /// /// public virtual int getDatiUt_step2b(ref byte[] int16Mem, int j) { int memIndex = 11700 + 2 * j; //inizio = DateTime.Now; //OsaiMemRW(R, FANUC.MemType.D, memIndex, ref int16Mem); //if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabUT-FamUT", int16Mem.Length), DateTime.Now.Subtract(inizio).Ticks); return memIndex; } /// /// Procedura di processing lettura memoria x DatiUt - Step 2a /// /// /// public virtual int getDatiUt_step2a(ref byte[] tabUt_UT) { int memIndex = 11300; //inizio = DateTime.Now; //OsaiMemRW(R, FANUC.MemType.D, memIndex, ref tabUt_UT); //if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabUT-UT", tabUt_UT.Length), DateTime.Now.Subtract(inizio).Ticks); return memIndex; } /// /// Procedura di processing lettura memoria x DatiUt - Step 1 /// /// /// public virtual int getDatiUt_step1(ref byte[] elencoUtMem) { int memIndex = 2960; //inizio = DateTime.Now; //OsaiMemRW(R, FANUC.MemType.D, memIndex, ref elencoUtMem); //if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-NUMUT", elencoUtMem.Length), DateTime.Now.Subtract(inizio).Ticks); return memIndex; } #endregion metodi adapter #region area metodi comunicazione con PLC/CNC public void checkPath() { } /// /// FeedRate globale /// public int FeedRate { get; set; } /// /// FeedRate per singolo PATH /// public int[] FeedRatePath { get; set; } /// /// FeedRate di gruppo MAX 20!!! /// public int[] FeedRateGrp { get; set; } /// /// SpeedRate mandrino globale /// public int SpeedRate { get; set; } /// /// OVERRIDE FeedRate globale /// public int FeedRateOver { get; set; } /// /// OVERRIDE FeedRate per singolo PATH /// public int[] FeedRateOverPath { get; set; } /// /// OVERRIDE dei rapidi /// public int RapidOver { get; set; } /// /// OVERRIDE Rapid per singolo PATH /// public int[] RapidOverPath { get; set; } /// /// OVERRIDE SpeedRate mandrino globale /// public int SpeedRateOver { get; set; } /// /// OVERRIDE SpeedRate per singolo PATH /// public int[] SpeedRateOverPath { get; set; } /// /// LOAD mandrino globale /// public int UnOpLoad { get; set; } /// /// recupera Vettore completo PosAct (fare override!) /// public virtual position PosAct { get { position answ = new position(); return answ; } } /// /// recupera pezzi OK (fare override!) /// public virtual int getNumPzOk { get { int answ = 0; return answ; } } /// /// recupera pezzi KO (fare override!) /// public virtual int getNumPzKo { get { int answ = 0; return answ; } } /// /// Aggiunge nel vettore coda codici M /// /// /// Codice da accodare /// Path (0,1,...) public void appendCodeMST(string Coda, string Codice, int idxPath) { switch (Coda) { case "S": codaS[idxPath].Add(Codice); break; case "T": codaT[idxPath].Add(Codice); break; case "M": default: codaM[idxPath].Add(Codice); break; } } /// /// recupera primo elemento coda M /// /// Path (0,1,...) /// protected string getNextMCode(int idxPath) { string answ = ""; if (codaM[idxPath].Count > 0) { // recupero codice M... answ = codaM[idxPath].First(); // tolgo elemento codaM[idxPath].RemoveAt(0); } return answ; } /// /// recupera primo elemento coda S /// /// Path (0,1,...) /// protected string getNextSCode(int idxPath) { string answ = ""; if (codaS[idxPath].Count > 0) { // recupero codice S... answ = codaS[idxPath].First(); // tolgo elemento codaS[idxPath].RemoveAt(0); } return answ; } /// /// recupera primo elemento coda T /// /// Path (0,1,...) /// protected string getNextTCode(int idxPath) { string answ = ""; if (codaT[idxPath].Count > 0) { // recupero codice T... answ = codaT[idxPath].First(); // tolgo elemento codaT[idxPath].RemoveAt(0); } return answ; } #endregion area metodi comunicazione con PLC/CNC #region metodi che prevedono salvataggio valori su file XML/BIN /// /// Processing delle variabili generiche Counters /// /// /// public bool procCounters(bool needSave) { uint delta = 0; uint valore = 0; int valoreInt = 0; StringBuilder sb = new StringBuilder(); string cKey = ""; if (elCounter != null) { // processo i counter MONOTONI CRESCENTI for (int i = 0; i < elCounter.Count; i++) { // nome counter cKey = string.Format("Counter_{0:000}", i + 1); // procedo solo SE HO FINESTRA VALIDA... if (istCounters[i].vcValid) { valore = Convert.ToUInt32(istCounters[i].vcMedian); if (valore >= currCounters[i]) { delta = valore - currCounters[i]; // controllo delta < 50% max... if (delta < uint.MaxValue / 2) { //processo comunque sempre... uint contTot = updateValUIntByIncr(i, delta, "Counter_{0:000}"); // passo valore totale all'adapter currGateway.updateItemNodeValue(cKey, contTot); // controllo valore riferimento... if (delta > 0) { // segnalo necessità salvataggio! needSave = true; } } } // ...aggiorno valore riferimento... currCounters[i] = valore; } sb.AppendLine(currGateway.getItemNode(cKey).ToString().Replace("|", " | ")); } } if (elRTCounter != null) { // processo i counter ASSOLUTI for (int i = 0; i < elRTCounter.Count; i++) { // nome counter cKey = string.Format("RTCounter_{0:000}", i + 1); // procedo solo SE HO FINESTRA VALIDA... if (istRTCounters[i].vcValid) { valore = Convert.ToUInt32(istRTCounters[i].vcMedian); if (valore != currRTCounters[i]) { delta = valore - currRTCounters[i]; // controllo delta < 50% max... if (delta < uint.MaxValue / 2) { //processo comunque sempre... updateValUInt(i, valore, "RTCounter_{0:000}"); // passo valore totale all'adapter currGateway.updateItemNodeValue(cKey, valore); // controllo valore riferimento... if (delta > 0) { // segnalo necessità salvataggio! needSave = true; } } } // ...aggiorno valore riferimento... currRTCounters[i] = valore; } sb.AppendLine(currGateway.getItemNode(cKey).ToString().Replace("|", " | ")); } } if (elRTVCount != null) { // processo i counter VALORI RTV foreach (var item in elRTVCount) { // nome counter cKey = item.Key; // procedo solo SE HO FINESTRA VALIDA... if (istRTVCount[item.Value].vcValid) { valoreInt = Convert.ToInt32(istRTVCount[item.Value].vcMedian); // passo valore totale all'adapter currGateway.updateItemNodeValue(cKey, valoreInt); // ...aggiorno valore riferimento... currRTVCount[item.Value] = valoreInt; } sb.AppendLine(currGateway.getItemNode(cKey).ToString().Replace("|", " | ")); } } // salvo su maschera... parentForm.dataMonitor_2 += sb.ToString(); return needSave; } /// /// Processing delle ore macchina ACCESA /// /// /// public bool procOreMaccOn(bool needSave) { double delta = 0; double valore = 0; StringBuilder sb = new StringBuilder(); if (istOreMaccOn.vcValid) { valore = istOreMaccOn.vcMedian; if (valore >= contOreMaccOn) { delta = valore - contOreMaccOn; // controllo delta < 50% max... if (delta < double.MaxValue / 2) { // processo comunque sempre... double contatore = updateValDoubleByIncr(0, delta, "ACC_TIME"); currAdpConf.ContOreMaccOn += delta; // salvo valore string newAccTime = contatore.ToString("0.000", CultureInfo.InvariantCulture); currGateway.updateItemNodeValue("ACC_TIME", newAccTime); // controllo incremento... if (delta > 0) { // segnalo necessità salvataggio! needSave = true; } } } // ...aggiorno valore riferimento... contOreMaccOn = valore; } // salvo su maschera... sb.AppendLine(string.Format("ACC_TIME: {0}", currGateway.getItemNode("ACC_TIME"))); parentForm.dataMonitor_1 += sb.ToString(); return needSave; } /// /// Processing delle ore macchina IN LAVORO /// /// /// public bool procOreMaccLav(bool needSave) { double delta = 0; double valore = 0; StringBuilder sb = new StringBuilder(); if (istOreMaccLav.vcValid) { valore = istOreMaccLav.vcMedian; if (valore >= contOreMaccLav) { delta = valore - contOreMaccLav; // controllo delta < 50% max... if (delta < double.MaxValue / 2) { double contatore = updateValDoubleByIncr(0, delta, "ACC_TIME_WORK"); currAdpConf.ContOreMaccLav += delta; // salvo valore string newAccTimeWork = contatore.ToString("0.000", CultureInfo.InvariantCulture); currGateway.updateItemNodeValue("ACC_TIME_WORK", newAccTimeWork); // controllo valore riferimento... if (delta > 0) { // segnalo necessità salvataggio! needSave = true; } } } // ...aggiorno valore riferimento... contOreMaccLav = valore; } // salvo su maschera... sb.AppendLine(string.Format("ACC_TIME_WORK: {0}", currGateway.getItemNode("ACC_TIME_WORK"))); parentForm.dataMonitor_1 += sb.ToString(); return needSave; } /// /// Processing contatore Slitta Tastatore /// /// /// public bool procSlittaTast(bool needSave) { double delta = 0; double valore = 0; StringBuilder sb = new StringBuilder(); if (istSlittaTast.vcValid) { valore = istSlittaTast.vcMedian; if (valore >= contSlittaTast) { delta = valore - contSlittaTast; // controllo delta < 50% max... if (delta < double.MaxValue / 2) { double contatore = updateValDoubleByIncr(0, delta, "SlittaTastatore_Count"); currAdpConf.ContSlittaTast += delta; // salvo valore currGateway.updateItemNodeValue("SlittaTastatore_Count", contatore.ToString("0", CultureInfo.InvariantCulture)); // controllo valore riferimento... if (delta > 0) { // segnalo necessità salvataggio! needSave = true; } } } // ...aggiorno valore riferimento... contSlittaTast = valore; } // salvo su maschera... sb.AppendLine(string.Format("SlittaTastatore_Count: {0}", currGateway.getItemNode("SlittaTastatore_Count")));// mSlittaTast.Value)); parentForm.dataMonitor_1 += sb.ToString(); return needSave; } /// /// Processing del program name /// /// /// public bool procProgrName(bool needSave) { // SOLO SE NON sono SOUR... if (currGateway.protocollo != gwProtocol.SOURS) { // controllo valore riferimento x tutti i path se sia cambiato programma... for (int i = 0; i < currAdpConf.nPath; i++) { if (istPathProgrName[i] != null) { if (istPathProgrName[i] != currPathProgrName[i]) { // prendo nuovo valore programma x path! currGateway.updateItemNodeValue(vettPath[i].currProgKey, istPathProgrName[i]); // segnalo necessità salvataggio! needSave = true; // ...aggiorno valore riferimento... currPathProgrName[i] = istPathProgrName[i]; } } } } return needSave; } /// /// Processing del particolare /// /// /// public bool procPartId(bool needSave) { if (currGateway.protocollo != gwProtocol.SOURS) { // controllo valore riferimento x tutti i path se sia cambiato num pz... for (int i = 0; i < currAdpConf.nPath; i++) { if (istPathPartId[i] != null) { if (istPathPartId[i] != currPathPartId[i]) { // aggiorno valore in Path RefList updateValString(i, istPathPartId[i], "Path_{0:00}_PartId"); // prendo nuovo valore programma x path! currGateway.updateItemNodeValue(vettPath[i].partIdKey, istPathPartId[i]); // imposto a ZERO i pezzi del nuovo articolo currGateway.updateItemNodeValue(vettPath[i].partCountKey, 0); // segnalo necessità salvataggio! needSave = true; // ...aggiorno valore riferimento... currPathPartId[i] = istPathPartId[i]; } } } } return needSave; } /// /// Processing del num pz prodotti /// /// /// public bool procPzProd(bool needSave) { if (currGateway.protocollo != gwProtocol.SOURS) { string outString = string.Format("Path_[1-{0}]_PZ_TOT: ", currAdpConf.nPath); // controllo valore riferimento x tutti i path se sia cambiato qta pezzi... for (int i = 0; i < currAdpConf.nPath; i++) { // controllo valore riferimento variato... if (istPathPartCount[i].vcMedian != currPathPartCount[i]) { if (istPathPartCount[i].vcMedian > currPathPartCount[i]) { uint delta = Convert.ToUInt32(istPathPartCount[i].vcMedian) - currPathPartCount[i]; uint contatore = updateValUIntByIncr(i, delta, "Path_{0:00}_PZ_TOT"); // passo valore num pz all'adapter currGateway.updateItemNodeValue(vettPath[i].partCountKey, contatore); } else // variato x difetto... azzero!!! { uint newVal = Convert.ToUInt32(istPathPartCount[i].vcMedian); updateValUInt(i, newVal, "Path_{0:00}_PZ_TOT"); // passo valore num pz all'adapter currGateway.updateItemNodeValue(vettPath[i].partCountKey, newVal); } // segnalo necessità salvataggio! needSave = true; // ...aggiorno valore riferimento... currPathPartCount[i] = Convert.ToUInt32(istPathPartCount[i].vcMedian); } outString += string.Format("{0} | ", currGateway.getItemNode(vettPath[i].partCountKey)); } // salvo su maschera... parentForm.dataMonitor_2 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine); } return needSave; } /// /// Processing delle variabili sul numero giri mandrino (totali) + tempo attività... /// /// /// public bool procGiriTotUnOp(bool needSave) { uint delta = 0; uint valore = 0; // Contatore giri mandrino string outString = string.Format("UnOp_[1-{0}]_KRev: ", currAdpConf.nUnOp); for (int i = 0; i < currAdpConf.nUnOp; i++) { // procedo solo SE HO FINESTRA VALIDA... if (istGiriElettrom[i].vcValid) { valore = Convert.ToUInt32(istGiriElettrom[i].vcMedian); if (valore >= contGiriElettrom[i]) { delta = valore - contGiriElettrom[i]; // controllo delta < 50% max... if (delta < uint.MaxValue / 2) { // processo comunque sempre... uint contatore = updateValUIntByIncr(i, delta, "UnOp_{0:00}_KRev"); // passo valore num giri (migliaia) all'adapter currGateway.updateItemNodeValue(vettUnOp[i].kRevKey, contatore); // controllo valore riferimento... if (delta > 0) { // segnalo necessità salvataggio! needSave = true; } } } // ...aggiorno valore riferimento... contGiriElettrom[i] = valore; } //outString += string.Format("{0} | ", currGateway.getItemNode(vettUnOp[i].kRevKey)); } // salvo su maschera... parentForm.dataMonitor_2 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine); // Contatore ORE ATTIVE mandrino outString = string.Format("UnOp_[1-{0}]_AccTime: ", currAdpConf.nUnOp); for (int i = 0; i < currAdpConf.nUnOp; i++) { // procedo solo SE HO FINESTRA VALIDA... if (istOreElettrom[i].vcValid) { valore = Convert.ToUInt32(istOreElettrom[i].vcMedian); if (valore >= contOreElettrom[i]) { delta = valore - contOreElettrom[i]; // controllo delta < 50% max... if (delta < uint.MaxValue / 2) { // processo comunque sempre... uint contatore = updateValUIntByIncr(i, delta, "UnOp_{0:00}_AccTime"); // passo valore num giri (migliaia) all'adapter currGateway.updateItemNodeValue(vettUnOp[i].accTimeKey, contatore); // controllo valore riferimento... if (delta > 0) { // segnalo necessità salvataggio! needSave = true; } } } // ...aggiorno valore riferimento... contOreElettrom[i] = valore; } //outString += string.Format("{0} | ", currGateway.getItemNode(vettUnOp[i].accTimeKey)); } return needSave; } /// /// Processing delle variabili sul numero cambi utensile (totali) /// /// /// public bool procNumCU(bool needSave) { uint delta = 0; uint valore = 0; string outString = string.Format("UnOp_[1-{0}]_NumCU: ", currAdpConf.nUnOp); for (int i = 0; i < currAdpConf.nUnOp; i++) { // procedo solo SE HO FINESTRA VALIDA... if (istNumCambiUt[i].vcValid) { valore = Convert.ToUInt32(istNumCambiUt[i].vcMedian); if (valore >= currNumCambiUt[i]) { delta = valore - currNumCambiUt[i]; // controllo delta < 50% max... if (delta < uint.MaxValue / 2) { // processo comunque sempre... uint contatore = updateValUIntByIncr(i, delta, "UnOp_{0:00}_NumCU"); // passo valore num CU all'adapter currGateway.updateItemNodeValue(vettUnOp[i].numCUKey, contatore); // controllo valore riferimento... if (delta > 0) { // segnalo necessità salvataggio! needSave = true; } } } // ...aggiorno valore riferimento... currNumCambiUt[i] = valore; } outString += string.Format("{0} | ", currGateway.getItemNode(vettUnOp[i].numCUKey)); } // salvo su maschera... parentForm.dataMonitor_2 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine); return needSave; } /// /// Processing delle variabili sul numero di ripetizioni /// /// /// public bool procRepetitions(bool needSave) { uint delta = 0; uint valore = 0; string outString = string.Format("UnOp_[1-{0}]_Count: ", currAdpConf.nUnOp); for (int i = 0; i < currAdpConf.nUnOp; i++) { // procedo solo SE HO FINESTRA VALIDA... if (istRepetitionUnOp[i].vcValid) { valore = Convert.ToUInt32(istRepetitionUnOp[i].vcMedian); if (valore >= currRepetitionUnOp[i]) { delta = valore - currRepetitionUnOp[i]; // controllo delta < 50% max... if (delta < uint.MaxValue / 2) { // processo comunque sempre... uint contatore = updateValUIntByIncr(i, delta, "UnOp_{0:00}_Count"); // passo valore num CU all'adapter currGateway.updateItemNodeValue(vettUnOp[i].countKey, contatore); // controllo valore riferimento... if (delta > 0) { // segnalo necessità salvataggio! needSave = true; } } } // ...aggiorno valore riferimento... currRepetitionUnOp[i] = valore; } outString += string.Format("{0} | ", currGateway.getItemNode(vettUnOp[i].countKey)); } // salvo su maschera... parentForm.dataMonitor_2 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine); return needSave; } /// /// Processing delle variabili sul totale m percorsi dagli assi /// /// /// public bool procMovTotAssi(bool needSave) { double delta = 0; uint valore = 0; string outString = string.Format("Axis_[1-{0}]_DistDone: ", currAdpConf.nAxis); for (int i = 0; i < currAdpConf.nAxis; i++) { // procedo solo SE HO FINESTRA VALIDA... if (istDistMovAssi[i].vcValid) { valore = Convert.ToUInt32(istDistMovAssi[i].vcMedian); if (valore >= contDistMovAssi[i]) { delta = valore - contDistMovAssi[i]; // controllo delta < 50% max... if (delta < double.MaxValue / 2) { // processo comunque sempre... double contTot = updateValDoubleByIncr(i, delta, "Axis_{0:00}_DistDone"); // passo valore totale all'adapter currGateway.updateItemNodeValue(vettAxis[i].distDoneKey, contTot.ToString("0.000", CultureInfo.InvariantCulture)); // controllo valore riferimento... if (delta > 0) { // segnalo necessità salvataggio! needSave = true; } } } // ...aggiorno valore riferimento... contDistMovAssi[i] = valore; } outString += string.Format("{0} | ", currGateway.getItemNode(vettAxis[i].distDoneKey)); } // salvo su maschera... parentForm.dataMonitor_3 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine); return needSave; } /// /// Processing delle variabili sul totale tempo lavoro degli assi /// /// /// public bool procAccTimeAssi(bool needSave) { double delta = 0; uint valore = 0; string outString = string.Format("Axis_[1-{0}]_AccTime: ", currAdpConf.nAxis); for (int i = 0; i < currAdpConf.nAxis; i++) { // procedo solo SE HO FINESTRA VALIDA... if (istAccTimeAssi[i].vcValid) { valore = Convert.ToUInt32(istAccTimeAssi[i].vcMedian); if (valore >= contAccTimeAssi[i]) { delta = valore - contAccTimeAssi[i]; // controllo delta < 50% max... if (delta < double.MaxValue / 2) { // salvo valore aggiuntivo x ore lavoro assi... double oreTot = updateValDoubleByIncr(i, delta, "Axis_{0:00}_AccTime"); currGateway.updateItemNodeValue(vettAxis[i].accTimeKey, oreTot.ToString("0.000", CultureInfo.InvariantCulture)); // controllo valore riferimento... if (delta > 0) { // segnalo necessità salvataggio! needSave = true; } } } // ...aggiorno valore riferimento... contAccTimeAssi[i] = valore; } outString += string.Format("{0} | ", currGateway.getItemNode(vettAxis[i].accTimeKey)); } // salvo su maschera... parentForm.dataMonitor_3 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine); return needSave; } /// /// Processing delle variabili sul totale num inversioni degli assi /// /// /// public bool procNumInvAssi(bool needSave) { long delta = 0; uint valore = 0; string outString = string.Format("Axis_[1-{0}]_InvDDone: ", currAdpConf.nAxis); for (int i = 0; i < currAdpConf.nAxis; i++) { // procedo solo SE HO FINESTRA VALIDA... if (istNumInvAssi[i].vcValid) { valore = Convert.ToUInt32(istNumInvAssi[i].vcMedian); if (valore >= contNumInvAssi[i]) { delta = valore - contNumInvAssi[i]; // controllo delta < 50% max... if (delta < long.MaxValue / 2) { // processo comunque sempre... long contTot = updateValLongByIncr(i, delta, "Axis_{0:00}_InvDDone"); // passo valore totale all'adapter currGateway.updateItemNodeValue(vettAxis[i].invDDoneKey, contTot); // controllo valore riferimento... if (delta > 0) { // segnalo necessità salvataggio! needSave = true; } } } // ...aggiorno valore riferimento... contNumInvAssi[i] = valore; } outString += string.Format("{0} | ", currGateway.getItemNode(vettAxis[i].invDDoneKey)); } // salvo su maschera... parentForm.dataMonitor_3 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine); return needSave; } /// /// Processing delle variabili sulle VacPump /// /// /// public bool procVacPump(bool needSave) { uint delta = 0; uint valore = 0; string outString = string.Format("VacPump_[1-{0}]_WrkTime: ", currAdpConf.nVacuumPump); for (int i = 0; i < currAdpConf.nVacuumPump; i++) { // procedo solo SE HO FINESTRA VALIDA... if (istVacPumpWrkTime[i].vcValid) { valore = Convert.ToUInt32(istVacPumpWrkTime[i].vcMedian); if (valore >= currVacPumpWrkTime[i]) { delta = valore - currVacPumpWrkTime[i]; // controllo delta < 50% max... if (delta < uint.MaxValue / 2) { // processo comunque sempre... uint contTot = updateValUIntByIncr(i, delta, "VacPump_{0:00}_WrkTime"); // passo valore totale all'adapter currGateway.updateItemNodeValue(vettVacPump[i].workTimeKey, contTot); // controllo valore riferimento... if (delta > 0) { // segnalo necessità salvataggio! needSave = true; } } } // ...aggiorno valore riferimento... currVacPumpWrkTime[i] = valore; } outString += string.Format("{0} | ", currGateway.getItemNode(vettVacPump[i].workTimeKey)); } // salvo su maschera... parentForm.dataMonitor_2 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine); return needSave; } /// /// Processing delle variabili sulle VacAct /// /// /// public bool procVacAct(bool needSave) { uint delta = 0; uint valore = 0; string outString = string.Format("VacPump_[1-{0}]_Count: ", currAdpConf.nVacuumPump); for (int i = 0; i < currAdpConf.nVacuumAct; i++) { // procedo solo SE HO FINESTRA VALIDA... if (istVacActCount[i].vcValid) { valore = Convert.ToUInt32(istVacActCount[i].vcMedian); if (valore >= currVacActCount[i]) { delta = valore - currVacActCount[i]; // controllo delta < 50% max... if (delta < uint.MaxValue / 2) { // processo comunque sempre... uint contTot = updateValUIntByIncr(i, delta, "VacAct_{0:00}_Count"); // passo valore totale all'adapter currGateway.updateItemNodeValue(vettVacAct[i].countKey, contTot); // controllo valore riferimento... if (delta > 0) { // segnalo necessità salvataggio! needSave = true; } } } // ...aggiorno valore riferimento... currVacActCount[i] = valore; } outString += string.Format("{0} | ", currGateway.getItemNode(vettVacAct[i].countKey)); } // salvo su maschera... parentForm.dataMonitor_2 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine); return needSave; } /// /// Processing delle variabili sui componenti Lubro /// /// /// public bool procLubro(bool needSave) { uint delta = 0; uint valore = 0; string outString = string.Format("Lubro_[1-{0}]_Count: ", currAdpConf.nLubro); for (int i = 0; i < currAdpConf.nLubro; i++) { valore = Convert.ToUInt32(istLubroCount[i].vcMedian); if (valore > currLubroCount[i]) { delta = valore - currLubroCount[i]; // controllo delta < 50% max... if (delta < uint.MaxValue / 2) { //processo comunque sempre... uint contTot = updateValUIntByIncr(i, delta, "Lubro_{0:00}_Count"); // passo valore totale all'adapter currGateway.updateItemNodeValue(vettLubro[i].countKey, contTot); // controllo valore riferimento... if (delta > 0) { // segnalo necessità salvataggio! needSave = true; } } // ...aggiorno valore riferimento... currLubroCount[i] = valore; } else { currGateway.updateItemNodeValue(vettLubro[i].countKey, currLubroCount[i]); } outString += string.Format("{0} | ", currGateway.getItemNode(vettLubro[i].countKey)); } // salvo su maschera... parentForm.dataMonitor_2 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine); return needSave; } /// /// Processing delle variabili sui componenti SlittaMag /// /// /// public bool procSlittaMag(bool needSave) { uint delta = 0; uint valore = 0; string outString = string.Format("SlittaMagazzino_[1-{0}]_Count: ", currAdpConf.nSlittaMag); for (int i = 0; i < currAdpConf.nSlittaMag; i++) { // procedo solo SE HO FINESTRA VALIDA... if (istSlittaMag[i].vcValid) { valore = Convert.ToUInt32(istSlittaMag[i].vcMedian); if (valore >= currSlittaMag[i]) { delta = valore - currSlittaMag[i]; // controllo delta < 50% max... if (delta < uint.MaxValue / 2) { //processo comunque sempre... uint contTot = updateValUIntByIncr(i, delta, "SlittaMagazzino_{0:00}_Count"); // passo valore totale all'adapter currGateway.updateItemNodeValue(vettSlittaMag[i].countKey, contTot); // controllo valore riferimento... if (delta > 0) { // segnalo necessità salvataggio! needSave = true; } } } // ...aggiorno valore riferimento... currSlittaMag[i] = valore; } outString += string.Format("{0} | ", currGateway.getItemNode(vettSlittaMag[i].countKey)); } // salvo su maschera... parentForm.dataMonitor_2 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine); return needSave; } /// /// Processing delle variabili sui componenti ProtMag /// /// /// public bool procProtMag(bool needSave) { uint delta = 0; uint valore = 0; string outString = string.Format("ProtMagazzino_[1-{0}]_Count: ", currAdpConf.nProtMag); for (int i = 0; i < currAdpConf.nProtMag; i++) {// procedo solo SE HO FINESTRA VALIDA... if (istProtMag[i].vcValid) { valore = Convert.ToUInt32(istProtMag[i].vcMedian); if (valore >= currProtMag[i]) { delta = valore - currProtMag[i]; // controllo delta < 50% max... if (delta < uint.MaxValue / 2) { //processo comunque sempre... uint contTot = updateValUIntByIncr(i, delta, "ProtMagazzino_{0:00}_Count"); // passo valore totale all'adapter currGateway.updateItemNodeValue(vettProtMag[i].countKey, contTot); // controllo valore riferimento... if (delta > 0) { // segnalo necessità salvataggio! needSave = true; } } } // ...aggiorno valore riferimento... currProtMag[i] = valore; } outString += string.Format("{0} | ", currGateway.getItemNode(vettProtMag[i].countKey)); } // salvo su maschera... parentForm.dataMonitor_2 += string.Format("{0}{1}", outString.Substring(0, outString.Length - 3), Environment.NewLine); return needSave; } #endregion metodi che prevedono salvataggio valori su file XML/BIN #region layer persistenza dati /// /// Dizionario di persistenza per i valori da salvare da/su file /// public Dictionary persistenceLayer; /// /// recupera valore salvato in persistence layer (se non c'è crea...) /// /// /// private string getStoredVal(string keyVal) { string value = ""; try { if (persistenceLayer != null) { if (!persistenceLayer.TryGetValue(keyVal, out value)) { persistenceLayer.Add(keyVal, "0"); } } } catch (Exception exc) { lg.Error(string.Format("Eccezione in getStoredVal: {0}{1}", Environment.NewLine, exc)); } return value; } /// /// recupera valore salvato in persistence layer (se non c'è crea...) come UINT /// /// /// private uint getStoredValUInt(string keyVal) { uint answ = 0; try { answ = Convert.ToUInt32(getStoredVal(keyVal)); } catch (Exception exc) { lg.Error(string.Format("Eccezione in getStoredValUInt: {0}{1}", Environment.NewLine, exc)); } // verifico che il valore sia minore di 9/10 del valore massimo... answ = (answ < (uint.MaxValue / 10 * 9)) ? answ : 0; return answ; } /// /// recupera valore salvato in persistence layer (se non c'è crea...) come INT /// /// /// private long getStoredValLong(string keyVal) { long answ = 0; try { answ = Convert.ToInt64(getStoredVal(keyVal)); } catch { } // verifico che il valore sia minore di 9/10 del valore massimo... answ = (answ < (long.MaxValue / 10 * 9)) ? answ : 0; return answ; } /// /// recupera valore salvato in persistence layer (se non c'è crea...) come double /// /// /// private double getStoredValDouble(string keyVal) { double answ = 0; try { answ = Convert.ToDouble(getStoredVal(keyVal)); } catch (Exception exc) { lg.Error(string.Format("Eccezione in getStoredValDouble: {0}{1}", Environment.NewLine, exc)); } answ = (answ < (double.MaxValue / 10 * 9)) ? answ : 0; return answ; } /// /// Aggiorna un valore del dizionario in SOSTITUZIONE /// /// /// /// /// Nuovo valore incrementato private void updateValString(int i, string newVal, string searchString) { // stringa da cercare.. string keyVal = string.Format(searchString, i + 1); // salvo in ram! persistenceLayer[keyVal] = newVal; } /// /// Aggiorna un valore del dizionario in SOSTITUZIONE e lo restituisce /// /// /// /// /// Nuovo valore incrementato private void updateValUInt(int i, uint newVal, string searchString) { // stringa da cercare.. string keyVal = string.Format(searchString, i + 1); // salvo in ram! persistenceLayer[keyVal] = newVal.ToString(); } /// /// Aggiorna un valore del dizionario in INCREMENTO e lo restituisce /// /// /// /// /// Nuovo valore incrementato private uint updateValUIntByIncr(int i, uint delta, string searchString) { // stringa da cercare.. string keyVal = string.Format(searchString, i + 1); // recupero valore precedente... uint contAct = getStoredValUInt(keyVal); // nuovo valore... contAct += delta; // salvo in ram! persistenceLayer[keyVal] = contAct.ToString(); // rendo il valore! return contAct; } /// /// Aggiorna un valore del dizionario in INCREMENTO e lo restituisce /// /// /// /// /// Nuovo valore incrementato private long updateValLongByIncr(int i, long delta, string searchString) { // stringa da cercare.. string keyVal = string.Format(searchString, i + 1); // recupero valore precedente... long contAct = getStoredValLong(keyVal); // nuovo valore... contAct += delta; // salvo in ram! persistenceLayer[keyVal] = contAct.ToString(); // rendo il valore! return contAct; } /// /// Aggiorna un valore del dizionario in INCREMENTO e lo restituisce /// /// /// /// /// Nuovo valore incrementato private double updateValDoubleByIncr(int i, double delta, string searchString) { // stringa da cercare.. string keyVal = string.Format(searchString, i + 1); // recupero valore precedente... double contAct = getStoredValDouble(keyVal); // nuovo valore... contAct += delta; // salvo in ram! persistenceLayer[keyVal] = contAct.ToString(); // rendo il valore! return contAct; } #endregion layer persistenza dati #region metodi helper /// /// Effettua accodamento messaggio sullo string builder indicato (con try/catch e eventuale log...) /// /// /// public void tryLogMessage(StringBuilder strBuild, string newLine) { try { strBuild.AppendLine(newLine); } catch (Exception exc) { lg.Error(exc, "Eccezione in accodamento messaggio su stringBuilder"); } } #endregion } }