From 0ff8b3c61ac34f64a7869cf7c4894b01eae80f91 Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Tue, 5 Nov 2024 19:28:43 +0100 Subject: [PATCH] Modifiche Generic + SIMULA - aggiunta gestione parametri link MemWrite - decodifica task2exe x aggiungere link vals - gestione demo in simula x calcolo ART/COMM numerici --- IOB-UT-NEXT/plcMemMapExt.cs | 7 + IOB-WIN-NEXT/DATA/CONF/MAIN.ini | 3 +- IOB-WIN-NEXT/DATA/CONF/SIMUL_01.ini | 2 +- IOB-WIN-NEXT/DATA/CONF/SIMUL_01.json | 24 ++- IOB-WIN-NEXT/DATA/CONF/VL27.ini | 6 +- IOB-WIN-NEXT/IOB-WIN-NEXT.csproj | 12 +- IOB-WIN-NEXT/Iob/Generic.cs | 251 +++++++++++++++++++++++++-- IOB-WIN-NEXT/Iob/Simula.cs | 64 +++++++ IOB-WIN-NEXT/packages.config | 2 +- 9 files changed, 343 insertions(+), 28 deletions(-) diff --git a/IOB-UT-NEXT/plcMemMapExt.cs b/IOB-UT-NEXT/plcMemMapExt.cs index 19b3a488..c06ff608 100644 --- a/IOB-UT-NEXT/plcMemMapExt.cs +++ b/IOB-UT-NEXT/plcMemMapExt.cs @@ -24,6 +24,13 @@ namespace IOB_UT_NEXT /// public Dictionary optKVP { get; set; } = new Dictionary(); + + /// + /// Dizionario opzionale di configurazione memorie WRITE con "alias", + /// impiegato tipicamente per poter gestire scritture valori INT su CNC/PLC che non accettano stringhe (es FANUC) + /// + public Dictionary mMapWriteLink { get; set; } = new Dictionary(); + #if false /// /// Base del NameSpace usato per le funzionalità di translate (parametri ACT-SET), da inserire come PRE diff --git a/IOB-WIN-NEXT/DATA/CONF/MAIN.ini b/IOB-WIN-NEXT/DATA/CONF/MAIN.ini index 87022992..3769dc35 100644 --- a/IOB-WIN-NEXT/DATA/CONF/MAIN.ini +++ b/IOB-WIN-NEXT/DATA/CONF/MAIN.ini @@ -45,6 +45,7 @@ CLI_INST=SteamWareSim ;STARTLIST=SIM_DP_01 ;NB: mettere copy always ai file di conf x fare test... -STARTLIST=FTP_SONATEST +;STARTLIST=FTP_SONATEST +STARTLIST=SIMUL_01 MAXCNC=10 \ No newline at end of file diff --git a/IOB-WIN-NEXT/DATA/CONF/SIMUL_01.ini b/IOB-WIN-NEXT/DATA/CONF/SIMUL_01.ini index 19b448a1..da4e3967 100644 --- a/IOB-WIN-NEXT/DATA/CONF/SIMUL_01.ini +++ b/IOB-WIN-NEXT/DATA/CONF/SIMUL_01.ini @@ -4,7 +4,7 @@ CNCTYPE=SIMULA PING_MS_TIMEOUT=500 MinDeltaSec=5 EnableRedisQueue=true -IOB_NAME=TFT_RAMA_001 +;IOB_NAME=TFT_RAMA_001 [MACHINE] VENDOR=STEAMWARE diff --git a/IOB-WIN-NEXT/DATA/CONF/SIMUL_01.json b/IOB-WIN-NEXT/DATA/CONF/SIMUL_01.json index b0645e73..d566650f 100644 --- a/IOB-WIN-NEXT/DATA/CONF/SIMUL_01.json +++ b/IOB-WIN-NEXT/DATA/CONF/SIMUL_01.json @@ -9,6 +9,15 @@ "size": 20, "displOrdinal": 1 }, + "setArtNum": { + "name": "setArtNum", + "description": "# Num Articolo", + "memAddr": "DB150.DBB112", + "tipoMem": "Int", + "index": 112, + "size": 4, + "displOrdinal": 1 + }, "setComm": { "name": "setComm", "description": "Commessa", @@ -18,6 +27,15 @@ "size": 20, "displOrdinal": 2 }, + "setCommNum": { + "name": "setCommNum", + "description": "# NumCommessa", + "memAddr": "DB150.DBB132", + "tipoMem": "Int", + "index": 132, + "size": 4, + "displOrdinal": 2 + }, "setPzComm": { "name": "setPzComm", "description": "Qta Richiesta", @@ -378,11 +396,15 @@ "path-confSetup": "C:\\MesData\\Setup\\setupConsumi.json", "replace-": "{{PODL}}", "replace-": "Kg{{Qty}} | {{Note}}" - } //, + }, //, //"BaseKeyTranslate": "ns=2;s=RamosaETN21.RamosaCJ2", //"RecipeKeyTranslate": { // "Present Value.General Fan": "Recipe.Chain Spped", // "Present Value.Bottom Overfeeding": "Recipe.Bottom Overfeeding", // "Present Value.Top Overfeeding": "Recipe.Top Overfeeding" //} + "mMapWriteLink": { + "setArt": "setArtNum", + "setComm": "setCommNum" + } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/DATA/CONF/VL27.ini b/IOB-WIN-NEXT/DATA/CONF/VL27.ini index 430b639e..a8c67c6b 100644 --- a/IOB-WIN-NEXT/DATA/CONF/VL27.ini +++ b/IOB-WIN-NEXT/DATA/CONF/VL27.ini @@ -9,7 +9,7 @@ MODEL=CROSSFLEX A1600 [CNC] ; FANUC! -IP=192.168.1.12 +IP=192.168.214.100\ PORT=9000 GETPRGNAME=true @@ -24,13 +24,13 @@ CMDADV1=?valore= CMDREBO=/sendReboot.aspx?idxMacchina= [MEMORY] -; Green 11.4 | Red: Y11.7 | Yellow: Y11.6 (bianco, eventualmente in lampeggio) | Emerg: X8.4 | +; Green 11.4 | Red: Y11.7 | Yellow: Y11.6 (bianco, eventualmente in lampeggio) | Emerg: X8.4 (negata)| ;BIT0=CONN BIT1=Y11.4 BIT2=PZCOUNT.PAR.6711 BIT3=Y11.7 BIT4=Y11.6 -BIT5=X8.4 +BIT5=!X8.4 AREAD_START=0 AREAD_SIZE=9999 AREAG_SIZE=48 diff --git a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj index 6de9eea9..dbacb5b4 100644 --- a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj +++ b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj @@ -147,8 +147,8 @@ False ExtLib\krcc.dll - - ..\packages\MapoSDK.6.14.2309.1908\lib\MapoSDK.dll + + ..\packages\MapoSDK.6.14.2411.518\lib\MapoSDK.dll ..\packages\MathNet.Numerics.4.15.0\lib\net461\MathNet.Numerics.dll @@ -515,7 +515,9 @@ - + + Always + @@ -837,7 +839,9 @@ Always - + + Always + diff --git a/IOB-WIN-NEXT/Iob/Generic.cs b/IOB-WIN-NEXT/Iob/Generic.cs index 120e17a2..6f7008b9 100644 --- a/IOB-WIN-NEXT/Iob/Generic.cs +++ b/IOB-WIN-NEXT/Iob/Generic.cs @@ -835,6 +835,46 @@ namespace IOB_WIN_NEXT.Iob } } + /// + /// URL per recupero traduzione CodArt in numerico... + /// + public string urlGetNumArt + { + get + { + string answ = ""; + try + { + answ = $@"{cIobConf.serverData.TRANSP}://{cIobConf.serverData.MPIP}{cIobConf.serverData.MPURL}{cIobConf.serverData.CMDALIVE}/getArtNum/{cIobConf.codIOB}"; + } + catch (Exception exc) + { + lgError(exc, "Errore in composizione urlGetNumArt"); + } + return answ; + } + } + + /// + /// URL per recupero traduzione CodComm in numerico... + /// + public string urlGetNumComm + { + get + { + string answ = ""; + try + { + answ = $@"{cIobConf.serverData.TRANSP}://{cIobConf.serverData.MPIP}{cIobConf.serverData.MPURL}{cIobConf.serverData.CMDALIVE}/getXdlNum/{cIobConf.codIOB}"; + } + catch (Exception exc) + { + lgError(exc, "Errore in composizione urlGetNumComm"); + } + return answ; + } + } + /// /// URL per recupero idle time IOB... /// @@ -1469,6 +1509,7 @@ namespace IOB_WIN_NEXT.Iob { bool taskOk = false; string taskVal = ""; + string newVal = ""; // cerco task specifici: se ho startSetup --> imposto bit DBB701.DBB0.4 foreach (var item in task2exe) { @@ -1509,6 +1550,69 @@ namespace IOB_WIN_NEXT.Iob break; + case taskType.setArtNum: + // in primis faccio una chiamata per tutta la tab SE fosse vuoto il dict di traduzione + if (DictNumArt == null || DictNumArt.Count == 0) + { + getNumArt(""); + } + // chiamo server x avere decodifica valore INT + newVal = getNumArt(item.Value); + // procedo come il resto cercando mappatura in memMap: recupero dati + // da memMap... + if (memMap != null && memMap.mMapWrite != null) + { + if (memMap.mMapWrite.ContainsKey(item.Key)) + { + dataConf currMem = memMap.mMapWrite[item.Key]; + string addr = currMem.memAddr; + taskVal = $"SET task: {item.Key} --> {newVal} | mem: {currMem.memAddr} - {currMem.size} byte"; + // salvo il nuovo valore nella memoria... così prox invio lo trasmetterà + memMap.mMapWrite[item.Key].value = newVal; + } + else + { + taskVal = $"NO DATA MEM, SET task: {item.Key} --> {newVal} ({item.Value})"; + } + } + else + { + taskVal = $"NO MemMap found, SET task: {item.Key} --> {newVal} ({item.Value})"; + } + + // salvo in currProd.. + saveProdData(new KeyValuePair(item.Key, newVal)); + break; + + case taskType.setCommNum: + // chiamo server x avere decodifica valore INT + newVal = getNumComm(item.Value); + // procedo come il resto cercando mappatura in memMap: recupero dati + // da memMap... + if (memMap != null && memMap.mMapWrite != null) + { + if (memMap.mMapWrite.ContainsKey(item.Key)) + { + dataConf currMem = memMap.mMapWrite[item.Key]; + string addr = currMem.memAddr; + taskVal = $"SET task: {item.Key} --> {newVal} | mem: {currMem.memAddr} - {currMem.size} byte"; + // salvo il nuovo valore nella memoria... così prox invio lo trasmetterà + memMap.mMapWrite[item.Key].value = newVal; + } + else + { + taskVal = $"NO DATA MEM, SET task: {item.Key} --> {newVal} ({item.Value})"; + } + } + else + { + taskVal = $"NO MemMap found, SET task: {item.Key} --> {newVal} ({item.Value})"; + } + + // salvo in currProd.. + saveProdData(new KeyValuePair(item.Key, newVal)); + break; + case taskType.forceResetPzCount: // reset contapezzi inizio setup taskOk = resetContapezziPLC(); @@ -2105,6 +2209,25 @@ namespace IOB_WIN_NEXT.Iob return answ; } + /// + /// Cerca se esiste un link tra aree di memoria in write e lo restituisce + /// + /// + /// + public string getOptWriteLink(string key) + { + string answ = ""; + // controllo SE HO il parametro + if (memMap != null && memMap.mMapWriteLink != null && memMap.mMapWriteLink.Count > 0) + { + if (memMap.mMapWriteLink.ContainsKey(key)) + { + answ = memMap.mMapWriteLink[key]; + } + } + return answ; + } + /// /// Restituisce info OVERRIDES /// @@ -2939,6 +3062,7 @@ namespace IOB_WIN_NEXT.Iob public Dictionary processTask(Dictionary task2exe) { Dictionary taskDone = new Dictionary(); + Dictionary task2Add = new Dictionary(); // eseguo realmente solo se NON disabilitata questa gestione (caso doppio PLC/HMI)... if (!cIobConf.disableExeTask) { @@ -2950,6 +3074,21 @@ namespace IOB_WIN_NEXT.Iob { idTask++; lgInfo($"[{idTask:00}] - {item.Key} --> {item.Value}"); + // verifico SE il task abbia un duplo writeLink e nel caso lo aggiungo... + var linkVal = getOptWriteLink(item.Key); + if (!string.IsNullOrEmpty(linkVal)) + { + // aggiungo a task2add... + task2Add.Add(linkVal, item.Value); + } + } + // se ho task Link da aggiungere li aggiungo! + if (task2Add.Count > 0) + { + foreach (var item in task2Add) + { + task2exe.Add(item.Key, item.Value); + } } // chiamo procedura esecutiva (diversa x ogni IOB) taskDone = executeTasks(task2exe); @@ -6007,23 +6146,6 @@ namespace IOB_WIN_NEXT.Iob return answ; } -#if false - /// - /// Traduzione del valore chiave configurato dal dizionario RecipeKeyTranslate + BaseKeyTranslate - /// - /// - /// - protected string RecipeKeyDecod(Dictionary keyDict, string currKey) - { - string answ = currKey; - if (keyDict != null) - { - answ = keyDict[currKey]; - } - return answ; - } -#endif - protected void raiseRefresh(newDisplayData currDispData) { if (currDispData != null) @@ -7638,6 +7760,101 @@ namespace IOB_WIN_NEXT.Iob } } + /// + /// Recupera valore numerico ARTICOLO x salvataggio valori INT + /// + /// + /// + protected string getNumArt(string value) + { + string answ = ""; + // cerco in dizionario corrente... + if (DictNumArt.Count > 0 && DictNumArt.ContainsKey(value)) + { + answ = DictNumArt[value]; + } + // altrimenti chiamo servizio + else + { + // chiamo MP-IO server + if (checkServerAlive) + { + string url2call = $"{urlGetNumArt}?CodArt={value}"; + if (verboseLog) + { + lgInfo("chiamata URL " + url2call); + } + var rawData = utils.callUrlNow(url2call); + // deserializzo e recupero KVP... + var dictArtSrv = JsonConvert.DeserializeObject>(rawData); + // se fosse una chiamata con valore vuoto --> salvo intera tabella... + if (string.IsNullOrEmpty(value)) + { + DictNumArt = dictArtSrv; + } + // altrimenti aggiungo a dizionario + else + { + foreach (var item in dictArtSrv) + { + if (!DictNumArt.ContainsKey(item.Key)) + { + DictNumArt.Add(item.Key, item.Value); + } + } + } + // ora cerco valore e restituisco + if (DictNumArt.ContainsKey(value)) + { + answ = DictNumArt[value]; + } + } + } + return answ; + } + + protected Dictionary DictNumArt { get; set; } = new Dictionary(); + + /// + /// Recupera valore numerico COMMESSA x salvataggio valori INT + /// + /// + /// + protected string getNumComm(string value) + { + string answ = ""; + // chiamo MP-IO server + if (checkServerAlive) + { + string url2call = $"{urlGetNumComm}?CodXdl={value}"; + if (verboseLog) + { + lgInfo("chiamata URL " + url2call); + } + // è direttamente il risultato! + value = utils.callUrlNow(url2call); + } + // restituisco + return answ; + } + +#if false + /// + /// Traduzione del valore chiave configurato dal dizionario RecipeKeyTranslate + BaseKeyTranslate + /// + /// + /// + protected string RecipeKeyDecod(Dictionary keyDict, string currKey) + { + string answ = currKey; + if (keyDict != null) + { + answ = keyDict[currKey]; + } + return answ; + } +#endif + /// /// recupera valore salvato in persistence layer (se non c'è crea...) /// diff --git a/IOB-WIN-NEXT/Iob/Simula.cs b/IOB-WIN-NEXT/Iob/Simula.cs index ef0fa7d7..ecaee0d8 100644 --- a/IOB-WIN-NEXT/Iob/Simula.cs +++ b/IOB-WIN-NEXT/Iob/Simula.cs @@ -221,6 +221,7 @@ namespace IOB_WIN_NEXT.Iob if (!disableSimStatus) { string taskVal = ""; + string newVal = ""; // verifico non sia null if (task2exe != null) { @@ -228,6 +229,7 @@ namespace IOB_WIN_NEXT.Iob foreach (var item in task2exe) { taskVal = ""; + newVal = ""; // converto richiesta in enum... taskType tName = taskType.nihil; Enum.TryParse(item.Key, out tName); @@ -260,6 +262,68 @@ namespace IOB_WIN_NEXT.Iob } } break; + case taskType.setArtNum: + // in primis faccio una chiamata per tutta la tab SE fosse vuoto il dict di traduzione + if (DictNumArt == null || DictNumArt.Count == 0) + { + getNumArt(""); + } + // chiamo server x avere decodifica valore INT + newVal = getNumArt(item.Value); + // procedo come il resto cercando mappatura in memMap: recupero dati + // da memMap... + if (memMap != null && memMap.mMapWrite != null) + { + if (memMap.mMapWrite.ContainsKey(item.Key)) + { + dataConf currMem = memMap.mMapWrite[item.Key]; + string addr = currMem.memAddr; + taskVal = $"SET task: {item.Key} --> {newVal} | mem: {currMem.memAddr} - {currMem.size} byte"; + // salvo il nuovo valore nella memoria... così prox invio lo trasmetterà + memMap.mMapWrite[item.Key].value = newVal; + } + else + { + taskVal = $"NO DATA MEM, SET task: {item.Key} --> {newVal} ({item.Value})"; + } + } + else + { + taskVal = $"NO MemMap found, SET task: {item.Key} --> {newVal} ({item.Value})"; + } + + // salvo in currProd.. + saveProdData(new KeyValuePair(item.Key, newVal)); + break; + + case taskType.setCommNum: + // chiamo server x avere decodifica valore INT + newVal = getNumComm(item.Value); + // procedo come il resto cercando mappatura in memMap: recupero dati + // da memMap... + if (memMap != null && memMap.mMapWrite != null) + { + if (memMap.mMapWrite.ContainsKey(item.Key)) + { + dataConf currMem = memMap.mMapWrite[item.Key]; + string addr = currMem.memAddr; + taskVal = $"SET task: {item.Key} --> {newVal} | mem: {currMem.memAddr} - {currMem.size} byte"; + // salvo il nuovo valore nella memoria... così prox invio lo trasmetterà + memMap.mMapWrite[item.Key].value = newVal; + } + else + { + taskVal = $"NO DATA MEM, SET task: {item.Key} --> {newVal} ({item.Value})"; + } + } + else + { + taskVal = $"NO MemMap found, SET task: {item.Key} --> {newVal} ({item.Value})"; + } + + // salvo in currProd.. + saveProdData(new KeyValuePair(item.Key, newVal)); + break; case taskType.nihil: case taskType.fixStopSetup: diff --git a/IOB-WIN-NEXT/packages.config b/IOB-WIN-NEXT/packages.config index 0df37a61..9bfd01a6 100644 --- a/IOB-WIN-NEXT/packages.config +++ b/IOB-WIN-NEXT/packages.config @@ -12,7 +12,7 @@ - +