From ed73fa7bde7fa1c2ec08bbf41b004cf54f04d49e Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Mon, 5 Oct 2020 11:19:54 +0200 Subject: [PATCH 01/26] Aggiunta 3 tipi adapter file based (base, Euromap63) --- IOB-UT/Enums.cs | 451 +++++++++++++++++++++++++++--------------------- 1 file changed, 256 insertions(+), 195 deletions(-) diff --git a/IOB-UT/Enums.cs b/IOB-UT/Enums.cs index 311e41b2..f72a39c1 100644 --- a/IOB-UT/Enums.cs +++ b/IOB-UT/Enums.cs @@ -5,6 +5,108 @@ using System.Text; namespace IOB_UT { + /// + /// Elenco MODI CNC + /// + public enum CNC_MODE + { + /// + /// Non definito + /// + ND = 0, + + /// + /// AUTOMATICO + /// + AUTO, + + /// + /// EDIT (MEMORY EDIT) + /// + EDIT, + + /// + /// MEN (MEMORY OPERATION) + /// + MEN, + + /// + /// MDI (MANUAL DATA INPUT) + /// + MDI, + + /// + /// HANDLE/INC (MANUAL HANDLE / INCREMENTAL FEED) + /// + HANDLE_INC, + + /// + /// HOME + /// + HOME, + + /// + /// JOG (MANUAL CONTINUOUS FEED) + /// + JOG, + + /// + /// JOG MAN + /// + JOG_MAN, + + /// + /// JOG_INC + /// + JOG_INC, + + /// + /// PROFILE + /// + PROFILE, + + /// + /// SEMI + /// + SEMI, + + /// + /// THND (TEACH IN HANDLE) + /// + THND, + + /// + /// TJOG (TEACH IN JOG) + /// + TJOG, + + /// + /// RMT (DNC OPERATION) + /// + RMT, + + /// + /// REF (MANUAL REFERENCE POSITION RETURN) + /// + REF + } + + /// + /// Elenco STATI CNC OSAI + /// + public enum CNC_STATUS_OSAI + { + IDLE = 1, + CYCLE, + HODA, + RUNH, + HRUN, + ERRO, + WAIT, + RESET, + EMERG, + INPUT + } /// /// Tipologie di DUMP memoria @@ -15,101 +117,13 @@ namespace IOB_UT /// Salvataggio all'avvio aree memoria (con sovrascrittura) /// STARTUP, + /// /// Campionamento periodico /// SAMPLE } - /// - /// Tipologia di adapters ammessi - /// - public enum tipoAdapter - { - /// - /// Adapter SIMULAZIONE - /// - SIMULA, - /// - /// adapter FANUC - /// - FANUC, - /// - /// adapter KAWASAKI e-controller - /// - KAWASAKI, - /// - /// Adapter non specificato - /// - ND, - /// - /// Adapter MTConnect - /// - MTConnect, - /// - /// Adapter OMRON - /// - OMRON, - /// - /// Adapter OSAI CNDEX (Cndex) - /// - OSAI_CNDEX, - /// - /// Adapter OSAI OPEN (ws) - /// - OSAI_OPEN, - /// - /// Adapter OSAI VB6 - /// - OSAI_VB6, - /// - /// Adapter SIEMENS - /// - SIEMENS, - /// - /// Adapter SIEMENS, interfaccia versione APROCHIM (filtro liquidi rettifiche) - /// - SIEMENS_APROCHIM, - /// - /// Adapter SIEMENS, interfaccia versione VIPA @2001 - /// - SIEMENS_AT2001, - /// - /// Adapter SIEMENS, interfaccia versione FAPE (punzonatrici) - /// - SIEMENS_FAPE, - /// - /// Adapter SIEMENS, interfaccia versione COMUR (dentatrice) - /// - SIEMENS_COMUR, - /// - /// Adapter SIEMENS, interfaccia versione INGENIA (Valvital, Automazione) - /// - SIEMENS_INGENIA, - /// - /// Adapter SIEMENS, interfaccia versione LASCO (Valvital, Pressa Bilancere) - /// - SIEMENS_LASCO, - /// - /// Adapter SIEMENS, interfaccia versione PRESSOIL + CEI (Valvital, Pressa Idraulica) - /// - SIEMENS_PRESSOIL_CEI, - /// - /// Adapter SIEMENS, interfaccia versione SAET (Valvital, forni / tempra) - /// - SIEMENS_SAET, - /// - /// Adapter SIEMENS, interfaccia versione SIMEC (Valvital, taglio) - /// - SIEMENS_SIMEC, - /// - /// Adapter SIEMENS, interfaccia versione Torri - /// - SIEMENS_TORRI, - /// - /// Metodi di WPS WebPageScraping (es x compressori Atlas Copco) - /// - WPS - } + /// /// Tipo di ciclo da processare /// @@ -119,40 +133,28 @@ namespace IOB_UT /// Very High Frequency (solo x invii...) /// VHF, + /// /// lettura dati ad alta frequenza /// HF, + /// /// lettura dati standard /// MF, + /// /// lettura dati bassa freq /// LF, + /// /// lettura dati bassissima priorità (re-sync stato allarmi) /// VLF } - /// - /// StFlag8: set di 8 bit (1 word) contente semaforo di variabili - /// - [Flags] - public enum StFlag8 : int - { - NONE = 0, - B0 = 1 << 0, - B1 = 1 << 1, - B2 = 1 << 2, - B3 = 1 << 3, - B4 = 1 << 4, - B5 = 1 << 5, - B6 = 1 << 6, - B7 = 1 << 7 - } /// /// StFlag32: set di 32 bit (4 word) contente semaforo di variabili /// @@ -193,6 +195,150 @@ namespace IOB_UT B30 = 1 << 30, B31 = 1 << 31 } + + /// + /// StFlag8: set di 8 bit (1 word) contente semaforo di variabili + /// + [Flags] + public enum StFlag8 : int + { + NONE = 0, + B0 = 1 << 0, + B1 = 1 << 1, + B2 = 1 << 2, + B3 = 1 << 3, + B4 = 1 << 4, + B5 = 1 << 5, + B6 = 1 << 6, + B7 = 1 << 7 + } + + /// + /// Tipologia di adapters ammessi + /// + public enum tipoAdapter + { + /// + /// Adapter SIMULAZIONE + /// + SIMULA, + + /// + /// adapter FANUC + /// + FANUC, + + /// + /// File Based exchange generic adapter + /// + FILE_GEN, + + /// + /// File Based exchange Euromap63 + /// + FILE_EUROM63, + + ///// + ///// File Based exchange SCM Xylog + ///// + //FILE_XYLOG, + + /// + /// adapter KAWASAKI e-controller + /// + KAWASAKI, + + /// + /// Adapter non specificato + /// + ND, + + /// + /// Adapter MTConnect + /// + MTConnect, + + /// + /// Adapter OMRON + /// + OMRON, + + /// + /// Adapter OSAI CNDEX (Cndex) + /// + OSAI_CNDEX, + + /// + /// Adapter OSAI OPEN (ws) + /// + OSAI_OPEN, + + /// + /// Adapter OSAI VB6 + /// + OSAI_VB6, + + /// + /// Adapter SIEMENS + /// + SIEMENS, + + /// + /// Adapter SIEMENS, interfaccia versione APROCHIM (filtro liquidi rettifiche) + /// + SIEMENS_APROCHIM, + + /// + /// Adapter SIEMENS, interfaccia versione VIPA @2001 + /// + SIEMENS_AT2001, + + /// + /// Adapter SIEMENS, interfaccia versione FAPE (punzonatrici) + /// + SIEMENS_FAPE, + + /// + /// Adapter SIEMENS, interfaccia versione COMUR (dentatrice) + /// + SIEMENS_COMUR, + + /// + /// Adapter SIEMENS, interfaccia versione INGENIA (Valvital, Automazione) + /// + SIEMENS_INGENIA, + + /// + /// Adapter SIEMENS, interfaccia versione LASCO (Valvital, Pressa Bilancere) + /// + SIEMENS_LASCO, + + /// + /// Adapter SIEMENS, interfaccia versione PRESSOIL + CEI (Valvital, Pressa Idraulica) + /// + SIEMENS_PRESSOIL_CEI, + + /// + /// Adapter SIEMENS, interfaccia versione SAET (Valvital, forni / tempra) + /// + SIEMENS_SAET, + + /// + /// Adapter SIEMENS, interfaccia versione SIMEC (Valvital, taglio) + /// + SIEMENS_SIMEC, + + /// + /// Adapter SIEMENS, interfaccia versione Torri + /// + SIEMENS_TORRI, + + /// + /// Metodi di WPS WebPageScraping (es x compressori Atlas Copco) + /// + WPS + } + #if false /// /// Enumerazione tipi di semaforo @@ -219,8 +365,9 @@ namespace IOB_UT /// Grigio/Spento /// SS - } + } #endif + /// /// Enumerazione tipi di tipi di URL x invio /// @@ -230,96 +377,10 @@ namespace IOB_UT /// Salvataggio FluxLog (valori estesi che non provocano calcoli di macchine a stati, eventi...) /// FLog, + /// /// INPUT segnali in ingresso (standard base MAPO) /// SignIN } - - /// - /// Elenco STATI CNC OSAI - /// - public enum CNC_STATUS_OSAI - { - IDLE = 1, - CYCLE, - HODA, - RUNH, - HRUN, - ERRO, - WAIT, - RESET, - EMERG, - INPUT - } - /// - /// Elenco MODI CNC - /// - public enum CNC_MODE - { - /// - /// Non definito - /// - ND = 0, - /// - /// AUTOMATICO - /// - AUTO, - /// - /// EDIT (MEMORY EDIT) - /// - EDIT, - /// - /// MEN (MEMORY OPERATION) - /// - MEN, - /// - /// MDI (MANUAL DATA INPUT) - /// - MDI, - /// - /// HANDLE/INC (MANUAL HANDLE / INCREMENTAL FEED) - /// - HANDLE_INC, - /// - /// HOME - /// - HOME, - /// - /// JOG (MANUAL CONTINUOUS FEED) - /// - JOG, - /// - /// JOG MAN - /// - JOG_MAN, - /// - /// JOG_INC - /// - JOG_INC, - /// - /// PROFILE - /// - PROFILE, - /// - /// SEMI - /// - SEMI, - /// - /// THND (TEACH IN HANDLE) - /// - THND, - /// - /// TJOG (TEACH IN JOG) - /// - TJOG, - /// - /// RMT (DNC OPERATION) - /// - RMT, - /// - /// REF (MANUAL REFERENCE POSITION RETURN) - /// - REF - } -} +} \ No newline at end of file From 35916e63d5252b0e1fe802c95196121639ba8f4a Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Mon, 5 Oct 2020 11:20:05 +0200 Subject: [PATCH 02/26] Inizio adapter file based da WPS --- IOB-WIN/IobFileGen.cs | 378 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 378 insertions(+) create mode 100644 IOB-WIN/IobFileGen.cs diff --git a/IOB-WIN/IobFileGen.cs b/IOB-WIN/IobFileGen.cs new file mode 100644 index 00000000..c5142351 --- /dev/null +++ b/IOB-WIN/IobFileGen.cs @@ -0,0 +1,378 @@ +using IOB_UT; +using MapoSDK; +using Newtonsoft.Json; +using OpenQA.Selenium; +using OpenQA.Selenium.Chrome; +using OpenQA.Selenium.Firefox; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.NetworkInformation; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace IOB_WIN +{ + /// + /// Generica classe per implementare WebPageScraping (scaricamento web pages anche js-based x recupero informazioni) + /// + public class IobFileGen : IobGeneric, IDisposable + { + /* -------------------------------------------------------------------------------- + * Controlli dotati di GENERICA pagina WEB in cui cercare e recuperare informazioni + * + * - il file di conf deve contenere l'URL di base + * - il file di conf deve contenere COSA cercare (es il "contenitore" del dato da estrarre) + * + * -------------------------------------------------------------------------------- */ + + /// + /// Pagina web da scaricare + /// + protected string baseUri = "http://127.0.0.1"; + + /// + /// Array di configurazione degli oggetti da cercare x decodifica e recupero info + /// + protected Dictionary dataLocatorLUT; + + /// + /// Driver per gestione chiamate crawling/scraping + /// + protected IWebDriver driver; + + /// + /// Elementi da recuperare nella apgina web + /// + protected IWebElement element; + + /// + /// Vettore della frequenza di ogni status trovato... invio ogni 100 rilevazioni (modulo 100, resto == 1) + /// + protected Dictionary freqUnknStatus = new Dictionary(); + + /// + /// Oggetti decodificati da pagina + /// + protected MonitoredItemsConf monitoredItems; + + /// + /// Estende l'init della classe base... + /// + /// + /// + public IobFileGen(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) + { + lgInfo("INIT IobWPS"); + //reloadAdapterConf(); + } + + /// + /// Ricarica conf adapter... + /// + private void reloadAdapterConf() + { + // init obj display + newDisplayData currDispData = new newDisplayData(); + lgInfo("BEGIN reloadAdapterConf"); + // inizializzo LUT decodifica + string jsonConf = getOptPar("LUT_CONF"); + if (!string.IsNullOrEmpty(jsonConf)) + { + string jsonFullPath = $"{Application.StartupPath}/DATA/CONF/{jsonConf}"; + lgInfo($"Apertura file {jsonFullPath}"); + StreamReader reader = new StreamReader(jsonFullPath); + string jsonData = reader.ReadToEnd(); + if (!string.IsNullOrEmpty(jsonData)) + { + try + { + monitoredItems = JsonConvert.DeserializeObject(jsonData); + // salvo baseUri + baseUri = monitoredItems.SrvData.baseUri; + lgInfo($"baseUri = {baseUri}"); + // imposto a zero la bitmap x riavvio! + B_input = 0; + // FORZO invio dati... + accodaSigIN(ref currDispData); + // loggo! + lgInfo($"init input bitmap to zero: {B_input}"); + } + catch (Exception exc) + { + lgError(exc, "Eccezione in decodifica conf json"); + } + } + reader.Dispose(); + } + lgInfo("DONE reloadAdapterConf"); + raiseRefresh(currDispData); + } + + #region Metodi specifici (da verificare/completare in implementazione) + + public void Dispose() + { + driver.Dispose(); + GC.SuppressFinalize(this); + } + + /// + /// Recupero dati dinamici in formato dictionary + /// + /// + public override Dictionary getDynData() + { + lgInfo("Chiamata getDynData x IOB WebPageScraping!"); + Dictionary outVal = new Dictionary(); + try + { + /* ---------------------------------------------------------- + * Recupero dalla TUTTE le chiavi richieste... + * */ + + string cKey = ""; + string cVal = ""; + // processo tutti i DynData... + foreach (var item in monitoredItems.DynData) + { + // cerco elemento indicato + element = driver.FindElement(By.Id(item.val)); + cVal = element.Text; + // verifico nome o key... + if (!string.IsNullOrEmpty(item.name)) + { + cKey = item.name; + } + else + { + element = driver.FindElement(By.Id(item.key)); + cKey = element.Text; + } + // controllo se devo inviare (per tipo di dato, x scadenza) + if (monItem2Send(cVal, item)) + { + item.actVal = cVal; + item.DTScad = DateTime.Now.AddSeconds(item.sPeriod); + // accodo! + outVal.Add(cKey, cVal); + } + } + } + catch (Exception exc) + { + lgError(exc, "Errore in getDynData x IOB WPS"); + } + return outVal; + } + + /// + /// Effettua processing del recupero delle OVERRIDE (spindle, feedrate, rapid) + /// + public override void processOverride() + { + } + + /// + /// Effettua lettura semafori principale + /// Parametri da aggiornare x display in form + /// + public override void readSemafori(ref newDisplayData currDispData) + { + // init a zero... + B_input = 0; + // ciclo! + try + { + // controllo SE il driver SIA attivo... + if (driver != null) + { + string cKey = ""; + string cVal = ""; + // IPOTESI: un UNICO oggetto decodifica status + if (monitoredItems.Status.Count == 1) + { + var item = monitoredItems.Status[0]; + // cerco elemento indicato + element = driver.FindElement(By.Id(item.val)); + cKey = element.Text; + // verifico se mancasse il mapping... + if (!item.codeMapping.ContainsKey(cKey)) + { + processUnknStatus(cKey); + } + else + { + // ora decodifico da variabile status a valore secondo impostazione "codeMapping" + cVal = item.codeMapping[cKey]; + B_input = int.Parse(cVal, System.Globalization.NumberStyles.HexNumber); + if (currDispData != null) + { + currDispData.semIn = Semaforo.SV; + } + } + } + } + else + { + lgError("Errore: driver non pronto (null)"); + } + // riporto bitmap... + reportRawInput(ref currDispData); + } + catch (Exception exc) + { + lgError(exc, "Errore in readSemafori x IOB WPS"); + if (currDispData != null) + currDispData.semIn = Semaforo.SR; + } + } + + public override void startAdapter(bool resetQueue) + { + // in primis RICARICO conf specifica... + reloadAdapterConf(); + // continuo con start... + base.startAdapter(resetQueue); + } + + /// + /// Override x chiusura driver... + /// + /// + /// + public override void stopAdapter(bool tryRestart, bool forceDequeue) + { + try + { + // in primis chiudo driver... + if (driver != null) + { + driver.Quit(); + } + } + catch (Exception exc) + { + lgError(exc, "Eccezione in tryDisconnect"); + } + // continuo + base.stopAdapter(tryRestart, forceDequeue); + } + + /// + /// Connessione + /// + public override void tryConnect() + { + // controllo ping --> segno connected... + connectionOk = (testPingMachine == IPStatus.Success); + if (connectionOk) + { + try + { + //var t = TaskEx.Run(() => startDriver()); + //t.Wait(); + // modalità sincrona + startDriver(); + lgInfo("Completato start driver"); + } + catch (Exception exc) + { + lgError(exc, "Eccezione in tryConnect"); + } + } + else + { + // aspetto prima di riprovare... + Thread.Sleep(200); + } + } + + /// + /// Disconnessione + /// + public override void tryDisconnect() + { + connectionOk = false; + try + { + // in primis chiudo driver... + if (driver != null) + //if (driver != null && driver.WindowHandles.Count > 0) + { + driver.Quit(); + } + } + catch (Exception exc) + { + lgError(exc, "Eccezione in tryDisconnect"); + } + } + + /// + /// Processo stati unknown... + /// + /// + private void processUnknStatus(string cKey) + { + // cerco se avevo già una key nella dictionary... + if (freqUnknStatus.ContainsKey(cKey)) + { + freqUnknStatus[cKey]++; + // se è 1 ogni 100 (%100, resto ==1) --> loggo... + if (freqUnknStatus[cKey] % 100 == 1) + { + lgInfo($"Errore in decodifica status: MAPPING non trovato per {cKey} | freq: {freqUnknStatus[cKey]}"); + // accodo come invio di tipo FLOG... + string sVal = string.Format("[UnknStatus] {0}, freq: {1}", cKey, freqUnknStatus); + // chiamo accodamento... + accodaFLog(sVal, qEncodeFLog("UnknStatus", sVal)); + } + } + else + { + // creo chiave con freq = 1 + freqUnknStatus.Add(cKey, 1); + // log iniziale + lgInfo($"Errore in decodifica status: MAPPING non trovato per {cKey}"); + } + } + + /// + /// Avvio del WebDriver + /// + private void startDriver() + { + if (monitoredItems.SrvData.driverName == "CHROME") + { + lgInfo("Starting CHROME Driver"); + // preparo opzione headless x CHROME + var o = new ChromeOptions(); + o.AddArgument("headless"); + ChromeDriverService service = ChromeDriverService.CreateDefaultService(Application.StartupPath); + service.HideCommandPromptWindow = true; + driver = new ChromeDriver(service, o); + } + else + { + lgInfo("Starting FIREFOX Driver"); + // preparo opzione headless x FIREFOX + var o = new FirefoxOptions(); + o.AddArgument("-headless"); + o.SetPreference("app.update.auto", false); + o.SetPreference("app.update.enabled", false); + FirefoxDriverService service = FirefoxDriverService.CreateDefaultService(Application.StartupPath); + service.HideCommandPromptWindow = true; + driver = new FirefoxDriver(service, o); + } + // aggiungo timeout x JScripts + driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(20); + driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(20); + // imposto pagina di acquisizione + driver.Navigate().GoToUrl(baseUri); + } + + #endregion Metodi specifici (da verificare/completare in implementazione) + } +} \ No newline at end of file From cd3e0108d4ffcb54b20078bc9851ff4c87051217 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Tue, 6 Oct 2020 13:40:11 +0200 Subject: [PATCH 03/26] update conf SIM --- IOB-WIN/DATA/CONF/SIMUL_01.ini | 2 +- IOB-WIN/DATA/CONF/SIMUL_02.ini | 2 +- IOB-WIN/DATA/CONF/SIMUL_03.ini | 2 +- IOB-WIN/DATA/CONF/SIMUL_04.ini | 2 +- IOB-WIN/DATA/CONF/SIMUL_05.ini | 2 +- IOB-WIN/DATA/CONF/SIMUL_06.ini | 2 +- IOB-WIN/DATA/CONF/SIMUL_07.ini | 2 +- IOB-WIN/DATA/CONF/SIMUL_08.ini | 2 +- IOB-WIN/DATA/CONF/SIM_DP_01.ini | 2 +- IOB-WIN/DATA/CONF/SIM_DP_02.ini | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/IOB-WIN/DATA/CONF/SIMUL_01.ini b/IOB-WIN/DATA/CONF/SIMUL_01.ini index ac18284d..c453dab5 100644 --- a/IOB-WIN/DATA/CONF/SIMUL_01.ini +++ b/IOB-WIN/DATA/CONF/SIMUL_01.ini @@ -55,7 +55,7 @@ SIM_WUCD=8000|20 ; indica gestione e simulazione bit 7 --> emergenza SIM_EMRG=4000|10 ; indica simulazione delle funzionalità power ON/ OFF -SIM_POW_ON_OFF=false +SIM_POW_ON_OFF=true T_ON=7 T_OFF=22 ; gestione DynData simulati diff --git a/IOB-WIN/DATA/CONF/SIMUL_02.ini b/IOB-WIN/DATA/CONF/SIMUL_02.ini index 3a312bf5..cb5e4701 100644 --- a/IOB-WIN/DATA/CONF/SIMUL_02.ini +++ b/IOB-WIN/DATA/CONF/SIMUL_02.ini @@ -58,7 +58,7 @@ FORCE_DYN_DATA=TRUE NEW_DYN_DATA=TRUE ;gestione invio pezzi in blocco ENABLE_SEND_PZC_BLOCK=TRUE -MIN_SEND_PZC_BLOCK=5 +MIN_SEND_PZC_BLOCK=0 MAX_SEND_PZC_BLOCK=100 MIN_DURATA_ODL=240 ; indica parametri gestione TcMan diff --git a/IOB-WIN/DATA/CONF/SIMUL_03.ini b/IOB-WIN/DATA/CONF/SIMUL_03.ini index 435eaf4b..1339e2fe 100644 --- a/IOB-WIN/DATA/CONF/SIMUL_03.ini +++ b/IOB-WIN/DATA/CONF/SIMUL_03.ini @@ -58,7 +58,7 @@ FORCE_DYN_DATA=TRUE NEW_DYN_DATA=TRUE ;gestione invio pezzi in blocco ENABLE_SEND_PZC_BLOCK=TRUE -MIN_SEND_PZC_BLOCK=5 +MIN_SEND_PZC_BLOCK=0 MAX_SEND_PZC_BLOCK=100 MIN_DURATA_ODL=240 ; indica parametri gestione TcMan diff --git a/IOB-WIN/DATA/CONF/SIMUL_04.ini b/IOB-WIN/DATA/CONF/SIMUL_04.ini index a442eae2..91d7ff31 100644 --- a/IOB-WIN/DATA/CONF/SIMUL_04.ini +++ b/IOB-WIN/DATA/CONF/SIMUL_04.ini @@ -58,7 +58,7 @@ FORCE_DYN_DATA=TRUE NEW_DYN_DATA=TRUE ;gestione invio pezzi in blocco ENABLE_SEND_PZC_BLOCK=TRUE -MIN_SEND_PZC_BLOCK=5 +MIN_SEND_PZC_BLOCK=0 MAX_SEND_PZC_BLOCK=100 MIN_DURATA_ODL=240 ; indica parametri gestione TcMan diff --git a/IOB-WIN/DATA/CONF/SIMUL_05.ini b/IOB-WIN/DATA/CONF/SIMUL_05.ini index 7d2a4d57..34e0e9f6 100644 --- a/IOB-WIN/DATA/CONF/SIMUL_05.ini +++ b/IOB-WIN/DATA/CONF/SIMUL_05.ini @@ -58,7 +58,7 @@ FORCE_DYN_DATA=TRUE NEW_DYN_DATA=TRUE ;gestione invio pezzi in blocco ENABLE_SEND_PZC_BLOCK=TRUE -MIN_SEND_PZC_BLOCK=5 +MIN_SEND_PZC_BLOCK=0 MAX_SEND_PZC_BLOCK=100 MIN_DURATA_ODL=240 ; indica parametri gestione TcMan diff --git a/IOB-WIN/DATA/CONF/SIMUL_06.ini b/IOB-WIN/DATA/CONF/SIMUL_06.ini index fcb35fdb..65c71337 100644 --- a/IOB-WIN/DATA/CONF/SIMUL_06.ini +++ b/IOB-WIN/DATA/CONF/SIMUL_06.ini @@ -58,7 +58,7 @@ FORCE_DYN_DATA=TRUE NEW_DYN_DATA=TRUE ;gestione invio pezzi in blocco ENABLE_SEND_PZC_BLOCK=TRUE -MIN_SEND_PZC_BLOCK=5 +MIN_SEND_PZC_BLOCK=0 MAX_SEND_PZC_BLOCK=100 MIN_DURATA_ODL=240 ; indica parametri gestione TcMan diff --git a/IOB-WIN/DATA/CONF/SIMUL_07.ini b/IOB-WIN/DATA/CONF/SIMUL_07.ini index 9fa3968a..e49824ef 100644 --- a/IOB-WIN/DATA/CONF/SIMUL_07.ini +++ b/IOB-WIN/DATA/CONF/SIMUL_07.ini @@ -58,7 +58,7 @@ FORCE_DYN_DATA=TRUE NEW_DYN_DATA=TRUE ;gestione invio pezzi in blocco ENABLE_SEND_PZC_BLOCK=TRUE -MIN_SEND_PZC_BLOCK=5 +MIN_SEND_PZC_BLOCK=0 MAX_SEND_PZC_BLOCK=100 MIN_DURATA_ODL=240 ; indica parametri gestione TcMan diff --git a/IOB-WIN/DATA/CONF/SIMUL_08.ini b/IOB-WIN/DATA/CONF/SIMUL_08.ini index 731ac086..63b75bd6 100644 --- a/IOB-WIN/DATA/CONF/SIMUL_08.ini +++ b/IOB-WIN/DATA/CONF/SIMUL_08.ini @@ -58,7 +58,7 @@ FORCE_DYN_DATA=TRUE NEW_DYN_DATA=TRUE ;gestione invio pezzi in blocco ENABLE_SEND_PZC_BLOCK=TRUE -MIN_SEND_PZC_BLOCK=5 +MIN_SEND_PZC_BLOCK=0 MAX_SEND_PZC_BLOCK=100 MIN_DURATA_ODL=240 ; indica parametri gestione TcMan diff --git a/IOB-WIN/DATA/CONF/SIM_DP_01.ini b/IOB-WIN/DATA/CONF/SIM_DP_01.ini index d96026df..20f9f7c4 100644 --- a/IOB-WIN/DATA/CONF/SIM_DP_01.ini +++ b/IOB-WIN/DATA/CONF/SIM_DP_01.ini @@ -41,7 +41,7 @@ PZCOUNT_MODE=BIT ENABLE_PZ_RESET=TRUE ;gestione invio pezzi in blocco ENABLE_SEND_PZC_BLOCK=TRUE -MIN_SEND_PZC_BLOCK=5 +MIN_SEND_PZC_BLOCK=0 MAX_SEND_PZC_BLOCK=100 MIN_DURATA_ODL=240 ; per il simulatore: 50|1 = WAIT 50, DURATION 1 con riferimento al PERIODO base (PER_BASE in ms, default 1 secondo) diff --git a/IOB-WIN/DATA/CONF/SIM_DP_02.ini b/IOB-WIN/DATA/CONF/SIM_DP_02.ini index a1bcf74d..64eae285 100644 --- a/IOB-WIN/DATA/CONF/SIM_DP_02.ini +++ b/IOB-WIN/DATA/CONF/SIM_DP_02.ini @@ -41,7 +41,7 @@ PZCOUNT_MODE=BIT ENABLE_PZ_RESET=TRUE ;gestione invio pezzi in blocco ENABLE_SEND_PZC_BLOCK=TRUE -MIN_SEND_PZC_BLOCK=5 +MIN_SEND_PZC_BLOCK=0 MAX_SEND_PZC_BLOCK=100 MIN_DURATA_ODL=240 ; per il simulatore: 50|1 = WAIT 50, DURATION 1 con riferimento al PERIODO base (PER_BASE in ms, default 1 secondo) From f560ae57ddcd7c5179d9fa7309924b4c851a9ef7 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Tue, 6 Oct 2020 13:40:25 +0200 Subject: [PATCH 04/26] update sim x MULTI --- IOB-WIN/IOB-WIN.csproj | 1 + IOB-WIN/IobSimula.cs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/IOB-WIN/IOB-WIN.csproj b/IOB-WIN/IOB-WIN.csproj index 668069fb..e64d62a7 100644 --- a/IOB-WIN/IOB-WIN.csproj +++ b/IOB-WIN/IOB-WIN.csproj @@ -157,6 +157,7 @@ + diff --git a/IOB-WIN/IobSimula.cs b/IOB-WIN/IobSimula.cs index bfe267f2..9872f1f7 100644 --- a/IOB-WIN/IobSimula.cs +++ b/IOB-WIN/IobSimula.cs @@ -366,6 +366,8 @@ namespace IOB_WIN { B_input = 0; } + // aggiungo NON emergenza... + B_input += (1 << 7); } } // in primis verifico SE posso inviare in blocco i pezzi...... SE MP online e SE NON E' MULTI From 685df365f454f9a3832d468607b0d4d1d59c7c58 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Tue, 6 Oct 2020 14:18:28 +0200 Subject: [PATCH 05/26] Aggiunta progetto test x FS watcher --- TestApp/TestApp.sln | 25 +++++++++++ TestApp/TestApp/Program.cs | 14 +++++++ TestApp/TestApp/Properties/AssemblyInfo.cs | 36 ++++++++++++++++ TestApp/TestApp/TestApp.csproj | 48 ++++++++++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 TestApp/TestApp.sln create mode 100644 TestApp/TestApp/Program.cs create mode 100644 TestApp/TestApp/Properties/AssemblyInfo.cs create mode 100644 TestApp/TestApp/TestApp.csproj diff --git a/TestApp/TestApp.sln b/TestApp/TestApp.sln new file mode 100644 index 00000000..fc358db9 --- /dev/null +++ b/TestApp/TestApp.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30413.136 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApp", "TestApp\TestApp.csproj", "{41CED9A1-A4F8-4F8D-97EC-CBEFC2B3F2EB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {41CED9A1-A4F8-4F8D-97EC-CBEFC2B3F2EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {41CED9A1-A4F8-4F8D-97EC-CBEFC2B3F2EB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {41CED9A1-A4F8-4F8D-97EC-CBEFC2B3F2EB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {41CED9A1-A4F8-4F8D-97EC-CBEFC2B3F2EB}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D37298AA-67AF-432E-B3BB-12C51CD28F92} + EndGlobalSection +EndGlobal diff --git a/TestApp/TestApp/Program.cs b/TestApp/TestApp/Program.cs new file mode 100644 index 00000000..5f7c5c27 --- /dev/null +++ b/TestApp/TestApp/Program.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace TestApp +{ + class Program + { + static void Main(string[] args) + { + } + } +} diff --git a/TestApp/TestApp/Properties/AssemblyInfo.cs b/TestApp/TestApp/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..3edf2271 --- /dev/null +++ b/TestApp/TestApp/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Le informazioni generali relative a un assembly sono controllate dal seguente +// set di attributi. Modificare i valori di questi attributi per modificare le informazioni +// associate a un assembly. +[assembly: AssemblyTitle("TestApp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TestApp")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Se si imposta ComVisible su false, i tipi in questo assembly non saranno visibili +// ai componenti COM. Se è necessario accedere a un tipo in questo assembly da +// COM, impostare su true l'attributo ComVisible per tale tipo. +[assembly: ComVisible(false)] + +// Se il progetto viene esposto a COM, il GUID seguente verrà utilizzato come ID della libreria dei tipi +[assembly: Guid("41ced9a1-a4f8-4f8d-97ec-cbefc2b3f2eb")] + +// Le informazioni sulla versione di un assembly sono costituite dai seguenti quattro valori: +// +// Versione principale +// Versione secondaria +// Numero di build +// Revisione +// +// È possibile specificare tutti i valori oppure impostare valori predefiniti per i numeri relativi alla revisione e alla build +// usando l'asterisco '*' come illustrato di seguito: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/TestApp/TestApp/TestApp.csproj b/TestApp/TestApp/TestApp.csproj new file mode 100644 index 00000000..a278554a --- /dev/null +++ b/TestApp/TestApp/TestApp.csproj @@ -0,0 +1,48 @@ + + + + + Debug + AnyCPU + {41CED9A1-A4F8-4F8D-97EC-CBEFC2B3F2EB} + Exe + TestApp + TestApp + v4.0 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + \ No newline at end of file From eba149dbd67c1c0d109afe1479a2bab7b914e0c7 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Tue, 6 Oct 2020 16:13:28 +0200 Subject: [PATCH 06/26] Applicazione test x modifiche filesystem, prove fatte in Zanoni x Euromap63 --- TestApp/TestApp.sln => TestApp.sln | 0 TestApp/FSWatch.cs | 109 ++++++++++++++++++ TestApp/NLog.config | 54 +++++++++ TestApp/{TestApp => }/Program.cs | 8 +- .../{TestApp => }/Properties/AssemblyInfo.cs | 0 TestApp/{TestApp => }/TestApp.csproj | 25 ++++ TestApp/Utils.cs | 23 ++++ TestApp/logs/.placeholder | 1 + TestApp/packages.config | 4 + 9 files changed, 221 insertions(+), 3 deletions(-) rename TestApp/TestApp.sln => TestApp.sln (100%) create mode 100644 TestApp/FSWatch.cs create mode 100644 TestApp/NLog.config rename TestApp/{TestApp => }/Program.cs (50%) rename TestApp/{TestApp => }/Properties/AssemblyInfo.cs (100%) rename TestApp/{TestApp => }/TestApp.csproj (67%) create mode 100644 TestApp/Utils.cs create mode 100644 TestApp/logs/.placeholder create mode 100644 TestApp/packages.config diff --git a/TestApp/TestApp.sln b/TestApp.sln similarity index 100% rename from TestApp/TestApp.sln rename to TestApp.sln diff --git a/TestApp/FSWatch.cs b/TestApp/FSWatch.cs new file mode 100644 index 00000000..89f8715c --- /dev/null +++ b/TestApp/FSWatch.cs @@ -0,0 +1,109 @@ +using System; +using System.IO; +using System.Security.Permissions; + +namespace TestApp +{ + /************************************************** + * Classe gestione verifica cambio files in directory + * + * links: + * https://docs.microsoft.com/it-it/dotnet/api/system.io.filesystemwatcher?view=netframework-4.0 + * https://www.c-sharpcorner.com/UploadFile/puranindia/filesystemwatcher-in-C-Sharp/ + * + * + * ***********************************************/ + public static class FSWatch + { + + /// + /// Metodo principale esecuzione check filesystem + /// + [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] + public static void Run() + { + //string[] args = Environment.GetCommandLineArgs(); + + //// If a directory is not specified, exit program. + //if (args.Length != 2) + //{ + // // Display the proper way to call the program. + // Console.WriteLine("Usage: Watcher.exe (directory)"); + // return; + //} + + try + { + // Create a new FileSystemWatcher and set its properties. + using (FileSystemWatcher watcher = new FileSystemWatcher()) + { + //watcher.Path = args[1]; + + watcher.Path = Directory.GetCurrentDirectory(); + + // NO guardo le subdirs + watcher.IncludeSubdirectories = false; + + // Watch for changes in LastAccess and LastWrite times, and + // the renaming of files or directories. + //watcher.NotifyFilter = NotifyFilters.DirectoryName + // | NotifyFilters.FileName + // | NotifyFilters.LastAccess + // | NotifyFilters.LastWrite + // | NotifyFilters.Size; + watcher.NotifyFilter = NotifyFilters.Attributes + | NotifyFilters.CreationTime + | NotifyFilters.DirectoryName + | NotifyFilters.FileName + | NotifyFilters.LastAccess + | NotifyFilters.LastWrite + | NotifyFilters.Security + | NotifyFilters.Size; + + // Only watch text files. + watcher.Filter = "*.*"; + + // Add event handlers. + watcher.Changed += OnChanged; + watcher.Created += OnChanged; + watcher.Error += OnError; + watcher.Deleted += OnChanged; + watcher.Renamed += OnRenamed; + + // Begin watching. + watcher.EnableRaisingEvents = true; + + // Wait for the user to quit the program. + Console.WriteLine("Press 'q' to quit the sample."); + while (Console.Read() != 'q') ; + } + } + catch (IOException e) + { + //Console.WriteLine("A Exception Occurred :" + e); + Utils.Log.Error("A Exception Occurred :" + e); + } + catch (Exception oe) + { + //Console.WriteLine("An Exception Occurred :" + oe); + Utils.Log.Error("An Exception Occurred :" + oe); + } + } + + private static void OnError(object sender, ErrorEventArgs e) => + // Specify what is done when a file is changed, created, or deleted. + Console.WriteLine($"{DateTime.Now} | Error: {e.GetException()}"); + + // Define the event handlers. + private static void OnChanged(object source, FileSystemEventArgs e) => + Utils.Log.Info($"File: {e.Name} {e.ChangeType}"); + // Specify what is done when a file is changed, created, or deleted. + //Console.WriteLine($"{DateTime.Now} | File: {e.Name} {e.ChangeType} ({e.FullPath})"); + + + private static void OnRenamed(object source, RenamedEventArgs e) => + Utils.Log.Info($"File: {e.OldName} renamed to {e.Name}"); + // Specify what is done when a file is renamed. + //Console.WriteLine($"{DateTime.Now} | File: {e.OldName} renamed to {e.Name} ({e.OldFullPath} --> {e.FullPath})"); + } +} \ No newline at end of file diff --git a/TestApp/NLog.config b/TestApp/NLog.config new file mode 100644 index 00000000..a6354580 --- /dev/null +++ b/TestApp/NLog.config @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/TestApp/TestApp/Program.cs b/TestApp/Program.cs similarity index 50% rename from TestApp/TestApp/Program.cs rename to TestApp/Program.cs index 5f7c5c27..5149f5b6 100644 --- a/TestApp/TestApp/Program.cs +++ b/TestApp/Program.cs @@ -5,10 +5,12 @@ using System.Text; namespace TestApp { - class Program + internal class Program { - static void Main(string[] args) + private static void Main(string[] args) { + // eseguo test FS Watcher + FSWatch.Run(); } } -} +} \ No newline at end of file diff --git a/TestApp/TestApp/Properties/AssemblyInfo.cs b/TestApp/Properties/AssemblyInfo.cs similarity index 100% rename from TestApp/TestApp/Properties/AssemblyInfo.cs rename to TestApp/Properties/AssemblyInfo.cs diff --git a/TestApp/TestApp/TestApp.csproj b/TestApp/TestApp.csproj similarity index 67% rename from TestApp/TestApp/TestApp.csproj rename to TestApp/TestApp.csproj index a278554a..dde66a30 100644 --- a/TestApp/TestApp/TestApp.csproj +++ b/TestApp/TestApp.csproj @@ -11,6 +11,8 @@ v4.0 512 true + + AnyCPU @@ -32,8 +34,15 @@ 4 + + ..\packages\NLog.4.7.5\lib\net40-client\NLog.dll + + + + + @@ -41,8 +50,24 @@ + + + + + Always + + + Always + + + + + + + + \ No newline at end of file diff --git a/TestApp/Utils.cs b/TestApp/Utils.cs new file mode 100644 index 00000000..473b5e49 --- /dev/null +++ b/TestApp/Utils.cs @@ -0,0 +1,23 @@ +using NLog; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace TestApp +{ + public class Utils + { + + /// + /// S + /// + public static Logger Log { get; private set; } + static Utils() + { + LogManager.ReconfigExistingLoggers(); + + Log = LogManager.GetCurrentClassLogger(); + } + } +} diff --git a/TestApp/logs/.placeholder b/TestApp/logs/.placeholder new file mode 100644 index 00000000..5f282702 --- /dev/null +++ b/TestApp/logs/.placeholder @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/TestApp/packages.config b/TestApp/packages.config new file mode 100644 index 00000000..73e35b24 --- /dev/null +++ b/TestApp/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From 14a0898c483924326e97f4985dbd557036a3799c Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Tue, 6 Oct 2020 19:22:05 +0200 Subject: [PATCH 07/26] Update x EM63... --- IOB-UT/Eurom63.cs | 125 + IOB-UT/IOB-UT.csproj | 1 + IOB-WIN/AdapterForm.cs | 3086 +++++++++++++------------ IOB-WIN/DATA/CONF/EM63.ini | 66 + IOB-WIN/DATA/CONF/EM63.json | 179 ++ IOB-WIN/IOB-WIN.csproj | 9 +- IOB-WIN/{IobFileGen.cs => IobFile.cs} | 61 +- IOB-WIN/IobFileEurom63.cs | 72 + IOB-WIN/Resources/ChangeLog.html | 227 +- 9 files changed, 2146 insertions(+), 1680 deletions(-) create mode 100644 IOB-UT/Eurom63.cs create mode 100644 IOB-WIN/DATA/CONF/EM63.ini create mode 100644 IOB-WIN/DATA/CONF/EM63.json rename IOB-WIN/{IobFileGen.cs => IobFile.cs} (89%) create mode 100644 IOB-WIN/IobFileEurom63.cs diff --git a/IOB-UT/Eurom63.cs b/IOB-UT/Eurom63.cs new file mode 100644 index 00000000..3edf7898 --- /dev/null +++ b/IOB-UT/Eurom63.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace IOB_UT +{ + /// + /// Classe di helper per metodi Euromap63 tramite File Exchange + /// + public class Eurom63 + { + public enum FileOpr + { + Copy = 0, + ReplaceAndCopy + } + + public enum FileType + { + NA = 0, + Dat, + Job, + Log, + Req, + Rsp + } + + public enum JobType + { + NA = 0, + AbortAll, + GetStatus, + GetParams, + GetProduction, + IsConnected, + SetDateTime, + SetParamOdl + } + + /// + /// Struttura per un file da processare + /// + public class FileTask + { + public string FileName { get; set; } = "SESS0000.FILE"; + public string Path { get; set; } = @"JOB\SESS0000.FILE"; + public Dictionary StrReplace { get; set; } = new Dictionary(); + public FileType Type { get; set; } = FileType.NA; + } + + /// + /// Generic communication session + /// + public class Session + { + /// + /// Session currently active + /// + public bool Active { get; set; } = false; + + /// + /// Indicates that must be repeated/restarted when not active + /// + public bool Cycle { get; set; } = false; + + /// + /// Session Description + /// + public string Description { get; set; } = ""; + + /// + /// Elenco dei file da processare + /// + public List FileList { get; set; } = new List(); + + /// + /// Numero MAX di esecuzioni da mantenere in HIST prima di eliminare i + vecchi (fare folder HIST\SESSnnnn) + /// + public int Max2Keep { get; set; } = 50; + + /// + /// Session check passed (= not to repeat) + /// + public bool Passed { get; set; } = false; + + /// + /// Session Name + /// + public string SessionName { get; set; } = "SESS0000"; + + /// + /// Start of communication + /// + public DateTime SessionStarted { get; set; } = DateTime.Now.AddMinutes(-5); + + /// + /// Session type + /// + public JobType SessionType { get; set; } = JobType.NA; + + /// + /// Estimated Validity limit + /// + public DateTime SessionValidUntil { get; set; } = DateTime.Now.AddMinutes(-1); + + /// + /// Set Step Order (=execution priority, 1...n) + /// + public int StepOrder { get; set; } = 999; + + /// + /// Standard session validity time + /// + public double ValidityMinutes { get; set; } = 1; + } + + public class SessionConf + { + public List ActiveSessions = new List(); + public string BaseDir { get; set; } = @"C:\"; + public List DynData { get; set; } = new List(); + } + } +} \ No newline at end of file diff --git a/IOB-UT/IOB-UT.csproj b/IOB-UT/IOB-UT.csproj index 54c5d7aa..faaeef15 100644 --- a/IOB-UT/IOB-UT.csproj +++ b/IOB-UT/IOB-UT.csproj @@ -99,6 +99,7 @@ + diff --git a/IOB-WIN/AdapterForm.cs b/IOB-WIN/AdapterForm.cs index ffea06b6..08bbbb31 100644 --- a/IOB-WIN/AdapterForm.cs +++ b/IOB-WIN/AdapterForm.cs @@ -13,1280 +13,1375 @@ using System.Windows.Forms; namespace IOB_WIN { - public partial class AdapterForm : Form - { - #region inizializzazione contatori - - /// - /// contatore veloce - /// - protected int fastCount; - - /// - /// Data-Ora prima apertura FORM... - /// - protected DateTime firstStart; - - /// - /// ultimo tentativo riavvio... - /// - protected DateTime lastStartTry; - - /// - /// contatore normale - /// - protected int normCount; - - /// - /// Contatore campionamento memoria - /// - protected int sampleMemCount; - - /// - /// contatore lento - /// - protected int slowCount; - - /// - /// contatore sync allarmi - /// - protected int verySlowCount; - - #endregion inizializzazione contatori - - #region inizializzazione oggetti base - - /// - /// Oggetto ultimo inviato stato IOB x REDIS - /// - protected IobWinStatus lastIobStatus = new IobWinStatus(); - - /// - /// Oggetto ultimo inviato stato MP-IO x REDIS - /// - protected ServerMpStatus lastSrvStatus = new ServerMpStatus(); - - /// - /// Temnpo attesa std in MS - /// - protected int waitRecMSec = 30000; - - /// - /// oggetto logging - /// - public static Logger lg; - - /// - /// Modello macchina - /// - public string curModel = ""; - - /// - /// Vendor macchina - /// - public string curVendor = ""; - - /// - /// configurazione caricata - /// - public IobConfiguration IOBConf; - - /// - /// Oggetto x gestione dell'adapter GENERICO (x poter usare metodi di ognuno...) - /// - public IobGeneric iobObj; - - /// - /// tipo di adapter prescelto... - /// - public tipoAdapter tipoScelto = tipoAdapter.SIMULA; - - /// - /// Codice IOB della macchina cui connettersi (x scegliere corretto file di conf...) - /// - protected string CurrIOB { get; set; } - - #endregion inizializzazione oggetti base - - #region utils ed helpers - - protected int delayShowLogMs { get; set; } = utils.CRI("delayShowLogMs"); - - /// - /// Stringa corrente di log... - /// - protected string logWatchString { get; set; } = ""; - - /// - /// Veto a NUOVE scritture in logWatch... - /// - protected DateTime logWatchWriteVeto { get; set; } = DateTime.Now; - - /// - /// Log verboso da configurazione (SOLO CHAIVE "verbose"... - /// - public bool isVerboseLog { get; set; } = utils.CRB("verbose"); - - /// - /// Logwatcher (in modalità "accodamento in testa" ultimi messaggi...) - /// - public string logWatcher + public partial class AdapterForm : Form { - get - { - return lblLogfile.Text; - } - set - { - try + #region inizializzazione contatori + + /// + /// contatore veloce + /// + protected int fastCount; + + /// + /// Data-Ora prima apertura FORM... + /// + protected DateTime firstStart; + + /// + /// ultimo tentativo riavvio... + /// + protected DateTime lastStartTry; + + /// + /// contatore normale + /// + protected int normCount; + + /// + /// Contatore campionamento memoria + /// + protected int sampleMemCount; + + /// + /// contatore lento + /// + protected int slowCount; + + /// + /// contatore sync allarmi + /// + protected int verySlowCount; + + #endregion inizializzazione contatori + + #region inizializzazione oggetti base + + /// + /// oggetto logging + /// + public static Logger lg; + + /// + /// Modello macchina + /// + public string curModel = ""; + + /// + /// Vendor macchina + /// + public string curVendor = ""; + + /// + /// configurazione caricata + /// + public IobConfiguration IOBConf; + + /// + /// Oggetto x gestione dell'adapter GENERICO (x poter usare metodi di ognuno...) + /// + public IobGeneric iobObj; + + /// + /// tipo di adapter prescelto... + /// + public tipoAdapter tipoScelto = tipoAdapter.SIMULA; + + /// + /// Oggetto ultimo inviato stato IOB x REDIS + /// + protected IobWinStatus lastIobStatus = new IobWinStatus(); + + /// + /// Oggetto ultimo inviato stato MP-IO x REDIS + /// + protected ServerMpStatus lastSrvStatus = new ServerMpStatus(); + + /// + /// Temnpo attesa std in MS + /// + protected int waitRecMSec = 30000; + + /// + /// Codice IOB della macchina cui connettersi (x scegliere corretto file di conf...) + /// + protected string CurrIOB { get; set; } + + #endregion inizializzazione oggetti base + + #region utils ed helpers + + /// + /// Log verboso da configurazione (SOLO CHAIVE "verbose"... + /// + public bool isVerboseLog { get; set; } = utils.CRB("verbose"); + + /// + /// Logwatcher (in modalità "accodamento in testa" ultimi messaggi...) + /// + public string logWatcher { - logWatchString = limitLine2show($"{value}{Environment.NewLine}{logWatchString}"); - DateTime adesso = DateTime.Now; - if (logWatchWriteVeto < adesso) - { - lblLogfile.Text = logWatchString; - lblLogfile.Refresh(); - logWatchWriteVeto = adesso.AddMilliseconds(delayShowLogMs); - } + get + { + return lblLogfile.Text; + } + set + { + try + { + logWatchString = limitLine2show($"{value}{Environment.NewLine}{logWatchString}"); + DateTime adesso = DateTime.Now; + if (logWatchWriteVeto < adesso) + { + lblLogfile.Text = logWatchString; + lblLogfile.Refresh(); + logWatchWriteVeto = adesso.AddMilliseconds(delayShowLogMs); + } + } + catch (Exception exc) + { + lgError($"Errore in esecuzione logWatcher{Environment.NewLine}--> {value}"); + if (isVerboseLog) + { + lgError($"{exc}"); + } + } + } } - catch (Exception exc) + + /// + /// Task watcher (in modalità "accodamento in testa" ultimi messaggi...) + /// + public string taskWatcher { - lgError($"Errore in esecuzione logWatcher{Environment.NewLine}--> {value}"); - if (isVerboseLog) - { - lgError($"{exc}"); - } + get + { + return lblTaskLog.Text; + } + set + { + try + { + lblTaskLog.Text = limitLine2show($"{value}{Environment.NewLine}{lblTaskLog.Text}"); + lblTaskLog.Refresh(); + } + catch (Exception exc) + { + lgError($"Errore in esecuzione taskWatcher{Environment.NewLine}--> {value}"); + if (isVerboseLog) + { + lgError($"{exc}"); + } + } + } } - } - } - /// - /// Task watcher (in modalità "accodamento in testa" ultimi messaggi...) - /// - public string taskWatcher - { - get - { - return lblTaskLog.Text; - } - set - { - try + protected int delayShowLogMs { get; set; } = utils.CRI("delayShowLogMs"); + + /// + /// Stringa corrente di log... + /// + protected string logWatchString { get; set; } = ""; + + /// + /// Veto a NUOVE scritture in logWatch... + /// + protected DateTime logWatchWriteVeto { get; set; } = DateTime.Now; + + /// + /// mostra un testo sulla status bar + LOG + /// + /// + public void displayTaskAndLog(string txt2show) { - lblTaskLog.Text = limitLine2show($"{value}{Environment.NewLine}{lblTaskLog.Text}"); - lblTaskLog.Refresh(); + lblStatus.Text = txt2show; + lblStatus.Invalidate(); + lgInfo(txt2show); } - catch (Exception exc) + + /// + /// Effettua un trim della stringa al numero max di linee da mostrare a video + /// + /// + /// + public string limitLine2show(string newString) { - lgError($"Errore in esecuzione taskWatcher{Environment.NewLine}--> {value}"); - if (isVerboseLog) - { - lgError($"{exc}"); - } + if (!string.IsNullOrEmpty(newString)) + { + // se num righe superiore a limite trimmo... + if (newString.Split('\n').Length > nLine2show) + { + //int idx = newString.LastIndexOf('\r'); + int idx = newString.LastIndexOf(Environment.NewLine); + newString = newString.Substring(0, idx); + } + } + return newString; } - } - } - /// - /// Effettua logging ERROR corretto impostanto anche la variabile IOB prima di scrivere... - /// - /// - protected void lgError(string txt2log) - { - if (!string.IsNullOrEmpty(txt2log)) - { - lg.Factory.Configuration.Variables["codIOB"] = this.CurrIOB; - lg.Error(txt2log); - // salvo anche in logwatcher... SE non si dimostra ricorsivo... - if (!txt2log.Contains("logWatcher")) + /// + /// Mostra update delle statistiche di comunicazione (numero chiamate, tempo medio...) + /// + /// + public void updateComStats(string txt2show) { - newDisplayData currDispData = new newDisplayData(); - currDispData.newLiveLogData = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} | ERROR | {txt2log}"; - updateFormDisplay(currDispData); + lblComStats.Text = string.Format("{0} | ", txt2show); } - } - } - /// - /// Effettua logging INFO corretto impostanto anche la variabile IOB prima di scrivere... - /// - /// - protected void lgInfo(string txt2log) - { - lg.Factory.Configuration.Variables["codIOB"] = this.CurrIOB; - lg.Info(txt2log); - // salvo anche in logwatcher... - newDisplayData currDispData = new newDisplayData(); - currDispData.newLiveLogData = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} | INFO | {txt2log}"; - updateFormDisplay(currDispData); - } - - /// - /// mostra un testo sulla status bar + LOG - /// - /// - public void displayTaskAndLog(string txt2show) - { - lblStatus.Text = txt2show; - lblStatus.Invalidate(); - lgInfo(txt2show); - } - - /// - /// Effettua un trim della stringa al numero max di linee da mostrare a video - /// - /// - /// - public string limitLine2show(string newString) - { - if (!string.IsNullOrEmpty(newString)) - { - // se num righe superiore a limite trimmo... - if (newString.Split('\n').Length > nLine2show) + /// + /// Effettua logging ERROR corretto impostanto anche la variabile IOB prima di scrivere... + /// + /// + protected void lgError(string txt2log) { - //int idx = newString.LastIndexOf('\r'); - int idx = newString.LastIndexOf(Environment.NewLine); - newString = newString.Substring(0, idx); + if (!string.IsNullOrEmpty(txt2log)) + { + lg.Factory.Configuration.Variables["codIOB"] = this.CurrIOB; + lg.Error(txt2log); + // salvo anche in logwatcher... SE non si dimostra ricorsivo... + if (!txt2log.Contains("logWatcher")) + { + newDisplayData currDispData = new newDisplayData(); + currDispData.newLiveLogData = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} | ERROR | {txt2log}"; + updateFormDisplay(currDispData); + } + } } - } - return newString; - } - /// - /// Mostra update delle statistiche di comunicazione (numero chiamate, tempo medio...) - /// - /// - public void updateComStats(string txt2show) - { - lblComStats.Text = string.Format("{0} | ", txt2show); - } + /// + /// Effettua logging INFO corretto impostanto anche la variabile IOB prima di scrivere... + /// + /// + protected void lgInfo(string txt2log) + { + lg.Factory.Configuration.Variables["codIOB"] = this.CurrIOB; + lg.Info(txt2log); + // salvo anche in logwatcher... + newDisplayData currDispData = new newDisplayData(); + currDispData.newLiveLogData = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} | INFO | {txt2log}"; + updateFormDisplay(currDispData); + } - #endregion utils ed helpers + #endregion utils ed helpers - #region gestione form e visibilità + #region gestione form e visibilità - /// - /// Avvio MainForm - /// - /// - public AdapterForm(string codIOB) - { - CurrIOB = codIOB; - // continuo avvio... - InitializeComponent(); - myGraphInitForm(); + /// + /// Avvio MainForm + /// + /// + public AdapterForm(string codIOB) + { + CurrIOB = codIOB; + // continuo avvio... + InitializeComponent(); + myGraphInitForm(); - checkEditMes2Plc(); + checkEditMes2Plc(); - // inizializzo orologi - firstStart = DateTime.Now; - lastStartTry = DateTime.Now; + // inizializzo orologi + firstStart = DateTime.Now; + lastStartTry = DateTime.Now; - waitRecMSec = utils.CRI("waitRecMSec"); + waitRecMSec = utils.CRI("waitRecMSec"); #if DEBUG - // Setup the logging view for Sentinel - http://sentinel.codeplex.com - var sentinelTarget = new NLogViewerTarget() - { - Name = "sentinel", - Address = "udp://127.0.0.1:9999", - IncludeNLogData = false - }; - var sentinelRule = new LoggingRule("*", LogLevel.Trace, sentinelTarget); - LogManager.Configuration.AddTarget("sentinel", sentinelTarget); - LogManager.Configuration.LoggingRules.Add(sentinelRule); + // Setup the logging view for Sentinel - http://sentinel.codeplex.com + var sentinelTarget = new NLogViewerTarget() + { + Name = "sentinel", + Address = "udp://127.0.0.1:9999", + IncludeNLogData = false + }; + var sentinelRule = new LoggingRule("*", LogLevel.Trace, sentinelTarget); + LogManager.Configuration.AddTarget("sentinel", sentinelTarget); + LogManager.Configuration.LoggingRules.Add(sentinelRule); #endif - LogManager.ReconfigExistingLoggers(); + LogManager.ReconfigExistingLoggers(); - lg = LogManager.GetCurrentClassLogger(); - displayTaskAndLog("MainForm Starting"); + lg = LogManager.GetCurrentClassLogger(); + displayTaskAndLog("MainForm Starting"); - // se abilitato autoload conf leggo file corretto... - if (utils.CRB("autoLoadConf")) - { - try - { - loadIniFile(defConfFilePath); - lgInfo("INI LOADED"); - } - catch (Exception exc) - { - displayTaskAndLog(string.Format("Eccezione in autoLoadConf: {0}", exc)); - } - } - else - { - // definisco e avvio tipo adapter generico - tipoScelto = tipoAdapter.ND; - curVendor = "ACME"; - curModel = "NONE"; - IOBConf = new IobConfiguration(); - loadIobType(); - displayTaskAndLog("Waiting for config file selection"); - } - - // cerco tra i parametri opzionali se ho il parametro di - int timerIntMs = utils.CRI("timerIntMs"); - if (IOBConf.optPar.ContainsKey("timerIntMs")) - { - // recupero - string rawVal = IOBConf.optPar["timerIntMs"]; - if (!string.IsNullOrEmpty(rawVal)) - { - int.TryParse(rawVal, out timerIntMs); - lgInfo($"Impostato timerIntMs da IOB.ini: {timerIntMs}"); - } - } - // Start timer periodico comunicazione - gather.Interval = timerIntMs; - gather.Enabled = true; - displayTaskAndLog(string.Format("Main timer set: {0}ms", gather.Interval)); - - // Start timer periodico interfaccia - displTimer.Interval = utils.CRI("timerIntMs"); - displTimer.Enabled = true; - - displayTaskAndLog("Program Running"); - - try - { - // verifico server online... - if (iobObj.checkServerAlive) - { - // segnalo reboot (programma)... - IobGeneric.callUrl(iobObj.urlReboot, true); - } - else - { - displayTaskAndLog("AdapterForm: Server OFFLINE"); - } - } - catch (Exception exc) - { - lgError(string.Format("AdapterForm: EXCEPTION in fase di chiamata URL di reboot:{0}{1}{2}", iobObj.urlReboot, Environment.NewLine, exc)); - } - displayTaskAndLog("Main Form OK"); - } - - /// - /// File configurazione default - /// - public string defConfFilePath - { - get - { - return string.Format(@"{0}\{1}.ini", utils.confDir, CurrIOB); - } - } - - /// - /// Fase chiusura Form - /// - /// - /// - private void MainForm_FormClosing(object sender, FormClosingEventArgs e) - { - closeAdapter(); - } - - /// - /// Completato resize form - /// - /// - /// - private void MainForm_Resize(object sender, EventArgs e) - { - } - - /// - /// Mostrata form - /// - /// - /// - private void MainForm_Shown(object sender, EventArgs e) - { - displayTaskAndLog("Main Form SHOWN"); - } - - /// - /// Init form (grafica) con helper x testi e varie - /// - protected void myGraphInitForm() - { - lblStatus.Text = "Loading"; - - // aggiunta tooltip x send forzato - ToolTip ttForceSend = new ToolTip(); - - // imposto delay. - ttForceSend.AutoPopDelay = 3000; - ttForceSend.InitialDelay = 500; - ttForceSend.ReshowDelay = 500; - // sempre visibile (che sia o meno attiva la form). - ttForceSend.ShowAlways = true; - - // imposto tooltip - ttForceSend.SetToolTip(this.chkForceDequeue, "Forza invio eventi allo stop"); - } - - #endregion gestione form e visibilità - - #region gestione metodi specifici FORM - - private void checkFastTask() - { - // decremento... - fastCount--; - // se il counter è a zero eseguo... - if (fastCount <= 0) - { - fastCount = utils.CRI("fastCount"); - - // avvio fase raccolta dati e invio con adapter - iobObj.getAndSend(gatherCycle.HF); - } - } - - private void checkNormTask() - { - // decremento... - normCount--; - // se il counter è a zero eseguo... - if (normCount <= 0) - { - normCount = utils.CRI("normCount"); - - // avvio fase raccolta dati e invio con adapter - iobObj.getAndSend(gatherCycle.MF); - } - } - - private void checkSampleMem() - { - // decremento contatore... - sampleMemCount--; - if (sampleMemCount <= 0) - { - sampleMemCount = utils.CRI("sampleMemCount"); - // avvio fase raccolta dati e invio con adapter - iobObj.saveMemDump(dumpType.SAMPLE); - } - } - - private void checkSendTask() - { - // avvio fase invio con adapter (code MST) - iobObj.getAndSend(gatherCycle.VHF); - } - - private void checkSlowTask() - { - slowCount--; - if (slowCount <= 0) - { - slowCount = utils.CRI("slowCount"); - - // avvio fase raccolta dati e invio con adapter - iobObj.getAndSend(gatherCycle.LF); - } - } - - private void checkVerySlowData() - { - verySlowCount--; - if (verySlowCount <= 0) - { - verySlowCount = utils.CRI("verySlowCount"); - // avvio fase raccolta dati e invio con adapter - iobObj.getAndSend(gatherCycle.VLF); - } - } - - /// - /// Chiusura adapter - /// - private void closeAdapter() - { - fermaTutto(true, false, true, false); - } - - /// - /// Ferma tutti i componenti adapter + update buttons - /// - /// indica se fermare il timer (gather) principale (solo se non si chiude) - /// indica se tentare di riconnettersi - /// indica se sia richeisto di SVUOTARE le code delel info - /// indica se si debba aggiornare la form (no se si sta chiudendo...) - private void fermaTutto(bool stopTimer, bool tryRestart, bool forceDequeue, bool updateForm) - { - iobObj.stopAdapter(tryRestart, forceDequeue); - // salvo! - savePersistLayer(utils.defPersLayerFile); - savePersistLayer(utils.histPersLayerFile); - - stop.Enabled = false; - start.Enabled = true; - restart.Enabled = false; - - if (stopTimer) - { - gather.Enabled = false; - iobObj.tryDisconnect(); - } - - newDisplayData currDispData = new newDisplayData(); - currDispData.semIn = Semaforo.SS; - currDispData.semOut = Semaforo.SS; - if (updateForm) - { - updateFormDisplay(currDispData); - } - } - - private void gather_Tick(object sender, EventArgs e) - { - bool doLog = false; - if (iobObj != null) - { - if (iobObj.periodicLog) - { - doLog = true; - } - try - { - refreshFormData(); - // check esecuzione SendTask (VHF) COMUNQUE... - checkSendTask(); - // eseguo cicli attivi SOLO se adapter è in EFFETTIVO running... - if (iobObj.adpRunning) - { - if (iobObj.connectionOk) + // se abilitato autoload conf leggo file corretto... + if (utils.CRB("autoLoadConf")) { - // se richiesto faccio memory DUMP INIZIALE! - if (iobObj.doStartMemDump) - { - lgInfo("Inizio dump memoria"); - iobObj.saveMemDump(dumpType.STARTUP); - // fatto! non ripeto... - iobObj.doStartMemDump = false; - lgInfo("Finito dump memoria"); - } - // controllo se sia abilitato sampleDump della meoria (periodico) - if (iobObj.doSampleMemory) - { - checkSampleMem(); - } - // check esecuzione FastTask - checkFastTask(); - // check esecuzione NormTask - checkNormTask(); - // check esecuzione SlowTask - checkSlowTask(); - // check esecuzione AlarmSync - checkVerySlowData(); - if (utils.CRI("waitEndCycle") > 0) - { - Thread.Sleep(utils.CRI("waitEndCycle")); - } + try + { + loadIniFile(defConfFilePath); + lgInfo("INI LOADED"); + } + catch (Exception exc) + { + displayTaskAndLog(string.Format("Eccezione in autoLoadConf: {0}", exc)); + } } else { - DateTime dtVeto = lastStartTry.AddMilliseconds(waitRecMSec); - if (iobObj.adpTryRestart && (DateTime.Now > dtVeto)) - { - if (doLog) + // definisco e avvio tipo adapter generico + tipoScelto = tipoAdapter.ND; + curVendor = "ACME"; + curModel = "NONE"; + IOBConf = new IobConfiguration(); + loadIobType(); + displayTaskAndLog("Waiting for config file selection"); + } + + // cerco tra i parametri opzionali se ho il parametro di + int timerIntMs = utils.CRI("timerIntMs"); + if (IOBConf.optPar.ContainsKey("timerIntMs")) + { + // recupero + string rawVal = IOBConf.optPar["timerIntMs"]; + if (!string.IsNullOrEmpty(rawVal)) { - lgInfo($"Retry Time Elapsed ({waitRecMSec} ms)--> tryConnect"); + int.TryParse(rawVal, out timerIntMs); + lgInfo($"Impostato timerIntMs da IOB.ini: {timerIntMs}"); } - lastStartTry = DateTime.Now; - iobObj.tryConnect(); - } } - } - else - { - if (doLog) + // Start timer periodico comunicazione + gather.Interval = timerIntMs; + gather.Enabled = true; + displayTaskAndLog(string.Format("Main timer set: {0}ms", gather.Interval)); + + // Start timer periodico interfaccia + displTimer.Interval = utils.CRI("timerIntMs"); + displTimer.Enabled = true; + + displayTaskAndLog("Program Running"); + + try { - lgInfo("Adapter stopped"); + // verifico server online... + if (iobObj.checkServerAlive) + { + // segnalo reboot (programma)... + IobGeneric.callUrl(iobObj.urlReboot, true); + } + else + { + displayTaskAndLog("AdapterForm: Server OFFLINE"); + } } - // verifico SE debba tentare il riavvio, ovvero NON running ma adpTryRestart e non ho riprovato x oltre waitRecMSec - DateTime dtVeto = lastStartTry.AddMilliseconds(waitRecMSec); - if (iobObj.adpTryRestart && (DateTime.Now > dtVeto)) + catch (Exception exc) { - lastStartTry = DateTime.Now; - avviaAdapter(chkForceDequeue.Checked); + lgError(string.Format("AdapterForm: EXCEPTION in fase di chiamata URL di reboot:{0}{1}{2}", iobObj.urlReboot, Environment.NewLine, exc)); } - } + displayTaskAndLog("Main Form OK"); } - catch (Exception exc) + + /// + /// File configurazione default + /// + public string defConfFilePath { - lgError(string.Format("Eccezione in fase di gatherTick: {0}{1}", Environment.NewLine, exc)); + get + { + return string.Format(@"{0}\{1}.ini", utils.confDir, CurrIOB); + } } - } - } - /// - /// Carica file ini della configurazione richiesta - /// - /// - private void loadIniFile(string iniConfFile) - { - // out di cosa faccio... - displayTaskAndLog(string.Format("Loading iniConfFile: {0}", iniConfFile)); - // leggo file - IniFile fIni = new IniFile(iniConfFile); - - // leggo vendor e modello... - curVendor = fIni.ReadString("MACHINE", "VENDOR", "ACME"); - curModel = fIni.ReadString("MACHINE", "MODEL", "NONE"); - // verifico tipo adapter - try - { - tipoScelto = (tipoAdapter)Enum.Parse(typeof(tipoAdapter), fIni.ReadString("IOB", "CNCTYPE", "DEMO")); - } - catch (Exception exc) - { - lgError($"Eccezione in conversione tipo adapter: richiesto un tipo non codificato...{Environment.NewLine}{exc}"); - tipoScelto = tipoAdapter.ND; - } - // carivo vettore parametri opzionai - Dictionary optParRead = new Dictionary(); - string[] optParRows = fIni.ReadSection("OPTPAR"); - if (optParRows.Length > 0) - { - try + /// + /// Init form (grafica) con helper x testi e varie + /// + protected void myGraphInitForm() { - string[] kvp; - foreach (var item in optParRows) - { - kvp = item.Split('='); - optParRead.Add(kvp[0], kvp[1]); - } - lgInfo($"Caricati {optParRead.Count} parametri opzionali da OPTPAR"); + lblStatus.Text = "Loading"; + + // aggiunta tooltip x send forzato + ToolTip ttForceSend = new ToolTip(); + + // imposto delay. + ttForceSend.AutoPopDelay = 3000; + ttForceSend.InitialDelay = 500; + ttForceSend.ReshowDelay = 500; + // sempre visibile (che sia o meno attiva la form). + ttForceSend.ShowAlways = true; + + // imposto tooltip + ttForceSend.SetToolTip(this.chkForceDequeue, "Forza invio eventi allo stop"); } - catch (Exception exc) + + /// + /// Fase chiusura Form + /// + /// + /// + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { - lgError(string.Format("EXCEPTION in fase di lettura OPTPAR: {0}{1}", Environment.NewLine, exc)); + closeAdapter(); } - } - // inizializzio conf IOB - IOBConf = new IobConfiguration - { - pingMsTimeout = fIni.ReadInteger("IOB", "PING_MS_TIMEOUT", 500) - , - vendor = curVendor - , - model = curModel - , - tipoIob = tipoScelto - , - optPar = optParRead - , - versIOB = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString() - , - codIOB = CurrIOB - , - cncIpAddr = fIni.ReadString("CNC", "IP", "::1") - , - cncPort = fIni.ReadString("CNC", "PORT", "0") - , - iniFileName = iniConfFile - , - cpuType = fIni.ReadString("CNC", "CPUTYPE", "") - , - rack = (short)fIni.ReadInteger("CNC", "RACK", 0) - , - slot = (short)fIni.ReadInteger("CNC", "SLOT", 0) - , - serverData = new serverMapo(fIni.ReadString("SERVER", "MPIP", "::1"), fIni.ReadString("SERVER", "MPURL", "/"), fIni.ReadString("SERVER", "CMDBASE", "/"), fIni.ReadString("SERVER", "CMDFLOG", "/"), fIni.ReadString("SERVER", "CMDALIVE", "/"), fIni.ReadString("SERVER", "CMDENABLED", "/"), fIni.ReadString("SERVER", "CMDREBO", "/"), fIni.ReadString("SERVER", "CMD_ODL_STARTED", "/IOB/getCurrOdlStart/")) - , - MAX_COUNTER_BLINK = Convert.ToInt32(fIni.ReadString("BLINK", "MAX_COUNTER_BLINK", "1")) - , - BLINK_FILT = Convert.ToInt32(fIni.ReadString("BLINK", "BLINK_FILT", "0")) - , - TCMaxDelayFactor = Convert.ToDouble(fIni.ReadString("OPTPAR", "TC_MAX_TC_FACTOR", "1.2").Replace(".", ",")) - , - TCLambda = Convert.ToDouble(fIni.ReadString("OPTPAR", "TC_LAMBDA", "0.5").Replace(".", ",")) - , - TCMaxIncrPz = Convert.ToDouble(fIni.ReadString("OPTPAR", "TC_MAX_INCR", "5").Replace(".", ",")) - }; - lgInfo($"Creato IOBConf!"); - loadIobType(); - // avvio macchina con adapter specificato... - if (utils.CRB("autoStartOnLoad")) - { - displayTaskAndLog("Auto Starting..."); - // avvio! - avviaAdapter(chkForceDequeue.Checked); - displayTaskAndLog("Auto Started!"); - } - try - { - // segnalo reboot (programma)... metto in coda invio... - //iobObj.sendToMoonPro(urlType.FLog, "IOB INI Loaded"); - //iobObj.QueueFLog.Enqueue(iobObj.qEncodeFLog("IOB-STATUS", "IOB INI Loaded")); - } - catch (Exception exc) - { - lgError(string.Format("EXCEPTION in fase di chiamata URL di segnalazione caricamento INI file:{0}{1}", Environment.NewLine, exc)); - } - } - - private void refreshFormData() - { - // aggiorno visualizzazioni varie in form... - evQueueLen = iobObj.QueueIN.Count; - flQueueLen = iobObj.QueueFLog.Count; - alQueueLen = iobObj.QueueAlarm.Count; - msQueueLen = iobObj.QueueMessages.Count; - // aggiorno labels counters... - counterIob = $"pz IOB {iobObj.contapezziIOB}"; - counterMac = $"pz PLC {iobObj.contapezziPLC}"; - // verifico IOB status - IobWinStatus currIobStatus = new IobWinStatus() - { - CodIob = iobObj.cIobConf.codIOB, - queueEvLen = evQueueLen, - queueFlLen = flQueueLen, - queueAlLen = alQueueLen, - queueMsLen = msQueueLen, - counterIOB = iobObj.contapezziIOB, - counterMAC = iobObj.contapezziPLC, - lastUpdate = lastIobStatus.lastUpdate, - online = utils.IOB_Online, - lastDataIn = iobObj.lastReadPLC - }; - // se diverso SALVO! - if (lastIobStatus.online != currIobStatus.online || lastIobStatus.lastDataIn != currIobStatus.lastDataIn || lastIobStatus.counterIOB != currIobStatus.counterIOB || lastIobStatus.counterMAC != currIobStatus.counterMAC || lastIobStatus.queueEvLen != currIobStatus.queueEvLen || lastIobStatus.queueFlLen != currIobStatus.queueFlLen || lastIobStatus.queueAlLen != currIobStatus.queueAlLen || lastIobStatus.queueMsLen != currIobStatus.queueMsLen) - { - // aggiorno data - currIobStatus.lastUpdate = DateTime.Now; - // salvo su redis e in obj corrente - iobObj.redisMan.iobStatus = currIobStatus; - lastIobStatus = currIobStatus; - } - // se diverso SALVO MP IO status - if (lastSrvStatus.online != utils.MPIO_Online) - { - // aggiorno - ServerMpStatus currSrvStatus = iobObj.redisMan.servStatus; - currSrvStatus.online = utils.MPIO_Online; - currSrvStatus.lastUpdate = DateTime.Now; - // salvo su redis e in obj corrente - iobObj.redisMan.servStatus = currSrvStatus; - lastSrvStatus = currSrvStatus; - } - } - - /// - /// Salva su file l'oggetto di persistenza dati - /// - /// - public void savePersistLayer(string filePath) - { - // in primis check semaforo salvataggio... - if (!iobObj.adpSaving) - { - // alzo semaforo salvataggio - iobObj.adpSaving = true; - // se HO dei dati... - if (iobObj.persistenceLayer != null) + /// + /// Completato resize form + /// + /// + /// + private void MainForm_Resize(object sender, EventArgs e) { - try - { - utils.WritePlain(iobObj.persistenceLayer, filePath); - } - catch (Exception exc) - { - lgError(string.Format("Errore salvataggio file{0}{1}", Environment.NewLine, exc)); - } } - else + + /// + /// Mostrata form + /// + /// + /// + private void MainForm_Shown(object sender, EventArgs e) { - lgInfo("persistenceLayer null, non salvato..."); + displayTaskAndLog("Main Form SHOWN"); } - // abbasso semaforo salvataggio - iobObj.adpSaving = false; - } - } - #endregion gestione metodi specifici FORM + #endregion gestione form e visibilità - #region Area BackGroundWorker + #region gestione metodi specifici FORM - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - /// - /// Effettua update form una volta ricevuto OBJ che contiene le varie innovazioni... - /// - /// - public void updateFormDisplay(newDisplayData currDispData) - { - // ciclo x ogni oggetto x caricare le innovazioni... - if (currDispData != null && currDispData.hasData) - { - // RealTime display - if (!string.IsNullOrWhiteSpace(currDispData.newInData)) + /// + /// Salva su file l'oggetto di persistenza dati + /// + /// + public void savePersistLayer(string filePath) { - dataMonitor_0 = limitLine2show($"{currDispData.newInData}{Environment.NewLine}{dataMonitor_0}"); + // in primis check semaforo salvataggio... + if (!iobObj.adpSaving) + { + // alzo semaforo salvataggio + iobObj.adpSaving = true; + // se HO dei dati... + if (iobObj.persistenceLayer != null) + { + try + { + utils.WritePlain(iobObj.persistenceLayer, filePath); + } + catch (Exception exc) + { + lgError(string.Format("Errore salvataggio file{0}{1}", Environment.NewLine, exc)); + } + } + else + { + lgInfo("persistenceLayer null, non salvato..."); + } + // abbasso semaforo salvataggio + iobObj.adpSaving = false; + } } - if (!string.IsNullOrWhiteSpace(currDispData.newSignalData)) + + private void checkFastTask() { - dataMonitor_1 = limitLine2show($"{currDispData.newSignalData}{Environment.NewLine}{dataMonitor_1}"); + // decremento... + fastCount--; + // se il counter è a zero eseguo... + if (fastCount <= 0) + { + fastCount = utils.CRI("fastCount"); + + // avvio fase raccolta dati e invio con adapter + iobObj.getAndSend(gatherCycle.HF); + } } - if (!string.IsNullOrWhiteSpace(currDispData.newFLogData)) + + private void checkNormTask() { - dataMonitor_3 = limitLine2show($"{currDispData.newFLogData}{Environment.NewLine}{dataMonitor_3}"); + // decremento... + normCount--; + // se il counter è a zero eseguo... + if (normCount <= 0) + { + normCount = utils.CRI("normCount"); + + // avvio fase raccolta dati e invio con adapter + iobObj.getAndSend(gatherCycle.MF); + } } - if (!string.IsNullOrWhiteSpace(currDispData.newUrlCallData)) + + private void checkSampleMem() { - dataMonitor_2 = limitLine2show($"{currDispData.newUrlCallData}{Environment.NewLine}{dataMonitor_2}"); + // decremento contatore... + sampleMemCount--; + if (sampleMemCount <= 0) + { + sampleMemCount = utils.CRI("sampleMemCount"); + // avvio fase raccolta dati e invio con adapter + iobObj.saveMemDump(dumpType.SAMPLE); + } } - // Bitmap lettura attuale - if (currDispData.counter >= 0) + private void checkSendTask() { - lblCounter.Text = currDispData.counter.ToString(); + // avvio fase invio con adapter (code MST) + iobObj.getAndSend(gatherCycle.VHF); } - // Bitmap lettura attuale - if (!string.IsNullOrWhiteSpace(currDispData.currBitmap)) + + private void checkSlowTask() { - lblBitmap.Text = currDispData.currBitmap; - lblBitmap.Refresh(); + slowCount--; + if (slowCount <= 0) + { + slowCount = utils.CRI("slowCount"); + + // avvio fase raccolta dati e invio con adapter + iobObj.getAndSend(gatherCycle.LF); + } } - // LiveLog - if (!string.IsNullOrWhiteSpace(currDispData.newLiveLogData)) + + private void checkVerySlowData() { - logWatcher = currDispData.newLiveLogData; + verySlowCount--; + if (verySlowCount <= 0) + { + verySlowCount = utils.CRI("verySlowCount"); + // avvio fase raccolta dati e invio con adapter + iobObj.getAndSend(gatherCycle.VLF); + } } - // semafori - if (currDispData.semOut != Semaforo.ND) + + /// + /// Chiusura adapter + /// + private void closeAdapter() { - //aggiorno comunque! - sOUT = currDispData.semOut; + fermaTutto(true, false, true, false); } - if (currDispData.semIn != Semaforo.ND) + + /// + /// Ferma tutti i componenti adapter + update buttons + /// + /// indica se fermare il timer (gather) principale (solo se non si chiude) + /// indica se tentare di riconnettersi + /// indica se sia richeisto di SVUOTARE le code delel info + /// indica se si debba aggiornare la form (no se si sta chiudendo...) + private void fermaTutto(bool stopTimer, bool tryRestart, bool forceDequeue, bool updateForm) { - //aggiorno comunque! - sIN = currDispData.semIn; + iobObj.stopAdapter(tryRestart, forceDequeue); + // salvo! + savePersistLayer(utils.defPersLayerFile); + savePersistLayer(utils.histPersLayerFile); + + stop.Enabled = false; + start.Enabled = true; + restart.Enabled = false; + + if (stopTimer) + { + gather.Enabled = false; + iobObj.tryDisconnect(); + } + + newDisplayData currDispData = new newDisplayData(); + currDispData.semIn = Semaforo.SS; + currDispData.semOut = Semaforo.SS; + if (updateForm) + { + updateFormDisplay(currDispData); + } } - } - } - #endregion Area BackGroundWorker - - #region Area gestione controlli threadSafe - - private delegate void SafeCallDelegate(string text); - - public void WriteTextSafe(string text) - { - if (lblOutMessage3.InvokeRequired) - { - var d = new SafeCallDelegate(WriteTextSafe); - lblOutMessage3.Invoke(d, new object[] { text }); - } - else - { - lblOutMessage3.Text = text; - } - } - - #endregion Area gestione controlli threadSafe - - - - #region Protected Properties - - /// - /// Valore protected comunicazione PLC - /// - protected bool _commPlcActive { get; set; } = false; - - /// - /// Valore protetto stato comunicazione - /// - protected int _commSrvActive { get; set; } = 0; - - /// - /// Valore protected semaforo IN - /// - protected Semaforo _sIN { get; set; } = Semaforo.ND; - - /// - /// Valore protected semaforo OUT - /// - protected Semaforo _sOUT { get; set; } = Semaforo.ND; - - protected int maxAlQueue { get; set; } - - protected int maxEvQueue { get; set; } - - protected int maxFlQueue { get; set; } - - protected int maxMsQueue { get; set; } - - protected int qAlLen { get; set; } - - protected int qEvLen { get; set; } - - protected int qFlLen { get; set; } - - protected int qMsLen { get; set; } - - protected int totQueue - { - get - { - return qEvLen + qFlLen + qAlLen + qMsLen; - } - } - - #endregion Protected Properties - - public int alQueueLen - { - set - { - qAlLen = value; - lblQueueAlarmLen.Text = qAlLen.ToString(); - showQueueData(); - // se supero max precedente, ed è > 10... loggo! - if (qAlLen > maxAlQueue && qAlLen > 10) + private void gather_Tick(object sender, EventArgs e) { - maxAlQueue = qAlLen; - lgInfo($"[WARN] Coda FLog di {value} record"); + bool doLog = false; + if (iobObj != null) + { + if (iobObj.periodicLog) + { + doLog = true; + } + try + { + refreshFormData(); + // check esecuzione SendTask (VHF) COMUNQUE... + checkSendTask(); + // eseguo cicli attivi SOLO se adapter è in EFFETTIVO running... + if (iobObj.adpRunning) + { + if (iobObj.connectionOk) + { + // se richiesto faccio memory DUMP INIZIALE! + if (iobObj.doStartMemDump) + { + lgInfo("Inizio dump memoria"); + iobObj.saveMemDump(dumpType.STARTUP); + // fatto! non ripeto... + iobObj.doStartMemDump = false; + lgInfo("Finito dump memoria"); + } + // controllo se sia abilitato sampleDump della meoria (periodico) + if (iobObj.doSampleMemory) + { + checkSampleMem(); + } + // check esecuzione FastTask + checkFastTask(); + // check esecuzione NormTask + checkNormTask(); + // check esecuzione SlowTask + checkSlowTask(); + // check esecuzione AlarmSync + checkVerySlowData(); + if (utils.CRI("waitEndCycle") > 0) + { + Thread.Sleep(utils.CRI("waitEndCycle")); + } + } + else + { + DateTime dtVeto = lastStartTry.AddMilliseconds(waitRecMSec); + if (iobObj.adpTryRestart && (DateTime.Now > dtVeto)) + { + if (doLog) + { + lgInfo($"Retry Time Elapsed ({waitRecMSec} ms)--> tryConnect"); + } + lastStartTry = DateTime.Now; + iobObj.tryConnect(); + } + } + } + else + { + if (doLog) + { + lgInfo("Adapter stopped"); + } + // verifico SE debba tentare il riavvio, ovvero NON running ma adpTryRestart e non ho riprovato x oltre waitRecMSec + DateTime dtVeto = lastStartTry.AddMilliseconds(waitRecMSec); + if (iobObj.adpTryRestart && (DateTime.Now > dtVeto)) + { + lastStartTry = DateTime.Now; + avviaAdapter(chkForceDequeue.Checked); + } + } + } + catch (Exception exc) + { + lgError(string.Format("Eccezione in fase di gatherTick: {0}{1}", Environment.NewLine, exc)); + } + } } - else + + /// + /// Carica file ini della configurazione richiesta + /// + /// + private void loadIniFile(string iniConfFile) { - maxAlQueue--; - maxAlQueue = maxAlQueue < qAlLen ? qAlLen : maxAlQueue; + // out di cosa faccio... + displayTaskAndLog(string.Format("Loading iniConfFile: {0}", iniConfFile)); + // leggo file + IniFile fIni = new IniFile(iniConfFile); + + // leggo vendor e modello... + curVendor = fIni.ReadString("MACHINE", "VENDOR", "ACME"); + curModel = fIni.ReadString("MACHINE", "MODEL", "NONE"); + // verifico tipo adapter + try + { + tipoScelto = (tipoAdapter)Enum.Parse(typeof(tipoAdapter), fIni.ReadString("IOB", "CNCTYPE", "DEMO")); + } + catch (Exception exc) + { + lgError($"Eccezione in conversione tipo adapter: richiesto un tipo non codificato...{Environment.NewLine}{exc}"); + tipoScelto = tipoAdapter.ND; + } + // carivo vettore parametri opzionai + Dictionary optParRead = new Dictionary(); + string[] optParRows = fIni.ReadSection("OPTPAR"); + if (optParRows.Length > 0) + { + try + { + string[] kvp; + foreach (var item in optParRows) + { + kvp = item.Split('='); + optParRead.Add(kvp[0], kvp[1]); + } + lgInfo($"Caricati {optParRead.Count} parametri opzionali da OPTPAR"); + } + catch (Exception exc) + { + lgError(string.Format("EXCEPTION in fase di lettura OPTPAR: {0}{1}", Environment.NewLine, exc)); + } + } + // inizializzio conf IOB + IOBConf = new IobConfiguration + { + pingMsTimeout = fIni.ReadInteger("IOB", "PING_MS_TIMEOUT", 500) + , + vendor = curVendor + , + model = curModel + , + tipoIob = tipoScelto + , + optPar = optParRead + , + versIOB = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString() + , + codIOB = CurrIOB + , + cncIpAddr = fIni.ReadString("CNC", "IP", "::1") + , + cncPort = fIni.ReadString("CNC", "PORT", "0") + , + iniFileName = iniConfFile + , + cpuType = fIni.ReadString("CNC", "CPUTYPE", "") + , + rack = (short)fIni.ReadInteger("CNC", "RACK", 0) + , + slot = (short)fIni.ReadInteger("CNC", "SLOT", 0) + , + serverData = new serverMapo(fIni.ReadString("SERVER", "MPIP", "::1"), fIni.ReadString("SERVER", "MPURL", "/"), fIni.ReadString("SERVER", "CMDBASE", "/"), fIni.ReadString("SERVER", "CMDFLOG", "/"), fIni.ReadString("SERVER", "CMDALIVE", "/"), fIni.ReadString("SERVER", "CMDENABLED", "/"), fIni.ReadString("SERVER", "CMDREBO", "/"), fIni.ReadString("SERVER", "CMD_ODL_STARTED", "/IOB/getCurrOdlStart/")) + , + MAX_COUNTER_BLINK = Convert.ToInt32(fIni.ReadString("BLINK", "MAX_COUNTER_BLINK", "1")) + , + BLINK_FILT = Convert.ToInt32(fIni.ReadString("BLINK", "BLINK_FILT", "0")) + , + TCMaxDelayFactor = Convert.ToDouble(fIni.ReadString("OPTPAR", "TC_MAX_TC_FACTOR", "1.2").Replace(".", ",")) + , + TCLambda = Convert.ToDouble(fIni.ReadString("OPTPAR", "TC_LAMBDA", "0.5").Replace(".", ",")) + , + TCMaxIncrPz = Convert.ToDouble(fIni.ReadString("OPTPAR", "TC_MAX_INCR", "5").Replace(".", ",")) + }; + lgInfo($"Creato IOBConf!"); + + loadIobType(); + // avvio macchina con adapter specificato... + if (utils.CRB("autoStartOnLoad")) + { + displayTaskAndLog("Auto Starting..."); + // avvio! + avviaAdapter(chkForceDequeue.Checked); + displayTaskAndLog("Auto Started!"); + } + try + { + // segnalo reboot (programma)... metto in coda invio... + //iobObj.sendToMoonPro(urlType.FLog, "IOB INI Loaded"); + //iobObj.QueueFLog.Enqueue(iobObj.qEncodeFLog("IOB-STATUS", "IOB INI Loaded")); + } + catch (Exception exc) + { + lgError(string.Format("EXCEPTION in fase di chiamata URL di segnalazione caricamento INI file:{0}{1}", Environment.NewLine, exc)); + } } - } - get - { - return qAlLen; - } - } - /// - /// Visualizzazione stato di comunicazione attiva con PLC - /// - public bool commPlcActive - { - get - { - return _commPlcActive; - } - set - { - _commPlcActive = value; - // se true --> comunica/verde, altrimenti grigio - lblCNC.ForeColor = value ? Color.SeaGreen : Color.Black; - statusStrip1.Refresh(); - } - } - - /// - /// Visualizzazione stato di comunicazione attiva con PLC: - /// 0 = NO PING - /// 1 = PING OK - /// 2 = IOB enabled - /// - public int commSrvActive - { - get - { - return _commSrvActive; - } - set - { - _commSrvActive = value; - switch (value) + private void refreshFormData() { - case 0: - lblSrvUrl.ForeColor = Color.Red; - break; - - case 1: - lblSrvUrl.ForeColor = Color.OrangeRed; - break; - - case 2: - lblSrvUrl.ForeColor = Color.SeaGreen; - break; - - default: - break; + // aggiorno visualizzazioni varie in form... + evQueueLen = iobObj.QueueIN.Count; + flQueueLen = iobObj.QueueFLog.Count; + alQueueLen = iobObj.QueueAlarm.Count; + msQueueLen = iobObj.QueueMessages.Count; + // aggiorno labels counters... + counterIob = $"pz IOB {iobObj.contapezziIOB}"; + counterMac = $"pz PLC {iobObj.contapezziPLC}"; + // verifico IOB status + IobWinStatus currIobStatus = new IobWinStatus() + { + CodIob = iobObj.cIobConf.codIOB, + queueEvLen = evQueueLen, + queueFlLen = flQueueLen, + queueAlLen = alQueueLen, + queueMsLen = msQueueLen, + counterIOB = iobObj.contapezziIOB, + counterMAC = iobObj.contapezziPLC, + lastUpdate = lastIobStatus.lastUpdate, + online = utils.IOB_Online, + lastDataIn = iobObj.lastReadPLC + }; + // se diverso SALVO! + if (lastIobStatus.online != currIobStatus.online || lastIobStatus.lastDataIn != currIobStatus.lastDataIn || lastIobStatus.counterIOB != currIobStatus.counterIOB || lastIobStatus.counterMAC != currIobStatus.counterMAC || lastIobStatus.queueEvLen != currIobStatus.queueEvLen || lastIobStatus.queueFlLen != currIobStatus.queueFlLen || lastIobStatus.queueAlLen != currIobStatus.queueAlLen || lastIobStatus.queueMsLen != currIobStatus.queueMsLen) + { + // aggiorno data + currIobStatus.lastUpdate = DateTime.Now; + // salvo su redis e in obj corrente + iobObj.redisMan.iobStatus = currIobStatus; + lastIobStatus = currIobStatus; + } + // se diverso SALVO MP IO status + if (lastSrvStatus.online != utils.MPIO_Online) + { + // aggiorno + ServerMpStatus currSrvStatus = iobObj.redisMan.servStatus; + currSrvStatus.online = utils.MPIO_Online; + currSrvStatus.lastUpdate = DateTime.Now; + // salvo su redis e in obj corrente + iobObj.redisMan.servStatus = currSrvStatus; + lastSrvStatus = currSrvStatus; + } } - statusStrip1.Refresh(); - } - } - public string counterIob - { - get - { - return lblPzCountIob.Text; - } - set - { - lblPzCountIob.Text = value; - } - } + #endregion gestione metodi specifici FORM - public string counterMac - { - get - { - return lblPzCountMac.Text; - } - set - { - lblPzCountMac.Text = value; - } - } + #region Area BackGroundWorker - /// - /// Stringa dati monitoraggio mostrata (1 SX)... - /// - public string dataMonitor_0 - { - get - { - return lblRawData.Text; - } - set - { - lblRawData.Text = value; - } - } - - /// - /// Stringa dati monitoraggio mostrata (1 SX)... - /// - public string dataMonitor_1 - { - get - { - return lblOutMessage.Text; - } - set - { - lblOutMessage.Text = value; - } - } - - /// - /// Stringa dati monitoraggio mostrata (2 centro)... - /// - public string dataMonitor_2 - { - get - { - return lblOutMessage2.Text; - } - set - { - lblOutMessage2.Text = value; - } - } - - /// - /// Stringa dati monitoraggio mostrata (3 dx)... - /// - public string dataMonitor_3 - { - get - { - return lblOutMessage3.Text; - } - set - { - lblOutMessage3.Text = value; - } - } - - /// - /// label del numero di record processati (libera) - /// - public string dataProcLabel - { - get - { - return lblDataProc.Text; - } - set - { - lblDataProc.Text = value; - } - } - - public bool enableEditMes2Plc { get; set; } - - public int evQueueLen - { - set - { - qEvLen = value; - lblQueueLen.Text = qEvLen.ToString(); - showQueueData(); - // se supero max precedente, ed è > 10... loggo! - if (qEvLen > maxEvQueue && qEvLen > 10) + /// + /// Effettua update form una volta ricevuto OBJ che contiene le varie innovazioni... + /// + /// + public void updateFormDisplay(newDisplayData currDispData) { - maxEvQueue = qEvLen; - lgInfo($"[WARN] Coda EV di {value} record"); + // ciclo x ogni oggetto x caricare le innovazioni... + if (currDispData != null && currDispData.hasData) + { + // RealTime display + if (!string.IsNullOrWhiteSpace(currDispData.newInData)) + { + dataMonitor_0 = limitLine2show($"{currDispData.newInData}{Environment.NewLine}{dataMonitor_0}"); + } + if (!string.IsNullOrWhiteSpace(currDispData.newSignalData)) + { + dataMonitor_1 = limitLine2show($"{currDispData.newSignalData}{Environment.NewLine}{dataMonitor_1}"); + } + if (!string.IsNullOrWhiteSpace(currDispData.newFLogData)) + { + dataMonitor_3 = limitLine2show($"{currDispData.newFLogData}{Environment.NewLine}{dataMonitor_3}"); + } + if (!string.IsNullOrWhiteSpace(currDispData.newUrlCallData)) + { + dataMonitor_2 = limitLine2show($"{currDispData.newUrlCallData}{Environment.NewLine}{dataMonitor_2}"); + } + + // Bitmap lettura attuale + if (currDispData.counter >= 0) + { + lblCounter.Text = currDispData.counter.ToString(); + } + // Bitmap lettura attuale + if (!string.IsNullOrWhiteSpace(currDispData.currBitmap)) + { + lblBitmap.Text = currDispData.currBitmap; + lblBitmap.Refresh(); + } + // LiveLog + if (!string.IsNullOrWhiteSpace(currDispData.newLiveLogData)) + { + logWatcher = currDispData.newLiveLogData; + } + // semafori + if (currDispData.semOut != Semaforo.ND) + { + //aggiorno comunque! + sOUT = currDispData.semOut; + } + if (currDispData.semIn != Semaforo.ND) + { + //aggiorno comunque! + sIN = currDispData.semIn; + } + } } - else + + protected override void Dispose(bool disposing) { - maxEvQueue--; - maxEvQueue = maxEvQueue < qEvLen ? qEvLen : maxEvQueue; + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); } - } - get - { - return qEvLen; - } - } - public int flQueueLen - { - set - { - qFlLen = value; - lblQueueFLogLen.Text = qFlLen.ToString(); - showQueueData(); - // se supero max precedente, ed è > 10... loggo! - if (qFlLen > maxFlQueue && qFlLen > 10) + #endregion Area BackGroundWorker + + #region Area gestione controlli threadSafe + + private delegate void SafeCallDelegate(string text); + + public void WriteTextSafe(string text) { - maxFlQueue = qFlLen; - lgInfo($"[WARN] Coda FLog di {value} record"); + if (lblOutMessage3.InvokeRequired) + { + var d = new SafeCallDelegate(WriteTextSafe); + lblOutMessage3.Invoke(d, new object[] { text }); + } + else + { + lblOutMessage3.Text = text; + } } - else + + #endregion Area gestione controlli threadSafe + + #region Protected Properties + + /// + /// Valore protected comunicazione PLC + /// + protected bool _commPlcActive { get; set; } = false; + + /// + /// Valore protetto stato comunicazione + /// + protected int _commSrvActive { get; set; } = 0; + + /// + /// Valore protected semaforo IN + /// + protected Semaforo _sIN { get; set; } = Semaforo.ND; + + /// + /// Valore protected semaforo OUT + /// + protected Semaforo _sOUT { get; set; } = Semaforo.ND; + + protected int maxAlQueue { get; set; } + + protected int maxEvQueue { get; set; } + + protected int maxFlQueue { get; set; } + + protected int maxMsQueue { get; set; } + + protected int qAlLen { get; set; } + + protected int qEvLen { get; set; } + + protected int qFlLen { get; set; } + + protected int qMsLen { get; set; } + + protected int totQueue { - maxFlQueue--; - maxFlQueue = maxFlQueue < qFlLen ? qFlLen : maxFlQueue; + get + { + return qEvLen + qFlLen + qAlLen + qMsLen; + } } - } - get - { - return qFlLen; - } - } - public int msQueueLen - { - set - { - qMsLen = value; - lblQueueMessLen.Text = qMsLen.ToString(); - showQueueData(); - // se supero max precedente, ed è > 10... loggo! - if (qMsLen > maxMsQueue && qMsLen > 10) + #endregion Protected Properties + + public int alQueueLen { - maxMsQueue = qMsLen; - lgInfo($"[WARN] Coda FLog di {value} record"); + set + { + qAlLen = value; + lblQueueAlarmLen.Text = qAlLen.ToString(); + showQueueData(); + // se supero max precedente, ed è > 10... loggo! + if (qAlLen > maxAlQueue && qAlLen > 10) + { + maxAlQueue = qAlLen; + lgInfo($"[WARN] Coda FLog di {value} record"); + } + else + { + maxAlQueue--; + maxAlQueue = maxAlQueue < qAlLen ? qAlLen : maxAlQueue; + } + } + get + { + return qAlLen; + } } - else + + /// + /// Visualizzazione stato di comunicazione attiva con PLC + /// + public bool commPlcActive { - maxMsQueue--; - maxMsQueue = maxMsQueue < qMsLen ? qMsLen : maxMsQueue; + get + { + return _commPlcActive; + } + set + { + _commPlcActive = value; + // se true --> comunica/verde, altrimenti grigio + lblCNC.ForeColor = value ? Color.SeaGreen : Color.Black; + statusStrip1.Refresh(); + } } - } - get - { - return qMsLen; - } - } - /// - /// Numero max linee da mostrare (da controllo)... - /// - public int nLine2show - { - get - { - int answ = 5; - try + /// + /// Visualizzazione stato di comunicazione attiva con PLC: + /// 0 = NO PING + /// 1 = PING OK + /// 2 = IOB enabled + /// + public int commSrvActive { - Int32.TryParse(nLines.Text, out answ); + get + { + return _commSrvActive; + } + set + { + _commSrvActive = value; + switch (value) + { + case 0: + lblSrvUrl.ForeColor = Color.Red; + break; + + case 1: + lblSrvUrl.ForeColor = Color.OrangeRed; + break; + + case 2: + lblSrvUrl.ForeColor = Color.SeaGreen; + break; + + default: + break; + } + statusStrip1.Refresh(); + } } - catch - { } - return answ; - } - set - { - nLines.Text = value.ToString(); - } - } - /// - /// Imposta COLORE SFONDO x Semaforo IN - /// - public Semaforo sIN - { - get - { - return _sIN; - } - set - { - _sIN = value; - bIN.BackColor = decSemaforo(value); - bIN.Refresh(); - } - } + public string counterIob + { + get + { + return lblPzCountIob.Text; + } + set + { + lblPzCountIob.Text = value; + } + } - /// - /// Imposta COLORE SFONDO x Semaforo OUT - /// - public Semaforo sOUT - { - get - { - return _sOUT; - } - set - { - _sOUT = value; - bOUT.BackColor = decSemaforo(value); - bOUT.Refresh(); - } - } + public string counterMac + { + get + { + return lblPzCountMac.Text; + } + set + { + lblPzCountMac.Text = value; + } + } - private void BtnOpenLog_Click(object sender, EventArgs e) - { - try - { - string logPath = $"{System.AppDomain.CurrentDomain.BaseDirectory}logs\\{CurrIOB}\\{DateTime.Today:yyyy-MM-dd}.log"; - Process.Start(logPath); - } - catch (Exception exc) - { - lgError($"Eccezione in show log (MAIN):{Environment.NewLine}{exc}"); - } - } + /// + /// Stringa dati monitoraggio mostrata (1 SX)... + /// + public string dataMonitor_0 + { + get + { + return lblRawData.Text; + } + set + { + lblRawData.Text = value; + } + } - private void BtnSendPLC_Click(object sender, EventArgs e) - { - // invia a MES il parametro selezionato (es ART / ODL / PRG NAME, come task2exe..) - Dictionary forcedTask = new Dictionary(); - // guardo i parametri... - if (txtValue.Text != "") - { - forcedTask.Add(cmbParamValues.SelectedValue.ToString(), txtValue.Text); - } + /// + /// Stringa dati monitoraggio mostrata (1 SX)... + /// + public string dataMonitor_1 + { + get + { + return lblOutMessage.Text; + } + set + { + lblOutMessage.Text = value; + } + } + + /// + /// Stringa dati monitoraggio mostrata (2 centro)... + /// + public string dataMonitor_2 + { + get + { + return lblOutMessage2.Text; + } + set + { + lblOutMessage2.Text = value; + } + } + + /// + /// Stringa dati monitoraggio mostrata (3 dx)... + /// + public string dataMonitor_3 + { + get + { + return lblOutMessage3.Text; + } + set + { + lblOutMessage3.Text = value; + } + } + + /// + /// label del numero di record processati (libera) + /// + public string dataProcLabel + { + get + { + return lblDataProc.Text; + } + set + { + lblDataProc.Text = value; + } + } + + public bool enableEditMes2Plc { get; set; } + + public int evQueueLen + { + set + { + qEvLen = value; + lblQueueLen.Text = qEvLen.ToString(); + showQueueData(); + // se supero max precedente, ed è > 10... loggo! + if (qEvLen > maxEvQueue && qEvLen > 10) + { + maxEvQueue = qEvLen; + lgInfo($"[WARN] Coda EV di {value} record"); + } + else + { + maxEvQueue--; + maxEvQueue = maxEvQueue < qEvLen ? qEvLen : maxEvQueue; + } + } + get + { + return qEvLen; + } + } + + public int flQueueLen + { + set + { + qFlLen = value; + lblQueueFLogLen.Text = qFlLen.ToString(); + showQueueData(); + // se supero max precedente, ed è > 10... loggo! + if (qFlLen > maxFlQueue && qFlLen > 10) + { + maxFlQueue = qFlLen; + lgInfo($"[WARN] Coda FLog di {value} record"); + } + else + { + maxFlQueue--; + maxFlQueue = maxFlQueue < qFlLen ? qFlLen : maxFlQueue; + } + } + get + { + return qFlLen; + } + } + + public int msQueueLen + { + set + { + qMsLen = value; + lblQueueMessLen.Text = qMsLen.ToString(); + showQueueData(); + // se supero max precedente, ed è > 10... loggo! + if (qMsLen > maxMsQueue && qMsLen > 10) + { + maxMsQueue = qMsLen; + lgInfo($"[WARN] Coda FLog di {value} record"); + } + else + { + maxMsQueue--; + maxMsQueue = maxMsQueue < qMsLen ? qMsLen : maxMsQueue; + } + } + get + { + return qMsLen; + } + } + + /// + /// Numero max linee da mostrare (da controllo)... + /// + public int nLine2show + { + get + { + int answ = 5; + try + { + Int32.TryParse(nLines.Text, out answ); + } + catch + { } + return answ; + } + set + { + nLines.Text = value.ToString(); + } + } + + /// + /// Imposta COLORE SFONDO x Semaforo IN + /// + public Semaforo sIN + { + get + { + return _sIN; + } + set + { + _sIN = value; + bIN.BackColor = decSemaforo(value); + bIN.Refresh(); + } + } + + /// + /// Imposta COLORE SFONDO x Semaforo OUT + /// + public Semaforo sOUT + { + get + { + return _sOUT; + } + set + { + _sOUT = value; + bOUT.BackColor = decSemaforo(value); + bOUT.Refresh(); + } + } + + /// + /// Decodifica colore da valore semaforico + /// + /// + /// + public static Color decSemaforo(Semaforo valore) + { + Color colore = Color.LightGray; + switch (valore) + { + case Semaforo.SV: + colore = Color.LightGreen; + break; + + case Semaforo.SG: + colore = Color.LightGoldenrodYellow; + break; + + case Semaforo.SR: + colore = Color.Red; + break; + + case Semaforo.SS: + colore = Color.DarkGray; + break; + + default: + colore = Color.LightGray; + break; + } + return colore; + } + + /// + /// Avvio l'adapter + /// + /// indica se sia richeisto di SVUOTARE le code delel info + public void avviaAdapter(bool resetQueue) + { + displayTaskAndLog("Adapter starting"); + // se NON sta girando... + if (!iobObj.adpRunning) + { + iobObj.startAdapter(resetQueue); + displayTaskAndLog("Adapter started!"); + + // fix buttons start/stop/dump + start.Enabled = false; + stop.Enabled = true; + restart.Enabled = true; + + displayTaskAndLog("Start Timers"); + // inizializzo contatori fast/mid/slow + fastCount = utils.CRI("fastCount"); + normCount = utils.CRI("normCount"); + slowCount = utils.CRI("slowCount"); + verySlowCount = utils.CRI("verySlowCount"); + displayTaskAndLog("Adapter Running..."); + // init max queue + maxEvQueue = 1; + maxFlQueue = 1; + + try + { + // segnalo reboot (programma)... + iobObj.QueueFLog.Enqueue(iobObj.qEncodeFLog("IOB-STATUS", "IOB Started")); + } + catch (Exception exc) + { + lgError(string.Format("EXCEPTION in fase di chiamata URL di segnalazione AVVIO IOB:{0}{1}", Environment.NewLine, exc)); + } + } + else + { + displayTaskAndLog("Adapter STILL Running..."); + } + } + + /// + /// Ferma l'adapter + /// + /// determina se si debba tentare riavvio automatico (per caduta connessione) + /// indica se sia richeisto di SVUOTARE le code delel info + /// indica se aggiornare la form prima di fermare + public void fermaAdapter(bool tryRestart, bool forceDequeue, bool updateForm) + { + fermaTutto(false, tryRestart, forceDequeue, updateForm); + } + + /// + /// MOstra info su coda complessiva + /// + protected void showQueueData() + { + lblQueueLenTop.Text = totQueue == 0 ? "realtime" : $"ev: {qEvLen} | flog: {qFlLen} | tot: {totQueue}"; + } + + private void BtnOpenLog_Click(object sender, EventArgs e) + { + try + { + string logPath = $"{System.AppDomain.CurrentDomain.BaseDirectory}logs\\{CurrIOB}\\{DateTime.Today:yyyy-MM-dd}.log"; + Process.Start(logPath); + } + catch (Exception exc) + { + lgError($"Eccezione in show log (MAIN):{Environment.NewLine}{exc}"); + } + } + + private void BtnSendPLC_Click(object sender, EventArgs e) + { + // invia a MES il parametro selezionato (es ART / ODL / PRG NAME, come task2exe..) + Dictionary forcedTask = new Dictionary(); + // guardo i parametri... + if (txtValue.Text != "") + { + forcedTask.Add(cmbParamValues.SelectedValue.ToString(), txtValue.Text); + } #if false // accodo SE !="" if (currItemCode != "") @@ -1302,387 +1397,300 @@ namespace IOB_WIN forcedTask.Add("setProg", currPrgName); } #endif - // chiedo esecuzione task! - iobObj.processTask(forcedTask); - toggleEditMes2Plc(); - } + // chiedo esecuzione task! + iobObj.processTask(forcedTask); + toggleEditMes2Plc(); + } - private void checkEditMes2Plc() - { - cmbParamValues.Enabled = enableEditMes2Plc; - txtValue.Enabled = enableEditMes2Plc; - if (enableEditMes2Plc) - { - // aggiorno (se possibile) i parametri selezionabili... - fixComboParameters(); - } - } - - private void ChkEdit_CheckedChanged(object sender, EventArgs e) - { - toggleEditMes2Plc(); - } - - private void displTimer_Tick(object sender, EventArgs e) - { - } - - private void fixComboParameters() - { - if (iobObj != null) - { - if (iobObj.memMap != null) + private void checkEditMes2Plc() { - if (iobObj.memMap.mMapWrite != null) - { - if (iobObj.memMap.mMapWrite.Count > 0) + cmbParamValues.Enabled = enableEditMes2Plc; + txtValue.Enabled = enableEditMes2Plc; + if (enableEditMes2Plc) { - List parametri = new List(); - foreach (var item in iobObj.memMap.mMapWrite) - { - parametri.Add(item.Key); - } - cmbParamValues.DataSource = parametri; + // aggiorno (se possibile) i parametri selezionabili... + fixComboParameters(); } - } } - } - } - /// - /// GEstione evento refresh - /// - /// - /// - private void IobObj_eh_refreshed(object sender, iobRefreshedEventArgs e) - { - // aggiorno! - updateFormDisplay(e.DisplayDataObject); - } - - /// - /// carica IOB richiesto - /// - private void loadIobType() - { - switch (tipoScelto) - { - case tipoAdapter.SIMULA: - iobObj = new IobSimula(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.FANUC: - iobObj = new IobFanuc(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.KAWASAKI: - iobObj = new IobKawasaki(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.MTConnect: - iobObj = new IobMTC(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.OMRON: - iobObj = new IobOmron(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.OSAI_OPEN: - case tipoAdapter.OSAI_CNDEX: - case tipoAdapter.OSAI_VB6: - // versione CVCncLib - iobObj = new IobOSAI(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.SIEMENS: - iobObj = new IobSiemens(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.SIEMENS_APROCHIM: - iobObj = new IobSiemensAprochim(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.SIEMENS_AT2001: - iobObj = new IobSiemensAt2001(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.SIEMENS_COMUR: - iobObj = new IobSiemensComur(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.SIEMENS_FAPE: - iobObj = new IobSiemensFape(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.SIEMENS_INGENIA: - iobObj = new IobSiemensIngenia(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.SIEMENS_LASCO: - iobObj = new IobSiemensLasco(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.SIEMENS_PRESSOIL_CEI: - iobObj = new IobSiemensPressoilCei(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.SIEMENS_SAET: - iobObj = new IobSiemensSaet(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.SIEMENS_SIMEC: - iobObj = new IobSiemensSimec(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.SIEMENS_TORRI: - iobObj = new IobSiemensTorri(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.WPS: - iobObj = new IobWPS(this, IOBConf); - start.Enabled = true; - break; - - case tipoAdapter.ND: - default: - iobObj = new IobSimula(this, IOBConf); - start.Enabled = false; - break; - } - lblCNC.Text = $"CNC: {IOBConf.tipoIob} [{IOBConf.cncIpAddr}:{IOBConf.cncPort}]"; - lblSrvUrl.Text = $"SRV: {IOBConf.serverData.MPIP} | URL: {IOBConf.serverData.MPURL}{IOBConf.serverData.CMDBASE}"; - - // aggancio evento refresh - iobObj.eh_refreshed += IobObj_eh_refreshed; - - // carico i default values su interfaccia - setDefaults(); - - displayTaskAndLog(string.Format("Caricata conf per adapter {0}", tipoScelto)); - } - - private void mLoadConf_Click(object sender, EventArgs e) - { - // mostro selettore file x leggere adapter.. - OpenFileDialog openFileDial = new OpenFileDialog(); - - // directory iniziale - openFileDial.InitialDirectory = utils.confDir; // string.Format(@"{0}\{1}", Application.StartupPath, utils.CRS("dataConfPath")); - // Set filter options and filter index. - openFileDial.Filter = "INI Files (.ini)|*.ini|All Files (*.*)|*.*"; - openFileDial.FilterIndex = 1; - // altre opzioni - openFileDial.Multiselect = false; - - // Call the ShowDialog method to show the dialog box. - DialogResult userClickedOK = openFileDial.ShowDialog(); - - // Process input if the user clicked OK. - if (userClickedOK == DialogResult.OK) - { - string iniConfFile = openFileDial.FileName; - loadIniFile(iniConfFile); - lgInfo("INI LOADED"); - } - } - - /// - /// Button restart - /// - /// - /// - private void restart_Click(object sender, EventArgs e) - { - string message = "Attenzione: con l'operazione di reset veranno persi (e non inviati) i dati eventualmente accumulati (indipendentemente dalla selezione del checkbox 'svuota coda')."; - string caption = "Conferma Reset Dati IOB"; - MessageBoxButtons buttons = MessageBoxButtons.YesNo; - DialogResult result; - - // verifica con messagebox - result = MessageBox.Show(message, caption, buttons); - // solo se ho conferma da utente - if (result == DialogResult.Yes) - { - // faccio stop... SENZA inviare - fermaAdapter(false, false, true); - displayTaskAndLog("RESTARTING: Adapter Stopped"); - // rileggo INI - loadIniFile(defConfFilePath); - displayTaskAndLog("RESTARTING: Ini File Reloaded"); - // faccio start... CON RESET delel code - avviaAdapter(true); - displayTaskAndLog("RESTARTING: Adapter Started"); - // resetto i data monitor... - dataMonitor_0 = ""; - dataMonitor_1 = ""; - dataMonitor_2 = ""; - dataMonitor_3 = ""; - } - } - - /// - /// impostazione valori defaults - /// - private void setDefaults() - { - stop.Enabled = false; - - evQueueLen = 0; - flQueueLen = 0; - nLine2show = utils.CRI("numRowConsole"); - } - - private void splitContainer1_Panel1_Paint(object sender, PaintEventArgs e) - { - } - - /// - /// Avvio dell'adapter - /// - /// - /// - private void start_Click(object sender, EventArgs e) - { - avviaAdapter(chkForceDequeue.Checked); - // salvo che ho avviato adapter - lgInfo("Completato LOAD Adapter"); - } - - /// - /// fermata dell'adapter - /// - /// - /// - private void stop_Click(object sender, EventArgs e) - { - fermaAdapter(false, chkForceDequeue.Checked, true); - // salvo che ho fermato adapter - lgInfo("UNLOAD Adapter"); - } - - private void TabData_Selected(object sender, TabControlEventArgs e) - { - } - - private void toggleEditMes2Plc() - { - // abilita i campi --> PLC per editing - enableEditMes2Plc = !enableEditMes2Plc; - checkEditMes2Plc(); - } - - /// - /// MOstra info su coda complessiva - /// - protected void showQueueData() - { - lblQueueLenTop.Text = totQueue == 0 ? "realtime" : $"ev: {qEvLen} | flog: {qFlLen} | tot: {totQueue}"; - } - - /// - /// Decodifica colore da valore semaforico - /// - /// - /// - public static Color decSemaforo(Semaforo valore) - { - Color colore = Color.LightGray; - switch (valore) - { - case Semaforo.SV: - colore = Color.LightGreen; - break; - - case Semaforo.SG: - colore = Color.LightGoldenrodYellow; - break; - - case Semaforo.SR: - colore = Color.Red; - break; - - case Semaforo.SS: - colore = Color.DarkGray; - break; - - default: - colore = Color.LightGray; - break; - } - return colore; - } - - /// - /// Avvio l'adapter - /// - /// indica se sia richeisto di SVUOTARE le code delel info - public void avviaAdapter(bool resetQueue) - { - displayTaskAndLog("Adapter starting"); - // se NON sta girando... - if (!iobObj.adpRunning) - { - iobObj.startAdapter(resetQueue); - displayTaskAndLog("Adapter started!"); - - // fix buttons start/stop/dump - start.Enabled = false; - stop.Enabled = true; - restart.Enabled = true; - - displayTaskAndLog("Start Timers"); - // inizializzo contatori fast/mid/slow - fastCount = utils.CRI("fastCount"); - normCount = utils.CRI("normCount"); - slowCount = utils.CRI("slowCount"); - verySlowCount = utils.CRI("verySlowCount"); - displayTaskAndLog("Adapter Running..."); - // init max queue - maxEvQueue = 1; - maxFlQueue = 1; - - try + private void ChkEdit_CheckedChanged(object sender, EventArgs e) { - // segnalo reboot (programma)... - iobObj.QueueFLog.Enqueue(iobObj.qEncodeFLog("IOB-STATUS", "IOB Started")); + toggleEditMes2Plc(); } - catch (Exception exc) - { - lgError(string.Format("EXCEPTION in fase di chiamata URL di segnalazione AVVIO IOB:{0}{1}", Environment.NewLine, exc)); - } - } - else - { - displayTaskAndLog("Adapter STILL Running..."); - } - } - /// - /// Ferma l'adapter - /// - /// determina se si debba tentare riavvio automatico (per caduta connessione) - /// indica se sia richeisto di SVUOTARE le code delel info - /// indica se aggiornare la form prima di fermare - public void fermaAdapter(bool tryRestart, bool forceDequeue, bool updateForm) - { - fermaTutto(false, tryRestart, forceDequeue, updateForm); + private void displTimer_Tick(object sender, EventArgs e) + { + } + + private void fixComboParameters() + { + if (iobObj != null) + { + if (iobObj.memMap != null) + { + if (iobObj.memMap.mMapWrite != null) + { + if (iobObj.memMap.mMapWrite.Count > 0) + { + List parametri = new List(); + foreach (var item in iobObj.memMap.mMapWrite) + { + parametri.Add(item.Key); + } + cmbParamValues.DataSource = parametri; + } + } + } + } + } + + /// + /// GEstione evento refresh + /// + /// + /// + private void IobObj_eh_refreshed(object sender, iobRefreshedEventArgs e) + { + // aggiorno! + updateFormDisplay(e.DisplayDataObject); + } + + /// + /// carica IOB richiesto + /// + private void loadIobType() + { + switch (tipoScelto) + { + case tipoAdapter.SIMULA: + iobObj = new IobSimula(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.FILE_GEN: + iobObj = new IobFile(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.FILE_EUROM63: + iobObj = new IobFileEurom63(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.FANUC: + iobObj = new IobFanuc(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.KAWASAKI: + iobObj = new IobKawasaki(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.MTConnect: + iobObj = new IobMTC(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.OMRON: + iobObj = new IobOmron(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.OSAI_OPEN: + case tipoAdapter.OSAI_CNDEX: + case tipoAdapter.OSAI_VB6: + // versione CVCncLib + iobObj = new IobOSAI(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.SIEMENS: + iobObj = new IobSiemens(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.SIEMENS_APROCHIM: + iobObj = new IobSiemensAprochim(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.SIEMENS_AT2001: + iobObj = new IobSiemensAt2001(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.SIEMENS_COMUR: + iobObj = new IobSiemensComur(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.SIEMENS_FAPE: + iobObj = new IobSiemensFape(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.SIEMENS_INGENIA: + iobObj = new IobSiemensIngenia(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.SIEMENS_LASCO: + iobObj = new IobSiemensLasco(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.SIEMENS_PRESSOIL_CEI: + iobObj = new IobSiemensPressoilCei(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.SIEMENS_SAET: + iobObj = new IobSiemensSaet(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.SIEMENS_SIMEC: + iobObj = new IobSiemensSimec(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.SIEMENS_TORRI: + iobObj = new IobSiemensTorri(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.WPS: + iobObj = new IobWPS(this, IOBConf); + start.Enabled = true; + break; + + case tipoAdapter.ND: + default: + iobObj = new IobSimula(this, IOBConf); + start.Enabled = false; + break; + } + lblCNC.Text = $"CNC: {IOBConf.tipoIob} [{IOBConf.cncIpAddr}:{IOBConf.cncPort}]"; + lblSrvUrl.Text = $"SRV: {IOBConf.serverData.MPIP} | URL: {IOBConf.serverData.MPURL}{IOBConf.serverData.CMDBASE}"; + + // aggancio evento refresh + iobObj.eh_refreshed += IobObj_eh_refreshed; + + // carico i default values su interfaccia + setDefaults(); + + displayTaskAndLog(string.Format("Caricata conf per adapter {0}", tipoScelto)); + } + + private void mLoadConf_Click(object sender, EventArgs e) + { + // mostro selettore file x leggere adapter.. + OpenFileDialog openFileDial = new OpenFileDialog(); + + // directory iniziale + openFileDial.InitialDirectory = utils.confDir; // string.Format(@"{0}\{1}", Application.StartupPath, utils.CRS("dataConfPath")); + // Set filter options and filter index. + openFileDial.Filter = "INI Files (.ini)|*.ini|All Files (*.*)|*.*"; + openFileDial.FilterIndex = 1; + // altre opzioni + openFileDial.Multiselect = false; + + // Call the ShowDialog method to show the dialog box. + DialogResult userClickedOK = openFileDial.ShowDialog(); + + // Process input if the user clicked OK. + if (userClickedOK == DialogResult.OK) + { + string iniConfFile = openFileDial.FileName; + loadIniFile(iniConfFile); + lgInfo("INI LOADED"); + } + } + + /// + /// Button restart + /// + /// + /// + private void restart_Click(object sender, EventArgs e) + { + string message = "Attenzione: con l'operazione di reset veranno persi (e non inviati) i dati eventualmente accumulati (indipendentemente dalla selezione del checkbox 'svuota coda')."; + string caption = "Conferma Reset Dati IOB"; + MessageBoxButtons buttons = MessageBoxButtons.YesNo; + DialogResult result; + + // verifica con messagebox + result = MessageBox.Show(message, caption, buttons); + // solo se ho conferma da utente + if (result == DialogResult.Yes) + { + // faccio stop... SENZA inviare + fermaAdapter(false, false, true); + displayTaskAndLog("RESTARTING: Adapter Stopped"); + // rileggo INI + loadIniFile(defConfFilePath); + displayTaskAndLog("RESTARTING: Ini File Reloaded"); + // faccio start... CON RESET delel code + avviaAdapter(true); + displayTaskAndLog("RESTARTING: Adapter Started"); + // resetto i data monitor... + dataMonitor_0 = ""; + dataMonitor_1 = ""; + dataMonitor_2 = ""; + dataMonitor_3 = ""; + } + } + + /// + /// impostazione valori defaults + /// + private void setDefaults() + { + stop.Enabled = false; + + evQueueLen = 0; + flQueueLen = 0; + nLine2show = utils.CRI("numRowConsole"); + } + + private void splitContainer1_Panel1_Paint(object sender, PaintEventArgs e) + { + } + + /// + /// Avvio dell'adapter + /// + /// + /// + private void start_Click(object sender, EventArgs e) + { + avviaAdapter(chkForceDequeue.Checked); + // salvo che ho avviato adapter + lgInfo("Completato LOAD Adapter"); + } + + /// + /// fermata dell'adapter + /// + /// + /// + private void stop_Click(object sender, EventArgs e) + { + fermaAdapter(false, chkForceDequeue.Checked, true); + // salvo che ho fermato adapter + lgInfo("UNLOAD Adapter"); + } + + private void TabData_Selected(object sender, TabControlEventArgs e) + { + } + + private void toggleEditMes2Plc() + { + // abilita i campi --> PLC per editing + enableEditMes2Plc = !enableEditMes2Plc; + checkEditMes2Plc(); + } } - } } \ No newline at end of file diff --git a/IOB-WIN/DATA/CONF/EM63.ini b/IOB-WIN/DATA/CONF/EM63.ini new file mode 100644 index 00000000..95c3a566 --- /dev/null +++ b/IOB-WIN/DATA/CONF/EM63.ini @@ -0,0 +1,66 @@ +;Configurazione IOB-WIN +[IOB] +;MAcchina con protocollo Euromap63 PlasticMetal NPM +CNCTYPE=FILE_EUROM63 +PING_MS_TIMEOUT=500 + +[MACHINE] +VENDOR=PlasticMetal +MODEL=MPW280SP + +[CNC] +;IP=192.168.1.55 +IP=10.74.82.253 +;IP=10.82.74.1 + +[SERVER] +MPIP=http://10.74.82.218 +;MPIP=http://192.168.1.150 +MPURL=/MP/IO +CMDBASE=/IOB/input/ +CMDFLOG=/IOB/flog/ +CMDALIVE=/IOB +CMDENABLED=/IOB/enabled/ +CMDADV1=?valore= +CMDREBO=/sendReboot.aspx?idxMacchina= + +[MEMORY] +ADDR_READ=DB0.DBB0 +ADDR_WRITE=DB0.DBB0 +SIZE_READ=1 +SIZE_WRITE=0 +;BIT0=CONN +BIT1=DB0.DBB1 +;BIT2=PZCOUNT.STD.DB700.DBW22 +BIT3=DB0.DBB3 +BIT4=DB0.DBB4 + + +[BLINK] +;MAX_COUNTER_BLINK = 30 +MAX_COUNTER_BLINK = 15 +;bit0 = 0 +;bit1 = 0 +;bit2 = 1 +;bit3 = 1 +;bit4 = 1 +;bit5 = 0 +;bit6 = 0 +;bit7 = 0 +BLINK_FILT=0 +;BLINK_FILT=28 + +[OPTPAR] +;PZCOUNT_MODE=STD.[PAR/MEM].info|BIT.indice +; attenzione memoria sempre base BYTE (1604 DW --> 6416...) +;PZCOUNT_MODE=STD.DB550.DBDW0 +PZCOUNT_MODE=NONE +DISABLE_PZCOUNT=TRUE +ENABLE_DYN_DATA=TRUE +FORCE_DYN_DATA=TRUE +; CONF variabili da recuperare in WebPage (stato macchina, contatori, variabili, ...) +LUT_CONF=EM63.json +timerIntMs=50 + +[BRANCH] +NAME=master diff --git a/IOB-WIN/DATA/CONF/EM63.json b/IOB-WIN/DATA/CONF/EM63.json new file mode 100644 index 00000000..c22410d2 --- /dev/null +++ b/IOB-WIN/DATA/CONF/EM63.json @@ -0,0 +1,179 @@ +{ + "BaseDir": "C:\\NPM_E63\\E63\\MPW280SP", + "DynData": [ + { + "key": "", + "name": "CLOCK_1", + "val": "ct4", + "unit": "DateTime", + "func": "CHANGE", + "sPeriod": 10 + }, + { + "key": "", + "name": "CLOCK_2", + "val": "ct4", + "unit": "DateTime", + "func": "SAMPLE", + "sPeriod": 10 + } + //{ + // "key": "ANALOGINPUTSR0C1", + // "val": "ANALOGINPUTSR0C2", + // "unit": "bar", + // "func": "CHANGE", + // "sPeriod": 3600 + //}, + //{ + // "key": "ANALOGINPUTSR1C1", + // "val": "ANALOGINPUTSR1C2", + // "unit": "°C", + // "func": "CHANGE", + // "sPeriod": 3600 + //}, + //{ + // "key": "ANALOGINPUTSR2C1", + // "val": "ANALOGINPUTSR2C2", + // "unit": "°C", + // "func": "CHANGE", + // "sPeriod": 3600 + //}, + //{ + // "key": "COUNTERSR0C1", + // "val": "COUNTERSR0C2", + // "unit": "ore", + // "func": "CHANGE", + // "sPeriod": 3600 + //}, + //{ + // "key": "COUNTERSR2C1", + // "val": "COUNTERSR2C2", + // "unit": "#", + // "func": "CHANGE", + // "sPeriod": 3600 + //}, + //{ + // "key": "DIGITALINPUTSR0C1", + // "val": "DIGITALINPUTSR0C2", + // "unit": "ENUM", + // "func": "CHANGE", + // "sPeriod": 3600 + //} + ], + "ActiveSessions": [ + { + "Description": "ConnectionStatus", + "SessionName": "SESS0000", + "SessionType": "IsConnected", + "ValidityMinutes": 1.0, + "FileList": [ + { + "FileName": "SESS0000.REQ", + "Path": "JOB\\SESS0000.REQ", + //"StrReplace": null, + "Type": "Req" + }, + { + "FileName": "SESS0000.JOB", + "Path": "JOB\\SESS0000.JOB", + //"StrReplace": null, + "Type": "Job" + }, + { + "FileName": "SESS0000.DAT", + "Path": "JOB\\SESS0000.DAT", + //"StrReplace": null, + "Type": "Dat" + }, + { + "FileName": "SESS0000.LOG", + "Path": "JOB\\SESS0000.LOG", + //"StrReplace": null, + "Type": "Log" + }, + { + "FileName": "SESS0000.RSP", + "Path": "JOB\\SESS0000.RSP", + //"StrReplace": null, + "Type": "Rsp" + } + ] + }, + { + "Description": "Abort All prev requests", + "SessionName": "SESS0001", + "SessionType": "AbortAll", + "ValidityMinutes": 0, + "FileList": [ + { + "FileName": "SESS0001.REQ", + "Path": "JOB\\SESS0001.REQ", + //"StrReplace": null, + "Type": "Req" + }, + { + "FileName": "SESS0001.JOB", + "Path": "JOB\\SESS0001.JOB", + //"StrReplace": null, + "Type": "Job" + }, + { + "FileName": "SESS0001.DAT", + "Path": "JOB\\SESS0001.DAT", + //"StrReplace": null, + "Type": "Dat" + }, + { + "FileName": "SESS0001.LOG", + "Path": "JOB\\SESS0001.LOG", + //"StrReplace": null, + "Type": "Log" + }, + { + "FileName": "SESS0001.RSP", + "Path": "JOB\\SESS0001.RSP", + //"StrReplace": null, + "Type": "Rsp" + } + ] + }, + { + "Description": "Set DateTime on machine at start", + "SessionName": "SESS0002", + "SessionType": "SetDateTime", + "ValidityMinutes": 0, + "FileList": [ + { + "FileName": "SESS0002.REQ", + "Path": "JOB\\SESS0002.REQ", + //"StrReplace": null, + "Type": "Req" + }, + { + "FileName": "SESS0002.JOB", + "Path": "JOB\\SESS0002.JOB", + //"StrReplace": null, + "Type": "Job" + }, + { + "FileName": "SESS0002.DAT", + "Path": "JOB\\SESS0002.DAT", + //"StrReplace": null, + "Type": "Dat" + }, + { + "FileName": "SESS0002.LOG", + "Path": "JOB\\SESS0002.LOG", + //"StrReplace": null, + "Type": "Log" + }, + { + "FileName": "SESS0002.RSP", + "Path": "JOB\\SESS0002.RSP", + //"StrReplace": null, + "Type": "Rsp" + } + ] + } + ] +} \ No newline at end of file diff --git a/IOB-WIN/IOB-WIN.csproj b/IOB-WIN/IOB-WIN.csproj index e64d62a7..efbbb7f1 100644 --- a/IOB-WIN/IOB-WIN.csproj +++ b/IOB-WIN/IOB-WIN.csproj @@ -148,6 +148,7 @@ + @@ -157,7 +158,7 @@ - + @@ -482,6 +483,12 @@ Always + + Always + + + Always + Always diff --git a/IOB-WIN/IobFileGen.cs b/IOB-WIN/IobFile.cs similarity index 89% rename from IOB-WIN/IobFileGen.cs rename to IOB-WIN/IobFile.cs index c5142351..4b77e61d 100644 --- a/IOB-WIN/IobFileGen.cs +++ b/IOB-WIN/IobFile.cs @@ -15,38 +15,25 @@ using System.Windows.Forms; namespace IOB_WIN { /// - /// Generica classe per implementare WebPageScraping (scaricamento web pages anche js-based x recupero informazioni) + /// Generica classe per implementare IOB basato su scambio FILE /// - public class IobFileGen : IobGeneric, IDisposable + public class IobFile : IobGeneric, IDisposable { /* -------------------------------------------------------------------------------- - * Controlli dotati di GENERICA pagina WEB in cui cercare e recuperare informazioni - * - * - il file di conf deve contenere l'URL di base - * - il file di conf deve contenere COSA cercare (es il "contenitore" del dato da estrarre) + * Controlli dotati di GENERICA funzionalità scambio info tramite file * * -------------------------------------------------------------------------------- */ /// - /// Pagina web da scaricare + /// Cartella di base per interscambio /// - protected string baseUri = "http://127.0.0.1"; + protected string BaseDir = @"C:\Steamware"; /// /// Array di configurazione degli oggetti da cercare x decodifica e recupero info /// protected Dictionary dataLocatorLUT; - /// - /// Driver per gestione chiamate crawling/scraping - /// - protected IWebDriver driver; - - /// - /// Elementi da recuperare nella apgina web - /// - protected IWebElement element; - /// /// Vettore della frequenza di ogni status trovato... invio ogni 100 rilevazioni (modulo 100, resto == 1) /// @@ -62,17 +49,18 @@ namespace IOB_WIN /// /// /// - public IobFileGen(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) + public IobFile(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) { - lgInfo("INIT IobWPS"); + lgInfo("INIT IobFile"); //reloadAdapterConf(); } /// /// Ricarica conf adapter... /// - private void reloadAdapterConf() + internal virtual void reloadAdapterConf() { +#if false // init obj display newDisplayData currDispData = new newDisplayData(); lgInfo("BEGIN reloadAdapterConf"); @@ -90,8 +78,8 @@ namespace IOB_WIN { monitoredItems = JsonConvert.DeserializeObject(jsonData); // salvo baseUri - baseUri = monitoredItems.SrvData.baseUri; - lgInfo($"baseUri = {baseUri}"); + baseDir = monitoredItems.SrvData.baseUri; + lgInfo($"baseUri = {baseDir}"); // imposto a zero la bitmap x riavvio! B_input = 0; // FORZO invio dati... @@ -108,13 +96,16 @@ namespace IOB_WIN } lgInfo("DONE reloadAdapterConf"); raiseRefresh(currDispData); +#endif } #region Metodi specifici (da verificare/completare in implementazione) public void Dispose() { +#if false driver.Dispose(); +#endif GC.SuppressFinalize(this); } @@ -124,8 +115,9 @@ namespace IOB_WIN /// public override Dictionary getDynData() { - lgInfo("Chiamata getDynData x IOB WebPageScraping!"); + lgInfo("Chiamata getDynData x IOB FILE!"); Dictionary outVal = new Dictionary(); +#if false try { /* ---------------------------------------------------------- @@ -162,8 +154,9 @@ namespace IOB_WIN } catch (Exception exc) { - lgError(exc, "Errore in getDynData x IOB WPS"); + lgError(exc, "Errore in getDynData x IOB FILE"); } +#endif return outVal; } @@ -185,6 +178,7 @@ namespace IOB_WIN // ciclo! try { +#if false // controllo SE il driver SIA attivo... if (driver != null) { @@ -218,12 +212,13 @@ namespace IOB_WIN { lgError("Errore: driver non pronto (null)"); } +#endif // riporto bitmap... reportRawInput(ref currDispData); } catch (Exception exc) { - lgError(exc, "Errore in readSemafori x IOB WPS"); + lgError(exc, "Errore in readSemafori x IOB FILE"); if (currDispData != null) currDispData.semIn = Semaforo.SR; } @@ -246,11 +241,13 @@ namespace IOB_WIN { try { +#if false // in primis chiudo driver... if (driver != null) { driver.Quit(); } +#endif } catch (Exception exc) { @@ -266,13 +263,12 @@ namespace IOB_WIN public override void tryConnect() { // controllo ping --> segno connected... - connectionOk = (testPingMachine == IPStatus.Success); + connectionOk = Directory.Exists(BaseDir); if (connectionOk) { +#if false try { - //var t = TaskEx.Run(() => startDriver()); - //t.Wait(); // modalità sincrona startDriver(); lgInfo("Completato start driver"); @@ -281,6 +277,7 @@ namespace IOB_WIN { lgError(exc, "Eccezione in tryConnect"); } +#endif } else { @@ -297,12 +294,14 @@ namespace IOB_WIN connectionOk = false; try { +#if false // in primis chiudo driver... if (driver != null) //if (driver != null && driver.WindowHandles.Count > 0) { driver.Quit(); } +#endif } catch (Exception exc) { @@ -344,6 +343,7 @@ namespace IOB_WIN /// private void startDriver() { +#if false if (monitoredItems.SrvData.driverName == "CHROME") { lgInfo("Starting CHROME Driver"); @@ -370,7 +370,8 @@ namespace IOB_WIN driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(20); driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(20); // imposto pagina di acquisizione - driver.Navigate().GoToUrl(baseUri); + driver.Navigate().GoToUrl(baseDir); +#endif } #endregion Metodi specifici (da verificare/completare in implementazione) diff --git a/IOB-WIN/IobFileEurom63.cs b/IOB-WIN/IobFileEurom63.cs new file mode 100644 index 00000000..26aff4e4 --- /dev/null +++ b/IOB-WIN/IobFileEurom63.cs @@ -0,0 +1,72 @@ +using IOB_UT; +using MapoSDK; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Windows.Forms; + +namespace IOB_WIN +{ + public class IobFileEurom63 : IobFile + { + /// + /// Oggetti decodificati da pagina + /// + protected Eurom63.SessionConf currentSessions; + + /// + /// Estende l'init della classe base... + /// + /// + /// + public IobFileEurom63(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) + { + lgInfo("INIT IobFileEurom63"); + } + + /// + /// Ricarica conf adapter... + /// + internal override void reloadAdapterConf() + { + // init obj display + newDisplayData currDispData = new newDisplayData(); + lgInfo("BEGIN reloadAdapterConf"); + // inizializzo LUT decodifica + string jsonConf = getOptPar("LUT_CONF"); + if (!string.IsNullOrEmpty(jsonConf)) + { + string jsonFullPath = $"{Application.StartupPath}/DATA/CONF/{jsonConf}"; + lgInfo($"Apertura file {jsonFullPath}"); + StreamReader reader = new StreamReader(jsonFullPath); + string jsonData = reader.ReadToEnd(); + if (!string.IsNullOrEmpty(jsonData)) + { + try + { + currentSessions = JsonConvert.DeserializeObject(jsonData); + + // salvo baseUri + BaseDir = currentSessions.BaseDir; + lgInfo($"baseDir = {BaseDir}"); + // imposto a zero la bitmap x riavvio! + B_input = 0; + // FORZO invio dati... + accodaSigIN(ref currDispData); + // loggo! + lgInfo($"init input bitmap to zero: {B_input}"); + } + catch (Exception exc) + { + lgError(exc, "Eccezione in decodifica conf json"); + } + } + reader.Dispose(); + } + lgInfo("DONE reloadAdapterConf"); + raiseRefresh(currDispData); + } + } +} \ No newline at end of file diff --git a/IOB-WIN/Resources/ChangeLog.html b/IOB-WIN/Resources/ChangeLog.html index 6c31df9b..7ab91d78 100644 --- a/IOB-WIN/Resources/ChangeLog.html +++ b/IOB-WIN/Resources/ChangeLog.html @@ -1,113 +1,120 @@ -

MAPO-IOB-WIN

- v: {{CURRENT-REL}} -
- Acquisitore MAPO-IOB per sistemi Windows -
- Note di rilascio: -
    -
  • - v.2.6.* → v.3.0.* -
      -
    • revisione sistema metodi invio in blocco
    • -
    • Gestione invio contapezzi in step > 1
    • -
    • Gestione eventi in blocco (indipendente e prioritario su EvBlock)
    • -
    • Gestione limite eventi memorizzabili
    • -
    • Integrazione REDIS
    • -
    • Integrazione IOB-MAN
    • -
    -
  • -
  • - v.2.5.* → v.2.6.* -
      -
    • revisione sistema timeout Ping
    • -
    • Gestione AutoODL in prod generale (non solo SIM)
    • -
    -
  • -
  • - v.2.4.* → v.2.5.* -
      -
    • Aggiunto adapter MTConnect
    • -
    • Ottimizzazione gestione SIEMENS
    • -
    -
  • -
  • - v.2.3.* → v.2.4.* -
      -
    • inserita gestione conf json x Flog acquisiti
    • -
    • gestione invio Json blocchi dati FLog
    • -
    • ottimizzazioni varie adapter Siemens
    • -
    • ottimizzazione processo svuotamento code
    • -
    • riduzione interferenza e interblocchi in fase di PLC assente
    • -
    -
  • -
  • - Ultime modifiche: -
      {{LAST-CHANGES}}
    -
  • -
  • - v.1.18.* → v.2.3.* -
      -
    • inserimento WPS x acontrolli WebPage human readable
    • -
    • fix gestione task2exe
    • -
    • aggiunte varie versioni PLC siemens
    • -
    • aggiunto PLC WPS x generiche web pages
    • -
    • revisitazione LOG ODL e contapezzi
    • -
    • modifica pagina presentazione dati (master) x resize
    • -
    • Attivazione IOB SIMULATOR per test di carico (sostituito type DEMO)
    • -
    • Aggiunto simulatore macchine MULTI pallet
    • -
    • Ottimizzazione simulatore
    • -
    • Ottimizzazioni PLC Siemens x riavvio post disconnessione (es spegnimento notturno)
    • -
    • Ottimizzazione processo chiusura in update applicazione
    • -
    • Aggiunta simulazione spegnimento con WU/CD
    • -
    -
  • -
  • - v.1.11.* → v.1.18.* -
      -
    • Inserimento controller SIEMENS con S7+ library
    • -
    • Inserimento nuove letture FANUC x programmi
    • -
    • Inserimento nuove letture FANUC x SysEx (informazioni sistema)
    • -
    • Inserimento invio FluxLog x parametri estesi (es SysEx, ProgName,...)
    • -
    • FIX visualizzazione dati FluxLog e URL inviati
    • -
    • FIX MAIN program da FANUC (non il current)
    • -
    • Inserita modalita' DUMP memoria (iniziale full + periodica)
    • -
    • Inserimento gestione contapezzi standard/checkBit in IOB.cfg
    • -
    • Inserimento contapezzi da area memoria X
    • -
    • NUOVA Gestione rami cliente e URL di update
    • -
    • Gestione modi CNC
    • -
    • Lettura dari dinamycs FANUC (feed, speed)
    • -
    • aggiunta gestione aree G0..G30 (overrides?)
    • -
    • fix errore disconnessione FANUC (allo spegnimento dl CNC) e memoria valori persistente a 1
    • -
    • fix globali x gestione log IN / FLOG + ottimizzaizone check FANUC (PING)
    • -
    • ottimizzazione fasi di restart in caso di assenza del server (evita reinvii inutili e migliora tempo ripartenza invio)
    • -
    • review procedure controllo connessione x FANUC (es Tornos II)
    • -
    • non richeide più privilegi admin x fare update
    • -
    • gestione segnali inverted
    • -
    • completata gestione configurabilità parametrica segnali (Tornos, CMZ, Biglia)
    • -
    • revisitazione LOG x distinguere processi IOB
    • -
    -
  • -
  • - v.0.1.* → v.0.10.* -
      -
    • Testato in produzione x update ad avvio e su richiesta
    • -
    • Testato in produzione x lettura dati da Fanuc
    • -
    • Inizio deploy con copia file su area IIS
    • -
    • Prima versione con autoupdate
    • -
    • Test PrettyBin x spostamento dll
    • -
    • Base acquisitore FANUC
    • -
    • Sistema base sw controllo in tray
    • -
    -
  • -
-
-
- +

MAPO-IOB-WIN

+ v: {{CURRENT-REL}} +
+ Acquisitore MAPO-IOB per sistemi Windows +
+ Note di rilascio: +
    +
  • + v.3.1.* → v.3.2.* +
      +
    • Nuovi simulatori con gestione emergenza
    • +
    • Fix gestione invio dati Redis
    • +
    • Implementazione IOB Eurom63
    • +
    +
  • +
  • + v.2.6.* → v.3.0.* +
      +
    • revisione sistema metodi invio in blocco
    • +
    • Gestione invio contapezzi in step > 1
    • +
    • Gestione eventi in blocco (indipendente e prioritario su EvBlock)
    • +
    • Gestione limite eventi memorizzabili
    • +
    • Integrazione REDIS
    • +
    • Integrazione IOB-MAN
    • +
    +
  • +
  • + v.2.5.* → v.2.6.* +
      +
    • revisione sistema timeout Ping
    • +
    • Gestione AutoODL in prod generale (non solo SIM)
    • +
    +
  • +
  • + v.2.4.* → v.2.5.* +
      +
    • Aggiunto adapter MTConnect
    • +
    • Ottimizzazione gestione SIEMENS
    • +
    +
  • +
  • + v.2.3.* → v.2.4.* +
      +
    • inserita gestione conf json x Flog acquisiti
    • +
    • gestione invio Json blocchi dati FLog
    • +
    • ottimizzazioni varie adapter Siemens
    • +
    • ottimizzazione processo svuotamento code
    • +
    • riduzione interferenza e interblocchi in fase di PLC assente
    • +
    +
  • +
  • + Ultime modifiche: +
      {{LAST-CHANGES}}
    +
  • +
  • + v.1.18.* → v.2.3.* +
      +
    • inserimento WPS x acontrolli WebPage human readable
    • +
    • fix gestione task2exe
    • +
    • aggiunte varie versioni PLC siemens
    • +
    • aggiunto PLC WPS x generiche web pages
    • +
    • revisitazione LOG ODL e contapezzi
    • +
    • modifica pagina presentazione dati (master) x resize
    • +
    • Attivazione IOB SIMULATOR per test di carico (sostituito type DEMO)
    • +
    • Aggiunto simulatore macchine MULTI pallet
    • +
    • Ottimizzazione simulatore
    • +
    • Ottimizzazioni PLC Siemens x riavvio post disconnessione (es spegnimento notturno)
    • +
    • Ottimizzazione processo chiusura in update applicazione
    • +
    • Aggiunta simulazione spegnimento con WU/CD
    • +
    +
  • +
  • + v.1.11.* → v.1.18.* +
      +
    • Inserimento controller SIEMENS con S7+ library
    • +
    • Inserimento nuove letture FANUC x programmi
    • +
    • Inserimento nuove letture FANUC x SysEx (informazioni sistema)
    • +
    • Inserimento invio FluxLog x parametri estesi (es SysEx, ProgName,...)
    • +
    • FIX visualizzazione dati FluxLog e URL inviati
    • +
    • FIX MAIN program da FANUC (non il current)
    • +
    • Inserita modalita' DUMP memoria (iniziale full + periodica)
    • +
    • Inserimento gestione contapezzi standard/checkBit in IOB.cfg
    • +
    • Inserimento contapezzi da area memoria X
    • +
    • NUOVA Gestione rami cliente e URL di update
    • +
    • Gestione modi CNC
    • +
    • Lettura dari dinamycs FANUC (feed, speed)
    • +
    • aggiunta gestione aree G0..G30 (overrides?)
    • +
    • fix errore disconnessione FANUC (allo spegnimento dl CNC) e memoria valori persistente a 1
    • +
    • fix globali x gestione log IN / FLOG + ottimizzaizone check FANUC (PING)
    • +
    • ottimizzazione fasi di restart in caso di assenza del server (evita reinvii inutili e migliora tempo ripartenza invio)
    • +
    • review procedure controllo connessione x FANUC (es Tornos II)
    • +
    • non richeide più privilegi admin x fare update
    • +
    • gestione segnali inverted
    • +
    • completata gestione configurabilità parametrica segnali (Tornos, CMZ, Biglia)
    • +
    • revisitazione LOG x distinguere processi IOB
    • +
    +
  • +
  • + v.0.1.* → v.0.10.* +
      +
    • Testato in produzione x update ad avvio e su richiesta
    • +
    • Testato in produzione x lettura dati da Fanuc
    • +
    • Inizio deploy con copia file su area IIS
    • +
    • Prima versione con autoupdate
    • +
    • Test PrettyBin x spostamento dll
    • +
    • Base acquisitore FANUC
    • +
    • Sistema base sw controllo in tray
    • +
    +
  • +
+ - -
- \ No newline at end of file From c80158329b37ec334b84cc012415d0b0d1a0f6fd Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Tue, 6 Oct 2020 20:55:26 +0200 Subject: [PATCH 08/26] Spostamento documentazione --- .../Siemens Punzonatrice FAPE/TM150701_ IO.pdf | Bin .../Sinumerik_Integrated_OPC_UA_2014_uk.pdf | Bin IOB-WIN/DATA/EUR63/.placeholder | 1 + IOB-WIN/DATA/HIST/.placeholder | 1 + 4 files changed, 2 insertions(+) rename Documentazione/{ => Siemens}/Siemens Punzonatrice FAPE/TM150701_ IO.pdf (100%) rename Documentazione/{ => Siemens}/Sinumerik_Integrated_OPC_UA_2014_uk.pdf (100%) create mode 100644 IOB-WIN/DATA/EUR63/.placeholder create mode 100644 IOB-WIN/DATA/HIST/.placeholder diff --git a/Documentazione/Siemens Punzonatrice FAPE/TM150701_ IO.pdf b/Documentazione/Siemens/Siemens Punzonatrice FAPE/TM150701_ IO.pdf similarity index 100% rename from Documentazione/Siemens Punzonatrice FAPE/TM150701_ IO.pdf rename to Documentazione/Siemens/Siemens Punzonatrice FAPE/TM150701_ IO.pdf diff --git a/Documentazione/Sinumerik_Integrated_OPC_UA_2014_uk.pdf b/Documentazione/Siemens/Sinumerik_Integrated_OPC_UA_2014_uk.pdf similarity index 100% rename from Documentazione/Sinumerik_Integrated_OPC_UA_2014_uk.pdf rename to Documentazione/Siemens/Sinumerik_Integrated_OPC_UA_2014_uk.pdf diff --git a/IOB-WIN/DATA/EUR63/.placeholder b/IOB-WIN/DATA/EUR63/.placeholder new file mode 100644 index 00000000..5f282702 --- /dev/null +++ b/IOB-WIN/DATA/EUR63/.placeholder @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/IOB-WIN/DATA/HIST/.placeholder b/IOB-WIN/DATA/HIST/.placeholder new file mode 100644 index 00000000..5f282702 --- /dev/null +++ b/IOB-WIN/DATA/HIST/.placeholder @@ -0,0 +1 @@ + \ No newline at end of file From b534bcbe86a5055fcaf6d6243bb595148d3564c4 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Tue, 6 Oct 2020 20:55:41 +0200 Subject: [PATCH 09/26] aggiunta segnaposto x file EM63 --- IOB-WIN/DATA/EUR63/SESS0000.JOB | 1 + IOB-WIN/DATA/EUR63/SESS0000.REQ | 1 + 2 files changed, 2 insertions(+) create mode 100644 IOB-WIN/DATA/EUR63/SESS0000.JOB create mode 100644 IOB-WIN/DATA/EUR63/SESS0000.REQ diff --git a/IOB-WIN/DATA/EUR63/SESS0000.JOB b/IOB-WIN/DATA/EUR63/SESS0000.JOB new file mode 100644 index 00000000..5f282702 --- /dev/null +++ b/IOB-WIN/DATA/EUR63/SESS0000.JOB @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/IOB-WIN/DATA/EUR63/SESS0000.REQ b/IOB-WIN/DATA/EUR63/SESS0000.REQ new file mode 100644 index 00000000..5f282702 --- /dev/null +++ b/IOB-WIN/DATA/EUR63/SESS0000.REQ @@ -0,0 +1 @@ + \ No newline at end of file From 270bbc40d10bfadc2ea29b717e23ca1453f725d9 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Tue, 6 Oct 2020 20:57:12 +0200 Subject: [PATCH 10/26] Aggiunta preliminare doc x Euromap63 --- .../DemoCom/Step_000_Info/REQ/GETID.job | 2 + .../DemoCom/Step_000_Info/REQ/GETINFO.job | 2 + .../DemoCom/Step_000_Info/REQ/SESS0004.REQ | 1 + .../DemoCom/Step_000_Info/REQ/SESS0005.REQ | 1 + .../DemoCom/Step_000_Info/RSP/GETID.DAT | 39 ++++++++++++++++++ .../DemoCom/Step_000_Info/RSP/GETINFO.DAT | 15 +++++++ .../Step_000_connected/REQ/SESS0000.REQ | 1 + .../DemoCom/Step_001_Descr/REQ/SESS0014.REQ | 1 + .../DemoCom/Step_001_Descr/REQ/SetCodU.job | 14 +++++++ .../DemoCom/Step_001_Descr/RSP/SetCodU.job | 14 +++++++ .../DemoCom/Step_001_Job02/REQ/SESS0002.REQ | 1 + .../DemoCom/Step_001_Job02/REQ/SetTime.JOB | 2 + .../DemoCom/Step_001_Job07/REQ/AbortAll.job | 7 ++++ .../DemoCom/Step_001_Job07/REQ/SESS0007.REQ | 1 + .../DemoCom/Step_002_JOB03/REQ/SESS0003.REQ | 1 + .../DemoCom/Step_002_JOB03/REQ/machstat.job | 12 ++++++ .../DemoCom/Step_002_JOB03/RSP/machstat.dat | 2 + .../DemoCom/Step_002_JOB14/REQ/SESS0014.REQ | 1 + .../DemoCom/Step_002_JOB14/RSP/Report14.DAT | 21 ++++++++++ Documentazione/Euromap63/eu63.pdf | Bin 0 -> 230275 bytes 20 files changed, 138 insertions(+) create mode 100644 Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/GETID.job create mode 100644 Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/GETINFO.job create mode 100644 Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/SESS0004.REQ create mode 100644 Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/SESS0005.REQ create mode 100644 Documentazione/Euromap63/DemoCom/Step_000_Info/RSP/GETID.DAT create mode 100644 Documentazione/Euromap63/DemoCom/Step_000_Info/RSP/GETINFO.DAT create mode 100644 Documentazione/Euromap63/DemoCom/Step_000_connected/REQ/SESS0000.REQ create mode 100644 Documentazione/Euromap63/DemoCom/Step_001_Descr/REQ/SESS0014.REQ create mode 100644 Documentazione/Euromap63/DemoCom/Step_001_Descr/REQ/SetCodU.job create mode 100644 Documentazione/Euromap63/DemoCom/Step_001_Descr/RSP/SetCodU.job create mode 100644 Documentazione/Euromap63/DemoCom/Step_001_Job02/REQ/SESS0002.REQ create mode 100644 Documentazione/Euromap63/DemoCom/Step_001_Job02/REQ/SetTime.JOB create mode 100644 Documentazione/Euromap63/DemoCom/Step_001_Job07/REQ/AbortAll.job create mode 100644 Documentazione/Euromap63/DemoCom/Step_001_Job07/REQ/SESS0007.REQ create mode 100644 Documentazione/Euromap63/DemoCom/Step_002_JOB03/REQ/SESS0003.REQ create mode 100644 Documentazione/Euromap63/DemoCom/Step_002_JOB03/REQ/machstat.job create mode 100644 Documentazione/Euromap63/DemoCom/Step_002_JOB03/RSP/machstat.dat create mode 100644 Documentazione/Euromap63/DemoCom/Step_002_JOB14/REQ/SESS0014.REQ create mode 100644 Documentazione/Euromap63/DemoCom/Step_002_JOB14/RSP/Report14.DAT create mode 100644 Documentazione/Euromap63/eu63.pdf diff --git a/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/GETID.job b/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/GETID.job new file mode 100644 index 00000000..ba59dde9 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/GETID.job @@ -0,0 +1,2 @@ +JOB GETID RESPONSE "GETID.log"; +GETID "GETID.DAT"; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/GETINFO.job b/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/GETINFO.job new file mode 100644 index 00000000..6e2fe365 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/GETINFO.job @@ -0,0 +1,2 @@ +JOB GETINFO RESPONSE "GETINFO.log"; +GETINFO "GETINFO.DAT"; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/SESS0004.REQ b/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/SESS0004.REQ new file mode 100644 index 00000000..b620ab5d --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/SESS0004.REQ @@ -0,0 +1 @@ +REQ_0004 EXECUTE "JOB\Info\GETID.job"; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/SESS0005.REQ b/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/SESS0005.REQ new file mode 100644 index 00000000..cb18c0b0 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/SESS0005.REQ @@ -0,0 +1 @@ +REQ_0005 EXECUTE "JOB\Info\GETINFO.job"; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_000_Info/RSP/GETID.DAT b/Documentazione/Euromap63/DemoCom/Step_000_Info/RSP/GETID.DAT new file mode 100644 index 00000000..8a086854 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_000_Info/RSP/GETID.DAT @@ -0,0 +1,39 @@ +ActStsMach, A, 0, 0, 0, "n/a", "Actual Machine Status" +ActStsCyc, A, 0, 0, 0, "n/a", "Actual Cycle Status" +ActCntCyc, N, 0, 0, 0, "cycles", "Actual Cycle Count" +ActCntMld, N, 0, 0, 0, "count", "Number of Cavities Run" +ActCntPrt, N, 0, 0, 0, "count", "Actual Piece Counter" +ActTmpBrlZn, N, 0, 1, 0, "celsius", "Barrel temperature Zone" +ActTmpMldZn, N, 0, 1, 0, "celsius", "Mold Temperature Zone Actual Temperature" +ActTmpOil, N, 0, 1, 0, "celsius", "Oil Actual temperature" +ActTmpCab, N, 0, 0, 0, "celsius", "Cabinet Actual temperature" +ActTmpMlt, N, 0, 0, 0, "celsius", "Melt Actual Temperature" +ActTimFill, N, 0, 2, 0, "seconds", "Actual Fill Time" +ActTimPlst, N, 0, 2, 0, "seconds", "Actual Plastification Time" +ActTimCyc, N, 0, 2, 0, "seconds", "Actual Cycle Time" +ActStrCsh, N, 0, 1, 0, "mm", "Actual Stroke Cushion Position" +ActStrPlst, N, 0, 1, 0, "mm", "Actual Stroke Plastification Position" +ActSpdPlstMax, N, 0, 0, 0, "RPM", "Max Speed Screw" +ActSpdPlstAve, N, 0, 0, 0, "RPM", "Average Speed Screw" +SetTimMach, A, 0, 0, 1, "n/a", "Clock Syncronization" +SetDescJob, A, 0, 0, 1, "n/a", "Job name" +SetDescOp, A, 0, 0, 1, "n/a", "Operator ID" +SetDescPrt, A, 0, 0, 1, "n/a", "Part name" +SetDescMld, A, 0, 0, 1, "n/a", "Mold or Tool Name" +SetCntMld, N, 0, 0, 1, "count", "Number of Cavities Run" +SetCntPrtBox, A, 0, 0, 1, "count", "Part Box Count" +SetCntPrt, N, 0, 0, 1, "n/a", "Piece Counter" +SetTmpBrlZn, N, 0, 1, 1, "celsius", "Barrel Zone Set Temperature" +SetTmpBrlZnStb, N, 0, 1, 1, "celsius", "Barrel Zone Standby Temperature" +SetTmpBrlZnHdev, N, 0, 1, 1, "celsius", "Barrel Temperature Zone High Deviation" +SetTmpBrlZnLdev, N, 0, 1, 1, "celsius", "Barrel Temperature Zone Low Deviation" +SetTmpMldZn, N, 0, 1, 1, "celsius", "Mold Temperature Zone Set Temperature" +SetTmpMldZnStb, N, 0, 1, 1, "celsius", "Mold Temperature Zone Standby Temperature" +SetTmpMldZnHdev, N, 0, 1, 1, "celsius", "Mold Temperature Zone High Deviation Setpoints" +SetTmpMldZnLdev, N, 0, 1, 1, "celsius", "Mold Temperature Zone Low Deviation Setpoints" +SetTmpOil, N, 0, 1, 1, "celsius", "Oil Set temperature" +SetTimCyc, N, 0, 1, 1, "seconds", "Overall Cycle Time Setpoint" +SetStrPlst, N, 0, 1, 1, "mm", "Actual Stroke Plastification Position" +OutXhour, N, 7, 0, 0, "count", " output per hour (NPM)" +InjSts, B, 7, 0, 0, "NoUnit", "Injection Status (NPM)" +ActPreCnt, N, 7, 0, 0, "count", " Actual Preselection Counter (NPM)" diff --git a/Documentazione/Euromap63/DemoCom/Step_000_Info/RSP/GETINFO.DAT b/Documentazione/Euromap63/DemoCom/Step_000_Info/RSP/GETINFO.DAT new file mode 100644 index 00000000..1aa028e9 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_000_Info/RSP/GETINFO.DAT @@ -0,0 +1,15 @@ +MachVendor, "Plastic Metal"; +MachNbr, "6037"; +MachDesc, ""; +ContrType, ""; +ContrVersion, ""; +Version, "1.05a July 2000"; +MaxJobs, 20; +MaxReports, ; +MaxArchives, ; +InjUnitNbr, 2; +MaterialNbr, ; +CharDef, "850"; +MaxSessions, 20; +ActiveJobs, "GETID" "MPW280SP\JOB\Info\GETID.job" "MPW280SP\GETID.DAT"; +ActiveJobs, "GETINFO" "MPW280SP\JOB\Info\GETINFO.job" "MPW280SP\GETINFO.DAT"; diff --git a/Documentazione/Euromap63/DemoCom/Step_000_connected/REQ/SESS0000.REQ b/Documentazione/Euromap63/DemoCom/Step_000_connected/REQ/SESS0000.REQ new file mode 100644 index 00000000..a8d26386 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_000_connected/REQ/SESS0000.REQ @@ -0,0 +1 @@ +00000003 CONNECT; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_001_Descr/REQ/SESS0014.REQ b/Documentazione/Euromap63/DemoCom/Step_001_Descr/REQ/SESS0014.REQ new file mode 100644 index 00000000..dff494c5 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_001_Descr/REQ/SESS0014.REQ @@ -0,0 +1 @@ +REQ_0014 EXECUTE "SetCodU.job"; diff --git a/Documentazione/Euromap63/DemoCom/Step_001_Descr/REQ/SetCodU.job b/Documentazione/Euromap63/DemoCom/Step_001_Descr/REQ/SetCodU.job new file mode 100644 index 00000000..bee58bb2 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_001_Descr/REQ/SetCodU.job @@ -0,0 +1,14 @@ +JOB SetID RESPONSE "SetCodU.log"; +//SET SetDescJob " "; +//SET SetDescPrt " " +//SET SetDescMld " "; +//SET SetDescOp " "; + +SET SetDescJob "Nr. 1000987654.01"; +SET SetDescPrt "STICK: 8 componenti SENZA assemblaggio"; +SET SetDescMld "Stampo componenti a 8 impronte"; +SET SetDescOp "Operatore 01"; + +//SET SetCntMld 2; +//SET SetCntPrt 10000; +//SET SetCntPrtBox 20; diff --git a/Documentazione/Euromap63/DemoCom/Step_001_Descr/RSP/SetCodU.job b/Documentazione/Euromap63/DemoCom/Step_001_Descr/RSP/SetCodU.job new file mode 100644 index 00000000..bee58bb2 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_001_Descr/RSP/SetCodU.job @@ -0,0 +1,14 @@ +JOB SetID RESPONSE "SetCodU.log"; +//SET SetDescJob " "; +//SET SetDescPrt " " +//SET SetDescMld " "; +//SET SetDescOp " "; + +SET SetDescJob "Nr. 1000987654.01"; +SET SetDescPrt "STICK: 8 componenti SENZA assemblaggio"; +SET SetDescMld "Stampo componenti a 8 impronte"; +SET SetDescOp "Operatore 01"; + +//SET SetCntMld 2; +//SET SetCntPrt 10000; +//SET SetCntPrtBox 20; diff --git a/Documentazione/Euromap63/DemoCom/Step_001_Job02/REQ/SESS0002.REQ b/Documentazione/Euromap63/DemoCom/Step_001_Job02/REQ/SESS0002.REQ new file mode 100644 index 00000000..b5f5020f --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_001_Job02/REQ/SESS0002.REQ @@ -0,0 +1 @@ +REQ_002 EXECUTE "SetTime.JOB"; diff --git a/Documentazione/Euromap63/DemoCom/Step_001_Job02/REQ/SetTime.JOB b/Documentazione/Euromap63/DemoCom/Step_001_Job02/REQ/SetTime.JOB new file mode 100644 index 00000000..a1457184 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_001_Job02/REQ/SetTime.JOB @@ -0,0 +1,2 @@ +JOB ImpostaOrario RESPONSE "SetTimeMach.rsp"; +SET SetTimMach 18370020201005; diff --git a/Documentazione/Euromap63/DemoCom/Step_001_Job07/REQ/AbortAll.job b/Documentazione/Euromap63/DemoCom/Step_001_Job07/REQ/AbortAll.job new file mode 100644 index 00000000..84f8d10e --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_001_Job07/REQ/AbortAll.job @@ -0,0 +1,7 @@ +JOB Abort1 RESPONSE "AbortAll.Log"; + +//ABORT EVENT Event1; +//ABORT ALL REPORTS; +//ABORT JOB Job1Name; +ABORT ALL JOBS; +//ABORT REPORT Report1Name; diff --git a/Documentazione/Euromap63/DemoCom/Step_001_Job07/REQ/SESS0007.REQ b/Documentazione/Euromap63/DemoCom/Step_001_Job07/REQ/SESS0007.REQ new file mode 100644 index 00000000..5617d5fd --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_001_Job07/REQ/SESS0007.REQ @@ -0,0 +1 @@ +REQ_0007 EXECUTE "JOB\AbortJobs\AbortAll.job"; diff --git a/Documentazione/Euromap63/DemoCom/Step_002_JOB03/REQ/SESS0003.REQ b/Documentazione/Euromap63/DemoCom/Step_002_JOB03/REQ/SESS0003.REQ new file mode 100644 index 00000000..61ab85cb --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_002_JOB03/REQ/SESS0003.REQ @@ -0,0 +1 @@ +REQ_0003 EXECUTE "JOB\Report\machstat.job"; diff --git a/Documentazione/Euromap63/DemoCom/Step_002_JOB03/REQ/machstat.job b/Documentazione/Euromap63/DemoCom/Step_002_JOB03/REQ/machstat.job new file mode 100644 index 00000000..8be4143e --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_002_JOB03/REQ/machstat.job @@ -0,0 +1,12 @@ +JOB machstat RESPONSE "machstat.log"; + +REPORT status REWRITE "machstat.dat" +START IMMEDIATE +//START TIME>= 10:25:00 +STOP NEVER +CYCLIC TIME 00:01:00 +//SESSIONS 10 +PARAMETERS +DATE, TIME, ActStsMach; + + diff --git a/Documentazione/Euromap63/DemoCom/Step_002_JOB03/RSP/machstat.dat b/Documentazione/Euromap63/DemoCom/Step_002_JOB03/RSP/machstat.dat new file mode 100644 index 00000000..ee3dc3eb --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_002_JOB03/RSP/machstat.dat @@ -0,0 +1,2 @@ +DATE, TIME, ActStsMach +20201005, 17:56:33, 1 000 diff --git a/Documentazione/Euromap63/DemoCom/Step_002_JOB14/REQ/SESS0014.REQ b/Documentazione/Euromap63/DemoCom/Step_002_JOB14/REQ/SESS0014.REQ new file mode 100644 index 00000000..9e05b52b --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_002_JOB14/REQ/SESS0014.REQ @@ -0,0 +1 @@ +REQ_0014 EXECUTE "JOB\Report\Report14.job"; diff --git a/Documentazione/Euromap63/DemoCom/Step_002_JOB14/RSP/Report14.DAT b/Documentazione/Euromap63/DemoCom/Step_002_JOB14/RSP/Report14.DAT new file mode 100644 index 00000000..ee0ec758 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_002_JOB14/RSP/Report14.DAT @@ -0,0 +1,21 @@ +DATE, TIME, ActCntCyc, ActTimCyc, ActTimFill, @OutXhour, SetDescJob +20201005, 18:38:17, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:18, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:19, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:20, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:21, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:22, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:23, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:24, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:25, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:26, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:27, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:28, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:29, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:30, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:31, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:33, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:34, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:35, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:36, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 +20201005, 18:38:37, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 diff --git a/Documentazione/Euromap63/eu63.pdf b/Documentazione/Euromap63/eu63.pdf new file mode 100644 index 0000000000000000000000000000000000000000..aba321d2f2c8a5e708388cda38c8646a8619bbbd GIT binary patch literal 230275 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 z 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

}cln&j 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

<#YOEYa3#>FiA+kn@rrT=FyCKjs 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%0DFkFqFgmp{#=KTFm_q|(^>Z}AVY=OAp$X}v! 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 literal 0 HcmV?d00001 From bceb0f860c06d89640d042d23ba2f137b96edfcc Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Tue, 6 Oct 2020 21:23:51 +0200 Subject: [PATCH 11/26] Fix step 01 (iniziato anche ..02..03) --- .../DemoCom/Step_000_Info/REQ/GETID.job | 2 - .../DemoCom/Step_000_Info/REQ/SESS0004.REQ | 1 - .../DemoCom/Step_000_Info/RSP/GETID.DAT | 39 ------------------- .../Step_000_connected/REQ/SESS0000.REQ | 1 - .../DemoCom/Step_01_CONN/SESS0000.REQ | 1 + .../DemoCom/Step_01_CONN/SESS0000.RSP.KO | 1 + .../DemoCom/Step_01_CONN/SESS0000.RSP.OK | 1 + .../RSP => Step_01_ID}/GETINFO.DAT | 0 .../REQ => Step_01_ID}/GETINFO.job | 0 .../REQ => Step_01_ID}/SESS0005.REQ | 0 .../DemoCom/Step_01_INFO/GETINFO.DAT | 15 +++++++ .../DemoCom/Step_01_INFO/GETINFO.job | 2 + .../DemoCom/Step_01_INFO/SESS0005.REQ | 1 + .../REQ/SESS0014.REQ | 0 .../REQ/SetCodU.job | 0 .../RSP/SetCodU.job | 0 .../REQ/SESS0002.REQ | 0 .../REQ/SetTime.JOB | 0 .../REQ/AbortAll.job | 0 .../REQ/SESS0007.REQ | 0 .../REQ/SESS0003.REQ | 0 .../REQ/machstat.job | 0 .../RSP/machstat.dat | 0 .../REQ/SESS0014.REQ | 0 .../RSP/Report14.DAT | 0 25 files changed, 21 insertions(+), 43 deletions(-) delete mode 100644 Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/GETID.job delete mode 100644 Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/SESS0004.REQ delete mode 100644 Documentazione/Euromap63/DemoCom/Step_000_Info/RSP/GETID.DAT delete mode 100644 Documentazione/Euromap63/DemoCom/Step_000_connected/REQ/SESS0000.REQ create mode 100644 Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.REQ create mode 100644 Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.RSP.KO create mode 100644 Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.RSP.OK rename Documentazione/Euromap63/DemoCom/{Step_000_Info/RSP => Step_01_ID}/GETINFO.DAT (100%) rename Documentazione/Euromap63/DemoCom/{Step_000_Info/REQ => Step_01_ID}/GETINFO.job (100%) rename Documentazione/Euromap63/DemoCom/{Step_000_Info/REQ => Step_01_ID}/SESS0005.REQ (100%) create mode 100644 Documentazione/Euromap63/DemoCom/Step_01_INFO/GETINFO.DAT create mode 100644 Documentazione/Euromap63/DemoCom/Step_01_INFO/GETINFO.job create mode 100644 Documentazione/Euromap63/DemoCom/Step_01_INFO/SESS0005.REQ rename Documentazione/Euromap63/DemoCom/{Step_001_Descr => Step_02_Descr}/REQ/SESS0014.REQ (100%) rename Documentazione/Euromap63/DemoCom/{Step_001_Descr => Step_02_Descr}/REQ/SetCodU.job (100%) rename Documentazione/Euromap63/DemoCom/{Step_001_Descr => Step_02_Descr}/RSP/SetCodU.job (100%) rename Documentazione/Euromap63/DemoCom/{Step_001_Job02 => Step_02_Job02}/REQ/SESS0002.REQ (100%) rename Documentazione/Euromap63/DemoCom/{Step_001_Job02 => Step_02_Job02}/REQ/SetTime.JOB (100%) rename Documentazione/Euromap63/DemoCom/{Step_001_Job07 => Step_02_Job07}/REQ/AbortAll.job (100%) rename Documentazione/Euromap63/DemoCom/{Step_001_Job07 => Step_02_Job07}/REQ/SESS0007.REQ (100%) rename Documentazione/Euromap63/DemoCom/{Step_002_JOB03 => Step_03_JOB03}/REQ/SESS0003.REQ (100%) rename Documentazione/Euromap63/DemoCom/{Step_002_JOB03 => Step_03_JOB03}/REQ/machstat.job (100%) rename Documentazione/Euromap63/DemoCom/{Step_002_JOB03 => Step_03_JOB03}/RSP/machstat.dat (100%) rename Documentazione/Euromap63/DemoCom/{Step_002_JOB14 => Step_03_JOB14}/REQ/SESS0014.REQ (100%) rename Documentazione/Euromap63/DemoCom/{Step_002_JOB14 => Step_03_JOB14}/RSP/Report14.DAT (100%) diff --git a/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/GETID.job b/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/GETID.job deleted file mode 100644 index ba59dde9..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/GETID.job +++ /dev/null @@ -1,2 +0,0 @@ -JOB GETID RESPONSE "GETID.log"; -GETID "GETID.DAT"; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/SESS0004.REQ b/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/SESS0004.REQ deleted file mode 100644 index b620ab5d..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/SESS0004.REQ +++ /dev/null @@ -1 +0,0 @@ -REQ_0004 EXECUTE "JOB\Info\GETID.job"; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_000_Info/RSP/GETID.DAT b/Documentazione/Euromap63/DemoCom/Step_000_Info/RSP/GETID.DAT deleted file mode 100644 index 8a086854..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_000_Info/RSP/GETID.DAT +++ /dev/null @@ -1,39 +0,0 @@ -ActStsMach, A, 0, 0, 0, "n/a", "Actual Machine Status" -ActStsCyc, A, 0, 0, 0, "n/a", "Actual Cycle Status" -ActCntCyc, N, 0, 0, 0, "cycles", "Actual Cycle Count" -ActCntMld, N, 0, 0, 0, "count", "Number of Cavities Run" -ActCntPrt, N, 0, 0, 0, "count", "Actual Piece Counter" -ActTmpBrlZn, N, 0, 1, 0, "celsius", "Barrel temperature Zone" -ActTmpMldZn, N, 0, 1, 0, "celsius", "Mold Temperature Zone Actual Temperature" -ActTmpOil, N, 0, 1, 0, "celsius", "Oil Actual temperature" -ActTmpCab, N, 0, 0, 0, "celsius", "Cabinet Actual temperature" -ActTmpMlt, N, 0, 0, 0, "celsius", "Melt Actual Temperature" -ActTimFill, N, 0, 2, 0, "seconds", "Actual Fill Time" -ActTimPlst, N, 0, 2, 0, "seconds", "Actual Plastification Time" -ActTimCyc, N, 0, 2, 0, "seconds", "Actual Cycle Time" -ActStrCsh, N, 0, 1, 0, "mm", "Actual Stroke Cushion Position" -ActStrPlst, N, 0, 1, 0, "mm", "Actual Stroke Plastification Position" -ActSpdPlstMax, N, 0, 0, 0, "RPM", "Max Speed Screw" -ActSpdPlstAve, N, 0, 0, 0, "RPM", "Average Speed Screw" -SetTimMach, A, 0, 0, 1, "n/a", "Clock Syncronization" -SetDescJob, A, 0, 0, 1, "n/a", "Job name" -SetDescOp, A, 0, 0, 1, "n/a", "Operator ID" -SetDescPrt, A, 0, 0, 1, "n/a", "Part name" -SetDescMld, A, 0, 0, 1, "n/a", "Mold or Tool Name" -SetCntMld, N, 0, 0, 1, "count", "Number of Cavities Run" -SetCntPrtBox, A, 0, 0, 1, "count", "Part Box Count" -SetCntPrt, N, 0, 0, 1, "n/a", "Piece Counter" -SetTmpBrlZn, N, 0, 1, 1, "celsius", "Barrel Zone Set Temperature" -SetTmpBrlZnStb, N, 0, 1, 1, "celsius", "Barrel Zone Standby Temperature" -SetTmpBrlZnHdev, N, 0, 1, 1, "celsius", "Barrel Temperature Zone High Deviation" -SetTmpBrlZnLdev, N, 0, 1, 1, "celsius", "Barrel Temperature Zone Low Deviation" -SetTmpMldZn, N, 0, 1, 1, "celsius", "Mold Temperature Zone Set Temperature" -SetTmpMldZnStb, N, 0, 1, 1, "celsius", "Mold Temperature Zone Standby Temperature" -SetTmpMldZnHdev, N, 0, 1, 1, "celsius", "Mold Temperature Zone High Deviation Setpoints" -SetTmpMldZnLdev, N, 0, 1, 1, "celsius", "Mold Temperature Zone Low Deviation Setpoints" -SetTmpOil, N, 0, 1, 1, "celsius", "Oil Set temperature" -SetTimCyc, N, 0, 1, 1, "seconds", "Overall Cycle Time Setpoint" -SetStrPlst, N, 0, 1, 1, "mm", "Actual Stroke Plastification Position" -OutXhour, N, 7, 0, 0, "count", " output per hour (NPM)" -InjSts, B, 7, 0, 0, "NoUnit", "Injection Status (NPM)" -ActPreCnt, N, 7, 0, 0, "count", " Actual Preselection Counter (NPM)" diff --git a/Documentazione/Euromap63/DemoCom/Step_000_connected/REQ/SESS0000.REQ b/Documentazione/Euromap63/DemoCom/Step_000_connected/REQ/SESS0000.REQ deleted file mode 100644 index a8d26386..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_000_connected/REQ/SESS0000.REQ +++ /dev/null @@ -1 +0,0 @@ -00000003 CONNECT; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.REQ b/Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.REQ new file mode 100644 index 00000000..82c6c8ca --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.REQ @@ -0,0 +1 @@ +SESSS0000 CONNECT; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.RSP.KO b/Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.RSP.KO new file mode 100644 index 00000000..35cc29f6 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.RSP.KO @@ -0,0 +1 @@ +SESSS0000 ERROR 05 00000004 "Warning of first connection: all previous job are lost"; diff --git a/Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.RSP.OK b/Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.RSP.OK new file mode 100644 index 00000000..7d6d36d5 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.RSP.OK @@ -0,0 +1 @@ +SESSS0000 PROCESSED; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_000_Info/RSP/GETINFO.DAT b/Documentazione/Euromap63/DemoCom/Step_01_ID/GETINFO.DAT similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_000_Info/RSP/GETINFO.DAT rename to Documentazione/Euromap63/DemoCom/Step_01_ID/GETINFO.DAT diff --git a/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/GETINFO.job b/Documentazione/Euromap63/DemoCom/Step_01_ID/GETINFO.job similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/GETINFO.job rename to Documentazione/Euromap63/DemoCom/Step_01_ID/GETINFO.job diff --git a/Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/SESS0005.REQ b/Documentazione/Euromap63/DemoCom/Step_01_ID/SESS0005.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_000_Info/REQ/SESS0005.REQ rename to Documentazione/Euromap63/DemoCom/Step_01_ID/SESS0005.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_01_INFO/GETINFO.DAT b/Documentazione/Euromap63/DemoCom/Step_01_INFO/GETINFO.DAT new file mode 100644 index 00000000..1aa028e9 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_01_INFO/GETINFO.DAT @@ -0,0 +1,15 @@ +MachVendor, "Plastic Metal"; +MachNbr, "6037"; +MachDesc, ""; +ContrType, ""; +ContrVersion, ""; +Version, "1.05a July 2000"; +MaxJobs, 20; +MaxReports, ; +MaxArchives, ; +InjUnitNbr, 2; +MaterialNbr, ; +CharDef, "850"; +MaxSessions, 20; +ActiveJobs, "GETID" "MPW280SP\JOB\Info\GETID.job" "MPW280SP\GETID.DAT"; +ActiveJobs, "GETINFO" "MPW280SP\JOB\Info\GETINFO.job" "MPW280SP\GETINFO.DAT"; diff --git a/Documentazione/Euromap63/DemoCom/Step_01_INFO/GETINFO.job b/Documentazione/Euromap63/DemoCom/Step_01_INFO/GETINFO.job new file mode 100644 index 00000000..6e2fe365 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_01_INFO/GETINFO.job @@ -0,0 +1,2 @@ +JOB GETINFO RESPONSE "GETINFO.log"; +GETINFO "GETINFO.DAT"; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_01_INFO/SESS0005.REQ b/Documentazione/Euromap63/DemoCom/Step_01_INFO/SESS0005.REQ new file mode 100644 index 00000000..cb18c0b0 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_01_INFO/SESS0005.REQ @@ -0,0 +1 @@ +REQ_0005 EXECUTE "JOB\Info\GETINFO.job"; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_001_Descr/REQ/SESS0014.REQ b/Documentazione/Euromap63/DemoCom/Step_02_Descr/REQ/SESS0014.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_001_Descr/REQ/SESS0014.REQ rename to Documentazione/Euromap63/DemoCom/Step_02_Descr/REQ/SESS0014.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_001_Descr/REQ/SetCodU.job b/Documentazione/Euromap63/DemoCom/Step_02_Descr/REQ/SetCodU.job similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_001_Descr/REQ/SetCodU.job rename to Documentazione/Euromap63/DemoCom/Step_02_Descr/REQ/SetCodU.job diff --git a/Documentazione/Euromap63/DemoCom/Step_001_Descr/RSP/SetCodU.job b/Documentazione/Euromap63/DemoCom/Step_02_Descr/RSP/SetCodU.job similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_001_Descr/RSP/SetCodU.job rename to Documentazione/Euromap63/DemoCom/Step_02_Descr/RSP/SetCodU.job diff --git a/Documentazione/Euromap63/DemoCom/Step_001_Job02/REQ/SESS0002.REQ b/Documentazione/Euromap63/DemoCom/Step_02_Job02/REQ/SESS0002.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_001_Job02/REQ/SESS0002.REQ rename to Documentazione/Euromap63/DemoCom/Step_02_Job02/REQ/SESS0002.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_001_Job02/REQ/SetTime.JOB b/Documentazione/Euromap63/DemoCom/Step_02_Job02/REQ/SetTime.JOB similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_001_Job02/REQ/SetTime.JOB rename to Documentazione/Euromap63/DemoCom/Step_02_Job02/REQ/SetTime.JOB diff --git a/Documentazione/Euromap63/DemoCom/Step_001_Job07/REQ/AbortAll.job b/Documentazione/Euromap63/DemoCom/Step_02_Job07/REQ/AbortAll.job similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_001_Job07/REQ/AbortAll.job rename to Documentazione/Euromap63/DemoCom/Step_02_Job07/REQ/AbortAll.job diff --git a/Documentazione/Euromap63/DemoCom/Step_001_Job07/REQ/SESS0007.REQ b/Documentazione/Euromap63/DemoCom/Step_02_Job07/REQ/SESS0007.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_001_Job07/REQ/SESS0007.REQ rename to Documentazione/Euromap63/DemoCom/Step_02_Job07/REQ/SESS0007.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_002_JOB03/REQ/SESS0003.REQ b/Documentazione/Euromap63/DemoCom/Step_03_JOB03/REQ/SESS0003.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_002_JOB03/REQ/SESS0003.REQ rename to Documentazione/Euromap63/DemoCom/Step_03_JOB03/REQ/SESS0003.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_002_JOB03/REQ/machstat.job b/Documentazione/Euromap63/DemoCom/Step_03_JOB03/REQ/machstat.job similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_002_JOB03/REQ/machstat.job rename to Documentazione/Euromap63/DemoCom/Step_03_JOB03/REQ/machstat.job diff --git a/Documentazione/Euromap63/DemoCom/Step_002_JOB03/RSP/machstat.dat b/Documentazione/Euromap63/DemoCom/Step_03_JOB03/RSP/machstat.dat similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_002_JOB03/RSP/machstat.dat rename to Documentazione/Euromap63/DemoCom/Step_03_JOB03/RSP/machstat.dat diff --git a/Documentazione/Euromap63/DemoCom/Step_002_JOB14/REQ/SESS0014.REQ b/Documentazione/Euromap63/DemoCom/Step_03_JOB14/REQ/SESS0014.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_002_JOB14/REQ/SESS0014.REQ rename to Documentazione/Euromap63/DemoCom/Step_03_JOB14/REQ/SESS0014.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_002_JOB14/RSP/Report14.DAT b/Documentazione/Euromap63/DemoCom/Step_03_JOB14/RSP/Report14.DAT similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_002_JOB14/RSP/Report14.DAT rename to Documentazione/Euromap63/DemoCom/Step_03_JOB14/RSP/Report14.DAT From 9d87a265ddb1f4ddb4a40225ff12894168937318 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Tue, 6 Oct 2020 21:27:42 +0200 Subject: [PATCH 12/26] COntinuo riorganizzazione step 02..03 --- .../DemoCom/Step_02_Descr/RSP/SetCodU.job | 14 -------------- .../DemoCom/Step_02_Descr/{REQ => }/SESS0014.REQ | 0 .../DemoCom/Step_02_Descr/{REQ => }/SetCodU.job | 0 .../DemoCom/Step_02_Job02/{REQ => }/SESS0002.REQ | 0 .../DemoCom/Step_02_Job02/{REQ => }/SetTime.JOB | 0 .../DemoCom/Step_02_Job07/{REQ => }/AbortAll.job | 0 .../DemoCom/Step_02_Job07/{REQ => }/SESS0007.REQ | 0 .../DemoCom/Step_03_JOB03/{REQ => }/SESS0003.REQ | 0 .../DemoCom/Step_03_JOB03/{RSP => }/machstat.dat | 0 .../DemoCom/Step_03_JOB03/{REQ => }/machstat.job | 0 .../DemoCom/Step_03_JOB14/{RSP => }/Report14.DAT | 0 .../DemoCom/Step_03_JOB14/{REQ => }/SESS0014.REQ | 0 12 files changed, 14 deletions(-) delete mode 100644 Documentazione/Euromap63/DemoCom/Step_02_Descr/RSP/SetCodU.job rename Documentazione/Euromap63/DemoCom/Step_02_Descr/{REQ => }/SESS0014.REQ (100%) rename Documentazione/Euromap63/DemoCom/Step_02_Descr/{REQ => }/SetCodU.job (100%) rename Documentazione/Euromap63/DemoCom/Step_02_Job02/{REQ => }/SESS0002.REQ (100%) rename Documentazione/Euromap63/DemoCom/Step_02_Job02/{REQ => }/SetTime.JOB (100%) rename Documentazione/Euromap63/DemoCom/Step_02_Job07/{REQ => }/AbortAll.job (100%) rename Documentazione/Euromap63/DemoCom/Step_02_Job07/{REQ => }/SESS0007.REQ (100%) rename Documentazione/Euromap63/DemoCom/Step_03_JOB03/{REQ => }/SESS0003.REQ (100%) rename Documentazione/Euromap63/DemoCom/Step_03_JOB03/{RSP => }/machstat.dat (100%) rename Documentazione/Euromap63/DemoCom/Step_03_JOB03/{REQ => }/machstat.job (100%) rename Documentazione/Euromap63/DemoCom/Step_03_JOB14/{RSP => }/Report14.DAT (100%) rename Documentazione/Euromap63/DemoCom/Step_03_JOB14/{REQ => }/SESS0014.REQ (100%) diff --git a/Documentazione/Euromap63/DemoCom/Step_02_Descr/RSP/SetCodU.job b/Documentazione/Euromap63/DemoCom/Step_02_Descr/RSP/SetCodU.job deleted file mode 100644 index bee58bb2..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_02_Descr/RSP/SetCodU.job +++ /dev/null @@ -1,14 +0,0 @@ -JOB SetID RESPONSE "SetCodU.log"; -//SET SetDescJob " "; -//SET SetDescPrt " " -//SET SetDescMld " "; -//SET SetDescOp " "; - -SET SetDescJob "Nr. 1000987654.01"; -SET SetDescPrt "STICK: 8 componenti SENZA assemblaggio"; -SET SetDescMld "Stampo componenti a 8 impronte"; -SET SetDescOp "Operatore 01"; - -//SET SetCntMld 2; -//SET SetCntPrt 10000; -//SET SetCntPrtBox 20; diff --git a/Documentazione/Euromap63/DemoCom/Step_02_Descr/REQ/SESS0014.REQ b/Documentazione/Euromap63/DemoCom/Step_02_Descr/SESS0014.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_02_Descr/REQ/SESS0014.REQ rename to Documentazione/Euromap63/DemoCom/Step_02_Descr/SESS0014.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_02_Descr/REQ/SetCodU.job b/Documentazione/Euromap63/DemoCom/Step_02_Descr/SetCodU.job similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_02_Descr/REQ/SetCodU.job rename to Documentazione/Euromap63/DemoCom/Step_02_Descr/SetCodU.job diff --git a/Documentazione/Euromap63/DemoCom/Step_02_Job02/REQ/SESS0002.REQ b/Documentazione/Euromap63/DemoCom/Step_02_Job02/SESS0002.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_02_Job02/REQ/SESS0002.REQ rename to Documentazione/Euromap63/DemoCom/Step_02_Job02/SESS0002.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_02_Job02/REQ/SetTime.JOB b/Documentazione/Euromap63/DemoCom/Step_02_Job02/SetTime.JOB similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_02_Job02/REQ/SetTime.JOB rename to Documentazione/Euromap63/DemoCom/Step_02_Job02/SetTime.JOB diff --git a/Documentazione/Euromap63/DemoCom/Step_02_Job07/REQ/AbortAll.job b/Documentazione/Euromap63/DemoCom/Step_02_Job07/AbortAll.job similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_02_Job07/REQ/AbortAll.job rename to Documentazione/Euromap63/DemoCom/Step_02_Job07/AbortAll.job diff --git a/Documentazione/Euromap63/DemoCom/Step_02_Job07/REQ/SESS0007.REQ b/Documentazione/Euromap63/DemoCom/Step_02_Job07/SESS0007.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_02_Job07/REQ/SESS0007.REQ rename to Documentazione/Euromap63/DemoCom/Step_02_Job07/SESS0007.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_03_JOB03/REQ/SESS0003.REQ b/Documentazione/Euromap63/DemoCom/Step_03_JOB03/SESS0003.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_03_JOB03/REQ/SESS0003.REQ rename to Documentazione/Euromap63/DemoCom/Step_03_JOB03/SESS0003.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_03_JOB03/RSP/machstat.dat b/Documentazione/Euromap63/DemoCom/Step_03_JOB03/machstat.dat similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_03_JOB03/RSP/machstat.dat rename to Documentazione/Euromap63/DemoCom/Step_03_JOB03/machstat.dat diff --git a/Documentazione/Euromap63/DemoCom/Step_03_JOB03/REQ/machstat.job b/Documentazione/Euromap63/DemoCom/Step_03_JOB03/machstat.job similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_03_JOB03/REQ/machstat.job rename to Documentazione/Euromap63/DemoCom/Step_03_JOB03/machstat.job diff --git a/Documentazione/Euromap63/DemoCom/Step_03_JOB14/RSP/Report14.DAT b/Documentazione/Euromap63/DemoCom/Step_03_JOB14/Report14.DAT similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_03_JOB14/RSP/Report14.DAT rename to Documentazione/Euromap63/DemoCom/Step_03_JOB14/Report14.DAT diff --git a/Documentazione/Euromap63/DemoCom/Step_03_JOB14/REQ/SESS0014.REQ b/Documentazione/Euromap63/DemoCom/Step_03_JOB14/SESS0014.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_03_JOB14/REQ/SESS0014.REQ rename to Documentazione/Euromap63/DemoCom/Step_03_JOB14/SESS0014.REQ From 4cf8709a0a67f96aa65acdee2aa4bc0740507944 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Tue, 6 Oct 2020 21:52:00 +0200 Subject: [PATCH 13/26] Continuo fix Euromap63 --- IOB-UT/Eurom63.cs | 39 +++++++++++++++++-- IOB-WIN/DATA/EUR63/SESS0000.JOB | 1 - IOB-WIN/DATA/EUR63/SESS0000.REQ | 1 - .../DATA/{EUR63 => EUR63_JOB}/.placeholder | 0 IOB-WIN/DATA/EUR63_JOB/SESS0000.REQ | 1 + 5 files changed, 36 insertions(+), 6 deletions(-) delete mode 100644 IOB-WIN/DATA/EUR63/SESS0000.JOB delete mode 100644 IOB-WIN/DATA/EUR63/SESS0000.REQ rename IOB-WIN/DATA/{EUR63 => EUR63_JOB}/.placeholder (100%) create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0000.REQ diff --git a/IOB-UT/Eurom63.cs b/IOB-UT/Eurom63.cs index 3edf7898..f706b32d 100644 --- a/IOB-UT/Eurom63.cs +++ b/IOB-UT/Eurom63.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; @@ -10,6 +11,8 @@ namespace IOB_UT /// public class Eurom63 { + #region Public Enums + public enum FileOpr { Copy = 0, @@ -38,15 +41,26 @@ namespace IOB_UT SetParamOdl } + #endregion Public Enums + + + + #region Public Classes + /// /// Struttura per un file da processare /// public class FileTask { - public string FileName { get; set; } = "SESS0000.FILE"; - public string Path { get; set; } = @"JOB\SESS0000.FILE"; + #region Public Properties + + public string FilePath { get; set; } = @"EUR63_JOB\SESS9999.REQ"; + public FileOpr OprReq { get; set; } = FileOpr.Copy; + public string RespKo { get; set; } = "ERROR"; + public string RespOk { get; set; } = "PROCESSED"; public Dictionary StrReplace { get; set; } = new Dictionary(); - public FileType Type { get; set; } = FileType.NA; + + #endregion Public Properties } /// @@ -54,6 +68,8 @@ namespace IOB_UT /// public class Session { + #region Public Properties + /// /// Session currently active /// @@ -113,13 +129,28 @@ namespace IOB_UT /// Standard session validity time /// public double ValidityMinutes { get; set; } = 1; + + #endregion Public Properties } public class SessionConf { + #region Public Fields + public List ActiveSessions = new List(); - public string BaseDir { get; set; } = @"C:\"; + + #endregion Public Fields + + + + #region Public Properties + + public string BaseDir { get; set; } = @"C:\EUROMAP63\"; public List DynData { get; set; } = new List(); + + #endregion Public Properties } + + #endregion Public Classes } } \ No newline at end of file diff --git a/IOB-WIN/DATA/EUR63/SESS0000.JOB b/IOB-WIN/DATA/EUR63/SESS0000.JOB deleted file mode 100644 index 5f282702..00000000 --- a/IOB-WIN/DATA/EUR63/SESS0000.JOB +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/IOB-WIN/DATA/EUR63/SESS0000.REQ b/IOB-WIN/DATA/EUR63/SESS0000.REQ deleted file mode 100644 index 5f282702..00000000 --- a/IOB-WIN/DATA/EUR63/SESS0000.REQ +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/IOB-WIN/DATA/EUR63/.placeholder b/IOB-WIN/DATA/EUR63_JOB/.placeholder similarity index 100% rename from IOB-WIN/DATA/EUR63/.placeholder rename to IOB-WIN/DATA/EUR63_JOB/.placeholder diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0000.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0000.REQ new file mode 100644 index 00000000..98436c00 --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0000.REQ @@ -0,0 +1 @@ +SESSS0000 CONNECT; \ No newline at end of file From 026d2df8a8462d1a8654d31949d71a6b7e69deb0 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Tue, 6 Oct 2020 22:24:49 +0200 Subject: [PATCH 14/26] Continuo riorganizzazione script EUR63 --- .../SESS0000.REQ | 0 .../SESS0000.RSP.KO | 0 .../SESS0000.RSP.OK | 0 .../Euromap63/DemoCom/Step_01_ID/GETINFO.job | 2 - .../Step_01_ID/{GETINFO.DAT => SESS0001.DAT} | 4 +- .../Euromap63/DemoCom/Step_01_ID/SESS0001.JOB | 2 + .../Euromap63/DemoCom/Step_01_ID/SESS0001.REQ | 1 + .../Euromap63/DemoCom/Step_01_ID/SESS0005.REQ | 1 - .../DemoCom/Step_01_INFO/GETINFO.job | 2 - .../DemoCom/Step_01_INFO/SESS0005.REQ | 1 - .../GETINFO.DAT => Step_02_INFO/SESS0002.DAT} | 4 +- .../DemoCom/Step_02_INFO/SESS0002.JOB | 2 + .../DemoCom/Step_02_INFO/SESS0002.REQ | 1 + .../SESS0014.REQ | 0 .../SetCodU.job | 0 .../SESS0002.REQ | 0 .../SetTime.JOB | 0 .../AbortAll.job | 0 .../SESS0007.REQ | 0 .../SESS0003.REQ | 0 .../machstat.dat | 0 .../machstat.job | 0 .../Report14.DAT | 0 .../SESS0014.REQ | 0 IOB-UT/Eurom63.cs | 6 +- IOB-WIN/DATA/CONF/EM63.json | 75 ++++++++++++------- IOB-WIN/DATA/EUR63_JOB/SESS0001.JOB | 2 + IOB-WIN/DATA/EUR63_JOB/SESS0001.REQ | 1 + IOB-WIN/DATA/EUR63_JOB/SESS0002.JOB | 2 + IOB-WIN/DATA/EUR63_JOB/SESS0002.REQ | 1 + 30 files changed, 70 insertions(+), 37 deletions(-) rename Documentazione/Euromap63/DemoCom/{Step_01_CONN => Step_00_CONN}/SESS0000.REQ (100%) rename Documentazione/Euromap63/DemoCom/{Step_01_CONN => Step_00_CONN}/SESS0000.RSP.KO (100%) rename Documentazione/Euromap63/DemoCom/{Step_01_CONN => Step_00_CONN}/SESS0000.RSP.OK (100%) delete mode 100644 Documentazione/Euromap63/DemoCom/Step_01_ID/GETINFO.job rename Documentazione/Euromap63/DemoCom/Step_01_ID/{GETINFO.DAT => SESS0001.DAT} (60%) create mode 100644 Documentazione/Euromap63/DemoCom/Step_01_ID/SESS0001.JOB create mode 100644 Documentazione/Euromap63/DemoCom/Step_01_ID/SESS0001.REQ delete mode 100644 Documentazione/Euromap63/DemoCom/Step_01_ID/SESS0005.REQ delete mode 100644 Documentazione/Euromap63/DemoCom/Step_01_INFO/GETINFO.job delete mode 100644 Documentazione/Euromap63/DemoCom/Step_01_INFO/SESS0005.REQ rename Documentazione/Euromap63/DemoCom/{Step_01_INFO/GETINFO.DAT => Step_02_INFO/SESS0002.DAT} (60%) create mode 100644 Documentazione/Euromap63/DemoCom/Step_02_INFO/SESS0002.JOB create mode 100644 Documentazione/Euromap63/DemoCom/Step_02_INFO/SESS0002.REQ rename Documentazione/Euromap63/DemoCom/{Step_02_Descr => Step_04_DESCR}/SESS0014.REQ (100%) rename Documentazione/Euromap63/DemoCom/{Step_02_Descr => Step_04_DESCR}/SetCodU.job (100%) rename Documentazione/Euromap63/DemoCom/{Step_02_Job02 => Step_98_Job02}/SESS0002.REQ (100%) rename Documentazione/Euromap63/DemoCom/{Step_02_Job02 => Step_98_Job02}/SetTime.JOB (100%) rename Documentazione/Euromap63/DemoCom/{Step_02_Job07 => Step_98_Job07}/AbortAll.job (100%) rename Documentazione/Euromap63/DemoCom/{Step_02_Job07 => Step_98_Job07}/SESS0007.REQ (100%) rename Documentazione/Euromap63/DemoCom/{Step_03_JOB03 => Step_99_JOB03}/SESS0003.REQ (100%) rename Documentazione/Euromap63/DemoCom/{Step_03_JOB03 => Step_99_JOB03}/machstat.dat (100%) rename Documentazione/Euromap63/DemoCom/{Step_03_JOB03 => Step_99_JOB03}/machstat.job (100%) rename Documentazione/Euromap63/DemoCom/{Step_03_JOB14 => Step_99_JOB14}/Report14.DAT (100%) rename Documentazione/Euromap63/DemoCom/{Step_03_JOB14 => Step_99_JOB14}/SESS0014.REQ (100%) create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0001.JOB create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0001.REQ create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0002.JOB create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0002.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.REQ b/Documentazione/Euromap63/DemoCom/Step_00_CONN/SESS0000.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.REQ rename to Documentazione/Euromap63/DemoCom/Step_00_CONN/SESS0000.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.RSP.KO b/Documentazione/Euromap63/DemoCom/Step_00_CONN/SESS0000.RSP.KO similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.RSP.KO rename to Documentazione/Euromap63/DemoCom/Step_00_CONN/SESS0000.RSP.KO diff --git a/Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.RSP.OK b/Documentazione/Euromap63/DemoCom/Step_00_CONN/SESS0000.RSP.OK similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_01_CONN/SESS0000.RSP.OK rename to Documentazione/Euromap63/DemoCom/Step_00_CONN/SESS0000.RSP.OK diff --git a/Documentazione/Euromap63/DemoCom/Step_01_ID/GETINFO.job b/Documentazione/Euromap63/DemoCom/Step_01_ID/GETINFO.job deleted file mode 100644 index 6e2fe365..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_01_ID/GETINFO.job +++ /dev/null @@ -1,2 +0,0 @@ -JOB GETINFO RESPONSE "GETINFO.log"; -GETINFO "GETINFO.DAT"; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_01_ID/GETINFO.DAT b/Documentazione/Euromap63/DemoCom/Step_01_ID/SESS0001.DAT similarity index 60% rename from Documentazione/Euromap63/DemoCom/Step_01_ID/GETINFO.DAT rename to Documentazione/Euromap63/DemoCom/Step_01_ID/SESS0001.DAT index 1aa028e9..695f1c08 100644 --- a/Documentazione/Euromap63/DemoCom/Step_01_ID/GETINFO.DAT +++ b/Documentazione/Euromap63/DemoCom/Step_01_ID/SESS0001.DAT @@ -11,5 +11,5 @@ InjUnitNbr, 2; MaterialNbr, ; CharDef, "850"; MaxSessions, 20; -ActiveJobs, "GETID" "MPW280SP\JOB\Info\GETID.job" "MPW280SP\GETID.DAT"; -ActiveJobs, "GETINFO" "MPW280SP\JOB\Info\GETINFO.job" "MPW280SP\GETINFO.DAT"; +ActiveJobs, "GETID" "SESS0001.JOB" "MPW280SP\SESS0001.DAT"; +ActiveJobs, "GETINFO" "SESS0002.JOB" "MPW280SP\SESS0002.DAT"; diff --git a/Documentazione/Euromap63/DemoCom/Step_01_ID/SESS0001.JOB b/Documentazione/Euromap63/DemoCom/Step_01_ID/SESS0001.JOB new file mode 100644 index 00000000..941c2c29 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_01_ID/SESS0001.JOB @@ -0,0 +1,2 @@ +JOB GETID RESPONSE "SESS0001.LOG"; +GETID "SESS0001.DAT"; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_01_ID/SESS0001.REQ b/Documentazione/Euromap63/DemoCom/Step_01_ID/SESS0001.REQ new file mode 100644 index 00000000..72ce2e2b --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_01_ID/SESS0001.REQ @@ -0,0 +1 @@ +SESS0001 EXECUTE "SESS0001.JOB"; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_01_ID/SESS0005.REQ b/Documentazione/Euromap63/DemoCom/Step_01_ID/SESS0005.REQ deleted file mode 100644 index cb18c0b0..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_01_ID/SESS0005.REQ +++ /dev/null @@ -1 +0,0 @@ -REQ_0005 EXECUTE "JOB\Info\GETINFO.job"; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_01_INFO/GETINFO.job b/Documentazione/Euromap63/DemoCom/Step_01_INFO/GETINFO.job deleted file mode 100644 index 6e2fe365..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_01_INFO/GETINFO.job +++ /dev/null @@ -1,2 +0,0 @@ -JOB GETINFO RESPONSE "GETINFO.log"; -GETINFO "GETINFO.DAT"; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_01_INFO/SESS0005.REQ b/Documentazione/Euromap63/DemoCom/Step_01_INFO/SESS0005.REQ deleted file mode 100644 index cb18c0b0..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_01_INFO/SESS0005.REQ +++ /dev/null @@ -1 +0,0 @@ -REQ_0005 EXECUTE "JOB\Info\GETINFO.job"; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_01_INFO/GETINFO.DAT b/Documentazione/Euromap63/DemoCom/Step_02_INFO/SESS0002.DAT similarity index 60% rename from Documentazione/Euromap63/DemoCom/Step_01_INFO/GETINFO.DAT rename to Documentazione/Euromap63/DemoCom/Step_02_INFO/SESS0002.DAT index 1aa028e9..b25a3449 100644 --- a/Documentazione/Euromap63/DemoCom/Step_01_INFO/GETINFO.DAT +++ b/Documentazione/Euromap63/DemoCom/Step_02_INFO/SESS0002.DAT @@ -11,5 +11,5 @@ InjUnitNbr, 2; MaterialNbr, ; CharDef, "850"; MaxSessions, 20; -ActiveJobs, "GETID" "MPW280SP\JOB\Info\GETID.job" "MPW280SP\GETID.DAT"; -ActiveJobs, "GETINFO" "MPW280SP\JOB\Info\GETINFO.job" "MPW280SP\GETINFO.DAT"; +ActiveJobs, "GETID" "MPW280SP\SESS0001.JOB" "MPW280SP\SESS0001.DAT"; +ActiveJobs, "GETINFO" "MPW280SP\SESS0002.JOB" "MPW280SP\SESS0002.DAT"; diff --git a/Documentazione/Euromap63/DemoCom/Step_02_INFO/SESS0002.JOB b/Documentazione/Euromap63/DemoCom/Step_02_INFO/SESS0002.JOB new file mode 100644 index 00000000..3b3ac5a0 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_02_INFO/SESS0002.JOB @@ -0,0 +1,2 @@ +JOB GETINFO RESPONSE "SESS0002.LOG"; +GETINFO "SESS0002.DAT"; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_02_INFO/SESS0002.REQ b/Documentazione/Euromap63/DemoCom/Step_02_INFO/SESS0002.REQ new file mode 100644 index 00000000..cced09c3 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_02_INFO/SESS0002.REQ @@ -0,0 +1 @@ +SESS0002 EXECUTE "SESS0002.JOB"; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_02_Descr/SESS0014.REQ b/Documentazione/Euromap63/DemoCom/Step_04_DESCR/SESS0014.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_02_Descr/SESS0014.REQ rename to Documentazione/Euromap63/DemoCom/Step_04_DESCR/SESS0014.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_02_Descr/SetCodU.job b/Documentazione/Euromap63/DemoCom/Step_04_DESCR/SetCodU.job similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_02_Descr/SetCodU.job rename to Documentazione/Euromap63/DemoCom/Step_04_DESCR/SetCodU.job diff --git a/Documentazione/Euromap63/DemoCom/Step_02_Job02/SESS0002.REQ b/Documentazione/Euromap63/DemoCom/Step_98_Job02/SESS0002.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_02_Job02/SESS0002.REQ rename to Documentazione/Euromap63/DemoCom/Step_98_Job02/SESS0002.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_02_Job02/SetTime.JOB b/Documentazione/Euromap63/DemoCom/Step_98_Job02/SetTime.JOB similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_02_Job02/SetTime.JOB rename to Documentazione/Euromap63/DemoCom/Step_98_Job02/SetTime.JOB diff --git a/Documentazione/Euromap63/DemoCom/Step_02_Job07/AbortAll.job b/Documentazione/Euromap63/DemoCom/Step_98_Job07/AbortAll.job similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_02_Job07/AbortAll.job rename to Documentazione/Euromap63/DemoCom/Step_98_Job07/AbortAll.job diff --git a/Documentazione/Euromap63/DemoCom/Step_02_Job07/SESS0007.REQ b/Documentazione/Euromap63/DemoCom/Step_98_Job07/SESS0007.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_02_Job07/SESS0007.REQ rename to Documentazione/Euromap63/DemoCom/Step_98_Job07/SESS0007.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_03_JOB03/SESS0003.REQ b/Documentazione/Euromap63/DemoCom/Step_99_JOB03/SESS0003.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_03_JOB03/SESS0003.REQ rename to Documentazione/Euromap63/DemoCom/Step_99_JOB03/SESS0003.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_03_JOB03/machstat.dat b/Documentazione/Euromap63/DemoCom/Step_99_JOB03/machstat.dat similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_03_JOB03/machstat.dat rename to Documentazione/Euromap63/DemoCom/Step_99_JOB03/machstat.dat diff --git a/Documentazione/Euromap63/DemoCom/Step_03_JOB03/machstat.job b/Documentazione/Euromap63/DemoCom/Step_99_JOB03/machstat.job similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_03_JOB03/machstat.job rename to Documentazione/Euromap63/DemoCom/Step_99_JOB03/machstat.job diff --git a/Documentazione/Euromap63/DemoCom/Step_03_JOB14/Report14.DAT b/Documentazione/Euromap63/DemoCom/Step_99_JOB14/Report14.DAT similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_03_JOB14/Report14.DAT rename to Documentazione/Euromap63/DemoCom/Step_99_JOB14/Report14.DAT diff --git a/Documentazione/Euromap63/DemoCom/Step_03_JOB14/SESS0014.REQ b/Documentazione/Euromap63/DemoCom/Step_99_JOB14/SESS0014.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_03_JOB14/SESS0014.REQ rename to Documentazione/Euromap63/DemoCom/Step_99_JOB14/SESS0014.REQ diff --git a/IOB-UT/Eurom63.cs b/IOB-UT/Eurom63.cs index f706b32d..519895ff 100644 --- a/IOB-UT/Eurom63.cs +++ b/IOB-UT/Eurom63.cs @@ -33,8 +33,10 @@ namespace IOB_UT { NA = 0, AbortAll, - GetStatus, + GetId, + GetInfo, GetParams, + GetStatus, GetProduction, IsConnected, SetDateTime, @@ -54,8 +56,8 @@ namespace IOB_UT { #region Public Properties - public string FilePath { get; set; } = @"EUR63_JOB\SESS9999.REQ"; public FileOpr OprReq { get; set; } = FileOpr.Copy; + public string Path { get; set; } = @"EUR63_JOB\SESS9999.REQ"; public string RespKo { get; set; } = "ERROR"; public string RespOk { get; set; } = "PROCESSED"; public Dictionary StrReplace { get; set; } = new Dictionary(); diff --git a/IOB-WIN/DATA/CONF/EM63.json b/IOB-WIN/DATA/CONF/EM63.json index c22410d2..21689332 100644 --- a/IOB-WIN/DATA/CONF/EM63.json +++ b/IOB-WIN/DATA/CONF/EM63.json @@ -62,40 +62,65 @@ ], "ActiveSessions": [ { - "Description": "ConnectionStatus", + "Cycle": false, + "Description": "Check Connection Status", + "Max2Keep": 10, "SessionName": "SESS0000", "SessionType": "IsConnected", + "StepOrder": 0, "ValidityMinutes": 1.0, "FileList": [ { - "FileName": "SESS0000.REQ", - "Path": "JOB\\SESS0000.REQ", - //"StrReplace": null, - "Type": "Req" + "Path": "EUR63_JOB\\SESS0000.REQ", + "OprReq": "FileOpr.Copy", + "RespKo": "ERROR", + "RespOk": "PROCESSED" + } + ] + }, + { + "Cycle": false, + "Description": "Get ID data", + "Max2Keep": 10, + "SessionName": "SESS0001", + "SessionType": "GetId", + "StepOrder": 1, + "ValidityMinutes": 1.0, + "FileList": [ + { + "Path": "EUR63_JOB\\SESS0001.REQ", + "OprReq": "FileOpr.Copy", + "RespKo": "ERROR", + "RespOk": "PROCESSED" }, { - "FileName": "SESS0000.JOB", - "Path": "JOB\\SESS0000.JOB", - //"StrReplace": null, - "Type": "Job" + "Path": "EUR63_JOB\\SESS0001.JOB", + "OprReq": "FileOpr.Copy", + "RespKo": "", + "RespOk": "" + } + ] + }, + { + "Cycle": false, + "Description": "Get INFO data", + "Max2Keep": 10, + "SessionName": "SESS0002", + "SessionType": "GetInfo", + "StepOrder": 2, + "ValidityMinutes": 1.0, + "FileList": [ + { + "Path": "EUR63_JOB\\SESS0002.REQ", + "OprReq": "FileOpr.Copy", + "RespKo": "ERROR", + "RespOk": "PROCESSED" }, { - "FileName": "SESS0000.DAT", - "Path": "JOB\\SESS0000.DAT", - //"StrReplace": null, - "Type": "Dat" - }, - { - "FileName": "SESS0000.LOG", - "Path": "JOB\\SESS0000.LOG", - //"StrReplace": null, - "Type": "Log" - }, - { - "FileName": "SESS0000.RSP", - "Path": "JOB\\SESS0000.RSP", - //"StrReplace": null, - "Type": "Rsp" + "Path": "EUR63_JOB\\SESS0002.JOB", + "OprReq": "FileOpr.Copy", + "RespKo": "", + "RespOk": "" } ] }, diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0001.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0001.JOB new file mode 100644 index 00000000..941c2c29 --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0001.JOB @@ -0,0 +1,2 @@ +JOB GETID RESPONSE "SESS0001.LOG"; +GETID "SESS0001.DAT"; \ No newline at end of file diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0001.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0001.REQ new file mode 100644 index 00000000..72ce2e2b --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0001.REQ @@ -0,0 +1 @@ +SESS0001 EXECUTE "SESS0001.JOB"; \ No newline at end of file diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0002.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0002.JOB new file mode 100644 index 00000000..3b3ac5a0 --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0002.JOB @@ -0,0 +1,2 @@ +JOB GETINFO RESPONSE "SESS0002.LOG"; +GETINFO "SESS0002.DAT"; \ No newline at end of file diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0002.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0002.REQ new file mode 100644 index 00000000..cced09c3 --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0002.REQ @@ -0,0 +1 @@ +SESS0002 EXECUTE "SESS0002.JOB"; \ No newline at end of file From 1960694d715e79c561bc00665435f5aa151c1480 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Tue, 6 Oct 2020 22:43:48 +0200 Subject: [PATCH 15/26] Completata conf step set datetime --- .../SESS0003.JOB} | 2 +- .../DemoCom/Step_03_ABORTALL/SESS0003.REQ | 1 + .../DemoCom/Step_04_SETTIME/SESS0004.JOB | 2 + .../DemoCom/Step_04_SETTIME/SESS0004.REQ | 1 + .../SESS0014.REQ | 0 .../SetCodU.job | 0 .../DemoCom/Step_98_Job02/SESS0002.REQ | 1 - .../DemoCom/Step_98_Job02/SetTime.JOB | 2 - .../DemoCom/Step_98_Job07/SESS0007.REQ | 1 - IOB-UT/Eurom63.cs | 2 +- IOB-WIN/DATA/CONF/EM63.json | 126 +++++++----------- IOB-WIN/DATA/EUR63_JOB/SESS0003.JOB | 7 + IOB-WIN/DATA/EUR63_JOB/SESS0003.REQ | 1 + IOB-WIN/DATA/EUR63_JOB/SESS0004.JOB | 2 + IOB-WIN/DATA/EUR63_JOB/SESS0004.REQ | 1 + 15 files changed, 68 insertions(+), 81 deletions(-) rename Documentazione/Euromap63/DemoCom/{Step_98_Job07/AbortAll.job => Step_03_ABORTALL/SESS0003.JOB} (74%) create mode 100644 Documentazione/Euromap63/DemoCom/Step_03_ABORTALL/SESS0003.REQ create mode 100644 Documentazione/Euromap63/DemoCom/Step_04_SETTIME/SESS0004.JOB create mode 100644 Documentazione/Euromap63/DemoCom/Step_04_SETTIME/SESS0004.REQ rename Documentazione/Euromap63/DemoCom/{Step_04_DESCR => Step_05_DESCR}/SESS0014.REQ (100%) rename Documentazione/Euromap63/DemoCom/{Step_04_DESCR => Step_05_DESCR}/SetCodU.job (100%) delete mode 100644 Documentazione/Euromap63/DemoCom/Step_98_Job02/SESS0002.REQ delete mode 100644 Documentazione/Euromap63/DemoCom/Step_98_Job02/SetTime.JOB delete mode 100644 Documentazione/Euromap63/DemoCom/Step_98_Job07/SESS0007.REQ create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0003.JOB create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0003.REQ create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0004.JOB create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0004.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_98_Job07/AbortAll.job b/Documentazione/Euromap63/DemoCom/Step_03_ABORTALL/SESS0003.JOB similarity index 74% rename from Documentazione/Euromap63/DemoCom/Step_98_Job07/AbortAll.job rename to Documentazione/Euromap63/DemoCom/Step_03_ABORTALL/SESS0003.JOB index 84f8d10e..881afaa9 100644 --- a/Documentazione/Euromap63/DemoCom/Step_98_Job07/AbortAll.job +++ b/Documentazione/Euromap63/DemoCom/Step_03_ABORTALL/SESS0003.JOB @@ -1,4 +1,4 @@ -JOB Abort1 RESPONSE "AbortAll.Log"; +JOB Abort1 RESPONSE "SESS0003.LOG"; //ABORT EVENT Event1; //ABORT ALL REPORTS; diff --git a/Documentazione/Euromap63/DemoCom/Step_03_ABORTALL/SESS0003.REQ b/Documentazione/Euromap63/DemoCom/Step_03_ABORTALL/SESS0003.REQ new file mode 100644 index 00000000..f14fbdf4 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_03_ABORTALL/SESS0003.REQ @@ -0,0 +1 @@ +SESS0003 EXECUTE "SESS0003.JOB"; diff --git a/Documentazione/Euromap63/DemoCom/Step_04_SETTIME/SESS0004.JOB b/Documentazione/Euromap63/DemoCom/Step_04_SETTIME/SESS0004.JOB new file mode 100644 index 00000000..2e412db3 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_04_SETTIME/SESS0004.JOB @@ -0,0 +1,2 @@ +JOB ImpostaOrario RESPONSE "SESS0004.LOG"; +SET SetTimMach {DTNow}; diff --git a/Documentazione/Euromap63/DemoCom/Step_04_SETTIME/SESS0004.REQ b/Documentazione/Euromap63/DemoCom/Step_04_SETTIME/SESS0004.REQ new file mode 100644 index 00000000..d29e9602 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_04_SETTIME/SESS0004.REQ @@ -0,0 +1 @@ +SESS0004 EXECUTE "SESS0004.JOB"; diff --git a/Documentazione/Euromap63/DemoCom/Step_04_DESCR/SESS0014.REQ b/Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0014.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_04_DESCR/SESS0014.REQ rename to Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0014.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_04_DESCR/SetCodU.job b/Documentazione/Euromap63/DemoCom/Step_05_DESCR/SetCodU.job similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_04_DESCR/SetCodU.job rename to Documentazione/Euromap63/DemoCom/Step_05_DESCR/SetCodU.job diff --git a/Documentazione/Euromap63/DemoCom/Step_98_Job02/SESS0002.REQ b/Documentazione/Euromap63/DemoCom/Step_98_Job02/SESS0002.REQ deleted file mode 100644 index b5f5020f..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_98_Job02/SESS0002.REQ +++ /dev/null @@ -1 +0,0 @@ -REQ_002 EXECUTE "SetTime.JOB"; diff --git a/Documentazione/Euromap63/DemoCom/Step_98_Job02/SetTime.JOB b/Documentazione/Euromap63/DemoCom/Step_98_Job02/SetTime.JOB deleted file mode 100644 index a1457184..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_98_Job02/SetTime.JOB +++ /dev/null @@ -1,2 +0,0 @@ -JOB ImpostaOrario RESPONSE "SetTimeMach.rsp"; -SET SetTimMach 18370020201005; diff --git a/Documentazione/Euromap63/DemoCom/Step_98_Job07/SESS0007.REQ b/Documentazione/Euromap63/DemoCom/Step_98_Job07/SESS0007.REQ deleted file mode 100644 index 5617d5fd..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_98_Job07/SESS0007.REQ +++ /dev/null @@ -1 +0,0 @@ -REQ_0007 EXECUTE "JOB\AbortJobs\AbortAll.job"; diff --git a/IOB-UT/Eurom63.cs b/IOB-UT/Eurom63.cs index 519895ff..7e99e0ff 100644 --- a/IOB-UT/Eurom63.cs +++ b/IOB-UT/Eurom63.cs @@ -57,7 +57,7 @@ namespace IOB_UT #region Public Properties public FileOpr OprReq { get; set; } = FileOpr.Copy; - public string Path { get; set; } = @"EUR63_JOB\SESS9999.REQ"; + public string Path { get; set; } = @"EUR63_JOB\SESS9999.FILE"; public string RespKo { get; set; } = "ERROR"; public string RespOk { get; set; } = "PROCESSED"; public Dictionary StrReplace { get; set; } = new Dictionary(); diff --git a/IOB-WIN/DATA/CONF/EM63.json b/IOB-WIN/DATA/CONF/EM63.json index 21689332..80173636 100644 --- a/IOB-WIN/DATA/CONF/EM63.json +++ b/IOB-WIN/DATA/CONF/EM63.json @@ -68,7 +68,7 @@ "SessionName": "SESS0000", "SessionType": "IsConnected", "StepOrder": 0, - "ValidityMinutes": 1.0, + "ValidityMinutes": 0.0, "FileList": [ { "Path": "EUR63_JOB\\SESS0000.REQ", @@ -85,7 +85,7 @@ "SessionName": "SESS0001", "SessionType": "GetId", "StepOrder": 1, - "ValidityMinutes": 1.0, + "ValidityMinutes": 0.0, "FileList": [ { "Path": "EUR63_JOB\\SESS0001.REQ", @@ -101,23 +101,46 @@ } ] }, + //{ + // "Cycle": false, + // "Description": "Get INFO data", + // "Max2Keep": 10, + // "SessionName": "SESS0002", + // "SessionType": "GetInfo", + // "StepOrder": 2, + // "ValidityMinutes": 0.0, + // "FileList": [ + // { + // "Path": "EUR63_JOB\\SESS0002.REQ", + // "OprReq": "FileOpr.Copy", + // "RespKo": "ERROR", + // "RespOk": "PROCESSED" + // }, + // { + // "Path": "EUR63_JOB\\SESS0002.JOB", + // "OprReq": "FileOpr.Copy", + // "RespKo": "", + // "RespOk": "" + // } + // ] + //}, { "Cycle": false, - "Description": "Get INFO data", + "Description": "Abort All prev requests", + "SessionName": "SESS0003", + "SessionType": "AbortAll", + "ValidityMinutes": 0.0, "Max2Keep": 10, - "SessionName": "SESS0002", - "SessionType": "GetInfo", - "StepOrder": 2, - "ValidityMinutes": 1.0, + "StepOrder": 3, "FileList": [ { - "Path": "EUR63_JOB\\SESS0002.REQ", + "Path": "EUR63_JOB\\SESS0003.REQ", "OprReq": "FileOpr.Copy", "RespKo": "ERROR", "RespOk": "PROCESSED" }, { - "Path": "EUR63_JOB\\SESS0002.JOB", + "Path": "EUR63_JOB\\SESS0003.JOB", "OprReq": "FileOpr.Copy", "RespKo": "", "RespOk": "" @@ -125,78 +148,31 @@ ] }, { - "Description": "Abort All prev requests", - "SessionName": "SESS0001", - "SessionType": "AbortAll", - "ValidityMinutes": 0, - "FileList": [ - { - "FileName": "SESS0001.REQ", - "Path": "JOB\\SESS0001.REQ", - //"StrReplace": null, - "Type": "Req" - }, - { - "FileName": "SESS0001.JOB", - "Path": "JOB\\SESS0001.JOB", - //"StrReplace": null, - "Type": "Job" - }, - { - "FileName": "SESS0001.DAT", - "Path": "JOB\\SESS0001.DAT", - //"StrReplace": null, - "Type": "Dat" - }, - { - "FileName": "SESS0001.LOG", - "Path": "JOB\\SESS0001.LOG", - //"StrReplace": null, - "Type": "Log" - }, - { - "FileName": "SESS0001.RSP", - "Path": "JOB\\SESS0001.RSP", - //"StrReplace": null, - "Type": "Rsp" - } - ] - }, - { + "Cycle": false, "Description": "Set DateTime on machine at start", - "SessionName": "SESS0002", + "SessionName": "SESS0004", "SessionType": "SetDateTime", - "ValidityMinutes": 0, + "ValidityMinutes": 0.0, + "Max2Keep": 10, + "StepOrder": 4, "FileList": [ { - "FileName": "SESS0002.REQ", - "Path": "JOB\\SESS0002.REQ", - //"StrReplace": null, - "Type": "Req" + "Path": "EUR63_JOB\\SESS0004.REQ", + "OprReq": "FileOpr.Copy", + "RespKo": "ERROR", + "RespOk": "PROCESSED" }, { - "FileName": "SESS0002.JOB", - "Path": "JOB\\SESS0002.JOB", - //"StrReplace": null, - "Type": "Job" - }, - { - "FileName": "SESS0002.DAT", - "Path": "JOB\\SESS0002.DAT", - //"StrReplace": null, - "Type": "Dat" - }, - { - "FileName": "SESS0002.LOG", - "Path": "JOB\\SESS0002.LOG", - //"StrReplace": null, - "Type": "Log" - }, - { - "FileName": "SESS0002.RSP", - "Path": "JOB\\SESS0002.RSP", - //"StrReplace": null, - "Type": "Rsp" + "Path": "EUR63_JOB\\SESS0004.JOB", + "OprReq": "FileOpr.ReplaceAndCopy", + "RespKo": "", + "RespOk": "", + "StrReplace": [ + { + "key": "{DTNow}", + "value": "DateTime.Now" + } + ] } ] } diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0003.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0003.JOB new file mode 100644 index 00000000..881afaa9 --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0003.JOB @@ -0,0 +1,7 @@ +JOB Abort1 RESPONSE "SESS0003.LOG"; + +//ABORT EVENT Event1; +//ABORT ALL REPORTS; +//ABORT JOB Job1Name; +ABORT ALL JOBS; +//ABORT REPORT Report1Name; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0003.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0003.REQ new file mode 100644 index 00000000..f14fbdf4 --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0003.REQ @@ -0,0 +1 @@ +SESS0003 EXECUTE "SESS0003.JOB"; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0004.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0004.JOB new file mode 100644 index 00000000..2e412db3 --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0004.JOB @@ -0,0 +1,2 @@ +JOB ImpostaOrario RESPONSE "SESS0004.LOG"; +SET SetTimMach {DTNow}; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0004.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0004.REQ new file mode 100644 index 00000000..d29e9602 --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0004.REQ @@ -0,0 +1 @@ +SESS0004 EXECUTE "SESS0004.JOB"; From 0eca9cb13675a26b1adcdc9435dc4a4c2e83835f Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Tue, 6 Oct 2020 23:00:41 +0200 Subject: [PATCH 16/26] Completato setup conf file Euromap63 x prod/status --- .../DemoCom/Step_05_DESCR/SESS0005.JOB | 19 +++ .../DemoCom/Step_05_DESCR/SESS0005.REQ | 1 + .../DemoCom/Step_05_DESCR/SESS0014.REQ | 1 - .../DemoCom/Step_05_DESCR/SetCodU.job | 14 -- .../SESS0006.DAT} | 0 .../DemoCom/Step_06_STATUS/SESS0006.JOB | 11 ++ .../DemoCom/Step_06_STATUS/SESS0006.REQ | 1 + .../SESS0007.DAT} | 0 .../DemoCom/Step_07_PROD/SESS0007.JOB | 11 ++ .../DemoCom/Step_07_PROD/SESS0007.REQ | 1 + .../DemoCom/Step_99_JOB03/SESS0003.REQ | 1 - .../DemoCom/Step_99_JOB03/machstat.job | 12 -- .../DemoCom/Step_99_JOB14/SESS0014.REQ | 1 - IOB-UT/Eurom63.cs | 2 + IOB-WIN/DATA/CONF/EM63.json | 123 +++++++++++++----- IOB-WIN/DATA/EUR63_JOB/SESS0005.JOB | 19 +++ IOB-WIN/DATA/EUR63_JOB/SESS0005.REQ | 1 + IOB-WIN/DATA/EUR63_JOB/SESS0006.JOB | 11 ++ IOB-WIN/DATA/EUR63_JOB/SESS0006.REQ | 1 + IOB-WIN/DATA/EUR63_JOB/SESS0007.JOB | 11 ++ IOB-WIN/DATA/EUR63_JOB/SESS0007.REQ | 1 + 21 files changed, 183 insertions(+), 59 deletions(-) create mode 100644 Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0005.JOB create mode 100644 Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0005.REQ delete mode 100644 Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0014.REQ delete mode 100644 Documentazione/Euromap63/DemoCom/Step_05_DESCR/SetCodU.job rename Documentazione/Euromap63/DemoCom/{Step_99_JOB03/machstat.dat => Step_06_STATUS/SESS0006.DAT} (100%) create mode 100644 Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.JOB create mode 100644 Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.REQ rename Documentazione/Euromap63/DemoCom/{Step_99_JOB14/Report14.DAT => Step_07_PROD/SESS0007.DAT} (100%) create mode 100644 Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.JOB create mode 100644 Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.REQ delete mode 100644 Documentazione/Euromap63/DemoCom/Step_99_JOB03/SESS0003.REQ delete mode 100644 Documentazione/Euromap63/DemoCom/Step_99_JOB03/machstat.job delete mode 100644 Documentazione/Euromap63/DemoCom/Step_99_JOB14/SESS0014.REQ create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0005.JOB create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0005.REQ create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0006.JOB create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0006.REQ create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0007.JOB create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0007.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0005.JOB b/Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0005.JOB new file mode 100644 index 00000000..bc3956cb --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0005.JOB @@ -0,0 +1,19 @@ +JOB SetID RESPONSE "SESS0005.LOG"; +//SET SetDescJob " "; +//SET SetDescPrt " " +//SET SetDescMld " "; +//SET SetDescOp " "; + +SET SetDescJob {ODL}; +SET SetDescPrt {DescrArt}; +SET SetDescMld {CodArt}; +SET SetDescOp {CodOpr}; + +//SET SetDescJob "Nr. 1000987654.01"; +//SET SetDescPrt "STICK: 8 componenti SENZA assemblaggio"; +//SET SetDescMld "Stampo componenti a 8 impronte"; +//SET SetDescOp "Operatore 01"; + +//SET SetCntMld 2; +//SET SetCntPrt 10000; +//SET SetCntPrtBox 20; diff --git a/Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0005.REQ b/Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0005.REQ new file mode 100644 index 00000000..34cd11bc --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0005.REQ @@ -0,0 +1 @@ +SESS0005 EXECUTE "SESS0005.JOB"; diff --git a/Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0014.REQ b/Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0014.REQ deleted file mode 100644 index dff494c5..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0014.REQ +++ /dev/null @@ -1 +0,0 @@ -REQ_0014 EXECUTE "SetCodU.job"; diff --git a/Documentazione/Euromap63/DemoCom/Step_05_DESCR/SetCodU.job b/Documentazione/Euromap63/DemoCom/Step_05_DESCR/SetCodU.job deleted file mode 100644 index bee58bb2..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_05_DESCR/SetCodU.job +++ /dev/null @@ -1,14 +0,0 @@ -JOB SetID RESPONSE "SetCodU.log"; -//SET SetDescJob " "; -//SET SetDescPrt " " -//SET SetDescMld " "; -//SET SetDescOp " "; - -SET SetDescJob "Nr. 1000987654.01"; -SET SetDescPrt "STICK: 8 componenti SENZA assemblaggio"; -SET SetDescMld "Stampo componenti a 8 impronte"; -SET SetDescOp "Operatore 01"; - -//SET SetCntMld 2; -//SET SetCntPrt 10000; -//SET SetCntPrtBox 20; diff --git a/Documentazione/Euromap63/DemoCom/Step_99_JOB03/machstat.dat b/Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.DAT similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_99_JOB03/machstat.dat rename to Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.DAT diff --git a/Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.JOB b/Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.JOB new file mode 100644 index 00000000..e39fb861 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.JOB @@ -0,0 +1,11 @@ +JOB machstat RESPONSE "SESS0006.LOG"; + +REPORT status REWRITE "SESS0006.DAT" +START IMMEDIATE +STOP NEVER +CYCLIC TIME 00:00:01 +SESSIONS 60 +PARAMETERS +DATE, TIME, ActStsMach; + + diff --git a/Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.REQ b/Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.REQ new file mode 100644 index 00000000..4a185f17 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.REQ @@ -0,0 +1 @@ +SESS0006 EXECUTE "SESS0006.JOB"; diff --git a/Documentazione/Euromap63/DemoCom/Step_99_JOB14/Report14.DAT b/Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.DAT similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_99_JOB14/Report14.DAT rename to Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.DAT diff --git a/Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.JOB b/Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.JOB new file mode 100644 index 00000000..3022aab8 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.JOB @@ -0,0 +1,11 @@ +JOB machstat RESPONSE "SESS0007.LOG"; + +REPORT status REWRITE "SESS0007.DAT" +START IMMEDIATE +STOP NEVER +CYCLIC TIME 00:00:02 +SESSIONS 30 +PARAMETERS +DATE, TIME, ActCntCyc, ActTimCyc, ActTimFill, @OutXhour, SetDescJob; + + diff --git a/Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.REQ b/Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.REQ new file mode 100644 index 00000000..de4d0350 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.REQ @@ -0,0 +1 @@ +SESS0007 EXECUTE "SESS0007.JOB"; diff --git a/Documentazione/Euromap63/DemoCom/Step_99_JOB03/SESS0003.REQ b/Documentazione/Euromap63/DemoCom/Step_99_JOB03/SESS0003.REQ deleted file mode 100644 index 61ab85cb..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_99_JOB03/SESS0003.REQ +++ /dev/null @@ -1 +0,0 @@ -REQ_0003 EXECUTE "JOB\Report\machstat.job"; diff --git a/Documentazione/Euromap63/DemoCom/Step_99_JOB03/machstat.job b/Documentazione/Euromap63/DemoCom/Step_99_JOB03/machstat.job deleted file mode 100644 index 8be4143e..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_99_JOB03/machstat.job +++ /dev/null @@ -1,12 +0,0 @@ -JOB machstat RESPONSE "machstat.log"; - -REPORT status REWRITE "machstat.dat" -START IMMEDIATE -//START TIME>= 10:25:00 -STOP NEVER -CYCLIC TIME 00:01:00 -//SESSIONS 10 -PARAMETERS -DATE, TIME, ActStsMach; - - diff --git a/Documentazione/Euromap63/DemoCom/Step_99_JOB14/SESS0014.REQ b/Documentazione/Euromap63/DemoCom/Step_99_JOB14/SESS0014.REQ deleted file mode 100644 index 9e05b52b..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_99_JOB14/SESS0014.REQ +++ /dev/null @@ -1 +0,0 @@ -REQ_0014 EXECUTE "JOB\Report\Report14.job"; diff --git a/IOB-UT/Eurom63.cs b/IOB-UT/Eurom63.cs index 7e99e0ff..275a0087 100644 --- a/IOB-UT/Eurom63.cs +++ b/IOB-UT/Eurom63.cs @@ -60,7 +60,9 @@ namespace IOB_UT public string Path { get; set; } = @"EUR63_JOB\SESS9999.FILE"; public string RespKo { get; set; } = "ERROR"; public string RespOk { get; set; } = "PROCESSED"; +#if false public Dictionary StrReplace { get; set; } = new Dictionary(); +#endif #endregion Public Properties } diff --git a/IOB-WIN/DATA/CONF/EM63.json b/IOB-WIN/DATA/CONF/EM63.json index 80173636..8a9f1c12 100644 --- a/IOB-WIN/DATA/CONF/EM63.json +++ b/IOB-WIN/DATA/CONF/EM63.json @@ -101,29 +101,29 @@ } ] }, - //{ - // "Cycle": false, - // "Description": "Get INFO data", - // "Max2Keep": 10, - // "SessionName": "SESS0002", - // "SessionType": "GetInfo", - // "StepOrder": 2, - // "ValidityMinutes": 0.0, - // "FileList": [ - // { - // "Path": "EUR63_JOB\\SESS0002.REQ", - // "OprReq": "FileOpr.Copy", - // "RespKo": "ERROR", - // "RespOk": "PROCESSED" - // }, - // { - // "Path": "EUR63_JOB\\SESS0002.JOB", - // "OprReq": "FileOpr.Copy", - // "RespKo": "", - // "RespOk": "" - // } - // ] - //}, + { + "Cycle": false, + "Description": "Get INFO data", + "Max2Keep": 10, + "SessionName": "SESS0002", + "SessionType": "GetInfo", + "StepOrder": 99, + "ValidityMinutes": 0.0, + "FileList": [ + { + "Path": "EUR63_JOB\\SESS0002.REQ", + "OprReq": "FileOpr.Copy", + "RespKo": "ERROR", + "RespOk": "PROCESSED" + }, + { + "Path": "EUR63_JOB\\SESS0002.JOB", + "OprReq": "FileOpr.Copy", + "RespKo": "", + "RespOk": "" + } + ] + }, { "Cycle": false, "Description": "Abort All prev requests", @@ -166,13 +166,76 @@ "Path": "EUR63_JOB\\SESS0004.JOB", "OprReq": "FileOpr.ReplaceAndCopy", "RespKo": "", - "RespOk": "", - "StrReplace": [ - { - "key": "{DTNow}", - "value": "DateTime.Now" - } - ] + "RespOk": "" + } + ] + }, + { + "Cycle": false, + "Description": "Set Param ODL at Setup", + "SessionName": "SESS0005", + "SessionType": "SetParamOdl", + "ValidityMinutes": 0.0, + "Max2Keep": 10, + "StepOrder": 5, + "FileList": [ + { + "Path": "EUR63_JOB\\SESS0005.REQ", + "OprReq": "FileOpr.Copy", + "RespKo": "ERROR", + "RespOk": "PROCESSED" + }, + { + "Path": "EUR63_JOB\\SESS0005.JOB", + "OprReq": "FileOpr.ReplaceAndCopy", + "RespKo": "", + "RespOk": "" + } + ] + }, + { + "Cycle": false, + "Description": "Get Machine Status", + "SessionName": "SESS0006", + "SessionType": "GetStatus", + "ValidityMinutes": 1.0, + "Max2Keep": 120, + "StepOrder": 6, + "FileList": [ + { + "Path": "EUR63_JOB\\SESS0006.REQ", + "OprReq": "FileOpr.Copy", + "RespKo": "ERROR", + "RespOk": "PROCESSED" + }, + { + "Path": "EUR63_JOB\\SESS0006.JOB", + "OprReq": "FileOpr.Copy", + "RespKo": "", + "RespOk": "" + } + ] + }, + { + "Cycle": false, + "Description": "Get Production", + "SessionName": "SESS0007", + "SessionType": "GetProduction", + "ValidityMinutes": 1.0, + "Max2Keep": 120, + "StepOrder": 7, + "FileList": [ + { + "Path": "EUR63_JOB\\SESS0007.REQ", + "OprReq": "FileOpr.Copy", + "RespKo": "ERROR", + "RespOk": "PROCESSED" + }, + { + "Path": "EUR63_JOB\\SESS0007.JOB", + "OprReq": "FileOpr.Copy", + "RespKo": "", + "RespOk": "" } ] } diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0005.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0005.JOB new file mode 100644 index 00000000..bc3956cb --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0005.JOB @@ -0,0 +1,19 @@ +JOB SetID RESPONSE "SESS0005.LOG"; +//SET SetDescJob " "; +//SET SetDescPrt " " +//SET SetDescMld " "; +//SET SetDescOp " "; + +SET SetDescJob {ODL}; +SET SetDescPrt {DescrArt}; +SET SetDescMld {CodArt}; +SET SetDescOp {CodOpr}; + +//SET SetDescJob "Nr. 1000987654.01"; +//SET SetDescPrt "STICK: 8 componenti SENZA assemblaggio"; +//SET SetDescMld "Stampo componenti a 8 impronte"; +//SET SetDescOp "Operatore 01"; + +//SET SetCntMld 2; +//SET SetCntPrt 10000; +//SET SetCntPrtBox 20; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0005.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0005.REQ new file mode 100644 index 00000000..34cd11bc --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0005.REQ @@ -0,0 +1 @@ +SESS0005 EXECUTE "SESS0005.JOB"; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0006.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0006.JOB new file mode 100644 index 00000000..e39fb861 --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0006.JOB @@ -0,0 +1,11 @@ +JOB machstat RESPONSE "SESS0006.LOG"; + +REPORT status REWRITE "SESS0006.DAT" +START IMMEDIATE +STOP NEVER +CYCLIC TIME 00:00:01 +SESSIONS 60 +PARAMETERS +DATE, TIME, ActStsMach; + + diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0006.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0006.REQ new file mode 100644 index 00000000..4a185f17 --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0006.REQ @@ -0,0 +1 @@ +SESS0006 EXECUTE "SESS0006.JOB"; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0007.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0007.JOB new file mode 100644 index 00000000..3022aab8 --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0007.JOB @@ -0,0 +1,11 @@ +JOB machstat RESPONSE "SESS0007.LOG"; + +REPORT status REWRITE "SESS0007.DAT" +START IMMEDIATE +STOP NEVER +CYCLIC TIME 00:00:02 +SESSIONS 30 +PARAMETERS +DATE, TIME, ActCntCyc, ActTimCyc, ActTimFill, @OutXhour, SetDescJob; + + diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0007.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0007.REQ new file mode 100644 index 00000000..de4d0350 --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0007.REQ @@ -0,0 +1 @@ +SESS0007 EXECUTE "SESS0007.JOB"; From eae72b26710f671fd49aed7c426a785e5d6b8f94 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Tue, 6 Oct 2020 23:02:45 +0200 Subject: [PATCH 17/26] refresh compilazione --- CVCncLib/CVCncLib.dll | Bin 967680 -> 967680 bytes IOB-WIN/IOB-WIN.csproj | 7 +++++++ 2 files changed, 7 insertions(+) diff --git a/CVCncLib/CVCncLib.dll b/CVCncLib/CVCncLib.dll index 7a3680a51e0e8a608097b279e6cda691346cf151..484da646f1ab38b63035e825e06911e99a3deb8b 100644 GIT binary patch delta 169 zcmZqZux{wEp3uR}eY>WyyS1CKwVSE6o4K`{rL~*2wVSQAo4vK0qqUo}wVSK8n|o_F zkL5yvWra>UhqY53dmJB5SoAZ~wEfCL9w6r3eq|xwA3g`5QSl5wzy!oHj0_Af&hat4 z*ucjS6zmdwaPd6nm`T4Kx5$JUmKQIW3zTMXwu%WYPAw{qDNf8SP0dN2F20dZjdj(X)qZ6m4-oTizp{|;51%{GsCWh-U;<(pMh1o#=lB?2 zY~W)E3U&!Lov(KO`q@H{2`QJgH(uI21t`tnY!wq)oLW>IQ=FJvnwpcUS6q^sm|H$w UU?ZR0bp4Hd=eM(L;`<{A0L%+OrT_o{ diff --git a/IOB-WIN/IOB-WIN.csproj b/IOB-WIN/IOB-WIN.csproj index efbbb7f1..9f482b23 100644 --- a/IOB-WIN/IOB-WIN.csproj +++ b/IOB-WIN/IOB-WIN.csproj @@ -504,6 +504,13 @@ Always + + Always + + + + Always + From eb1a82d897baf22d2c195fffb3615cf0dff9fd9b Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Wed, 7 Oct 2020 10:16:09 +0200 Subject: [PATCH 18/26] Update x deserializzare correttamente conf EM63 --- IOB-UT/Eurom63.cs | 6 +-- IOB-WIN/DATA/CONF/EM63.json | 96 +++++++++++-------------------------- 2 files changed, 28 insertions(+), 74 deletions(-) diff --git a/IOB-UT/Eurom63.cs b/IOB-UT/Eurom63.cs index 275a0087..dfb85a5a 100644 --- a/IOB-UT/Eurom63.cs +++ b/IOB-UT/Eurom63.cs @@ -45,8 +45,6 @@ namespace IOB_UT #endregion Public Enums - - #region Public Classes /// @@ -141,12 +139,10 @@ namespace IOB_UT { #region Public Fields - public List ActiveSessions = new List(); + public Dictionary ActiveSessions = new Dictionary(); #endregion Public Fields - - #region Public Properties public string BaseDir { get; set; } = @"C:\EUROMAP63\"; diff --git a/IOB-WIN/DATA/CONF/EM63.json b/IOB-WIN/DATA/CONF/EM63.json index 8a9f1c12..28054657 100644 --- a/IOB-WIN/DATA/CONF/EM63.json +++ b/IOB-WIN/DATA/CONF/EM63.json @@ -2,7 +2,7 @@ "BaseDir": "C:\\NPM_E63\\E63\\MPW280SP", "DynData": [ { - "key": "", + "key": "CLOCK_1", "name": "CLOCK_1", "val": "ct4", "unit": "DateTime", @@ -10,58 +10,16 @@ "sPeriod": 10 }, { - "key": "", + "key": "CLOCK_2", "name": "CLOCK_2", "val": "ct4", "unit": "DateTime", "func": "SAMPLE", "sPeriod": 10 } - //{ - // "key": "ANALOGINPUTSR0C1", - // "val": "ANALOGINPUTSR0C2", - // "unit": "bar", - // "func": "CHANGE", - // "sPeriod": 3600 - //}, - //{ - // "key": "ANALOGINPUTSR1C1", - // "val": "ANALOGINPUTSR1C2", - // "unit": "°C", - // "func": "CHANGE", - // "sPeriod": 3600 - //}, - //{ - // "key": "ANALOGINPUTSR2C1", - // "val": "ANALOGINPUTSR2C2", - // "unit": "°C", - // "func": "CHANGE", - // "sPeriod": 3600 - //}, - //{ - // "key": "COUNTERSR0C1", - // "val": "COUNTERSR0C2", - // "unit": "ore", - // "func": "CHANGE", - // "sPeriod": 3600 - //}, - //{ - // "key": "COUNTERSR2C1", - // "val": "COUNTERSR2C2", - // "unit": "#", - // "func": "CHANGE", - // "sPeriod": 3600 - //}, - //{ - // "key": "DIGITALINPUTSR0C1", - // "val": "DIGITALINPUTSR0C2", - // "unit": "ENUM", - // "func": "CHANGE", - // "sPeriod": 3600 - //} ], - "ActiveSessions": [ - { + "ActiveSessions": { + "0": { "Cycle": false, "Description": "Check Connection Status", "Max2Keep": 10, @@ -72,13 +30,13 @@ "FileList": [ { "Path": "EUR63_JOB\\SESS0000.REQ", - "OprReq": "FileOpr.Copy", + "OprReq": "Copy", "RespKo": "ERROR", "RespOk": "PROCESSED" } ] }, - { + "1": { "Cycle": false, "Description": "Get ID data", "Max2Keep": 10, @@ -89,19 +47,19 @@ "FileList": [ { "Path": "EUR63_JOB\\SESS0001.REQ", - "OprReq": "FileOpr.Copy", + "OprReq": "Copy", "RespKo": "ERROR", "RespOk": "PROCESSED" }, { "Path": "EUR63_JOB\\SESS0001.JOB", - "OprReq": "FileOpr.Copy", + "OprReq": "Copy", "RespKo": "", "RespOk": "" } ] }, - { + "99": { "Cycle": false, "Description": "Get INFO data", "Max2Keep": 10, @@ -112,19 +70,19 @@ "FileList": [ { "Path": "EUR63_JOB\\SESS0002.REQ", - "OprReq": "FileOpr.Copy", + "OprReq": "Copy", "RespKo": "ERROR", "RespOk": "PROCESSED" }, { "Path": "EUR63_JOB\\SESS0002.JOB", - "OprReq": "FileOpr.Copy", + "OprReq": "Copy", "RespKo": "", "RespOk": "" } ] }, - { + "3": { "Cycle": false, "Description": "Abort All prev requests", "SessionName": "SESS0003", @@ -135,19 +93,19 @@ "FileList": [ { "Path": "EUR63_JOB\\SESS0003.REQ", - "OprReq": "FileOpr.Copy", + "OprReq": "Copy", "RespKo": "ERROR", "RespOk": "PROCESSED" }, { "Path": "EUR63_JOB\\SESS0003.JOB", - "OprReq": "FileOpr.Copy", + "OprReq": "Copy", "RespKo": "", "RespOk": "" } ] }, - { + "4": { "Cycle": false, "Description": "Set DateTime on machine at start", "SessionName": "SESS0004", @@ -158,19 +116,19 @@ "FileList": [ { "Path": "EUR63_JOB\\SESS0004.REQ", - "OprReq": "FileOpr.Copy", + "OprReq": "Copy", "RespKo": "ERROR", "RespOk": "PROCESSED" }, { "Path": "EUR63_JOB\\SESS0004.JOB", - "OprReq": "FileOpr.ReplaceAndCopy", + "OprReq": "ReplaceAndCopy", "RespKo": "", "RespOk": "" } ] }, - { + "5": { "Cycle": false, "Description": "Set Param ODL at Setup", "SessionName": "SESS0005", @@ -181,19 +139,19 @@ "FileList": [ { "Path": "EUR63_JOB\\SESS0005.REQ", - "OprReq": "FileOpr.Copy", + "OprReq": "Copy", "RespKo": "ERROR", "RespOk": "PROCESSED" }, { "Path": "EUR63_JOB\\SESS0005.JOB", - "OprReq": "FileOpr.ReplaceAndCopy", + "OprReq": "ReplaceAndCopy", "RespKo": "", "RespOk": "" } ] }, - { + "6": { "Cycle": false, "Description": "Get Machine Status", "SessionName": "SESS0006", @@ -204,19 +162,19 @@ "FileList": [ { "Path": "EUR63_JOB\\SESS0006.REQ", - "OprReq": "FileOpr.Copy", + "OprReq": "Copy", "RespKo": "ERROR", "RespOk": "PROCESSED" }, { "Path": "EUR63_JOB\\SESS0006.JOB", - "OprReq": "FileOpr.Copy", + "OprReq": "Copy", "RespKo": "", "RespOk": "" } ] }, - { + "7": { "Cycle": false, "Description": "Get Production", "SessionName": "SESS0007", @@ -227,17 +185,17 @@ "FileList": [ { "Path": "EUR63_JOB\\SESS0007.REQ", - "OprReq": "FileOpr.Copy", + "OprReq": "Copy", "RespKo": "ERROR", "RespOk": "PROCESSED" }, { "Path": "EUR63_JOB\\SESS0007.JOB", - "OprReq": "FileOpr.Copy", + "OprReq": "Copy", "RespKo": "", "RespOk": "" } ] } - ] + } } \ No newline at end of file From 0e7bb96f36c8450fd6488436d3359c5046236d18 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Wed, 7 Oct 2020 15:29:05 +0200 Subject: [PATCH 19/26] OK conf x pulizia preliminare directory --- IOB-UT/Eurom63.cs | 33 +++++----- IOB-WIN/DATA/CONF/EM63.json | 7 +++ IOB-WIN/IobFile.cs | 121 +++++++++++++++--------------------- IOB-WIN/IobFileEurom63.cs | 34 +++++++++- 4 files changed, 104 insertions(+), 91 deletions(-) diff --git a/IOB-UT/Eurom63.cs b/IOB-UT/Eurom63.cs index dfb85a5a..e95b8db8 100644 --- a/IOB-UT/Eurom63.cs +++ b/IOB-UT/Eurom63.cs @@ -65,6 +65,23 @@ namespace IOB_UT #endregion Public Properties } + public class ProtoConf + { + #region Public Fields + + public Dictionary ActiveSessions = new Dictionary(); + + #endregion Public Fields + + #region Public Properties + + public string BaseDir { get; set; } = @"C:\EUROMAP63\"; + public List cleanupExt { get; set; } = new List(); + public List DynData { get; set; } = new List(); + + #endregion Public Properties + } + /// /// Generic communication session /// @@ -135,22 +152,6 @@ namespace IOB_UT #endregion Public Properties } - public class SessionConf - { - #region Public Fields - - public Dictionary ActiveSessions = new Dictionary(); - - #endregion Public Fields - - #region Public Properties - - public string BaseDir { get; set; } = @"C:\EUROMAP63\"; - public List DynData { get; set; } = new List(); - - #endregion Public Properties - } - #endregion Public Classes } } \ No newline at end of file diff --git a/IOB-WIN/DATA/CONF/EM63.json b/IOB-WIN/DATA/CONF/EM63.json index 28054657..bf967db5 100644 --- a/IOB-WIN/DATA/CONF/EM63.json +++ b/IOB-WIN/DATA/CONF/EM63.json @@ -1,5 +1,12 @@ { "BaseDir": "C:\\NPM_E63\\E63\\MPW280SP", + "cleanupExt": [ + "*.dat", + "*.job", + "*.log", + "*.req", + "*.rsp" + ], "DynData": [ { "key": "CLOCK_1", diff --git a/IOB-WIN/IobFile.cs b/IOB-WIN/IobFile.cs index 4b77e61d..2f94ca41 100644 --- a/IOB-WIN/IobFile.cs +++ b/IOB-WIN/IobFile.cs @@ -24,6 +24,8 @@ namespace IOB_WIN * * -------------------------------------------------------------------------------- */ + #region Protected Fields + /// /// Cartella di base per interscambio /// @@ -39,10 +41,9 @@ namespace IOB_WIN /// protected Dictionary freqUnknStatus = new Dictionary(); - /// - /// Oggetti decodificati da pagina - /// - protected MonitoredItemsConf monitoredItems; + #endregion Protected Fields + + #region Public Constructors /// /// Estende l'init della classe base... @@ -55,6 +56,10 @@ namespace IOB_WIN //reloadAdapterConf(); } + #endregion Public Constructors + + #region Internal Methods + /// /// Ricarica conf adapter... /// @@ -99,13 +104,48 @@ namespace IOB_WIN #endif } + #endregion Internal Methods + #region Metodi specifici (da verificare/completare in implementazione) + /// + /// Processo stati unknown... + /// + /// + private void processUnknStatus(string cKey) + { + // cerco se avevo già una key nella dictionary... + if (freqUnknStatus.ContainsKey(cKey)) + { + freqUnknStatus[cKey]++; + // se è 1 ogni 100 (%100, resto ==1) --> loggo... + if (freqUnknStatus[cKey] % 100 == 1) + { + lgInfo($"Errore in decodifica status: MAPPING non trovato per {cKey} | freq: {freqUnknStatus[cKey]}"); + // accodo come invio di tipo FLOG... + string sVal = string.Format("[UnknStatus] {0}, freq: {1}", cKey, freqUnknStatus); + // chiamo accodamento... + accodaFLog(sVal, qEncodeFLog("UnknStatus", sVal)); + } + } + else + { + // creo chiave con freq = 1 + freqUnknStatus.Add(cKey, 1); + // log iniziale + lgInfo($"Errore in decodifica status: MAPPING non trovato per {cKey}"); + } + } + + /// + /// Pulizia preliminare folder comunicazione + /// + internal virtual void cleanupFolder() + { + } + public void Dispose() { -#if false - driver.Dispose(); -#endif GC.SuppressFinalize(this); } @@ -228,6 +268,8 @@ namespace IOB_WIN { // in primis RICARICO conf specifica... reloadAdapterConf(); + // pulizia preliminare folder + cleanupFolder(); // continuo con start... base.startAdapter(resetQueue); } @@ -309,71 +351,6 @@ namespace IOB_WIN } } - /// - /// Processo stati unknown... - /// - /// - private void processUnknStatus(string cKey) - { - // cerco se avevo già una key nella dictionary... - if (freqUnknStatus.ContainsKey(cKey)) - { - freqUnknStatus[cKey]++; - // se è 1 ogni 100 (%100, resto ==1) --> loggo... - if (freqUnknStatus[cKey] % 100 == 1) - { - lgInfo($"Errore in decodifica status: MAPPING non trovato per {cKey} | freq: {freqUnknStatus[cKey]}"); - // accodo come invio di tipo FLOG... - string sVal = string.Format("[UnknStatus] {0}, freq: {1}", cKey, freqUnknStatus); - // chiamo accodamento... - accodaFLog(sVal, qEncodeFLog("UnknStatus", sVal)); - } - } - else - { - // creo chiave con freq = 1 - freqUnknStatus.Add(cKey, 1); - // log iniziale - lgInfo($"Errore in decodifica status: MAPPING non trovato per {cKey}"); - } - } - - /// - /// Avvio del WebDriver - /// - private void startDriver() - { -#if false - if (monitoredItems.SrvData.driverName == "CHROME") - { - lgInfo("Starting CHROME Driver"); - // preparo opzione headless x CHROME - var o = new ChromeOptions(); - o.AddArgument("headless"); - ChromeDriverService service = ChromeDriverService.CreateDefaultService(Application.StartupPath); - service.HideCommandPromptWindow = true; - driver = new ChromeDriver(service, o); - } - else - { - lgInfo("Starting FIREFOX Driver"); - // preparo opzione headless x FIREFOX - var o = new FirefoxOptions(); - o.AddArgument("-headless"); - o.SetPreference("app.update.auto", false); - o.SetPreference("app.update.enabled", false); - FirefoxDriverService service = FirefoxDriverService.CreateDefaultService(Application.StartupPath); - service.HideCommandPromptWindow = true; - driver = new FirefoxDriver(service, o); - } - // aggiungo timeout x JScripts - driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(20); - driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(20); - // imposto pagina di acquisizione - driver.Navigate().GoToUrl(baseDir); -#endif - } - #endregion Metodi specifici (da verificare/completare in implementazione) } } \ No newline at end of file diff --git a/IOB-WIN/IobFileEurom63.cs b/IOB-WIN/IobFileEurom63.cs index 26aff4e4..3db13f22 100644 --- a/IOB-WIN/IobFileEurom63.cs +++ b/IOB-WIN/IobFileEurom63.cs @@ -11,10 +11,16 @@ namespace IOB_WIN { public class IobFileEurom63 : IobFile { + #region Protected Fields + /// /// Oggetti decodificati da pagina /// - protected Eurom63.SessionConf currentSessions; + protected Eurom63.ProtoConf confE63; + + #endregion Protected Fields + + #region Public Constructors /// /// Estende l'init della classe base... @@ -26,6 +32,26 @@ namespace IOB_WIN lgInfo("INIT IobFileEurom63"); } + #endregion Public Constructors + + #region Internal Methods + + /// + /// Pulizia preliminare folder comunicazione + /// + internal override void cleanupFolder() + { + // elimino OGNI file per tipo configurato + foreach (var cleanExt in confE63.cleanupExt) + { + string[] file2del = Directory.GetFiles(BaseDir, cleanExt); + foreach (var file in file2del) + { + File.Delete(file); + } + } + } + /// /// Ricarica conf adapter... /// @@ -46,10 +72,10 @@ namespace IOB_WIN { try { - currentSessions = JsonConvert.DeserializeObject(jsonData); + confE63 = JsonConvert.DeserializeObject(jsonData); // salvo baseUri - BaseDir = currentSessions.BaseDir; + BaseDir = confE63.BaseDir; lgInfo($"baseDir = {BaseDir}"); // imposto a zero la bitmap x riavvio! B_input = 0; @@ -68,5 +94,7 @@ namespace IOB_WIN lgInfo("DONE reloadAdapterConf"); raiseRefresh(currDispData); } + + #endregion Internal Methods } } \ No newline at end of file From 3c71872d659c45e944a7ad69e94338a1aa388435 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Wed, 7 Oct 2020 16:24:51 +0200 Subject: [PATCH 20/26] inizio gestione controllo init... --- IOB-UT/Eurom63.cs | 56 ++++++++- IOB-WIN/DATA/CONF/EM63.json | 86 +++++--------- IOB-WIN/IOB-WIN.csproj | 46 +++++++- IOB-WIN/IobFile.cs | 15 +-- IOB-WIN/IobFileEurom63.cs | 228 ++++++++++++++++++++++++++++++++++++ 5 files changed, 361 insertions(+), 70 deletions(-) diff --git a/IOB-UT/Eurom63.cs b/IOB-UT/Eurom63.cs index e95b8db8..be93e9ec 100644 --- a/IOB-UT/Eurom63.cs +++ b/IOB-UT/Eurom63.cs @@ -13,6 +13,47 @@ namespace IOB_UT { #region Public Enums + /// + /// Elenco dei livelli di comunicazione attivi + /// + public enum ComLevel + { + /// + /// Comunicazione NON attiva + /// + None = 0, + + /// + /// COntrollo comunicazione col PLC + /// + IsConnected, + + /// + /// Ricezione info preliminari macchina + /// + HasInfo, + + /// + /// Impostato data-ora correnti + /// + TimeSet, + + /// + /// Verificato il canale di comunicazione è OK, NON ci sono report attivi + /// + ChannelOk, + + /// + /// Richiesti report (NON ancora attivi) + /// + DataRequested, + + /// + /// Campionamento dati attivo (1/+ report in lettura) + /// + Sampling + } + public enum FileOpr { Copy = 0, @@ -56,11 +97,6 @@ namespace IOB_UT public FileOpr OprReq { get; set; } = FileOpr.Copy; public string Path { get; set; } = @"EUR63_JOB\SESS9999.FILE"; - public string RespKo { get; set; } = "ERROR"; - public string RespOk { get; set; } = "PROCESSED"; -#if false - public Dictionary StrReplace { get; set; } = new Dictionary(); -#endif #endregion Public Properties } @@ -119,6 +155,16 @@ namespace IOB_UT /// public bool Passed { get; set; } = false; + /// + /// TAG per risposta con errori + /// + public string RespKo { get; set; } = "ERROR"; + + /// + /// Tag per risposta positiva + /// + public string RespOk { get; set; } = "PROCESSED"; + /// /// Session Name /// diff --git a/IOB-WIN/DATA/CONF/EM63.json b/IOB-WIN/DATA/CONF/EM63.json index bf967db5..3c2d9bdf 100644 --- a/IOB-WIN/DATA/CONF/EM63.json +++ b/IOB-WIN/DATA/CONF/EM63.json @@ -36,10 +36,8 @@ "ValidityMinutes": 0.0, "FileList": [ { - "Path": "EUR63_JOB\\SESS0000.REQ", - "OprReq": "Copy", - "RespKo": "ERROR", - "RespOk": "PROCESSED" + "Path": "DATA\\EUR63_JOB\\SESS0000.REQ", + "OprReq": "Copy" } ] }, @@ -53,16 +51,12 @@ "ValidityMinutes": 0.0, "FileList": [ { - "Path": "EUR63_JOB\\SESS0001.REQ", - "OprReq": "Copy", - "RespKo": "ERROR", - "RespOk": "PROCESSED" + "Path": "DATA\\EUR63_JOB\\SESS0001.REQ", + "OprReq": "Copy" }, { - "Path": "EUR63_JOB\\SESS0001.JOB", - "OprReq": "Copy", - "RespKo": "", - "RespOk": "" + "Path": "DATA\\EUR63_JOB\\SESS0001.JOB", + "OprReq": "Copy" } ] }, @@ -76,16 +70,12 @@ "ValidityMinutes": 0.0, "FileList": [ { - "Path": "EUR63_JOB\\SESS0002.REQ", - "OprReq": "Copy", - "RespKo": "ERROR", - "RespOk": "PROCESSED" + "Path": "DATA\\EUR63_JOB\\SESS0002.REQ", + "OprReq": "Copy" }, { - "Path": "EUR63_JOB\\SESS0002.JOB", - "OprReq": "Copy", - "RespKo": "", - "RespOk": "" + "Path": "DATA\\EUR63_JOB\\SESS0002.JOB", + "OprReq": "Copy" } ] }, @@ -99,16 +89,12 @@ "StepOrder": 3, "FileList": [ { - "Path": "EUR63_JOB\\SESS0003.REQ", - "OprReq": "Copy", - "RespKo": "ERROR", - "RespOk": "PROCESSED" + "Path": "DATA\\EUR63_JOB\\SESS0003.REQ", + "OprReq": "Copy" }, { - "Path": "EUR63_JOB\\SESS0003.JOB", - "OprReq": "Copy", - "RespKo": "", - "RespOk": "" + "Path": "DATA\\EUR63_JOB\\SESS0003.JOB", + "OprReq": "Copy" } ] }, @@ -122,16 +108,12 @@ "StepOrder": 4, "FileList": [ { - "Path": "EUR63_JOB\\SESS0004.REQ", - "OprReq": "Copy", - "RespKo": "ERROR", - "RespOk": "PROCESSED" + "Path": "DATA\\EUR63_JOB\\SESS0004.REQ", + "OprReq": "Copy" }, { - "Path": "EUR63_JOB\\SESS0004.JOB", - "OprReq": "ReplaceAndCopy", - "RespKo": "", - "RespOk": "" + "Path": "DATA\\EUR63_JOB\\SESS0004.JOB", + "OprReq": "ReplaceAndCopy" } ] }, @@ -145,16 +127,14 @@ "StepOrder": 5, "FileList": [ { - "Path": "EUR63_JOB\\SESS0005.REQ", + "Path": "DATA\\EUR63_JOB\\SESS0005.REQ", "OprReq": "Copy", "RespKo": "ERROR", "RespOk": "PROCESSED" }, { - "Path": "EUR63_JOB\\SESS0005.JOB", - "OprReq": "ReplaceAndCopy", - "RespKo": "", - "RespOk": "" + "Path": "DATA\\EUR63_JOB\\SESS0005.JOB", + "OprReq": "ReplaceAndCopy" } ] }, @@ -168,16 +148,12 @@ "StepOrder": 6, "FileList": [ { - "Path": "EUR63_JOB\\SESS0006.REQ", - "OprReq": "Copy", - "RespKo": "ERROR", - "RespOk": "PROCESSED" + "Path": "DATA\\EUR63_JOB\\SESS0006.REQ", + "OprReq": "Copy" }, { - "Path": "EUR63_JOB\\SESS0006.JOB", - "OprReq": "Copy", - "RespKo": "", - "RespOk": "" + "Path": "DATA\\EUR63_JOB\\SESS0006.JOB", + "OprReq": "Copy" } ] }, @@ -191,16 +167,12 @@ "StepOrder": 7, "FileList": [ { - "Path": "EUR63_JOB\\SESS0007.REQ", - "OprReq": "Copy", - "RespKo": "ERROR", - "RespOk": "PROCESSED" + "Path": "DATA\\EUR63_JOB\\SESS0007.REQ", + "OprReq": "Copy" }, { - "Path": "EUR63_JOB\\SESS0007.JOB", - "OprReq": "Copy", - "RespKo": "", - "RespOk": "" + "Path": "DATA\\EUR63_JOB\\SESS0007.JOB", + "OprReq": "Copy" } ] } diff --git a/IOB-WIN/IOB-WIN.csproj b/IOB-WIN/IOB-WIN.csproj index 9f482b23..e4171f7a 100644 --- a/IOB-WIN/IOB-WIN.csproj +++ b/IOB-WIN/IOB-WIN.csproj @@ -507,7 +507,51 @@ Always - + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + Always diff --git a/IOB-WIN/IobFile.cs b/IOB-WIN/IobFile.cs index 2f94ca41..c9484db3 100644 --- a/IOB-WIN/IobFile.cs +++ b/IOB-WIN/IobFile.cs @@ -60,6 +60,14 @@ namespace IOB_WIN #region Internal Methods + /// + /// Pulizia preliminare folder comunicazione + /// + internal virtual void cleanupFolder() + { + // + } + /// /// Ricarica conf adapter... /// @@ -137,13 +145,6 @@ namespace IOB_WIN } } - /// - /// Pulizia preliminare folder comunicazione - /// - internal virtual void cleanupFolder() - { - } - public void Dispose() { GC.SuppressFinalize(this); diff --git a/IOB-WIN/IobFileEurom63.cs b/IOB-WIN/IobFileEurom63.cs index 3db13f22..6bf73aba 100644 --- a/IOB-WIN/IobFileEurom63.cs +++ b/IOB-WIN/IobFileEurom63.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using System.Windows.Forms; namespace IOB_WIN @@ -13,6 +14,16 @@ namespace IOB_WIN { #region Protected Fields + /// + /// step di comunicazione attivo + /// + protected Eurom63.ComLevel actLevel = Eurom63.ComLevel.None; + + /// + /// DIrectory eseguibile corrente + /// + protected string appPath = Directory.GetCurrentDirectory(); + /// /// Oggetti decodificati da pagina /// @@ -36,6 +47,48 @@ namespace IOB_WIN #region Internal Methods + /// + /// Metodi preliminari x comunicazione: + /// - richiesta connessione + /// - richiesta stato attivo + /// + internal void checkCommStatus() + { + // init obj display + newDisplayData currDispData = new newDisplayData(); + + switch (actLevel) + { + case Eurom63.ComLevel.None: + tryConnect(); + break; + + case Eurom63.ComLevel.IsConnected: + break; + + case Eurom63.ComLevel.HasInfo: + break; + + case Eurom63.ComLevel.TimeSet: + break; + + case Eurom63.ComLevel.ChannelOk: + break; + + case Eurom63.ComLevel.DataRequested: + break; + + case Eurom63.ComLevel.Sampling: + break; + + default: + break; + } + + lgInfo("DONE checkCommStatus"); + raiseRefresh(currDispData); + } + /// /// Pulizia preliminare folder comunicazione /// @@ -95,6 +148,181 @@ namespace IOB_WIN raiseRefresh(currDispData); } + /// + /// Connessione + /// + public override void tryConnect() + { + // controllo ping --> segno connected... + connectionOk = Directory.Exists(BaseDir); + if (connectionOk) + { + // verifico se ci sia risp CONNECT + var connectSession = confE63.ActiveSessions[0]; + if (checkResp(connectSession)) + { + // aggiorno livello + actLevel = Eurom63.ComLevel.IsConnected; + // elimino file sessione + cleanupSession(connectSession); + } + // richiedo SE non ci fosse i dati CONNECT... + else + { + processSession(connectSession); + } + } + else + { + // aspetto prima di riprovare... + Thread.Sleep(100); + } + } + + /// + /// Disconnessione + /// + public override void tryDisconnect() + { + connectionOk = false; + try + { + cleanupFolder(); + } + catch (Exception exc) + { + lgError(exc, "Eccezione in tryDisconnect"); + } + } + #endregion Internal Methods + + #region Protected Methods + + /// + /// Verifica una sessione configurata (ovvero la comunicazione su TUTTI i file associati) + /// + /// + /// + protected bool checkResp(Eurom63.Session session) + { + bool answ = false; + string fileName = ""; + if (session != null) + { + fileName = $"{BaseDir}\\{session.SessionName}.RSP"; + if (File.Exists(fileName)) + { + // verifico contenuto + string rawData = File.ReadAllText(fileName); + answ = rawData.Contains(session.RespOk); + } + } + return answ; + } + + /// + /// Elimina tutti i file della sessione indicata + /// + /// + /// + protected bool cleanupSession(Eurom63.Session session) + { + bool answ = false; + if (session != null) + { + string[] file2del = Directory.GetFiles(BaseDir, $"{session.SessionName}.*"); + foreach (var file in file2del) + { + File.Delete(file); + } + } + return answ; + } + + /// + /// Processa i file della sessione indicata (copy + transform) + /// + /// + /// + protected bool processSession(Eurom63.Session session) + { + bool answ = false; + if (session != null) + { + string fileFrom = ""; + string fileTo = ""; + // processo OGNI file sessione x farne copia + foreach (var file2Proc in session.FileList) + { + fileFrom = $"{appPath}\\{file2Proc.Path}"; + fileTo = $"{BaseDir}\\{Path.GetFileName(file2Proc.Path)}"; + File.Copy(fileFrom, fileTo, true); + } + } + return answ; + } + + /// + /// Effettua lettura semafori principale + /// Parametri da aggiornare x display in form + /// + public override void readSemafori(ref newDisplayData currDispData) + { + // in primis controllo status... + checkCommStatus(); + + // init a zero... + B_input = 0; + // ciclo! + try + { +#if false + // controllo SE il driver SIA attivo... + if (driver != null) + { + string cKey = ""; + string cVal = ""; + // IPOTESI: un UNICO oggetto decodifica status + if (monitoredItems.Status.Count == 1) + { + var item = monitoredItems.Status[0]; + // cerco elemento indicato + element = driver.FindElement(By.Id(item.val)); + cKey = element.Text; + // verifico se mancasse il mapping... + if (!item.codeMapping.ContainsKey(cKey)) + { + processUnknStatus(cKey); + } + else + { + // ora decodifico da variabile status a valore secondo impostazione "codeMapping" + cVal = item.codeMapping[cKey]; + B_input = int.Parse(cVal, System.Globalization.NumberStyles.HexNumber); + if (currDispData != null) + { + currDispData.semIn = Semaforo.SV; + } + } + } + } + else + { + lgError("Errore: driver non pronto (null)"); + } +#endif + // riporto bitmap... + reportRawInput(ref currDispData); + } + catch (Exception exc) + { + lgError(exc, "Errore in readSemafori x IOB FILE"); + if (currDispData != null) + currDispData.semIn = Semaforo.SR; + } + } + + #endregion Protected Methods } } \ No newline at end of file From cdd7921b87c6df98be8c9ece5f41059292e30b09 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Wed, 7 Oct 2020 17:01:13 +0200 Subject: [PATCH 21/26] Avanzato fino a check preliminari... --- IOB-WIN/IobFileEurom63.cs | 285 +++++++++++++++++++++++--------------- 1 file changed, 171 insertions(+), 114 deletions(-) diff --git a/IOB-WIN/IobFileEurom63.cs b/IOB-WIN/IobFileEurom63.cs index 6bf73aba..05032fba 100644 --- a/IOB-WIN/IobFileEurom63.cs +++ b/IOB-WIN/IobFileEurom63.cs @@ -1,4 +1,5 @@ -using IOB_UT; +using CncLib.OPENcontrol; +using IOB_UT; using MapoSDK; using Newtonsoft.Json; using System; @@ -45,6 +46,137 @@ namespace IOB_WIN #endregion Public Constructors + #region Private Methods + + private void abortPrevJob() + { + throw new NotImplementedException(); + } + + /// + /// Processa una sessione + /// - andando a verificare l'esistenza della REQ + se esito positivo pulizia + /// - andando a richeidere di nuovo risposta + /// + /// + /// + private void processSession(Eurom63.ComLevel nextLevel, Eurom63.Session connectSession) + { + // controllo esistenza directory --> segno connected... + connectionOk = Directory.Exists(BaseDir); + if (connectionOk) + { + // verifico se ci sia risp CONNECT + if (checkResp(connectSession)) + { + // aggiorno livello + actLevel = nextLevel; + // elimino file sessione + cleanupSession(connectSession); + } + // richiedo SE non ci fosse i dati CONNECT... + else + { + processSession(connectSession); + } + } + else + { + // aspetto prima di riprovare... + Thread.Sleep(50); + } + } + + private void setMachineTime() + { + throw new NotImplementedException(); + } + + #endregion Private Methods + + #region Protected Methods + + /// + /// Verifica una sessione configurata (ovvero la comunicazione su TUTTI i file associati) + /// + /// + /// + protected bool checkResp(Eurom63.Session session) + { + bool answ = false; + string fileName = ""; + if (session != null) + { + fileName = $"{BaseDir}\\{session.SessionName}.RSP"; + if (File.Exists(fileName)) + { + // verifico contenuto + string rawData = File.ReadAllText(fileName); + answ = rawData.Contains(session.RespOk); + if (!answ) + { + // se NON ok faccio pulizia... + cleanupSession(session); + } + } + } + return answ; + } + + /// + /// Elimina tutti i file della sessione indicata + /// + /// + /// + protected bool cleanupSession(Eurom63.Session session) + { + bool answ = false; + if (session != null) + { + string[] file2del = Directory.GetFiles(BaseDir, $"{session.SessionName}.*"); + foreach (var file in file2del) + { + File.Delete(file); + } + } + return answ; + } + + /// + /// Processa i file della sessione indicata (copy + transform) + /// + /// + /// + protected bool processSession(Eurom63.Session session) + { + bool answ = false; + if (session != null) + { + string fileFrom = ""; + string fileTo = ""; + // processo OGNI file sessione x farne copia + foreach (var file2Proc in session.FileList) + { + fileFrom = $"{appPath}\\{file2Proc.Path}"; + fileTo = $"{BaseDir}\\{Path.GetFileName(file2Proc.Path)}"; + File.Copy(fileFrom, fileTo, true); + } + } + return answ; + } + + /// + /// Effettua richiesta info x macchina (validare startup process) + /// + protected void requestInfo() + { + var nextLevel = Eurom63.ComLevel.HasInfo; + var connectSession = confE63.ActiveSessions[1]; + processSession(nextLevel, connectSession); + } + + #endregion Protected Methods + #region Internal Methods /// @@ -64,12 +196,15 @@ namespace IOB_WIN break; case Eurom63.ComLevel.IsConnected: + requestInfo(); break; case Eurom63.ComLevel.HasInfo: + setMachineTime(); break; case Eurom63.ComLevel.TimeSet: + abortPrevJob(); break; case Eurom63.ComLevel.ChannelOk: @@ -148,120 +283,9 @@ namespace IOB_WIN raiseRefresh(currDispData); } - /// - /// Connessione - /// - public override void tryConnect() - { - // controllo ping --> segno connected... - connectionOk = Directory.Exists(BaseDir); - if (connectionOk) - { - // verifico se ci sia risp CONNECT - var connectSession = confE63.ActiveSessions[0]; - if (checkResp(connectSession)) - { - // aggiorno livello - actLevel = Eurom63.ComLevel.IsConnected; - // elimino file sessione - cleanupSession(connectSession); - } - // richiedo SE non ci fosse i dati CONNECT... - else - { - processSession(connectSession); - } - } - else - { - // aspetto prima di riprovare... - Thread.Sleep(100); - } - } - - /// - /// Disconnessione - /// - public override void tryDisconnect() - { - connectionOk = false; - try - { - cleanupFolder(); - } - catch (Exception exc) - { - lgError(exc, "Eccezione in tryDisconnect"); - } - } - #endregion Internal Methods - #region Protected Methods - - /// - /// Verifica una sessione configurata (ovvero la comunicazione su TUTTI i file associati) - /// - /// - /// - protected bool checkResp(Eurom63.Session session) - { - bool answ = false; - string fileName = ""; - if (session != null) - { - fileName = $"{BaseDir}\\{session.SessionName}.RSP"; - if (File.Exists(fileName)) - { - // verifico contenuto - string rawData = File.ReadAllText(fileName); - answ = rawData.Contains(session.RespOk); - } - } - return answ; - } - - /// - /// Elimina tutti i file della sessione indicata - /// - /// - /// - protected bool cleanupSession(Eurom63.Session session) - { - bool answ = false; - if (session != null) - { - string[] file2del = Directory.GetFiles(BaseDir, $"{session.SessionName}.*"); - foreach (var file in file2del) - { - File.Delete(file); - } - } - return answ; - } - - /// - /// Processa i file della sessione indicata (copy + transform) - /// - /// - /// - protected bool processSession(Eurom63.Session session) - { - bool answ = false; - if (session != null) - { - string fileFrom = ""; - string fileTo = ""; - // processo OGNI file sessione x farne copia - foreach (var file2Proc in session.FileList) - { - fileFrom = $"{appPath}\\{file2Proc.Path}"; - fileTo = $"{BaseDir}\\{Path.GetFileName(file2Proc.Path)}"; - File.Copy(fileFrom, fileTo, true); - } - } - return answ; - } + #region Public Methods /// /// Effettua lettura semafori principale @@ -274,6 +298,13 @@ namespace IOB_WIN // init a zero... B_input = 0; + + // se sono OLTRE i primi 2 step --> accesa... + if (actLevel > Eurom63.ComLevel.None) + { + B_input += (1 << 0); + } + // ciclo! try { @@ -323,6 +354,32 @@ namespace IOB_WIN } } - #endregion Protected Methods + /// + /// Connessione + /// + public override void tryConnect() + { + var nextLevel = Eurom63.ComLevel.IsConnected; + var connectSession = confE63.ActiveSessions[0]; + processSession(nextLevel, connectSession); + } + + /// + /// Disconnessione + /// + public override void tryDisconnect() + { + connectionOk = false; + try + { + cleanupFolder(); + } + catch (Exception exc) + { + lgError(exc, "Eccezione in tryDisconnect"); + } + } + + #endregion Public Methods } } \ No newline at end of file From dd99e448954e5b2cb5a687159a67771ae9218be0 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Wed, 7 Oct 2020 17:20:49 +0200 Subject: [PATCH 22/26] riorganizzazione JOBS --- IOB-WIN/DATA/CONF/EM63.json | 88 ++++++++++++++--------------- IOB-WIN/DATA/EUR63_JOB/SESS0002.JOB | 4 +- IOB-WIN/DATA/EUR63_JOB/SESS0002.REQ | 2 +- IOB-WIN/DATA/EUR63_JOB/SESS0004.JOB | 13 ++++- IOB-WIN/DATA/EUR63_JOB/SESS0004.REQ | 2 +- IOB-WIN/DATA/EUR63_JOB/SESS0005.JOB | 24 +++----- IOB-WIN/DATA/EUR63_JOB/SESS0005.REQ | 2 +- IOB-WIN/DATA/EUR63_JOB/SESS0006.JOB | 11 ---- IOB-WIN/DATA/EUR63_JOB/SESS0006.REQ | 1 - IOB-WIN/DATA/EUR63_JOB/SESS0007.JOB | 11 ---- IOB-WIN/DATA/EUR63_JOB/SESS0007.REQ | 1 - IOB-WIN/DATA/EUR63_JOB/SESS0010.JOB | 19 +++++++ IOB-WIN/DATA/EUR63_JOB/SESS0010.REQ | 1 + IOB-WIN/DATA/EUR63_JOB/SESS0019.JOB | 2 + IOB-WIN/DATA/EUR63_JOB/SESS0019.REQ | 1 + IOB-WIN/IobFileEurom63.cs | 22 ++++++-- 16 files changed, 107 insertions(+), 97 deletions(-) delete mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0006.JOB delete mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0006.REQ delete mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0007.JOB delete mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0007.REQ create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0010.JOB create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0010.REQ create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0019.JOB create mode 100644 IOB-WIN/DATA/EUR63_JOB/SESS0019.REQ diff --git a/IOB-WIN/DATA/CONF/EM63.json b/IOB-WIN/DATA/CONF/EM63.json index 3c2d9bdf..dff04d96 100644 --- a/IOB-WIN/DATA/CONF/EM63.json +++ b/IOB-WIN/DATA/CONF/EM63.json @@ -60,14 +60,14 @@ } ] }, - "99": { + "2": { "Cycle": false, - "Description": "Get INFO data", - "Max2Keep": 10, + "Description": "Set DateTime on machine at start", "SessionName": "SESS0002", - "SessionType": "GetInfo", - "StepOrder": 99, + "SessionType": "SetDateTime", "ValidityMinutes": 0.0, + "Max2Keep": 10, + "StepOrder": 2, "FileList": [ { "Path": "DATA\\EUR63_JOB\\SESS0002.REQ", @@ -75,7 +75,7 @@ }, { "Path": "DATA\\EUR63_JOB\\SESS0002.JOB", - "OprReq": "Copy" + "OprReq": "ReplaceAndCopy" } ] }, @@ -100,11 +100,11 @@ }, "4": { "Cycle": false, - "Description": "Set DateTime on machine at start", + "Description": "Get Machine Status", "SessionName": "SESS0004", - "SessionType": "SetDateTime", - "ValidityMinutes": 0.0, - "Max2Keep": 10, + "SessionType": "GetStatus", + "ValidityMinutes": 1.0, + "Max2Keep": 120, "StepOrder": 4, "FileList": [ { @@ -113,65 +113,65 @@ }, { "Path": "DATA\\EUR63_JOB\\SESS0004.JOB", - "OprReq": "ReplaceAndCopy" + "OprReq": "Copy" } ] }, "5": { "Cycle": false, - "Description": "Set Param ODL at Setup", + "Description": "Get Production", "SessionName": "SESS0005", - "SessionType": "SetParamOdl", - "ValidityMinutes": 0.0, - "Max2Keep": 10, + "SessionType": "GetProduction", + "ValidityMinutes": 1.0, + "Max2Keep": 120, "StepOrder": 5, "FileList": [ { "Path": "DATA\\EUR63_JOB\\SESS0005.REQ", + "OprReq": "Copy" + }, + { + "Path": "DATA\\EUR63_JOB\\SESS0005.JOB", + "OprReq": "Copy" + } + ] + }, + "10": { + "Cycle": false, + "Description": "Set Param ODL at Setup", + "SessionName": "SESS0010", + "SessionType": "SetParamOdl", + "ValidityMinutes": 0.0, + "Max2Keep": 10, + "StepOrder": 10, + "FileList": [ + { + "Path": "DATA\\EUR63_JOB\\SESS0010.REQ", "OprReq": "Copy", "RespKo": "ERROR", "RespOk": "PROCESSED" }, { - "Path": "DATA\\EUR63_JOB\\SESS0005.JOB", + "Path": "DATA\\EUR63_JOB\\SESS0010.JOB", "OprReq": "ReplaceAndCopy" } ] }, - "6": { + "19": { "Cycle": false, - "Description": "Get Machine Status", - "SessionName": "SESS0006", - "SessionType": "GetStatus", - "ValidityMinutes": 1.0, - "Max2Keep": 120, - "StepOrder": 6, + "Description": "Get INFO data", + "Max2Keep": 10, + "SessionName": "SESS0019", + "SessionType": "GetInfo", + "StepOrder": 19, + "ValidityMinutes": 0.0, "FileList": [ { - "Path": "DATA\\EUR63_JOB\\SESS0006.REQ", + "Path": "DATA\\EUR63_JOB\\SESS0019.REQ", "OprReq": "Copy" }, { - "Path": "DATA\\EUR63_JOB\\SESS0006.JOB", - "OprReq": "Copy" - } - ] - }, - "7": { - "Cycle": false, - "Description": "Get Production", - "SessionName": "SESS0007", - "SessionType": "GetProduction", - "ValidityMinutes": 1.0, - "Max2Keep": 120, - "StepOrder": 7, - "FileList": [ - { - "Path": "DATA\\EUR63_JOB\\SESS0007.REQ", - "OprReq": "Copy" - }, - { - "Path": "DATA\\EUR63_JOB\\SESS0007.JOB", + "Path": "DATA\\EUR63_JOB\\SESS0019.JOB", "OprReq": "Copy" } ] diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0002.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0002.JOB index 3b3ac5a0..2e412db3 100644 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0002.JOB +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0002.JOB @@ -1,2 +1,2 @@ -JOB GETINFO RESPONSE "SESS0002.LOG"; -GETINFO "SESS0002.DAT"; \ No newline at end of file +JOB ImpostaOrario RESPONSE "SESS0004.LOG"; +SET SetTimMach {DTNow}; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0002.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0002.REQ index cced09c3..d29e9602 100644 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0002.REQ +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0002.REQ @@ -1 +1 @@ -SESS0002 EXECUTE "SESS0002.JOB"; \ No newline at end of file +SESS0004 EXECUTE "SESS0004.JOB"; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0004.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0004.JOB index 2e412db3..e39fb861 100644 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0004.JOB +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0004.JOB @@ -1,2 +1,11 @@ -JOB ImpostaOrario RESPONSE "SESS0004.LOG"; -SET SetTimMach {DTNow}; +JOB machstat RESPONSE "SESS0006.LOG"; + +REPORT status REWRITE "SESS0006.DAT" +START IMMEDIATE +STOP NEVER +CYCLIC TIME 00:00:01 +SESSIONS 60 +PARAMETERS +DATE, TIME, ActStsMach; + + diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0004.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0004.REQ index d29e9602..4a185f17 100644 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0004.REQ +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0004.REQ @@ -1 +1 @@ -SESS0004 EXECUTE "SESS0004.JOB"; +SESS0006 EXECUTE "SESS0006.JOB"; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0005.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0005.JOB index bc3956cb..3022aab8 100644 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0005.JOB +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0005.JOB @@ -1,19 +1,11 @@ -JOB SetID RESPONSE "SESS0005.LOG"; -//SET SetDescJob " "; -//SET SetDescPrt " " -//SET SetDescMld " "; -//SET SetDescOp " "; +JOB machstat RESPONSE "SESS0007.LOG"; -SET SetDescJob {ODL}; -SET SetDescPrt {DescrArt}; -SET SetDescMld {CodArt}; -SET SetDescOp {CodOpr}; +REPORT status REWRITE "SESS0007.DAT" +START IMMEDIATE +STOP NEVER +CYCLIC TIME 00:00:02 +SESSIONS 30 +PARAMETERS +DATE, TIME, ActCntCyc, ActTimCyc, ActTimFill, @OutXhour, SetDescJob; -//SET SetDescJob "Nr. 1000987654.01"; -//SET SetDescPrt "STICK: 8 componenti SENZA assemblaggio"; -//SET SetDescMld "Stampo componenti a 8 impronte"; -//SET SetDescOp "Operatore 01"; -//SET SetCntMld 2; -//SET SetCntPrt 10000; -//SET SetCntPrtBox 20; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0005.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0005.REQ index 34cd11bc..de4d0350 100644 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0005.REQ +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0005.REQ @@ -1 +1 @@ -SESS0005 EXECUTE "SESS0005.JOB"; +SESS0007 EXECUTE "SESS0007.JOB"; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0006.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0006.JOB deleted file mode 100644 index e39fb861..00000000 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0006.JOB +++ /dev/null @@ -1,11 +0,0 @@ -JOB machstat RESPONSE "SESS0006.LOG"; - -REPORT status REWRITE "SESS0006.DAT" -START IMMEDIATE -STOP NEVER -CYCLIC TIME 00:00:01 -SESSIONS 60 -PARAMETERS -DATE, TIME, ActStsMach; - - diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0006.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0006.REQ deleted file mode 100644 index 4a185f17..00000000 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0006.REQ +++ /dev/null @@ -1 +0,0 @@ -SESS0006 EXECUTE "SESS0006.JOB"; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0007.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0007.JOB deleted file mode 100644 index 3022aab8..00000000 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0007.JOB +++ /dev/null @@ -1,11 +0,0 @@ -JOB machstat RESPONSE "SESS0007.LOG"; - -REPORT status REWRITE "SESS0007.DAT" -START IMMEDIATE -STOP NEVER -CYCLIC TIME 00:00:02 -SESSIONS 30 -PARAMETERS -DATE, TIME, ActCntCyc, ActTimCyc, ActTimFill, @OutXhour, SetDescJob; - - diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0007.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0007.REQ deleted file mode 100644 index de4d0350..00000000 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0007.REQ +++ /dev/null @@ -1 +0,0 @@ -SESS0007 EXECUTE "SESS0007.JOB"; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0010.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0010.JOB new file mode 100644 index 00000000..bc3956cb --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0010.JOB @@ -0,0 +1,19 @@ +JOB SetID RESPONSE "SESS0005.LOG"; +//SET SetDescJob " "; +//SET SetDescPrt " " +//SET SetDescMld " "; +//SET SetDescOp " "; + +SET SetDescJob {ODL}; +SET SetDescPrt {DescrArt}; +SET SetDescMld {CodArt}; +SET SetDescOp {CodOpr}; + +//SET SetDescJob "Nr. 1000987654.01"; +//SET SetDescPrt "STICK: 8 componenti SENZA assemblaggio"; +//SET SetDescMld "Stampo componenti a 8 impronte"; +//SET SetDescOp "Operatore 01"; + +//SET SetCntMld 2; +//SET SetCntPrt 10000; +//SET SetCntPrtBox 20; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0010.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0010.REQ new file mode 100644 index 00000000..34cd11bc --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0010.REQ @@ -0,0 +1 @@ +SESS0005 EXECUTE "SESS0005.JOB"; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0019.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0019.JOB new file mode 100644 index 00000000..3b3ac5a0 --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0019.JOB @@ -0,0 +1,2 @@ +JOB GETINFO RESPONSE "SESS0002.LOG"; +GETINFO "SESS0002.DAT"; \ No newline at end of file diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0019.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0019.REQ new file mode 100644 index 00000000..cced09c3 --- /dev/null +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0019.REQ @@ -0,0 +1 @@ +SESS0002 EXECUTE "SESS0002.JOB"; \ No newline at end of file diff --git a/IOB-WIN/IobFileEurom63.cs b/IOB-WIN/IobFileEurom63.cs index 05032fba..2208bd7c 100644 --- a/IOB-WIN/IobFileEurom63.cs +++ b/IOB-WIN/IobFileEurom63.cs @@ -48,11 +48,6 @@ namespace IOB_WIN #region Private Methods - private void abortPrevJob() - { - throw new NotImplementedException(); - } - /// /// Processa una sessione /// - andando a verificare l'esistenza della REQ + se esito positivo pulizia @@ -87,7 +82,7 @@ namespace IOB_WIN } } - private void setMachineTime() + private void requestSampleData() { throw new NotImplementedException(); } @@ -96,6 +91,13 @@ namespace IOB_WIN #region Protected Methods + protected void abortPrevJob() + { + var nextLevel = Eurom63.ComLevel.ChannelOk; + var connectSession = confE63.ActiveSessions[4]; + processSession(nextLevel, connectSession); + } + /// /// Verifica una sessione configurata (ovvero la comunicazione su TUTTI i file associati) /// @@ -175,6 +177,13 @@ namespace IOB_WIN processSession(nextLevel, connectSession); } + protected void setMachineTime() + { + var nextLevel = Eurom63.ComLevel.TimeSet; + var connectSession = confE63.ActiveSessions[3]; + processSession(nextLevel, connectSession); + } + #endregion Protected Methods #region Internal Methods @@ -208,6 +217,7 @@ namespace IOB_WIN break; case Eurom63.ComLevel.ChannelOk: + requestSampleData(); break; case Eurom63.ComLevel.DataRequested: From c8634dc63b7359c6181ad3b40bf4de7ed2bd6d21 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Wed, 7 Oct 2020 19:50:24 +0200 Subject: [PATCH 23/26] update conf script, messo tutto in rewrite e sample a sessioni 5 minuti (NO APPEND), da testare... --- .../DemoCom/Step_02_SETTIME/SESS0002.JOB | 2 + .../DemoCom/Step_02_SETTIME/SESS0002.REQ | 1 + .../DemoCom/Step_04_SETTIME/SESS0004.JOB | 2 - .../DemoCom/Step_04_STATUS/SESS0004.DAT | 2 + .../SESS0004.JOB} | 4 +- .../SESS0004.REQ | 0 .../DemoCom/Step_05_PROD/SESS0005.DAT | 2 + .../DemoCom/Step_05_PROD/SESS0005.JOB | 25 +++ .../SESS0005.REQ | 0 .../DemoCom/Step_06_STATUS/SESS0006.DAT | 2 - .../DemoCom/Step_06_STATUS/SESS0006.REQ | 1 - .../DemoCom/Step_07_PROD/SESS0007.DAT | 21 -- .../DemoCom/Step_07_PROD/SESS0007.JOB | 11 -- .../DemoCom/Step_07_PROD/SESS0007.REQ | 1 - .../SESS0002.DAT | 0 .../SESS0002.JOB | 0 .../SESS0002.REQ | 0 .../SESS0005.JOB | 0 .../DemoCom/Step_99_DESCR/SESS0005.REQ | 1 + IOB-UT/Eurom63.cs | 20 +- IOB-WIN/DATA/CONF/EM63.json | 51 ++--- IOB-WIN/DATA/EUR63_JOB/SESS0002.JOB | 2 +- IOB-WIN/DATA/EUR63_JOB/SESS0002.REQ | 2 +- IOB-WIN/DATA/EUR63_JOB/SESS0004.JOB | 4 +- IOB-WIN/DATA/EUR63_JOB/SESS0004.REQ | 2 +- IOB-WIN/DATA/EUR63_JOB/SESS0005.JOB | 28 ++- IOB-WIN/DATA/EUR63_JOB/SESS0005.REQ | 2 +- IOB-WIN/DATA/EUR63_JOB/SESS0010.JOB | 2 +- IOB-WIN/DATA/EUR63_JOB/SESS0010.REQ | 2 +- IOB-WIN/DATA/EUR63_JOB/SESS0019.JOB | 4 +- IOB-WIN/DATA/EUR63_JOB/SESS0019.REQ | 2 +- IOB-WIN/DATA/TEMP/.placeholder | 1 + IOB-WIN/IOB-WIN.csproj | 31 +-- IOB-WIN/IobFileEurom63.cs | 179 ++++++++++++++---- 34 files changed, 268 insertions(+), 139 deletions(-) create mode 100644 Documentazione/Euromap63/DemoCom/Step_02_SETTIME/SESS0002.JOB create mode 100644 Documentazione/Euromap63/DemoCom/Step_02_SETTIME/SESS0002.REQ delete mode 100644 Documentazione/Euromap63/DemoCom/Step_04_SETTIME/SESS0004.JOB create mode 100644 Documentazione/Euromap63/DemoCom/Step_04_STATUS/SESS0004.DAT rename Documentazione/Euromap63/DemoCom/{Step_06_STATUS/SESS0006.JOB => Step_04_STATUS/SESS0004.JOB} (56%) rename Documentazione/Euromap63/DemoCom/{Step_04_SETTIME => Step_04_STATUS}/SESS0004.REQ (100%) create mode 100644 Documentazione/Euromap63/DemoCom/Step_05_PROD/SESS0005.DAT create mode 100644 Documentazione/Euromap63/DemoCom/Step_05_PROD/SESS0005.JOB rename Documentazione/Euromap63/DemoCom/{Step_05_DESCR => Step_05_PROD}/SESS0005.REQ (100%) delete mode 100644 Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.DAT delete mode 100644 Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.REQ delete mode 100644 Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.DAT delete mode 100644 Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.JOB delete mode 100644 Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.REQ rename Documentazione/Euromap63/DemoCom/{Step_02_INFO => Step_19_INFO}/SESS0002.DAT (100%) rename Documentazione/Euromap63/DemoCom/{Step_02_INFO => Step_19_INFO}/SESS0002.JOB (100%) rename Documentazione/Euromap63/DemoCom/{Step_02_INFO => Step_19_INFO}/SESS0002.REQ (100%) rename Documentazione/Euromap63/DemoCom/{Step_05_DESCR => Step_99_DESCR}/SESS0005.JOB (100%) create mode 100644 Documentazione/Euromap63/DemoCom/Step_99_DESCR/SESS0005.REQ create mode 100644 IOB-WIN/DATA/TEMP/.placeholder diff --git a/Documentazione/Euromap63/DemoCom/Step_02_SETTIME/SESS0002.JOB b/Documentazione/Euromap63/DemoCom/Step_02_SETTIME/SESS0002.JOB new file mode 100644 index 00000000..ac48c1bf --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_02_SETTIME/SESS0002.JOB @@ -0,0 +1,2 @@ +JOB ImpostaOrario RESPONSE "SESS0002.LOG"; +SET SetTimMach {DTNow}; diff --git a/Documentazione/Euromap63/DemoCom/Step_02_SETTIME/SESS0002.REQ b/Documentazione/Euromap63/DemoCom/Step_02_SETTIME/SESS0002.REQ new file mode 100644 index 00000000..c647022a --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_02_SETTIME/SESS0002.REQ @@ -0,0 +1 @@ +SESS0002 EXECUTE "SESS0002.JOB"; diff --git a/Documentazione/Euromap63/DemoCom/Step_04_SETTIME/SESS0004.JOB b/Documentazione/Euromap63/DemoCom/Step_04_SETTIME/SESS0004.JOB deleted file mode 100644 index 2e412db3..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_04_SETTIME/SESS0004.JOB +++ /dev/null @@ -1,2 +0,0 @@ -JOB ImpostaOrario RESPONSE "SESS0004.LOG"; -SET SetTimMach {DTNow}; diff --git a/Documentazione/Euromap63/DemoCom/Step_04_STATUS/SESS0004.DAT b/Documentazione/Euromap63/DemoCom/Step_04_STATUS/SESS0004.DAT new file mode 100644 index 00000000..4ee79a7f --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_04_STATUS/SESS0004.DAT @@ -0,0 +1,2 @@ +DATE, TIME, ActStsMach +20201007, 18:49:57, 0A000 diff --git a/Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.JOB b/Documentazione/Euromap63/DemoCom/Step_04_STATUS/SESS0004.JOB similarity index 56% rename from Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.JOB rename to Documentazione/Euromap63/DemoCom/Step_04_STATUS/SESS0004.JOB index e39fb861..ca69cf84 100644 --- a/Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.JOB +++ b/Documentazione/Euromap63/DemoCom/Step_04_STATUS/SESS0004.JOB @@ -1,6 +1,6 @@ -JOB machstat RESPONSE "SESS0006.LOG"; +JOB machstat RESPONSE "SESS0004.LOG"; -REPORT status REWRITE "SESS0006.DAT" +REPORT status REWRITE "SESS0004.DAT" START IMMEDIATE STOP NEVER CYCLIC TIME 00:00:01 diff --git a/Documentazione/Euromap63/DemoCom/Step_04_SETTIME/SESS0004.REQ b/Documentazione/Euromap63/DemoCom/Step_04_STATUS/SESS0004.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_04_SETTIME/SESS0004.REQ rename to Documentazione/Euromap63/DemoCom/Step_04_STATUS/SESS0004.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_05_PROD/SESS0005.DAT b/Documentazione/Euromap63/DemoCom/Step_05_PROD/SESS0005.DAT new file mode 100644 index 00000000..621d2e37 --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_05_PROD/SESS0005.DAT @@ -0,0 +1,2 @@ +DATE, TIME, ActCntCyc, ActTimCyc, ActTimFill, @OutXhour, SetDescJob +20201007, 19:44:42, 4568, 8.61, 0.50, 10046, Nr. 1000987654.01 diff --git a/Documentazione/Euromap63/DemoCom/Step_05_PROD/SESS0005.JOB b/Documentazione/Euromap63/DemoCom/Step_05_PROD/SESS0005.JOB new file mode 100644 index 00000000..f387774a --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_05_PROD/SESS0005.JOB @@ -0,0 +1,25 @@ +JOB machstat RESPONSE "SESS0005.LOG"; + +REPORT status REWRITE "SESS0005.DAT" +START IMMEDIATE +STOP NEVER +CYCLIC TIME 00:00:03 +SESSIONS 100 +//PARAMETERS +//DATE, TIME, ActCntCyc, ActTimCyc, ActTimFill, @OutXhour, SetDescJob; +PARAMETERS +DATE, TIME +, ActCntCyc, ActTimCyc, ActTimFill +, @OutXhour +//, SetTmpBrlZnStb[1] +//, SetTmpBrlZn[2], SetTmpBrlZnHdev[2], SetTmpBrlZnLdev[2] +//, ActTmpBrlZn[1], ActTmpBrlZn[2], ActTmpBrlZn[3] +//, SetTmpMldZn[50], SetTmpMldZnStb[50], SetTmpMldZnHdev[50], SetTmpMldZnLdev[50], ActTmpMldZn[50] +//, SetTmpMldZn[51], SetTmpMldZnStb[51], SetTmpMldZnHdev[51], SetTmpMldZnLdev[51], ActTmpMldZn[51] +//, ActTmpCab, ActTmpMlt +//, ActStrCsh, ActStrCsh +//, ActSpdPlstMax, ActSpdPlstAve +, SetDescJob +//, ActCntPrt +//, ActTmpOil +; \ No newline at end of file diff --git a/Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0005.REQ b/Documentazione/Euromap63/DemoCom/Step_05_PROD/SESS0005.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0005.REQ rename to Documentazione/Euromap63/DemoCom/Step_05_PROD/SESS0005.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.DAT b/Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.DAT deleted file mode 100644 index ee3dc3eb..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.DAT +++ /dev/null @@ -1,2 +0,0 @@ -DATE, TIME, ActStsMach -20201005, 17:56:33, 1 000 diff --git a/Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.REQ b/Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.REQ deleted file mode 100644 index 4a185f17..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_06_STATUS/SESS0006.REQ +++ /dev/null @@ -1 +0,0 @@ -SESS0006 EXECUTE "SESS0006.JOB"; diff --git a/Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.DAT b/Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.DAT deleted file mode 100644 index ee0ec758..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.DAT +++ /dev/null @@ -1,21 +0,0 @@ -DATE, TIME, ActCntCyc, ActTimCyc, ActTimFill, @OutXhour, SetDescJob -20201005, 18:38:17, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:18, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:19, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:20, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:21, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:22, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:23, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:24, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:25, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:26, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:27, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:28, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:29, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:30, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:31, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:33, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:34, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:35, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:36, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 -20201005, 18:38:37, 1218, 0.00, 0.00, 10046, Nr. 1000675432.11 diff --git a/Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.JOB b/Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.JOB deleted file mode 100644 index 3022aab8..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.JOB +++ /dev/null @@ -1,11 +0,0 @@ -JOB machstat RESPONSE "SESS0007.LOG"; - -REPORT status REWRITE "SESS0007.DAT" -START IMMEDIATE -STOP NEVER -CYCLIC TIME 00:00:02 -SESSIONS 30 -PARAMETERS -DATE, TIME, ActCntCyc, ActTimCyc, ActTimFill, @OutXhour, SetDescJob; - - diff --git a/Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.REQ b/Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.REQ deleted file mode 100644 index de4d0350..00000000 --- a/Documentazione/Euromap63/DemoCom/Step_07_PROD/SESS0007.REQ +++ /dev/null @@ -1 +0,0 @@ -SESS0007 EXECUTE "SESS0007.JOB"; diff --git a/Documentazione/Euromap63/DemoCom/Step_02_INFO/SESS0002.DAT b/Documentazione/Euromap63/DemoCom/Step_19_INFO/SESS0002.DAT similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_02_INFO/SESS0002.DAT rename to Documentazione/Euromap63/DemoCom/Step_19_INFO/SESS0002.DAT diff --git a/Documentazione/Euromap63/DemoCom/Step_02_INFO/SESS0002.JOB b/Documentazione/Euromap63/DemoCom/Step_19_INFO/SESS0002.JOB similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_02_INFO/SESS0002.JOB rename to Documentazione/Euromap63/DemoCom/Step_19_INFO/SESS0002.JOB diff --git a/Documentazione/Euromap63/DemoCom/Step_02_INFO/SESS0002.REQ b/Documentazione/Euromap63/DemoCom/Step_19_INFO/SESS0002.REQ similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_02_INFO/SESS0002.REQ rename to Documentazione/Euromap63/DemoCom/Step_19_INFO/SESS0002.REQ diff --git a/Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0005.JOB b/Documentazione/Euromap63/DemoCom/Step_99_DESCR/SESS0005.JOB similarity index 100% rename from Documentazione/Euromap63/DemoCom/Step_05_DESCR/SESS0005.JOB rename to Documentazione/Euromap63/DemoCom/Step_99_DESCR/SESS0005.JOB diff --git a/Documentazione/Euromap63/DemoCom/Step_99_DESCR/SESS0005.REQ b/Documentazione/Euromap63/DemoCom/Step_99_DESCR/SESS0005.REQ new file mode 100644 index 00000000..34cd11bc --- /dev/null +++ b/Documentazione/Euromap63/DemoCom/Step_99_DESCR/SESS0005.REQ @@ -0,0 +1 @@ +SESS0005 EXECUTE "SESS0005.JOB"; diff --git a/IOB-UT/Eurom63.cs b/IOB-UT/Eurom63.cs index be93e9ec..8b7bf53c 100644 --- a/IOB-UT/Eurom63.cs +++ b/IOB-UT/Eurom63.cs @@ -39,19 +39,19 @@ namespace IOB_UT TimeSet, /// - /// Verificato il canale di comunicazione è OK, NON ci sono report attivi + /// Verificato il canale di comunicazione è OK, fatta pulizia con AbortAll, NON ci sono report attivi /// ChannelOk, /// - /// Richiesti report (NON ancora attivi) + /// Status data richiesti /// - DataRequested, + StatusRequested, /// - /// Campionamento dati attivo (1/+ report in lettura) + /// Prod data richiesti /// - Sampling + ProdRequested } public enum FileOpr @@ -165,6 +165,16 @@ namespace IOB_UT /// public string RespOk { get; set; } = "PROCESSED"; + /// + /// Seconds before do a new retry (default = 0 --> no veto) + /// + public double RetrySec { get; set; } = 0; + + /// + /// Veto for retry operation + /// + public DateTime RetryVeto { get; set; } = DateTime.Now; + /// /// Session Name /// diff --git a/IOB-WIN/DATA/CONF/EM63.json b/IOB-WIN/DATA/CONF/EM63.json index dff04d96..cb11a952 100644 --- a/IOB-WIN/DATA/CONF/EM63.json +++ b/IOB-WIN/DATA/CONF/EM63.json @@ -30,6 +30,7 @@ "Cycle": false, "Description": "Check Connection Status", "Max2Keep": 10, + "RetrySec": 5, "SessionName": "SESS0000", "SessionType": "IsConnected", "StepOrder": 0, @@ -51,11 +52,11 @@ "ValidityMinutes": 0.0, "FileList": [ { - "Path": "DATA\\EUR63_JOB\\SESS0001.REQ", + "Path": "DATA\\EUR63_JOB\\SESS0001.JOB", "OprReq": "Copy" }, { - "Path": "DATA\\EUR63_JOB\\SESS0001.JOB", + "Path": "DATA\\EUR63_JOB\\SESS0001.REQ", "OprReq": "Copy" } ] @@ -63,44 +64,47 @@ "2": { "Cycle": false, "Description": "Set DateTime on machine at start", + "RetrySec": 10, "SessionName": "SESS0002", "SessionType": "SetDateTime", "ValidityMinutes": 0.0, "Max2Keep": 10, "StepOrder": 2, "FileList": [ - { - "Path": "DATA\\EUR63_JOB\\SESS0002.REQ", - "OprReq": "Copy" - }, { "Path": "DATA\\EUR63_JOB\\SESS0002.JOB", "OprReq": "ReplaceAndCopy" + }, + { + "Path": "DATA\\EUR63_JOB\\SESS0002.REQ", + "OprReq": "Copy" } ] }, "3": { "Cycle": false, "Description": "Abort All prev requests", + "RetrySec": 10, "SessionName": "SESS0003", "SessionType": "AbortAll", - "ValidityMinutes": 0.0, + "ValidityMinutes": 0.2, "Max2Keep": 10, "StepOrder": 3, "FileList": [ { - "Path": "DATA\\EUR63_JOB\\SESS0003.REQ", + "Path": "DATA\\EUR63_JOB\\SESS0003.JOB", "OprReq": "Copy" }, { - "Path": "DATA\\EUR63_JOB\\SESS0003.JOB", + "Path": "DATA\\EUR63_JOB\\SESS0003.REQ", "OprReq": "Copy" } ] }, "4": { - "Cycle": false, + "Cycle": true, "Description": "Get Machine Status", + "RetrySec": 15, "SessionName": "SESS0004", "SessionType": "GetStatus", "ValidityMinutes": 1.0, @@ -108,18 +112,19 @@ "StepOrder": 4, "FileList": [ { - "Path": "DATA\\EUR63_JOB\\SESS0004.REQ", + "Path": "DATA\\EUR63_JOB\\SESS0004.JOB", "OprReq": "Copy" }, { - "Path": "DATA\\EUR63_JOB\\SESS0004.JOB", + "Path": "DATA\\EUR63_JOB\\SESS0004.REQ", "OprReq": "Copy" } ] }, "5": { - "Cycle": false, + "Cycle": true, "Description": "Get Production", + "RetrySec": 15, "SessionName": "SESS0005", "SessionType": "GetProduction", "ValidityMinutes": 1.0, @@ -127,11 +132,11 @@ "StepOrder": 5, "FileList": [ { - "Path": "DATA\\EUR63_JOB\\SESS0005.REQ", + "Path": "DATA\\EUR63_JOB\\SESS0005.JOB", "OprReq": "Copy" }, { - "Path": "DATA\\EUR63_JOB\\SESS0005.JOB", + "Path": "DATA\\EUR63_JOB\\SESS0005.REQ", "OprReq": "Copy" } ] @@ -139,21 +144,20 @@ "10": { "Cycle": false, "Description": "Set Param ODL at Setup", + "RetrySec": 5, "SessionName": "SESS0010", "SessionType": "SetParamOdl", "ValidityMinutes": 0.0, "Max2Keep": 10, "StepOrder": 10, "FileList": [ - { - "Path": "DATA\\EUR63_JOB\\SESS0010.REQ", - "OprReq": "Copy", - "RespKo": "ERROR", - "RespOk": "PROCESSED" - }, { "Path": "DATA\\EUR63_JOB\\SESS0010.JOB", "OprReq": "ReplaceAndCopy" + }, + { + "Path": "DATA\\EUR63_JOB\\SESS0010.REQ", + "OprReq": "Copy" } ] }, @@ -161,17 +165,18 @@ "Cycle": false, "Description": "Get INFO data", "Max2Keep": 10, + "RetrySec": 5, "SessionName": "SESS0019", "SessionType": "GetInfo", "StepOrder": 19, "ValidityMinutes": 0.0, "FileList": [ { - "Path": "DATA\\EUR63_JOB\\SESS0019.REQ", + "Path": "DATA\\EUR63_JOB\\SESS0019.JOB", "OprReq": "Copy" }, { - "Path": "DATA\\EUR63_JOB\\SESS0019.JOB", + "Path": "DATA\\EUR63_JOB\\SESS0019.REQ", "OprReq": "Copy" } ] diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0002.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0002.JOB index 2e412db3..ac48c1bf 100644 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0002.JOB +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0002.JOB @@ -1,2 +1,2 @@ -JOB ImpostaOrario RESPONSE "SESS0004.LOG"; +JOB ImpostaOrario RESPONSE "SESS0002.LOG"; SET SetTimMach {DTNow}; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0002.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0002.REQ index d29e9602..c647022a 100644 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0002.REQ +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0002.REQ @@ -1 +1 @@ -SESS0004 EXECUTE "SESS0004.JOB"; +SESS0002 EXECUTE "SESS0002.JOB"; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0004.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0004.JOB index e39fb861..ca69cf84 100644 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0004.JOB +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0004.JOB @@ -1,6 +1,6 @@ -JOB machstat RESPONSE "SESS0006.LOG"; +JOB machstat RESPONSE "SESS0004.LOG"; -REPORT status REWRITE "SESS0006.DAT" +REPORT status REWRITE "SESS0004.DAT" START IMMEDIATE STOP NEVER CYCLIC TIME 00:00:01 diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0004.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0004.REQ index 4a185f17..d29e9602 100644 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0004.REQ +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0004.REQ @@ -1 +1 @@ -SESS0006 EXECUTE "SESS0006.JOB"; +SESS0004 EXECUTE "SESS0004.JOB"; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0005.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0005.JOB index 3022aab8..f387774a 100644 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0005.JOB +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0005.JOB @@ -1,11 +1,25 @@ -JOB machstat RESPONSE "SESS0007.LOG"; +JOB machstat RESPONSE "SESS0005.LOG"; -REPORT status REWRITE "SESS0007.DAT" +REPORT status REWRITE "SESS0005.DAT" START IMMEDIATE STOP NEVER -CYCLIC TIME 00:00:02 -SESSIONS 30 +CYCLIC TIME 00:00:03 +SESSIONS 100 +//PARAMETERS +//DATE, TIME, ActCntCyc, ActTimCyc, ActTimFill, @OutXhour, SetDescJob; PARAMETERS -DATE, TIME, ActCntCyc, ActTimCyc, ActTimFill, @OutXhour, SetDescJob; - - +DATE, TIME +, ActCntCyc, ActTimCyc, ActTimFill +, @OutXhour +//, SetTmpBrlZnStb[1] +//, SetTmpBrlZn[2], SetTmpBrlZnHdev[2], SetTmpBrlZnLdev[2] +//, ActTmpBrlZn[1], ActTmpBrlZn[2], ActTmpBrlZn[3] +//, SetTmpMldZn[50], SetTmpMldZnStb[50], SetTmpMldZnHdev[50], SetTmpMldZnLdev[50], ActTmpMldZn[50] +//, SetTmpMldZn[51], SetTmpMldZnStb[51], SetTmpMldZnHdev[51], SetTmpMldZnLdev[51], ActTmpMldZn[51] +//, ActTmpCab, ActTmpMlt +//, ActStrCsh, ActStrCsh +//, ActSpdPlstMax, ActSpdPlstAve +, SetDescJob +//, ActCntPrt +//, ActTmpOil +; \ No newline at end of file diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0005.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0005.REQ index de4d0350..34cd11bc 100644 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0005.REQ +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0005.REQ @@ -1 +1 @@ -SESS0007 EXECUTE "SESS0007.JOB"; +SESS0005 EXECUTE "SESS0005.JOB"; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0010.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0010.JOB index bc3956cb..14278cfa 100644 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0010.JOB +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0010.JOB @@ -1,4 +1,4 @@ -JOB SetID RESPONSE "SESS0005.LOG"; +JOB SetID RESPONSE "SESS0010.LOG"; //SET SetDescJob " "; //SET SetDescPrt " " //SET SetDescMld " "; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0010.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0010.REQ index 34cd11bc..1a589005 100644 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0010.REQ +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0010.REQ @@ -1 +1 @@ -SESS0005 EXECUTE "SESS0005.JOB"; +SESS0010 EXECUTE "SESS0010.JOB"; diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0019.JOB b/IOB-WIN/DATA/EUR63_JOB/SESS0019.JOB index 3b3ac5a0..06249f76 100644 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0019.JOB +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0019.JOB @@ -1,2 +1,2 @@ -JOB GETINFO RESPONSE "SESS0002.LOG"; -GETINFO "SESS0002.DAT"; \ No newline at end of file +JOB GETINFO RESPONSE "SESS0019.LOG"; +GETINFO "SESS0019.DAT"; \ No newline at end of file diff --git a/IOB-WIN/DATA/EUR63_JOB/SESS0019.REQ b/IOB-WIN/DATA/EUR63_JOB/SESS0019.REQ index cced09c3..536ba257 100644 --- a/IOB-WIN/DATA/EUR63_JOB/SESS0019.REQ +++ b/IOB-WIN/DATA/EUR63_JOB/SESS0019.REQ @@ -1 +1 @@ -SESS0002 EXECUTE "SESS0002.JOB"; \ No newline at end of file +SESS0019 EXECUTE "SESS0019.JOB"; \ No newline at end of file diff --git a/IOB-WIN/DATA/TEMP/.placeholder b/IOB-WIN/DATA/TEMP/.placeholder new file mode 100644 index 00000000..5f282702 --- /dev/null +++ b/IOB-WIN/DATA/TEMP/.placeholder @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/IOB-WIN/IOB-WIN.csproj b/IOB-WIN/IOB-WIN.csproj index e4171f7a..9f16907d 100644 --- a/IOB-WIN/IOB-WIN.csproj +++ b/IOB-WIN/IOB-WIN.csproj @@ -516,10 +516,10 @@ Always - + Always - + Always @@ -528,6 +528,18 @@ Always + + Always + + + Always + + + Always + + + Always + Always @@ -540,21 +552,12 @@ Always - - Always - - - Always - - - Always - - - Always - Always + + Always + diff --git a/IOB-WIN/IobFileEurom63.cs b/IOB-WIN/IobFileEurom63.cs index 2208bd7c..c425008e 100644 --- a/IOB-WIN/IobFileEurom63.cs +++ b/IOB-WIN/IobFileEurom63.cs @@ -49,42 +49,28 @@ namespace IOB_WIN #region Private Methods /// - /// Processa una sessione - /// - andando a verificare l'esistenza della REQ + se esito positivo pulizia - /// - andando a richeidere di nuovo risposta + /// Se la sessione fosse scaduta o non attiva --> torna al livello indicato /// - /// - /// - private void processSession(Eurom63.ComLevel nextLevel, Eurom63.Session connectSession) + /// + private void checkSessionActive(Eurom63.Session currSession, Eurom63.ComLevel nextLevel) { - // controllo esistenza directory --> segno connected... - connectionOk = Directory.Exists(BaseDir); - if (connectionOk) + // SOLO SE ha senso che controllo (sono in sampling...) + if (actLevel > Eurom63.ComLevel.ChannelOk) { - // verifico se ci sia risp CONNECT - if (checkResp(connectSession)) + // devono essere ATTIVE le sessioni di campionamento... + if (!confE63.ActiveSessions[4].Active || !confE63.ActiveSessions[5].Active) { - // aggiorno livello - actLevel = nextLevel; - // elimino file sessione - cleanupSession(connectSession); - } - // richiedo SE non ci fosse i dati CONNECT... - else - { - processSession(connectSession); + DateTime adesso = DateTime.Now; + // devono NON essere scadute... + if (confE63.ActiveSessions[4].SessionValidUntil < adesso || confE63.ActiveSessions[5].SessionValidUntil < adesso) + { + // elimino TUTTE le risposte... + cleanupResp(); + // richiedo abortall... + abortPrevJob(); + } } } - else - { - // aspetto prima di riprovare... - Thread.Sleep(50); - } - } - - private void requestSampleData() - { - throw new NotImplementedException(); } #endregion Private Methods @@ -94,7 +80,7 @@ namespace IOB_WIN protected void abortPrevJob() { var nextLevel = Eurom63.ComLevel.ChannelOk; - var connectSession = confE63.ActiveSessions[4]; + var connectSession = confE63.ActiveSessions[3]; processSession(nextLevel, connectSession); } @@ -126,7 +112,21 @@ namespace IOB_WIN } /// - /// Elimina tutti i file della sessione indicata + /// verifica periodica dei campionamenti: + /// - i due jobs devono essere attivi e non scaduti + /// - non devo aver già resettato... + /// + protected void checkSampling() + { + var currSession = confE63.ActiveSessions[4]; + checkSessionActive(currSession, Eurom63.ComLevel.ChannelOk); + + currSession = confE63.ActiveSessions[5]; + checkSessionActive(currSession, Eurom63.ComLevel.ChannelOk); + } + + /// + /// Elimina i file della sessione indicata (SE è un task ciclico --> solo RSP) /// /// /// @@ -135,7 +135,14 @@ namespace IOB_WIN bool answ = false; if (session != null) { - string[] file2del = Directory.GetFiles(BaseDir, $"{session.SessionName}.*"); + string searchPattern = $"{session.SessionName}.*"; + // task ciclico? + if (session.Cycle) + { + // solo risposta! + searchPattern = $"{session.SessionName}.RSP"; + } + string[] file2del = Directory.GetFiles(BaseDir, searchPattern); foreach (var file in file2del) { File.Delete(file); @@ -144,12 +151,66 @@ namespace IOB_WIN return answ; } + /// + /// Processa una sessione + /// - andando a verificare l'esistenza della REQ + se esito positivo pulizia + /// - andando a richeidere di nuovo risposta + /// + /// + /// + protected void processSession(Eurom63.ComLevel nextLevel, Eurom63.Session connectSession) + { + if (connectSession != null) + { + // controllo esistenza directory --> segno connected... + connectionOk = Directory.Exists(BaseDir); + if (connectionOk) + { + // verifico se ci sia risp CONNECT + if (checkResp(connectSession)) + { + // aggiorno livello + actLevel = nextLevel; + // elimino file sessione + cleanupSession(connectSession); + connectSession.Active = false; + connectSession.Passed = true; + } + // richiedo SE non ci fosse i dati CONNECT... + else + { + DateTime adesso = DateTime.Now; + // evito di richiedere SE non fosse già scaduta richiesta... + if (adesso > connectSession.RetryVeto) + { + processSessionFile(connectSession); + connectSession.Active = true; + connectSession.Passed = false; + connectSession.SessionStarted = adesso; + connectSession.SessionValidUntil = adesso.AddMinutes(connectSession.ValidityMinutes); + connectSession.RetryVeto = adesso.AddSeconds(connectSession.RetrySec); + } + } + } + else + { + // aspetto prima di riprovare... + Thread.Sleep(50); + } + } + else + { + // aspetto prima di riprovare... + Thread.Sleep(50); + } + } + /// /// Processa i file della sessione indicata (copy + transform) /// /// /// - protected bool processSession(Eurom63.Session session) + protected bool processSessionFile(Eurom63.Session session) { bool answ = false; if (session != null) @@ -161,7 +222,19 @@ namespace IOB_WIN { fileFrom = $"{appPath}\\{file2Proc.Path}"; fileTo = $"{BaseDir}\\{Path.GetFileName(file2Proc.Path)}"; - File.Copy(fileFrom, fileTo, true); + if (file2Proc.OprReq == Eurom63.FileOpr.Copy) + { + File.Copy(fileFrom, fileTo, true); + } + else + { + // leggo file originale... + string rawData = File.ReadAllText(fileFrom); + // processo sostituzioni + rawData = rawData.Replace("{DTNow}", DateTime.Now.ToString("HHmmssyyyyMMdd")); + // ora in posizione definitiva + File.WriteAllText(fileTo, rawData); + } } } return answ; @@ -177,10 +250,24 @@ namespace IOB_WIN processSession(nextLevel, connectSession); } + protected void requestProdData() + { + var nextLevel = Eurom63.ComLevel.ProdRequested; + var connectSession = confE63.ActiveSessions[5]; + processSession(nextLevel, connectSession); + } + + protected void requestStatusData() + { + var nextLevel = Eurom63.ComLevel.StatusRequested; + var connectSession = confE63.ActiveSessions[4]; + processSession(nextLevel, connectSession); + } + protected void setMachineTime() { var nextLevel = Eurom63.ComLevel.TimeSet; - var connectSession = confE63.ActiveSessions[3]; + var connectSession = confE63.ActiveSessions[2]; processSession(nextLevel, connectSession); } @@ -217,13 +304,15 @@ namespace IOB_WIN break; case Eurom63.ComLevel.ChannelOk: - requestSampleData(); + requestStatusData(); break; - case Eurom63.ComLevel.DataRequested: + case Eurom63.ComLevel.StatusRequested: + requestProdData(); break; - case Eurom63.ComLevel.Sampling: + case Eurom63.ComLevel.ProdRequested: + checkSampling(); break; default: @@ -250,6 +339,18 @@ namespace IOB_WIN } } + /// + /// Pulizia folder da tutti i file RSP + /// + internal void cleanupResp() + { + string[] file2del = Directory.GetFiles(BaseDir, "*.RSP"); + foreach (var file in file2del) + { + File.Delete(file); + } + } + /// /// Ricarica conf adapter... /// From ac212c2068d930aca399f6cbe43890ac87a316d7 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Wed, 7 Oct 2020 20:01:03 +0200 Subject: [PATCH 24/26] refresh json conf --- IOB-WIN/DATA/CONF/EM63.json | 6 +++--- IOB-WIN/IobFileEurom63.cs | 31 +++++++++++++++++++------------ Jenkinsfile | 6 +++--- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/IOB-WIN/DATA/CONF/EM63.json b/IOB-WIN/DATA/CONF/EM63.json index cb11a952..5984ff3f 100644 --- a/IOB-WIN/DATA/CONF/EM63.json +++ b/IOB-WIN/DATA/CONF/EM63.json @@ -87,7 +87,7 @@ "RetrySec": 10, "SessionName": "SESS0003", "SessionType": "AbortAll", - "ValidityMinutes": 0.2, + "ValidityMinutes": 0.0, "Max2Keep": 10, "StepOrder": 3, "FileList": [ @@ -107,7 +107,7 @@ "RetrySec": 15, "SessionName": "SESS0004", "SessionType": "GetStatus", - "ValidityMinutes": 1.0, + "ValidityMinutes": 5.0, "Max2Keep": 120, "StepOrder": 4, "FileList": [ @@ -127,7 +127,7 @@ "RetrySec": 15, "SessionName": "SESS0005", "SessionType": "GetProduction", - "ValidityMinutes": 1.0, + "ValidityMinutes": 5.0, "Max2Keep": 120, "StepOrder": 5, "FileList": [ diff --git a/IOB-WIN/IobFileEurom63.cs b/IOB-WIN/IobFileEurom63.cs index c425008e..44822382 100644 --- a/IOB-WIN/IobFileEurom63.cs +++ b/IOB-WIN/IobFileEurom63.cs @@ -58,14 +58,17 @@ namespace IOB_WIN if (actLevel > Eurom63.ComLevel.ChannelOk) { // devono essere ATTIVE le sessioni di campionamento... - if (!confE63.ActiveSessions[4].Active || !confE63.ActiveSessions[5].Active) + if (!currSession.Active) { DateTime adesso = DateTime.Now; // devono NON essere scadute... - if (confE63.ActiveSessions[4].SessionValidUntil < adesso || confE63.ActiveSessions[5].SessionValidUntil < adesso) + if (currSession.SessionValidUntil < adesso) { // elimino TUTTE le risposte... cleanupResp(); + cleanupFolder(); + // imposto livello... + actLevel = Eurom63.ComLevel.ChannelOk; // richiedo abortall... abortPrevJob(); } @@ -135,17 +138,21 @@ namespace IOB_WIN bool answ = false; if (session != null) { - string searchPattern = $"{session.SessionName}.*"; - // task ciclico? - if (session.Cycle) + // solo se scaduta validità... + if (session.SessionValidUntil < DateTime.Now) { - // solo risposta! - searchPattern = $"{session.SessionName}.RSP"; - } - string[] file2del = Directory.GetFiles(BaseDir, searchPattern); - foreach (var file in file2del) - { - File.Delete(file); + string searchPattern = $"{session.SessionName}.*"; + // task ciclico? + if (session.Cycle) + { + // solo risposta! + searchPattern = $"{session.SessionName}.RSP"; + } + string[] file2del = Directory.GetFiles(BaseDir, searchPattern); + foreach (var file in file2del) + { + File.Delete(file); + } } } return answ; diff --git a/Jenkinsfile b/Jenkinsfile index f2e21cdd..6805741b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,9 +9,9 @@ pipeline { steps { /* calcolo numero versione... diverso x branch MASTER/DEVELOP */ script { - withEnv(['NEXT_BUILD_NUMBER=705']) { - // env.versionNumber = VersionNumber(versionNumberString : '3.2.${BUILD_DATE_FORMATTED, "yyMM"}.${BUILDS_ALL_TIME}', projectStartDate : '2006-01-01', skipFailedBuilds: true) - env.versionNumber = VersionNumber(versionNumberString : '3.2.${BUILD_DATE_FORMATTED, "yyMM"}.${BUILDS_ALL_TIME}', projectStartDate : '2006-01-01', skipFailedBuilds: true, overrideBuildsAllTime: '${NEXT_BUILD_NUMBER}') + withEnv(['NEXT_BUILD_NUMBER=706']) { + // env.versionNumber = VersionNumber(versionNumberString : '3.3.${BUILD_DATE_FORMATTED, "yyMM"}.${BUILDS_ALL_TIME}', projectStartDate : '2006-01-01', skipFailedBuilds: true) + env.versionNumber = VersionNumber(versionNumberString : '3.3.${BUILD_DATE_FORMATTED, "yyMM"}.${BUILDS_ALL_TIME}', projectStartDate : '2006-01-01', skipFailedBuilds: true, overrideBuildsAllTime: '${NEXT_BUILD_NUMBER}') env.APP_NAME = 'MAPO-IOB-WIN' } } From 32fe69f4b44922db38eb6318db72cca51d79ab89 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Wed, 7 Oct 2020 22:02:44 +0200 Subject: [PATCH 25/26] aggiunta segnaposto metodi x prod e contapezzi --- .../DemoCom/Step_04_STATUS/SESS0004.DAT | 2 +- .../DemoCom/Step_05_PROD/SESS0005.DAT | 2 +- IOB-WIN/IobFileEurom63.cs | 56 +++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/Documentazione/Euromap63/DemoCom/Step_04_STATUS/SESS0004.DAT b/Documentazione/Euromap63/DemoCom/Step_04_STATUS/SESS0004.DAT index 4ee79a7f..2447e9a1 100644 --- a/Documentazione/Euromap63/DemoCom/Step_04_STATUS/SESS0004.DAT +++ b/Documentazione/Euromap63/DemoCom/Step_04_STATUS/SESS0004.DAT @@ -1,2 +1,2 @@ DATE, TIME, ActStsMach -20201007, 18:49:57, 0A000 +20201007, 21:28:10, 0A000 diff --git a/Documentazione/Euromap63/DemoCom/Step_05_PROD/SESS0005.DAT b/Documentazione/Euromap63/DemoCom/Step_05_PROD/SESS0005.DAT index 621d2e37..7f1bedb2 100644 --- a/Documentazione/Euromap63/DemoCom/Step_05_PROD/SESS0005.DAT +++ b/Documentazione/Euromap63/DemoCom/Step_05_PROD/SESS0005.DAT @@ -1,2 +1,2 @@ DATE, TIME, ActCntCyc, ActTimCyc, ActTimFill, @OutXhour, SetDescJob -20201007, 19:44:42, 4568, 8.61, 0.50, 10046, Nr. 1000987654.01 +20201007, 21:29:52, 5302, 8.61, 0.50, 10058, Nr. 1000987654.01 diff --git a/IOB-WIN/IobFileEurom63.cs b/IOB-WIN/IobFileEurom63.cs index 44822382..57f3fc5b 100644 --- a/IOB-WIN/IobFileEurom63.cs +++ b/IOB-WIN/IobFileEurom63.cs @@ -405,6 +405,33 @@ namespace IOB_WIN #region Public Methods + /// + /// Effettua vero processing contapezzi + /// + public override void processContapezzi() + { + if (utils.CRB("enableContapezzi")) + { + // controllo se sono in sampling della produzione + if (actLevel > Eurom63.ComLevel.ProdRequested) + { + } + +#if false + // cerco parametro contapezzi... + string currPzCount = getDataItemValue(mtcParams.keyPartCount); + + // se ho un contapezzi... processo... + if (!string.IsNullOrEmpty(currPzCount)) + { + int newVal = -1; + Int32.TryParse(currPzCount, out newVal); + contapezziPLC = newVal > -1 ? newVal : contapezziPLC; + } +#endif + } + } + /// /// Effettua lettura semafori principale /// Parametri da aggiornare x display in form @@ -426,6 +453,15 @@ namespace IOB_WIN // ciclo! try { + // controllo di essere in sampling... + if (actLevel > Eurom63.ComLevel.ChannelOk) + { + // controllo se sono in sampling dello stato + if (actLevel > Eurom63.ComLevel.StatusRequested) + { + } + } + #if false // controllo SE il driver SIA attivo... if (driver != null) @@ -472,6 +508,26 @@ namespace IOB_WIN } } + /// + /// Effettua reset del contapezzi, NON PERMESSO per EM63 (read only) + /// + /// + public override bool resetcontapezziPLC() + { + bool answ = false; + return answ; + } + + /// + /// Effettua IMPOSTAZIONE FORZATA del contapezzi, NON PERMESSO per EM63 (read only) + /// + /// + public override bool setcontapezziPLC(int newPzCount) + { + bool answ = false; + return answ; + } + /// /// Connessione /// From 1efcbec672c1b729183885460c5d30d3222e0c35 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Wed, 7 Oct 2020 22:46:48 +0200 Subject: [PATCH 26/26] Completato metodi decodifica SIA sstatus SIA pzCount --- IOB-WIN/IobFileEurom63.cs | 183 ++++++++++++++++++++++++++++---------- 1 file changed, 136 insertions(+), 47 deletions(-) diff --git a/IOB-WIN/IobFileEurom63.cs b/IOB-WIN/IobFileEurom63.cs index 57f3fc5b..eaf6fff6 100644 --- a/IOB-WIN/IobFileEurom63.cs +++ b/IOB-WIN/IobFileEurom63.cs @@ -415,20 +415,47 @@ namespace IOB_WIN // controllo se sono in sampling della produzione if (actLevel > Eurom63.ComLevel.ProdRequested) { - } + /************************************************************ + * + * EXAMPLE + * DATE, TIME, ActCntCyc, ActTimCyc, ActTimFill, @OutXhour, SetDescJob + * 20201007, 21:29:52, 5302, 8.61, 0.50, 10058, Nr. 1000987654.01 + * + * devo prendere il 3° valore + * + * + ************************************************************/ -#if false - // cerco parametro contapezzi... - string currPzCount = getDataItemValue(mtcParams.keyPartCount); - - // se ho un contapezzi... processo... - if (!string.IsNullOrEmpty(currPzCount)) - { - int newVal = -1; - Int32.TryParse(currPzCount, out newVal); - contapezziPLC = newVal > -1 ? newVal : contapezziPLC; + // leggo il file della produzione HARD CODED... + var sessProd = confE63.ActiveSessions[5]; + string currPzCount = ""; + if (sessProd != null) + { + if (sessProd.Active) + { + // nome file... + string fileName = $"{BaseDir}\\{sessProd.SessionName}.DAT"; + if (File.Exists(fileName)) + { + // leggo il file... + string[] rawLines = File.ReadAllLines(fileName); + // devo avere almeno 2 righe... + if (rawLines.Length >= 2) + { + string[] statusData = rawLines[2].Split(','); + currPzCount = statusData[2].Trim(); + // salvo se valido + if (!string.IsNullOrEmpty(currPzCount)) + { + int newVal = -1; + Int32.TryParse(currPzCount, out newVal); + contapezziPLC = newVal > -1 ? newVal : contapezziPLC; + } + } + } + } + } } -#endif } } @@ -459,44 +486,106 @@ namespace IOB_WIN // controllo se sono in sampling dello stato if (actLevel > Eurom63.ComLevel.StatusRequested) { + /* ----------------------------------------------------- + * bitmap MAPO + * B0: POWER_ON + * B1: RUN + * B2: pzCount + * B3: allarme + * B4: manuale + * B5: allarme TCiclo (SLOW) + ----------------------------------------------------- */ + + /****************************************************************** + * + * EXAMPLE file content + * DATE, TIME, ActStsMach + * 20201007, 21:28:10, 0A000 + * + * Configurazione array status: 5 char status decoding + * + * Pos1: (status) + * 0: poweron + * 1: poweroff + * + * Pos2: (mode) + * A: AUTO + * S: SEMI auto + * M: Manual + * U: Setup + * H: Hord + * C: Maintenance + * 0: Unknown + * I: Idle + * + * Pos3: (assist call) + * 0: No assistance + * 2: Assistance required + * + * Pos4: (Bad part) + * 0: last cycle not bad + * 1: last cycle bad + * + * Pos5: Active Alarm + * 0: No alarm + * 1: Alarm + * + * + * + *******************************************************************/ + + // leggo il file dela produzione HARD CODED... + var sessStatus = confE63.ActiveSessions[4]; + string currStatus = "00000"; + if (sessStatus != null) + { + if (sessStatus.Active) + { + // nome file... + string fileName = $"{BaseDir}\\{sessStatus.SessionName}.DAT"; + if (File.Exists(fileName)) + { + // leggo il file... + string[] rawLines = File.ReadAllLines(fileName); + // devo avere almeno 2 righe... + if (rawLines.Length >= 2) + { + string[] statusData = rawLines[2].Split(','); + currStatus = statusData[2].Trim(); + if (!string.IsNullOrEmpty(currStatus)) + { + currDispData.semIn = Semaforo.SV; + } + } + } + } + } + // processo il currentStatus... parto da poweron + B_input = currStatus[0] == '1' ? 0 : 1; + // ora MODE + switch (currStatus[1]) + { + case 'A': + B_input += (1 << 1); + break; + + case 'S': + case 'M': + case 'U': + B_input += (1 << 4); + break; + + default: + break; + } + // ora cerco allarmi + if (currStatus[5] == '1') + { + B_input += (1 << 3); + } } } -#if false - // controllo SE il driver SIA attivo... - if (driver != null) - { - string cKey = ""; - string cVal = ""; - // IPOTESI: un UNICO oggetto decodifica status - if (monitoredItems.Status.Count == 1) - { - var item = monitoredItems.Status[0]; - // cerco elemento indicato - element = driver.FindElement(By.Id(item.val)); - cKey = element.Text; - // verifico se mancasse il mapping... - if (!item.codeMapping.ContainsKey(cKey)) - { - processUnknStatus(cKey); - } - else - { - // ora decodifico da variabile status a valore secondo impostazione "codeMapping" - cVal = item.codeMapping[cKey]; - B_input = int.Parse(cVal, System.Globalization.NumberStyles.HexNumber); - if (currDispData != null) - { - currDispData.semIn = Semaforo.SV; - } - } - } - } - else - { - lgError("Errore: driver non pronto (null)"); - } -#endif // riporto bitmap... reportRawInput(ref currDispData); }