diff --git a/IOB-UT-NEXT/Enums.cs b/IOB-UT-NEXT/Enums.cs index 99e1da4b..52a04d7f 100644 --- a/IOB-UT-NEXT/Enums.cs +++ b/IOB-UT-NEXT/Enums.cs @@ -294,6 +294,16 @@ namespace IOB_UT_NEXT /// OpcUa, + /// + /// Adapter OPC-UA CMS + /// + OpcUaCMS, + + /// + /// Adapter OPC-UA SCM + /// + OpcUaSCM, + /// /// Adapter OPC-UA per Ewon /// diff --git a/IOB-UT-NEXT/ToMapo.cs b/IOB-UT-NEXT/ToMapo.cs index 267045c7..369cdd1c 100644 --- a/IOB-UT-NEXT/ToMapo.cs +++ b/IOB-UT-NEXT/ToMapo.cs @@ -458,6 +458,16 @@ namespace IOB_UT_NEXT /// public Dictionary mMapWrite { get; set; } = new Dictionary(); + /// + /// Elenco dei SOLI item sottoscritti (se vuoto TUTTI) + /// + public List subscribedItems { get; set; } = new List(); + + /// + /// Elenco dei NodeId da ignorare intesi come interi rami (se vuoto NON filtro) + /// + public List filterItemsNodeId { get; set; } = new List(); + #endregion Public Properties } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/AdapterForm.cs b/IOB-WIN-NEXT/AdapterForm.cs index 4af037c8..ece6dab5 100644 --- a/IOB-WIN-NEXT/AdapterForm.cs +++ b/IOB-WIN-NEXT/AdapterForm.cs @@ -1211,6 +1211,12 @@ namespace IOB_WIN_NEXT start.Enabled = true; break; + case tipoAdapter.OpcUaCMS: + case tipoAdapter.OpcUaSCM: + iobObj = new IobOpcUaCMS(this, IOBConf); + start.Enabled = true; + break; + case tipoAdapter.OpcUaEwon: iobObj = new IobOpcUaEwon(this, IOBConf); start.Enabled = true; diff --git a/IOB-WIN-NEXT/DATA/CONF/FP_TR2.ini b/IOB-WIN-NEXT/DATA/CONF/FP_TR2.ini new file mode 100644 index 00000000..67f19087 --- /dev/null +++ b/IOB-WIN-NEXT/DATA/CONF/FP_TR2.ini @@ -0,0 +1,74 @@ +;Configurazione IOB-WIN +[IOB] +;Centro di lavoro OpcUa +CNCTYPE=OpcUaCMS +;CNCTYPE=OpcUa +PING_MS_TIMEOUT=500 + +[MACHINE] +VENDOR=CMS +MODEL=Eidos + +[CNC] +IP=192.168.2.12 +PORT=62541 +;IP=192.168.250.53 +;PORT=4840 +GETPRGNAME=true + +[SERVER] +MPIP=http://192.168.2.252 +MPURL=/MP/IO +CMDBASE=/IOB/input/ +CMDFLOG=/IOB/flog/ +CMDALIVE=/IOB +CMDENABLED=/IOB/enabled/ +CMDADV1=?valore= +CMDREBO=/sendReboot.aspx?idxMacchina= +CMD_ODL_STARTED=/IOB/getCurrOdlStart/ +CMD_FORCLE_SPLIT_ODL=/IOB/forceSplitOdlFull/ +CMD_IDLE_TIME=/IOB/getIdlePeriod/ + +[MEMORY] +ADDR_READ=DB9999.DBB0 +ADDR_WRITE=DB9999.DBB0 +SIZE_READ=0 +SIZE_WRITE=0 +;BIT0=CONN +;BIT1=DB60.DBB1 +;BIT2=PZCOUNT.STD.DB700.DBW22 +;BIT3=DB60.DBB3 +;BIT4=DB60.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] +AUTO_CHANGE_ODL=true +CHANGE_ODL_MODE=PZCOUNT_RESET +PZCOUNT_MODE=OPC +DISABLE_PZCOUNT=FALSE +ENABLE_SEND_PZC_BLOCK=TRUE +MIN_SEND_PZC_BLOCK=0 +MAX_SEND_PZC_BLOCK=100 +ENABLE_DYN_DATA=FALSE +FORCE_DYN_DATA=TRUE +ENABLE_DATA_FILTER=TRUE +ENABLE_CLI_RESTART=TRUE +; conf parametri memoria READ/WRITE +OPC_PARAM_CONF=FP_TR2.json + +[BRANCH] +NAME=master diff --git a/IOB-WIN-NEXT/DATA/CONF/FP_TR2.json b/IOB-WIN-NEXT/DATA/CONF/FP_TR2.json new file mode 100644 index 00000000..c7d34b51 --- /dev/null +++ b/IOB-WIN-NEXT/DATA/CONF/FP_TR2.json @@ -0,0 +1,83 @@ +{ + "BrowseFullVal": "ns=2;s=Machine", + "BrowseNSIndex": 2, + "BrowseValue": 0, + "keyPartCount": "ProductionProcesses/01/Programs/01/RepsDone", + "keyPartReq": "ProductionProcesses/01/Programs/01/RepsTarget", + "keyPartId": "", + "keyProgName": "ProductionProcesses/01/Programs/01/Name", + "keyRunMode": "Status", + "pingAsPowerOn": true, + "condWork": [ + { + "keyName": "Status", + "targetValue": "EXE" + } + ], + "condPowerOn": { + "checkMode": "AND", + "checkList": [ + { + "keyName": "Power", + "targetValue": "true" + } + ] + }, + "condReady": { + "checkMode": "AND", + "checkList": [ + { + "keyName": "Status", + "targetValue": "READY" + } + ] + }, + "condManual": { + "checkMode": "AND", + "checkList": [ + { + "keyName": "Status", + "targetValue": "MDI" + } + ] + }, + "condEStop": { + "checkMode": "AND", + "checkList": [ + { + "keyName": "Emergency", + "targetValue": "false" + } + ] + }, + "condError": { + "checkMode": "AND", + "checkList": [ + { + "keyName": "Alarm", + "targetValue": "true" + } + ] + }, + "condCountEnabled": { + "checkMode": "AND", + "checkList": [] + }, + "fluxLogVeto": [ + "L2p1CommonVariable" + ], + "itemTranslation": { + "avail": "Machine Available", + "rstat": "Execution Mode", + "mode": "Controller Mode", + "ncprog": "Program Name", + "IO_150": "Qta Prodotta (metri)", + "lpremain": "Qta Richiesta", + "fdovrd": "PATH FEED OVERRIDE", + "rovrd": "PATH RAPID OVERRIDE" + }, + "filterItemsNodeId": [ + "ns=2;s=Machine/Axes", + "ns=2;s=Machine/OperatingGroups" + ] +} \ No newline at end of file diff --git a/IOB-WIN-NEXT/DATA/CONF/MAIN.ini b/IOB-WIN-NEXT/DATA/CONF/MAIN.ini index 5370415f..735286f9 100644 --- a/IOB-WIN-NEXT/DATA/CONF/MAIN.ini +++ b/IOB-WIN-NEXT/DATA/CONF/MAIN.ini @@ -71,6 +71,5 @@ CLI_INST=SteamWareSim ;STARTLIST=OPC_UA ;STARTLIST=SIM_PIZ03 ;STARTLIST=FOV062 -STARTLIST=3013 - +STARTLIST=FP_TR2 MAXCNC=10 \ No newline at end of file diff --git a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj index 879b7028..f42062ec 100644 --- a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj +++ b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj @@ -182,6 +182,7 @@ + @@ -340,6 +341,12 @@ Always + + Always + + + Always + Always diff --git a/IOB-WIN-NEXT/IobOpcUa.cs b/IOB-WIN-NEXT/IobOpcUa.cs index 526cee7c..b9665ce3 100644 --- a/IOB-WIN-NEXT/IobOpcUa.cs +++ b/IOB-WIN-NEXT/IobOpcUa.cs @@ -86,7 +86,7 @@ namespace IOB_WIN_NEXT { bool.TryParse(getOptPar("ENABLE_DATA_FILTER"), out enableDataFilter); } - // gestione restart MTC client... + // gestione restart OpcUa client... if (!string.IsNullOrEmpty(getOptPar("ENABLE_CLI_RESTART"))) { bool.TryParse(getOptPar("ENABLE_CLI_RESTART"), out enableCliRestart); @@ -316,15 +316,50 @@ namespace IOB_WIN_NEXT if (connected) { // faccio un primo browse dei dati... + Dictionary nodeIdNameList = new Dictionary(); if (!string.IsNullOrEmpty(opcUaParams.BrowseFullVal)) { - selectedItemList = UA_ref.Browse(opcUaParams.BrowseFullVal); + UA_ref.Browse(opcUaParams.BrowseFullVal, opcUaParams.filterItemsNodeId, ref nodeIdNameList); } else { - selectedItemList = UA_ref.Browse(opcUaParams.BrowseNSIndex, opcUaParams.BrowseValue); + UA_ref.Browse(opcUaParams.BrowseNSIndex, opcUaParams.BrowseValue, opcUaParams.filterItemsNodeId, ref nodeIdNameList); } - // sottoscrivo a rilevazione cambio dati + // loggo elenco degli item sottocrivibili... + lgInfo("---------- AVAILABLE FOR SUBSCRIBE ----------"); + foreach (var item in nodeIdNameList) + { + lgInfo(item.Key); + } + lgInfo("---------- END LIST ----------"); + + // se ho un insieme non vuoto degli item sottoscritti carico solo quelli + if (opcUaParams.subscribedItems != null && opcUaParams.subscribedItems.Count > 0) + { + // cerco e aggiungo SOLO quelle indicati + foreach (var currItem in opcUaParams.subscribedItems) + { + if (nodeIdNameList.ContainsKey(currItem)) + { + selectedItemList.Add(currItem, nodeIdNameList[currItem]); + } + } + } + // altrimenti tutti! + else + { + selectedItemList = nodeIdNameList; + } + + // loggo elenco degli item sottocrivibili... + lgInfo("---------- SUBSCRIBED NODES ----------"); + foreach (var item in nodeIdNameList) + { + lgInfo(item.Key); + } + lgInfo("---------- END LIST ----------"); + + // sottoscrivo a rilevazione cambio dati solo l'incrocio degli insiemi List subscribedItems = UA_ref.SubscribeToDataChanges(selectedItemList); // aggiungo come DataItems int dSamplePeriod = 0; @@ -735,37 +770,39 @@ namespace IOB_WIN_NEXT { string jsonFullPath = $"{Application.StartupPath}/DATA/CONF/{fileName}"; lgInfo($"Apertura file {jsonFullPath}"); - StreamReader reader = new StreamReader(jsonFullPath); - string jsonData = reader.ReadToEnd().Replace("\n", "").Replace("\r", ""); - if (!string.IsNullOrEmpty(jsonData)) + using (StreamReader reader = new StreamReader(jsonFullPath)) { - lgInfo($"File json composto da {jsonData.Length} caratteri"); - try + string jsonData = reader.ReadToEnd().Replace("\n", "").Replace("\r", ""); + if (!string.IsNullOrEmpty(jsonData)) { - opcUaParams = JsonConvert.DeserializeObject(jsonData); - lgInfo($"Decodifica aree OpcUaParamConf: trovati {opcUaParams.paramsEndThresh.Count} valori paramsEndThresh"); - // sistemo se ci sono dati memMap... - memMap = new plcMemMap(); - if (opcUaParams.mMapWrite != null) + lgInfo($"File json composto da {jsonData.Length} caratteri"); + try { - memMap.mMapWrite = opcUaParams.mMapWrite; + opcUaParams = JsonConvert.DeserializeObject(jsonData); + lgInfo($"Decodifica aree OpcUaParamConf: trovati {opcUaParams.paramsEndThresh.Count} valori paramsEndThresh"); + // sistemo se ci sono dati memMap... + memMap = new plcMemMap(); + if (opcUaParams.mMapWrite != null) + { + memMap.mMapWrite = opcUaParams.mMapWrite; + } + if (opcUaParams.mMapRead != null) + { + memMap.mMapRead = opcUaParams.mMapRead; + } + setupMemMap(); } - if (opcUaParams.mMapRead != null) + catch (Exception exc) { - memMap.mMapRead = opcUaParams.mMapRead; + lgError($"Eccezione in decodifica conf json OPC-UA:{Environment.NewLine}{exc}"); } - setupMemMap(); } - catch (Exception exc) + else { - lgError($"Eccezione in decodifica conf json OPC-UA:{Environment.NewLine}{exc}"); + lgError("Errore in loadOpcUaConf: file json vuoto!"); } } - else - { - lgError("Errore in loadOpcUaConf: file json vuoto!"); - } - reader.Dispose(); + //reader.Dispose(); } #endregion Protected Methods diff --git a/IOB-WIN-NEXT/IobOpcUaCMS.cs b/IOB-WIN-NEXT/IobOpcUaCMS.cs new file mode 100644 index 00000000..c30e24bb --- /dev/null +++ b/IOB-WIN-NEXT/IobOpcUaCMS.cs @@ -0,0 +1,372 @@ +using MapoSDK; +using Newtonsoft.Json; +using Opc.Ua; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.NetworkInformation; +using System.Text; +using System.Threading.Tasks; + +namespace IOB_WIN_NEXT +{ + public class IobOpcUaCMS : IobOpcUa + { + #region Protected Fields + + /// + /// Modalità cambio ODL + /// + protected string CHANGE_ODL_MODE = ""; + + protected bool testDone = false; + + #endregion Protected Fields + + #region Public Constructors + + /// + /// Estende l'init della classe base, impiegando il pacchetto Nuget OPC-UA foundation con la gestione specifica per CMS/SCM (es. Eidos termoformatrice) + /// https://github.com/OPCFoundation/UA-.NETStandard + /// + /// + /// + public IobOpcUaCMS(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) + { + // inizializzo classe base... + if (!string.IsNullOrEmpty(getOptPar("CHANGE_ODL_MODE"))) + { + CHANGE_ODL_MODE = getOptPar("CHANGE_ODL_MODE"); + } + + // impostazioni specifiche OpcUA SCM + } + + #endregion Public Constructors + + #region Protected Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + protected override void decodeToBaseBitmap() + { + DateTime adesso = DateTime.Now; + // init a zero... + B_input = 0; + + /* ----------------------------------------------------- + * STATE MACHINE 60 STD / SIMULA + *------------------------------------------------------ + * bitmap MAPO + * B0: POWER_ON + * B1: RUN + * B2: pzCount + * B3: allarme + * B4: manuale + * B5: SlowTC (NON gestito qui) + * B6: warm-up / cool-down (NON GESTITO ?!?) + * B7: emergenza + ---------------------------------------------------- */ + + // se valido il check ping lo eseguo... altrimenti lo do x buono + bool checkPing = !opcUaParams.pingAsPowerOn; + string currRun = ""; + if (!checkPing) + { + checkPing = (testPingMachine == IPStatus.Success); + } + // bit 0 (poweron) imposto a 1 SE pingo + PowerOn=="ON"... + bool powerOnOk = checkPing && hasPowerOn; + // procedo SOLO SE mi da ping OK... + if (checkPing) + { + B_input = powerOnOk ? 1 : 0; + + // variabili RUN... + currRun = getDataItemValue(opcUaParams.keyRunMode); + + // salvo running come = working... + isRunning = isWorking; + + // se ho emergenza premuta --> emergenza! + if (hasEStopArmed) + { + B_input += (1 << 7); + } + //// se ho emergenza premuta --> emergenza! + //if (isWarmUpCoolDown) + //{ + // B_input += (1 << 6); + //} + // se ho almeno 1 allarme E NON SONO IN AUTO --> ALARM! + if (hasError) + { + B_input += (1 << 3); + } + if (isWorking) + { + // RUN = LAVORA! + B_input += (1 << 1); + } + else if (powerOnOk && (!isReady || isManual)) + { + // se NON ready --> manual + B_input += (1 << 4); + } + } + + // controllo se sono poweroff e se non ho dati buoni da > 2 minuti --> disconnetto + if (adesso.Subtract(lastCurrent).TotalMinutes > 5) + { + tryDisconnect(); + } + + // solo se non ho veto check + int vFactor = 2; + if (vetoCheckStatus < adesso) + { + lgInfo($"Stato variabili checkPing: {testPingMachine}"); + // imposto veto per vetoSeconds... + vetoCheckStatus = adesso.AddSeconds(vetoSeconds * vFactor); + } + + // log opzionale! + if (verboseLog) + { + lgInfo($"Trasformazione checkPing: {checkPing} | hasPowerOn: {hasPowerOn} | B_input: {B_input} | currRun = {currRun}"); + } + } + + /// + /// Effettua vera scrittura parametri + /// + /// + protected override void plcWriteParams(ref List updatedPar) + { +#if false + if (!testDone) + { + try + { + if (UA_ref != null) + { + UA_ref.WriteTestNodes(); + testDone = true; + } + } + catch (Exception exc) + { + lgError($"Eccezione in WriteTestNodes{Environment.NewLine}{exc}"); + } + } +#endif + + dataConf currMem = null; + int byteSize = 0; + string memAddrWrite = ""; + string serObj = ""; + if (updatedPar != null) + { + List nodes2Write = new List(); + // controllo i parametri... ne gestisco 4... + foreach (var item in updatedPar) + { + try + { + memAddrWrite = ""; + int valInt = 0; + double valReal = 0; + // cerco in area memMapWrite... + if (memMap.mMapWrite.ContainsKey(item.uid)) + { + // recupero! + currMem = memMap.mMapWrite[item.uid]; + byteSize = currMem.size; + memAddrWrite = currMem.memAddr; + + WriteValue commWriteVal = new WriteValue(); + commWriteVal.NodeId = new NodeId(currMem.memAddr); + commWriteVal.AttributeId = Attributes.Value; + commWriteVal.Value = new DataValue(); + commWriteVal.Value.Value = item.reqValue; + + // faccio preliminarmente upsertKey... + upsertKey(currMem.name, currMem.value); + serObj = JsonConvert.SerializeObject(item); + lgInfo($"Inizio processing plcWriteParams per {currMem.name} | valore richiesto {currMem.value}"); + lgInfo($"---------------{Environment.NewLine}UPDATED PARAM:{Environment.NewLine}{serObj}{Environment.NewLine}---------------"); + serObj = JsonConvert.SerializeObject(currMem); + lgInfo($"---------------{Environment.NewLine}MEMORY CONTENT:{Environment.NewLine}{serObj}{Environment.NewLine}---------------"); + + switch (currMem.tipoMem) + { + case plcDataType.Boolean: + break; + + case plcDataType.Int: + case plcDataType.DInt: + case plcDataType.Word: + case plcDataType.DWord: + int.TryParse(item.reqValue, out valInt); + commWriteVal.Value.Value = valInt; + memAddrWrite = currMem.memAddr; + break; + + case plcDataType.Real: + double.TryParse(item.reqValue, out valReal); + commWriteVal.Value.Value = valReal; + break; + + case plcDataType.String: + + // verifico caso speciale: se è art/comm scrivo AFFIANCATE... + if (item.uid == "setArt" | item.uid == "setComm") + { + // accodo commessa + articolo con padding secondo lunghezza... + string codArt = ""; + if (currProdData.ContainsKey("setArt")) + { + codArt = string.IsNullOrEmpty(currProdData["setArt"]) ? "" : currProdData["setArt"]; + } + string codComm = ""; + if (currProdData.ContainsKey("setComm")) + { + codComm = string.IsNullOrEmpty(currProdData["setComm"]) ? "" : currProdData["setComm"]; + } + // padding... + codArt = codArt.PadRight(20, ' '); + codComm = codComm.PadRight(20, ' '); + commWriteVal.Value.Value = $"{codComm}{codArt}"; + } + break; + + default: + break; + } + lgInfo($"---------------{Environment.NewLine}OPC-UA data:{Environment.NewLine}NodeId: {commWriteVal.NodeId}{Environment.NewLine}Value: {commWriteVal.Value.Value}{Environment.NewLine}---------------"); + + if (!string.IsNullOrEmpty(memAddrWrite)) + { + nodes2Write.Add(commWriteVal); + } + else + { + lgInfo($"Errore: memAddrWrite vuoto!"); + } + } + else + { + lgInfo($"Errore uid non trovato in area write memory: {item.uid}, ci sono {memMap.mMapWrite.Count} in area write"); + } + } + catch (Exception exc) + { + lgError($"Eccezione in fase di plcWriteParams per item {item.uid} con valore {item.value}{Environment.NewLine}{exc}"); + } + } + + if (nodes2Write.Count > 0) + { + UA_ref.WriteNodes(nodes2Write); + } + } + } + + #endregion Protected Methods + + #region Public Methods + + /// + /// Processo i task richiesti e li elimino dalla coda 1:1 + /// + /// + public override Dictionary executeTasks(Dictionary task2exe) + { + // uso metodo base x ora + return base.executeTasks(task2exe); + } + + /// + /// Effettua vero processing contapezzi + /// + public override void processContapezzi() + { + if (utils.CRB("enableContapezzi")) + { + // check condizione validazione + if (checkMultiCondition(opcUaParams.condCountEnabled.checkList, opcUaParams.condCountEnabled.checkMode) || opcUaParams.condCountEnabled.checkList.Count == 0) + { + // cerco parametro contapezzi... + string currPzCount = getDataItemValue(opcUaParams.keyPartCount); + + // se ho un contapezzi... processo... + if (!string.IsNullOrEmpty(currPzCount)) + { + int newVal = -1; + bool fatto = Int32.TryParse(currPzCount, out newVal); + + if (fatto) + { + // gestione decremento contapezzi: viene "messo via" solo SE c'è un effettivo decremento contapezzi... + if (newVal < contapezziPLC) + { + pzCountResetted = true; + // incremento contatore richiesta + countKeyRichiesta = countKeyRichiesta + 1; + // log + lgInfo("Contapezzi resettato (PLC) --> pzCountResetted = true"); + } + + // salvo nuovo valore contapezziPLC + contapezziPLC = newVal > -1 ? newVal : contapezziPLC; + } + else + { + lgError($"Errore in decodifica valore contapezzi, valore rilevato: {currPzCount}"); + } + } + else + { + lgError("Errore in decodifica valore contapezzi, valore vuoto!"); + } + } + + if (CHANGE_ODL_MODE == "PZCOUNT_RESET") + { + // controllo comunque, se è ZERO il contapezzi, e sul server è maggiore il valore x ODL e NON abilitato il trigger reset --> abilito trigger... + if (!pzCountResetted && contapezziPLC == 0 && contapezziIOB > 0) + { + pzCountResetted = true; + // incremento contatore richiesta + countKeyRichiesta = countKeyRichiesta + 1; + // log + lgInfo("Contapezzi resettato (PLC==0 e IOB>PLC) --> pzCountResetted = true"); + } + } + } + } + + /// + /// Effettua reset del contapezzi, NON POSSIBILE in questa versione + /// + /// + public override bool resetcontapezziPLC() + { + bool answ = false; + return answ; + } + + /// + /// Effettua IMPOSTAZIONE FORZATA del contapezzi, NON POSSIBILE in questa versione + /// + /// + public override bool setcontapezziPLC(int newPzCount) + { + bool answ = false; + return answ; + } + + #endregion Public Methods + } +} \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobOpcUaEwon.cs b/IOB-WIN-NEXT/IobOpcUaEwon.cs index a280dd4e..b6c452c2 100644 --- a/IOB-WIN-NEXT/IobOpcUaEwon.cs +++ b/IOB-WIN-NEXT/IobOpcUaEwon.cs @@ -33,7 +33,7 @@ namespace IOB_WIN_NEXT /// public IobOpcUaEwon(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) { - // inizializzo calsse base... + // inizializzo classe base... if (!string.IsNullOrEmpty(getOptPar("CHANGE_ODL_MODE"))) { CHANGE_ODL_MODE = getOptPar("CHANGE_ODL_MODE"); diff --git a/IOB-WIN-NEXT/IobSiemensTorri.cs b/IOB-WIN-NEXT/IobSiemensTorri.cs index c0b8cc75..153b4057 100644 --- a/IOB-WIN-NEXT/IobSiemensTorri.cs +++ b/IOB-WIN-NEXT/IobSiemensTorri.cs @@ -17,6 +17,12 @@ namespace IOB_WIN_NEXT * mod: 2019.04.06: aggiunta indicazione (IOB--> PLC) di stato setup su DB701.B0.4 * -------------------------------------------------------------------------------- */ + #region Protected Fields + + protected Dictionary lastReadAlarms = new Dictionary(); + + #endregion Protected Fields + #region Public Constructors /// @@ -32,6 +38,50 @@ namespace IOB_WIN_NEXT #endregion Public Constructors + #region Private Methods + + private int checkAlarmBank(string memAddrAlarms) + { + int trovato = 0; + uint valDW = 0; + var MemBlockPZ = new byte[4]; + bool fatto = S7ReadBB(ref MemBlockPZ, memAddrAlarms, 4); + //if (fatto) + //{ + valDW = S7.Net.Types.DWord.FromByteArray(MemBlockPZ.ToArray()); + // se <> 0 --> log e accodo a dynData + if (valDW != 0) + { + string key = $"MTH_ALARM_{memAddrAlarms}_{valDW}"; + var biteVal = baseUtils.binaryForm(valDW); + lgInfo($"Stato allarmi rilevati: {key} | {valDW} | {biteVal}"); + // accodo a dictionary + string almMsg = $"{DateTime.Now} | val {valDW} | {biteVal}"; + // se non ci fosse aggiungo + if (!lastReadAlarms.ContainsKey(key)) + { + lastReadAlarms.Add(key, almMsg); + } + trovato++; + } + //} + return trovato; + } + + private void checkAlarms() + { + // leggo i banchi allarmi : cablato D700.DBDW2 --> D700 DBDW14, sono 4 banchi a 32 bit da verificare + + int trovati = 0; + // ciclo nei 4 banchi... + trovati += checkAlarmBank("DB700.DBDW2"); + trovati += checkAlarmBank("DB700.DBDW6"); + trovati += checkAlarmBank("DB700.DBDW10"); + trovati += checkAlarmBank("DB700.DBDW14"); + } + + #endregion Private Methods + #region Protected Methods /// @@ -208,48 +258,6 @@ namespace IOB_WIN_NEXT } } - private void checkAlarms() - { - // leggo i banchi allarmi : cablato D700.DBDW2 --> D700 DBDW14, sono 4 banchi a 32 bit da verificare - - int trovati = 0; - // ciclo nei 4 banchi... - trovati += checkAlarmBank("DB700.DBDW2"); - trovati += checkAlarmBank("DB700.DBDW6"); - trovati += checkAlarmBank("DB700.DBDW10"); - trovati += checkAlarmBank("DB700.DBDW14"); - } - - private int checkAlarmBank(string memAddrAlarms) - { - int trovato = 0; - uint valDW = 0; - var MemBlockPZ = new byte[4]; - bool fatto = S7ReadBB(ref MemBlockPZ, memAddrAlarms, 4); - //if (fatto) - //{ - valDW = S7.Net.Types.DWord.FromByteArray(MemBlockPZ.ToArray()); - // se <> 0 --> log e accodo a dynData - if (valDW != 0) - { - string key = $"MTH_ALARM_{memAddrAlarms}_{valDW}"; - var biteVal = baseUtils.binaryForm(valDW); - lgInfo($"Stato allarmi rilevati: {key} | {valDW} | {biteVal}"); - // accodo a dictionary - string almMsg = $"{DateTime.Now} | val {valDW} | {biteVal}"; - // se non ci fosse aggiungo - if (!lastReadAlarms.ContainsKey(key)) - { - lastReadAlarms.Add(key, almMsg); - } - trovato++; - } - //} - return trovato; - } - - protected Dictionary lastReadAlarms = new Dictionary(); - #endregion Protected Methods #region Public Methods @@ -291,6 +299,7 @@ namespace IOB_WIN_NEXT break; case taskType.fixStopSetup: + MemBlock[0] = 0; taskVal = "VALUE DB701.0.4 --> 0"; lgInfo($"Chiamata fixStopSetup: taskOk: {taskOk} | taskVal: {taskVal}"); break; @@ -302,6 +311,7 @@ namespace IOB_WIN_NEXT break; case taskType.stopSetup: + MemBlock[0] = 0; taskVal = "VALUE DB701.0.4 --> 0"; lgInfo($"Chiamata stopSetup: taskOk: {taskOk} | taskVal: {taskVal}"); break; diff --git a/IOB-WIN-NEXT/UAClient.cs b/IOB-WIN-NEXT/UAClient.cs index 5ea7e49f..dc99903e 100644 --- a/IOB-WIN-NEXT/UAClient.cs +++ b/IOB-WIN-NEXT/UAClient.cs @@ -180,13 +180,13 @@ namespace IOB_WIN_NEXT /// /// Browse Server nodes /// - public Dictionary Browse(ushort startNodeNS, uint startNodeVal) + public bool Browse(ushort startNodeNS, uint startNodeVal, List vetoBrowse, ref Dictionary nodeIdNameList) { - Dictionary nodeIdNameList = new Dictionary(); + bool fatto = false; if (m_session == null || m_session.Connected == false) { m_output.WriteLine("Session not connected!"); - return nodeIdNameList; + return false; } try @@ -213,8 +213,17 @@ namespace IOB_WIN_NEXT foreach (ReferenceDescription result in browseResults) { m_output.WriteLine($" NodeId = {result.NodeId}, DisplayName = {result.DisplayName.Text}, NodeClass = {result.NodeClass}, Others: {result.BinaryEncodingId} | {result.BrowseName}"); - nodeIdNameList.Add(result.NodeId.ToString(), result.DisplayName.Text); + // se NON fa parte dell'elenco dei VETO di filterItems... + if (!vetoBrowse.Contains($"{result.NodeId}")) + { + // se mancasse aggiungo... + if (!nodeIdNameList.ContainsKey($"{result.NodeId}")) + { + nodeIdNameList.Add(result.NodeId.ToString(), result.DisplayName.Text); + } + } } + fatto = true; } catch (Exception ex) { @@ -222,19 +231,19 @@ namespace IOB_WIN_NEXT m_output.WriteLine($"Browse Error : {ex.Message}."); } - return nodeIdNameList; + return fatto; } /// /// Browse Server nodes /// - public Dictionary Browse(string browsePath) + public bool Browse(string browsePath, List vetoBrowse, ref Dictionary nodeIdNameList) { - Dictionary nodeIdNameList = new Dictionary(); + bool fatto = false; if (m_session == null || m_session.Connected == false) { m_output.WriteLine("Session not connected!"); - return nodeIdNameList; + return false; } try @@ -260,9 +269,27 @@ namespace IOB_WIN_NEXT foreach (ReferenceDescription result in browseResults) { + // se veto --> loggo veto + if (vetoBrowse.Contains($"{result.NodeId}")) + { + m_output.WriteLine($"| FILTERED --> NodeId = {result.NodeId}, DisplayName = {result.DisplayName.Text}, NodeClass = {result.NodeClass}, Others: {result.BinaryEncodingId} | {result.BrowseName}"); + } + // se NON fa parte dell'elenco dei VETO di filterItems... + else { m_output.WriteLine($" NodeId = {result.NodeId}, DisplayName = {result.DisplayName.Text}, NodeClass = {result.NodeClass}, Others: {result.BinaryEncodingId} | {result.BrowseName}"); - nodeIdNameList.Add(result.NodeId.ToString(), result.DisplayName.Text); + // se mancasse aggiungo... + if (!nodeIdNameList.ContainsKey($"{result.NodeId}")) + { + nodeIdNameList.Add($"{result.NodeId}", result.DisplayName.Text); + // se è un nodo object --> faccio sub browse! + if (result.NodeClass != NodeClass.Variable) + { + this.Browse($"{result.NodeId}",vetoBrowse, ref nodeIdNameList); + } + } + } } + fatto = true; } catch (Exception ex) { @@ -270,7 +297,7 @@ namespace IOB_WIN_NEXT m_output.WriteLine($"Browse Error : {ex.Message}."); } - return nodeIdNameList; + return fatto; } ///