From 5662a0847f747331543e2289c55e6ef3578e97d8 Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Fri, 29 Nov 2024 12:10:05 +0100 Subject: [PATCH] Update x scrittura anche singoli valori come siemens OPC-UA --- IOB-WIN-NEXT/DATA/CONF/MAIN.ini | 2 +- ...nd_RAMA_100_47.ini => Tend_RAMA_10_47.ini} | 4 +- ..._RAMA_100_47.json => Tend_RAMA_10_47.json} | 142 ++++--------- ..._alarm.json => Tend_RAMA_10_47_alarm.json} | 0 IOB-WIN-NEXT/IOB-WIN-NEXT.csproj | 6 +- IOB-WIN-NEXT/IobOpc/OpcUa.cs | 12 +- IOB-WIN-NEXT/IobOpc/OpcUaSiemens.cs | 192 ++++++++++++++++++ IOB-WIN-NEXT/IobOpc/OpcUaSiemensRama.cs | 2 +- IOB-WIN-NEXT/UAClient.cs | 131 +++++++++++- 9 files changed, 380 insertions(+), 111 deletions(-) rename IOB-WIN-NEXT/DATA/CONF/{Tend_RAMA_100_47.ini => Tend_RAMA_10_47.ini} (94%) rename IOB-WIN-NEXT/DATA/CONF/{Tend_RAMA_100_47.json => Tend_RAMA_10_47.json} (92%) rename IOB-WIN-NEXT/DATA/CONF/{Tend_RAMA_100_47_alarm.json => Tend_RAMA_10_47_alarm.json} (100%) diff --git a/IOB-WIN-NEXT/DATA/CONF/MAIN.ini b/IOB-WIN-NEXT/DATA/CONF/MAIN.ini index 4491fc9f..9fa23d68 100644 --- a/IOB-WIN-NEXT/DATA/CONF/MAIN.ini +++ b/IOB-WIN-NEXT/DATA/CONF/MAIN.ini @@ -49,7 +49,7 @@ CLI_INST=SteamWareSim ;NB: mettere copy always ai file di conf x fare test... ;STARTLIST=SIMUL_01 -STARTLIST=Tend_RAMA_100_47 +STARTLIST=Tend_RAMA_10_47 MAXCNC=10 \ No newline at end of file diff --git a/IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_100_47.ini b/IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_10_47.ini similarity index 94% rename from IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_100_47.ini rename to IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_10_47.ini index 0c18e6d1..56e576ea 100644 --- a/IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_100_47.ini +++ b/IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_10_47.ini @@ -70,9 +70,9 @@ READ_ERROR_MAX=10 READ_ERROR_SLEEP_TIME=30000 MAX_ERR_CHECK=400 ; conf parametri memoria READ/WRITE -OPC_PARAM_CONF=Tend_RAMA_100_47.json +OPC_PARAM_CONF=Tend_RAMA_10_47.json ;; conf aree allarme -;ALARM_CONF=Tend_RAMA_100_47_alarm.json +;ALARM_CONF=Tend_RAMA_10_47_alarm.json ENABLE_MEM_REWRITE=FALSE [BRANCH] diff --git a/IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_100_47.json b/IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_10_47.json similarity index 92% rename from IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_100_47.json rename to IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_10_47.json index 5494ae87..53480619 100644 --- a/IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_100_47.json +++ b/IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_10_47.json @@ -813,240 +813,178 @@ "OPC_SP_FabSpeed_ChainSpeed": { "name": "OPC_SP_FabSpeed_ChainSpeed", "description": "Chain Speed", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fabric Transport\"#Chain Speed - m_min", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fabric Transport\"#Chain Speed - m_min" }, "OPC_SP_FabSpeed_TOffOverFeed": { "name": "OPC_SP_FabSpeed_TOffOverFeed", "description": "TakeOff Overfeeding", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fabric Transport\"#Take Off Overfeeding - %", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fabric Transport\"#Take Off Overfeeding - %" }, "OPC_SP_Spind_WidthMast": { "name": "OPC_SP_Spind_WidthMast", "description": "Width Master", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Width\"#Width Master - cm", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Width\"#Width Master - cm" }, "OPC_SP_Spind_WidthV1": { "name": "OPC_SP_Spind_WidthV1", "description": "Diff V1", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Width\"#Differentiation V1 - cm", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Width\"#Differentiation V1 - cm" }, "OPC_SP_Spind_WidthV2": { "name": "OPC_SP_Spind_WidthV2", "description": "Diff V2", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Width\"#Differentiation V2 - cm", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Width\"#Differentiation V2 - cm" }, "OPC_SP_Spind_WidthV3": { "name": "OPC_SP_Spind_WidthV3", "description": "Diff V3", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Width\"#Differentiation V3 - cm", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Width\"#Differentiation V3 - cm" }, "OPC_SP_Spind_WidthV4": { "name": "OPC_SP_Spind_WidthV4", "description": "Diff V4", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Width\"#Differentiation V4 - cm", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Width\"#Differentiation V4 - cm" }, "OPC_SP_Spind_WidthV5": { "name": "OPC_SP_Spind_WidthV5", "description": "Diff V5", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Width\"#Differentiation V5 - cm", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Width\"#Differentiation V5 - cm" }, "OPC_SP_Spind_WidthV6": { "name": "OPC_SP_Spind_WidthV6", "description": "Diff V6", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Width\"#Differentiation V6 - cm", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Width\"#Differentiation V6 - cm" }, "OPC_SP_Spind_WidthV7": { "name": "OPC_SP_Spind_WidthV7", "description": "Diff V7", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Width\"#Differentiation V7 - cm", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Width\"#Differentiation V7 - cm" }, "OPC_SP_OvenSpeedCoolCell1": { "name": "OPC_SP_OvenSpeedCoolCell1", "description": "Cooling Fan", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Cooling Fan 1 - %", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Cooling Fan 1 - %" }, "OPC_SP_OvenSpeedExFan1": { "name": "OPC_SP_OvenSpeedExFan1", "description": "Exhaust Fan 1", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Exaust Fan 1 - %", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Exaust Fan 1 - %" }, "OPC_SP_OvenSpeedExFan2": { "name": "OPC_SP_OvenSpeedExFan2", "description": "Exhaust Fan 2", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Exaust Fan 2 - %", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Exaust Fan 2 - %" }, "OPC_SP_OvenSpeedFan101": { "name": "OPC_SP_OvenSpeedFan101", "description": "Fan V1", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V1 - %", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V1 - %" }, "OPC_SP_OvenSpeedFan101A": { "name": "OPC_SP_OvenSpeedFan101A", "description": "Fan V1A", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V1A - %", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V1A - %" }, "OPC_SP_OvenSpeedFan103": { "name": "OPC_SP_OvenSpeedFan103", "description": "Fan V2", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V2 - %", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V2 - %" }, "OPC_SP_OvenSpeedFan103A": { "name": "OPC_SP_OvenSpeedFan103A", "description": "Fan V2A", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V2A - %", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V2A - %" }, "OPC_SP_OvenSpeedFan105": { "name": "OPC_SP_OvenSpeedFan105", "description": "Fan V3", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V3 - %", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V3 - %" }, "OPC_SP_OvenSpeedFan105A": { "name": "OPC_SP_OvenSpeedFan105A", "description": "Fan V3A", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V3A - %", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V3A - %" }, "OPC_SP_OvenSpeedFan107": { "name": "OPC_SP_OvenSpeedFan107", "description": "Fan V4", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V4 - %", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V4 - %" }, "OPC_SP_OvenSpeedFan107A": { "name": "OPC_SP_OvenSpeedFan107A", "description": "Fan V4A", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V4A - %", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V4A - %" }, "OPC_SP_OvenSpeedFan109": { "name": "OPC_SP_OvenSpeedFan109", "description": "Fan V5", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V5 - %", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V5 - %" }, "OPC_SP_OvenSpeedFan109A": { "name": "OPC_SP_OvenSpeedFan109A", "description": "Fan V5A", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V5A - %", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Fans\"#Fan V5A - %" }, "OPC_SP_Temp_Burner1": { "name": "OPC_SP_Temp_Burner1", "description": "Burner 1", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 1 Temperature - °C", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 1 Temperature - °C" }, "OPC_SP_Temp_Burner2": { "name": "OPC_SP_Temp_Burner2", "description": "Burner 2", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 2 Temperature - °C", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 2 Temperature - °C" }, "OPC_SP_Temp_Burner3": { "name": "OPC_SP_Temp_Burner3", "description": "Burner 3", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 3 Temperature - °C", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 3 Temperature - °C" }, "OPC_SP_Temp_Burner4": { "name": "OPC_SP_Temp_Burner4", "description": "Burner 4", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 4 Temperature - °C", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 4 Temperature - °C" }, "OPC_SP_Temp_Burner5": { "name": "OPC_SP_Temp_Burner5", "description": "Burner 5", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 5 Temperature - °C", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 5 Temperature - °C" }, "OPC_SP_Temp_Burner6": { "name": "OPC_SP_Temp_Burner6", "description": "Burner 6", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 6 Temperature - °C", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 6 Temperature - °C" }, "OPC_SP_Temp_Burner7": { "name": "OPC_SP_Temp_Burner7", "description": "Burner 7", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 7 Temperature - °C", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 7 Temperature - °C" }, "OPC_SP_Temp_Burner8": { "name": "OPC_SP_Temp_Burner8", "description": "Burner 8", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 8 Temperature - °C", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 8 Temperature - °C" }, "OPC_SP_Temp_Burner9": { "name": "OPC_SP_Temp_Burner9", "description": "Burner 9", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 9 Temperature - °C", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#Burner 9 Temperature - °C" }, "OPC_SP_Termoset_ThermoTime": { "name": "OPC_SP_Termoset_ThermoTime", "description": "Thermoset Time", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Thermoset\"#Thermoset Time", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Thermoset\"#Thermoset Time" }, "OPC_SP_Termoset_ThermoTemp": { "name": "OPC_SP_Termoset_ThermoTemp", "description": "Thermoset Temperature", - "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Thermoset\"#Thermoset Temperature", - "tipoMem": "FloatABCD", - "factor": 1 + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Thermoset\"#Thermoset Temperature" + }, + "ResetCounter": { + "name": "ResetCounter", + "description": "Reset Contapezzi", + "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Reset partial meter counter\"", + "tipoMem": "Boolean" } }, "WatchDog": { diff --git a/IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_100_47_alarm.json b/IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_10_47_alarm.json similarity index 100% rename from IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_100_47_alarm.json rename to IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_10_47_alarm.json diff --git a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj index 10ad323e..8d5c846f 100644 --- a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj +++ b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj @@ -546,13 +546,13 @@ - + Always - + Always - + Always diff --git a/IOB-WIN-NEXT/IobOpc/OpcUa.cs b/IOB-WIN-NEXT/IobOpc/OpcUa.cs index 6a839703..5f90de7a 100644 --- a/IOB-WIN-NEXT/IobOpc/OpcUa.cs +++ b/IOB-WIN-NEXT/IobOpc/OpcUa.cs @@ -2735,7 +2735,17 @@ namespace IOB_WIN_NEXT.IobOpc // valori "diretti" if (listWriteReq.Count > 0) { - UA_ref.WriteNodes(listWriteReq); + var toWrite = new Dictionary>(); + foreach (var item in listWriteReq) + { + toWrite.Add(item.NodeId, new List() { $"{item.Value.Value}" }); + } + + UA_ref.WriteValues(toWrite); + // modalità calssica alternativa?!? +#if false + UA_ref.WriteNodes(listWriteReq); +#endif } // se valori Udt con modalità alternativa if (nodesUdt2Write.Count > 0) diff --git a/IOB-WIN-NEXT/IobOpc/OpcUaSiemens.cs b/IOB-WIN-NEXT/IobOpc/OpcUaSiemens.cs index c9be612c..8362a869 100644 --- a/IOB-WIN-NEXT/IobOpc/OpcUaSiemens.cs +++ b/IOB-WIN-NEXT/IobOpc/OpcUaSiemens.cs @@ -4,6 +4,7 @@ using Newtonsoft.Json; using Opc.Ua; using System; using System.Collections.Generic; +using System.Linq; using System.Net.NetworkInformation; namespace IOB_WIN_NEXT.IobOpc @@ -397,5 +398,196 @@ namespace IOB_WIN_NEXT.IobOpc #endif #endregion Protected Methods + + + + /// + /// Effettua vera scrittura parametri + /// + /// + protected override void plcWriteParams(ref List updatedPar) + { + // solo se connesso! + if (connectionOk) + { + dataConf currMem = null; + int byteSize = 0; + string memAddrWrite = ""; + string serObj = ""; + if (updatedPar != null) + { + // valori da scrivere in memoria + Dictionary nodes2Write = new Dictionary(); + Dictionary> nodesUdt2Write = new Dictionary>(); + Dictionary currUdsDict = new Dictionary(); + // controllo i parametri... ne gestisco 4... + foreach (var item in updatedPar) + { + if (connectionOk) + { + Opc.Ua.DataValue currNodeVal = new DataValue(); + 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; + + // init obj scrittura + WriteValue commWriteVal = new WriteValue(); + commWriteVal.Value = new DataValue(); + commWriteVal.AttributeId = Attributes.Value; + + // faccio preliminarmente upsertKey... + upsertKey(memAddrWrite, 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}---------------"); + + // verifico se devo processare byte[]... + bool isUds = memAddrWrite.Contains(opcUaParams.kvDelim); + + if (isUds) + { + // ciclo e calcolo valore + int iPos = memAddrWrite.IndexOf(opcUaParams.kvDelim); + string nodeId = memAddrWrite.Substring(0, iPos); + string varName = memAddrWrite.Substring(iPos + 1); + + //cerco se ci sia già un record Uds... + if (nodesUdt2Write.ContainsKey(nodeId)) + { + currUdsDict = nodesUdt2Write[nodeId]; + // controllo valore... + if (currUdsDict.ContainsKey(varName)) + { + currUdsDict[varName] = item.reqValue; + } + else + { + currUdsDict.Add(varName, item.reqValue); + } + nodesUdt2Write[nodeId] = currUdsDict; + } + else + { + currUdsDict = new Dictionary(); + currUdsDict.Add(varName, item.reqValue); + nodesUdt2Write.Add(nodeId, currUdsDict); + } + } + else + { + // init generico x scrittura nell'oggetto OPC-UA direttamente + commWriteVal.NodeId = new NodeId(memAddrWrite); + commWriteVal.Value.Value = item.reqValue; + + // check tipo specifico + 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; + break; + + case plcDataType.Real: + double.TryParse(item.reqValue, out valReal); + commWriteVal.Value.Value = valReal; + break; + + case plcDataType.String: + commWriteVal.Value.Value = item.reqValue; + break; + + default: + break; + } + } + lgInfo($"---------------{Environment.NewLine}OPC-UA data:{Environment.NewLine}NodeId: {commWriteVal.NodeId}{Environment.NewLine}Value: {commWriteVal.Value.Value}{Environment.NewLine}---------------"); + + // se supero soglia errori lettura --> disconnetto e resetto + if (numErroriCheck >= maxErroriCheck) + { + lgInfo($"numErroriCheck: {numErroriCheck} --> richiesta disconnessione adapter con tryDisconnect"); + + numErroriCheck = 0; + tryDisconnect(); + } + else + { + if (!string.IsNullOrEmpty(memAddrWrite) && !string.IsNullOrEmpty($"{commWriteVal.NodeId}")) + { + // cerco se ci fosse già --> aggiorno + if (nodes2Write.ContainsKey($"{commWriteVal.NodeId}")) + { + nodes2Write[$"{commWriteVal.NodeId}"] = commWriteVal; + } + else + { + nodes2Write.Add($"{commWriteVal.NodeId}", commWriteVal); + } + // 2023.09.19 resetto richiesta + item.reqValue = ""; + } + 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 (connectionOk && (nodes2Write.Count + nodesUdt2Write.Count) > 0) + { + List listWriteReq = nodes2Write.Select(x => x.Value).ToList(); + // valori "diretti" + if (listWriteReq.Count > 0) + { + var toWrite = new Dictionary>(); + foreach (var item in listWriteReq) + { + toWrite.Add(item.NodeId, new List() { $"{item.Value.Value}" }); + } + // scrittura modalità siemens + UA_ref.WriteValues(toWrite); + } + // se valori Udt con modalità alternativa + if (nodesUdt2Write.Count > 0) + { + foreach (var item in nodesUdt2Write) + { + UA_ref.WriteNodesUdt(item.Key, item.Value); + } + } + + } + } + } + + } } } \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobOpc/OpcUaSiemensRama.cs b/IOB-WIN-NEXT/IobOpc/OpcUaSiemensRama.cs index 6f8e3bc9..e6ba841e 100644 --- a/IOB-WIN-NEXT/IobOpc/OpcUaSiemensRama.cs +++ b/IOB-WIN-NEXT/IobOpc/OpcUaSiemensRama.cs @@ -172,7 +172,7 @@ namespace IOB_WIN_NEXT.IobOpc objItem resetCnt = new objItem() { uid = "ResetCounter", - reqValue = "true", + reqValue = "1", name = "ResetCounter" }; ListaCalcParams.Add(resetCnt); diff --git a/IOB-WIN-NEXT/UAClient.cs b/IOB-WIN-NEXT/UAClient.cs index 2f9cc00d..7f352842 100644 --- a/IOB-WIN-NEXT/UAClient.cs +++ b/IOB-WIN-NEXT/UAClient.cs @@ -860,6 +860,135 @@ namespace IOB_WIN_NEXT } } + /// + /// Writes values to node Ids + /// + /// Mulitple NodeIds with there values (multiple possible if not a scalar). + /// Throws and forwards any exception with short error description. + public void WriteValues(Dictionary> valuesByNodeId) + { + //Create a collection of values to write + WriteValueCollection valuesToWrite = new WriteValueCollection(); + + foreach (var keyValuePair in valuesByNodeId) + { + NodeId nodeId = keyValuePair.Key; + IEnumerable values = keyValuePair.Value; + + //Get the OPC UA data type and the Rank + Node node = m_session.ReadNode(nodeId); + VariableNode variableNode = (VariableNode)node.DataLock; + NodeId datatypeId = variableNode.DataType; + BuiltInType targetype = TypeInfo.GetBuiltInType(datatypeId); + + //Ensure that target type is not null by reading the node of the data type id + if (targetype == BuiltInType.Null) + { + try + { + //Get the node id of the parent base data type + NodeId tempNodeId = GetParentDataType(datatypeId, m_session); + targetype = TypeInfo.GetBuiltInType(tempNodeId); + if (targetype == BuiltInType.Null)//Ensure that the entered node id is not of type struct + { + throw new Exception("The entered node id may be of type struct. Please use the methods for read/write structs."); + } + } + catch + { + throw new Exception("The node id data type is not castable. Please check the data type."); + } + + } + int valueRank = variableNode.ValueRank; + DataValue dataValue = null; + + //Check if there is a value entered + if (!values.Any() || nodeId == null) //no value in the textbox + { + throw new Exception("There is no NodeId or value entered."); + } + + //Ensure that boolean entries have lower case initial and float, double and long double have the rigth format + List tempValues = new List(); + if (targetype == BuiltInType.Boolean) + { + foreach (string tempValue in values) + { + tempValues.Add(tempValue.ToLower()); + } + values = tempValues; + } + if (targetype == BuiltInType.Float || targetype == BuiltInType.Double) + { + foreach (string tempValue in values) + { + tempValues.Add(tempValue.Replace(',', '.')); + } + values = tempValues; + } + + //Check if the inputed value has the type matrix or array + if (valueRank >= ValueRanks.OneDimension) + { + //Cast values in the target type + Array castValues = TypeInfo.CastArray(values.ToArray(), BuiltInType.Null, targetype, (object source, BuiltInType srcType, BuiltInType dstType) => TypeInfo.Cast(source, dstType)); + + if (valueRank == ValueRanks.OneDimension) //Check if inputed value is array + { + dataValue = new DataValue(new Variant(castValues, new TypeInfo(targetype, valueRank))); + } + else //Inputed value has more then one dimension + { + //Get matrix dimensions + int[] dimensions = new int[valueRank]; + for (int i = 0; i < valueRank; i++) + { + dimensions[i] = (int)variableNode.ArrayDimensions[i]; + } + Matrix matrix = new Matrix(castValues, targetype, dimensions); + dataValue = new DataValue(new Variant(matrix)); + } + } + else + { + try //OPC UA data type with type scalar + { + dataValue = new DataValue(new Variant(TypeInfo.Cast(values.First(), targetype))); + } + catch //no OPC UA data type + { + throw new FormatException($"The value inputed [{values.First()}] is not convertable to type {targetype}."); + } + } + //Create a WriteValue using the NodeId, dataValue and attributeType + WriteValue valueToWrite = new WriteValue() + { + Value = dataValue, + NodeId = nodeId, + AttributeId = Attributes.Value + }; + + //Add the dataValues to the collection + valuesToWrite.Add(valueToWrite); + } + + StatusCodeCollection result; + //Write the collection to the server + m_session.Write(null, valuesToWrite, out result, out _); + foreach (StatusCode code in result) + { + + lgDebug($" {code}"); +#if false + if (code != 0) + { + throw new Exception(code.ToString()); + } +#endif + } + } + /// /// Write a list of nodes to the Server /// @@ -898,7 +1027,7 @@ namespace IOB_WIN_NEXT foreach (StatusCode writeResult in results) { - lgDebug(" {writeResult}"); + lgDebug($" {writeResult}"); } } catch (Exception ex)