diff --git a/IOB-UT-NEXT/Enums.cs b/IOB-UT-NEXT/Enums.cs index 8b141de7..4d80db55 100644 --- a/IOB-UT-NEXT/Enums.cs +++ b/IOB-UT-NEXT/Enums.cs @@ -18,6 +18,27 @@ namespace IOB_UT_NEXT OR } + /// + /// Modalità di calcolo tra serie di valori + /// + public enum calcMode + { + /// + /// NEssun processing + /// + None = 0, + + /// + /// somma dei valori + /// + sum, + + /// + /// produttoria + /// + prod + } + /// /// Elenco MODI CNC /// diff --git a/IOB-UT-NEXT/ToMapo.cs b/IOB-UT-NEXT/ToMapo.cs index e0208cb4..f4984ff4 100644 --- a/IOB-UT-NEXT/ToMapo.cs +++ b/IOB-UT-NEXT/ToMapo.cs @@ -166,7 +166,6 @@ namespace IOB_UT_NEXT /// public void setupData() { - // inizializzo vettore valore allarmi x banco int8 x iniziare alarmsState = new uint[size]; alarmsMask = new uint[size]; @@ -260,6 +259,11 @@ namespace IOB_UT_NEXT /// public string keyEStop { get; set; } = ""; + /// + /// Nome variabile x ExeMode + /// + public string keyExeMode { get; set; } = ""; + /// /// Nome variabile x pezzi FATTI /// @@ -286,9 +290,14 @@ namespace IOB_UT_NEXT public string keyRunMode { get; set; } = ""; /// - /// Nome variabile x ExeMode + /// Aree di memoria lettura /// - public string keyExeMode { get; set; } = ""; + public Dictionary mMapRead { get; set; } = new Dictionary(); + + /// + /// Aree di memoria scrittura + /// + public Dictionary mMapWrite { get; set; } = new Dictionary(); /// /// Dictionary dei nomi da cercare come "endsWith" a cui applicare la soglia indicata @@ -310,15 +319,18 @@ namespace IOB_UT_NEXT /// public bool runModeTrad { get; set; } = false; - /// - /// Aree di memoria lettura - /// - public Dictionary mMapRead { get; set; } = new Dictionary(); + #endregion Public Properties + } - /// - /// Aree di memoria scrittura - /// - public Dictionary mMapWrite { get; set; } = new Dictionary(); + /// + /// Oggetto x processing valori (elenco valori e modalità) + /// + public class calcConf + { + #region Public Properties + + public calcMode calcMode { get; set; } = calcMode.None; + public List listVal { get; set; } = new List(); #endregion Public Properties } @@ -498,6 +510,22 @@ namespace IOB_UT_NEXT /// public uint BrowseValue { get; set; } = 5001; + /// + /// Lista valori calcolati/derivati da processare + /// + public Dictionary calcValues { get; set; } = new Dictionary(); + + /// + /// Numero minimo di secondi di durata di uno status + /// + public int minSecStatusDuration { get; set; } = 1; + + /// + /// Numero minimo di secondi di attesa finale (es prima di chiedere chiusura ODL) + /// + public int minSecFinalWait { get; set; } = 30; + + /// /// Struttura dati x check condizione Contapezzi Abilitato (se vuoto = sempre abilitato) /// @@ -553,6 +581,12 @@ namespace IOB_UT_NEXT /// public List filterItemsNodeId { get; set; } = new List(); + /// + /// Elenco item flux da FILTRARE per chiave tradotta/VALORE + /// es: Cimolai / Baglietto, RunModeVal NON VOGLIO inviare quando il valore è 0 + /// + public Dictionary> fluxLogKeyValVeto { get; set; } = new Dictionary>(); + public UserIdent Identity { get; set; } = new UserIdent(); /// @@ -585,13 +619,6 @@ namespace IOB_UT_NEXT /// public WatchDogConf WatchDog { get; set; } = new WatchDogConf(); - - /// - /// Elenco item flux da FILTRARE per chiave tradotta/VALORE - /// es: Cimolai / Baglietto, RunModeVal NON VOGLIO inviare quando il valore è 0 - /// - public Dictionary> fluxLogKeyValVeto { get; set; } = new Dictionary>(); - #endregion Public Properties } diff --git a/IOB-WIN-NEXT/DATA/CONF/BAGLIETTO_CIMOLAI_01.ini b/IOB-WIN-NEXT/DATA/CONF/BAGLIETTO_CIMOLAI_01.ini index 1fb48a94..49b8a96f 100644 --- a/IOB-WIN-NEXT/DATA/CONF/BAGLIETTO_CIMOLAI_01.ini +++ b/IOB-WIN-NEXT/DATA/CONF/BAGLIETTO_CIMOLAI_01.ini @@ -71,7 +71,6 @@ CSV_ADD_HEADER=true VETO_SEND_SNAPSHOT=3 - ;NO_PING=FALSE ; conf aree allarme ALARM_CONF=BAGLIETTO_CIMOLAI_01_alarm.json diff --git a/IOB-WIN-NEXT/DATA/CONF/BAGLIETTO_CIMOLAI_01.json b/IOB-WIN-NEXT/DATA/CONF/BAGLIETTO_CIMOLAI_01.json index 4166f851..c5c90e95 100644 --- a/IOB-WIN-NEXT/DATA/CONF/BAGLIETTO_CIMOLAI_01.json +++ b/IOB-WIN-NEXT/DATA/CONF/BAGLIETTO_CIMOLAI_01.json @@ -193,5 +193,18 @@ "-1", "0" ] + }, + "minSecStatusDuration": 10, + "minSecFinalWait": 180, + "calcValues": { + "PesoTot": { + "calcMode": "sum", + "listVal": [ + "PLC/DB231/peso1", + "PLC/DB231/peso2", + "PLC/DB231/peso3", + "PLC/DB231/peso4" + ] + } } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobGeneric.cs b/IOB-WIN-NEXT/IobGeneric.cs index a08be818..beb86200 100644 --- a/IOB-WIN-NEXT/IobGeneric.cs +++ b/IOB-WIN-NEXT/IobGeneric.cs @@ -1173,6 +1173,26 @@ namespace IOB_WIN_NEXT } } + /// + /// URL per richiesta chiusura manuale ad utente x ODL corrente (metodo GET)... + /// + public string urlODLAskClose + { + get + { + string answ = ""; + try + { + answ = $@"{cIobConf.serverData.TRANSP}://{cIobConf.serverData.MPIP}{cIobConf.serverData.MPURL}{cIobConf.serverData.CMDALIVE}/askCloseODL/{cIobConf.codIOB}?idxOdl="; + } + catch (Exception exc) + { + lgError(exc, "Errore in composizione urlODLClose"); + } + return answ; + } + } + /// /// URL per chiusura ODL corrente (metodo GET)... /// @@ -5846,14 +5866,37 @@ namespace IOB_WIN_NEXT protected bool tryCloseODL() { bool fatto = false; + string fullUrl = $"{urlODLClose}{currIdxODL}"; try { - // invio chiamata URL x reset ODL su macchina - string rawSplit = callUrl($"{urlODLClose}{currIdxODL}", false); - fatto = (rawSplit != "KO") ? true : false; + // invio chiamata URL x chiusura ODL su macchina + string callResp = callUrl(fullUrl, false); + fatto = (callResp != "KO") ? true : false; } catch { } + lgInfo($"Eseguito tryCloseODL per {currIdxODL} | url: {fullUrl} | esito: {fatto}"); + return fatto; + } + + + /// + /// Effettua chiamata MP-IO per cheidere all'utente se vuole effettuare chiusura ODL corrente della macchina + /// + /// + protected bool tryAskCloseODL() + { + bool fatto = false; + string fullUrl = $"{urlODLAskClose}{currIdxODL}"; + try + { + // invio chiamata URL x chiusura ODL su macchina + string callResp = callUrl(fullUrl, false); + fatto = (callResp != "KO") ? true : false; + } + catch + { } + lgInfo($"Eseguito tryAskCloseODL per {currIdxODL} | url: {fullUrl} | esito: {fatto}"); return fatto; } diff --git a/IOB-WIN-NEXT/IobOpcUa.cs b/IOB-WIN-NEXT/IobOpcUa.cs index e471ce4f..45bddd7e 100644 --- a/IOB-WIN-NEXT/IobOpcUa.cs +++ b/IOB-WIN-NEXT/IobOpcUa.cs @@ -165,6 +165,22 @@ namespace IOB_WIN_NEXT return answ; } + /// + /// Recupera valore OPC-UA direttamente in formato double + /// + /// + /// + public double getDataItemValueDouble(string diKey) + { + double answ = 0; + string rawVal = getDataItemValue(diKey); + if (rawVal != null) + { + double.TryParse(diKey, out answ); + } + return answ; + } + /// /// Recupero dati dinamici... /// @@ -531,7 +547,7 @@ namespace IOB_WIN_NEXT return changed; } - internal virtual void procRunMode(ref string currRun) + protected virtual void procRunMode(ref string currRun) { // variabili RUN... se richiesto invio runMode if (opcUaParams.runModeSend) diff --git a/IOB-WIN-NEXT/IobOpcUaMBHCimolai.cs b/IOB-WIN-NEXT/IobOpcUaMBHCimolai.cs index 374a5279..6cb15f3e 100644 --- a/IOB-WIN-NEXT/IobOpcUaMBHCimolai.cs +++ b/IOB-WIN-NEXT/IobOpcUaMBHCimolai.cs @@ -170,14 +170,14 @@ namespace IOB_WIN_NEXT #region Internal Methods - internal override void procRunMode(ref string currRun) + protected override void procRunMode(ref string currRun) { // variabili RUN... se richiesto invio runMode if (opcUaParams.runModeSend) { - currRun = $"{currAct}"; - // effettuo processing SPECIFICO currAct x gestione snapshot... - if (currAct == 10) + currRun = $"{currRunMode}"; + // effettuo processing SPECIFICO currRunMode x gestione snapshot... + if (currRunMode == 10) { if (DateTime.Now > vetoSnapshot) { @@ -236,6 +236,98 @@ namespace IOB_WIN_NEXT } } } + + // gestione dei macro-stati del travel... SOLO se in esecuzione da travel o con ODL>0... + if (currExeMode > 0) + { + double pesoTot = 0; + DateTime adesso = DateTime.Now; + // può cambiare stato se per ALMENO minSecStatus è rimasto nello status corrente... + bool canChange = adesso.Subtract(currTravelStateStart).TotalSeconds > opcUaParams.minSecStatusDuration; + if (canChange) + { + // STEP 1: verifico se sia iniziato caricamento... + if (currTravelState == travelState.Idle) + { + if (currIdxODL > 0) + { + currTravelState = travelState.StartOdl; + currTravelStateStart = adesso; + } + } + // sono nell'esecuzione ODL, controllo il resto + else + { + // nb: vedere se usare isWorkingCimolai / isManualCimolai + + // verifico il valore della variabile calcolata del PESO totale... + if (dataItemMem.ContainsKey("PesoTot")) + { + pesoTot = getDataItemValueDouble("PesoTot"); + } + // ...oppuresommo direttamente + else + { + pesoTot += getDataItemValueDouble("PLC/DB231/peso1"); + pesoTot += getDataItemValueDouble("PLC/DB231/peso2"); + pesoTot += getDataItemValueDouble("PLC/DB231/peso3"); + pesoTot += getDataItemValueDouble("PLC/DB231/peso4"); + } + + // STEP 2: verifico se sia iniziato caricamento... + if (currTravelState == travelState.StartOdl) + { + if (pesoTot > 0) + { + currTravelState = travelState.UpLift; + currTravelStateStart = adesso; + } + } + // STEP 3: verifico se sia terminato caricamento... + else if (currTravelState == travelState.UpLift) + { + if (pesoTot == 0) + { + currTravelState = travelState.Move; + currTravelStateStart = adesso; + } + } + // STEP 4: verifico se sia terminato movimento... + else if (currTravelState == travelState.Move) + { + if (pesoTot > 0) + { + currTravelState = travelState.DownLift; + currTravelStateStart = adesso; + } + } + // STEP 5: verifico se sia terminato scaricamento... + else if (currTravelState == travelState.DownLift) + { + if (pesoTot == 0) + { + currTravelState = travelState.WaitClose; + currTravelStateStart = adesso; + } + } + } + } + + // ora verifico solo condizione finale x eventuale chiusura... + bool sendAskClose = adesso.Subtract(currTravelStateStart).TotalSeconds > opcUaParams.minSecFinalWait; + if (currTravelState == travelState.WaitClose && sendAskClose) + { + // chiama richiesta chiusura x utente + tryAskCloseODL(); + // resetta contatore x nuova richeista finale eventuale... + currTravelStateStart = adesso; + } + } + else + { + // altrimenti forzo a "Idle" state + currTravelState = travelState.Idle; + } } #endregion Internal Methods @@ -244,7 +336,8 @@ namespace IOB_WIN_NEXT protected int lastAct = 0; - protected int lastExe = 0; + + protected int lastExeMode = 0; protected int VETO_SEND_SNAPSHOT = 10; @@ -257,14 +350,14 @@ namespace IOB_WIN_NEXT /// /// Attività corrente (INT) da keyRunMode valore di PLC/DB231/Attivita /// - protected int currAct + protected int currRunMode { get { int answ = 0; - if (!string.IsNullOrEmpty(opcUaParams.keyExeMode)) + if (!string.IsNullOrEmpty(opcUaParams.keyRunMode)) { - string currRun = getDataItemValue(opcUaParams.keyExeMode); + string currRun = getDataItemValue(opcUaParams.keyRunMode); if (!string.IsNullOrEmpty(currRun)) { int.TryParse(currRun, out answ); @@ -277,7 +370,7 @@ namespace IOB_WIN_NEXT /// /// Attività corrente (INT) da keyExeMode valore di PLC/DB231/InCorso /// - protected int currExe + protected int currExeMode { get { @@ -413,15 +506,15 @@ namespace IOB_WIN_NEXT } // verifico se aggiornare stato LAST ACTION - if (lastAct != currAct && currAct != 0) + if (lastAct != currRunMode && currRunMode != 0) { // registro solo azioni > 1 e < 10 - if (currAct > 1 && currAct < 10) + if (currRunMode > 1 && currRunMode < 10) { // escludo le azioni 4 e 5 (che sono anche in concomitanza con 2-3) - if (currAct < 4 || currAct > 5) + if (currRunMode < 4 || currRunMode > 5) { - lastAct = currAct; + lastAct = currRunMode; } } } @@ -431,10 +524,10 @@ namespace IOB_WIN_NEXT { // se rilevo variazione exe (curr/last) // --> registro richiesta attreazzaggio PODL da info commessa - if (lastExe != currExe) + if (lastExeMode != currExeMode) { // se 0--> 1 --> registro - if (currExe == 1) + if (currExeMode == 1) { lgInfo("--------------------------------------------"); // prendo senza stringa PODL @@ -455,7 +548,7 @@ namespace IOB_WIN_NEXT lgInfo("--------------------------------------------"); } // registro exe mode - lastExe = currExe; + lastExeMode = currExeMode; } } @@ -675,7 +768,7 @@ namespace IOB_WIN_NEXT WriteValue commWriteVal = new WriteValue(); commWriteVal.NodeId = new NodeId(item.Key); commWriteVal.AttributeId = Attributes.Value; - commWriteVal.Value = new DataValue(); + commWriteVal.Value = new DataValue();\ commWriteVal.Value.Value = item.Value; nodes2Write.Add(commWriteVal); @@ -722,5 +815,21 @@ namespace IOB_WIN_NEXT } #endregion Private Methods + + protected DateTime currTravelStateStart { get; set; } = DateTime.Today.AddYears(-1); + protected travelState currTravelState { get; set; } = travelState.Idle; + + /// + /// Definizione stati travel + /// + protected enum travelState + { + Idle = 0, + StartOdl, + UpLift, + Move, + DownLift, + WaitClose + } } } \ No newline at end of file