diff --git a/IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_100_47.json b/IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_100_47.json
index d8d36f8e..663b2be0 100644
--- a/IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_100_47.json
+++ b/IOB-WIN-NEXT/DATA/CONF/Tend_RAMA_100_47.json
@@ -974,77 +974,77 @@
"OPC_SP_Temp_Burner1": {
"name": "OPC_SP_Temp_Burner1",
"description": "Burner 1",
- "memAddr": "\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.0",
+ "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.0",
"tipoMem": "FloatABCD",
"factor": 1
},
"OPC_SP_Temp_Burner2": {
"name": "OPC_SP_Temp_Burner2",
"description": "Burner 2",
- "memAddr": "\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.4",
+ "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.4",
"tipoMem": "FloatABCD",
"factor": 1
},
"OPC_SP_Temp_Burner3": {
"name": "OPC_SP_Temp_Burner3",
"description": "Burner 3",
- "memAddr": "\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.8",
+ "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.8",
"tipoMem": "FloatABCD",
"factor": 1
},
"OPC_SP_Temp_Burner4": {
"name": "OPC_SP_Temp_Burner4",
"description": "Burner 4",
- "memAddr": "\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.12",
+ "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.12",
"tipoMem": "FloatABCD",
"factor": 1
},
"OPC_SP_Temp_Burner5": {
"name": "OPC_SP_Temp_Burner5",
"description": "Burner 5",
- "memAddr": "\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.16",
+ "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.16",
"tipoMem": "FloatABCD",
"factor": 1
},
"OPC_SP_Temp_Burner6": {
"name": "OPC_SP_Temp_Burner6",
"description": "Burner 6",
- "memAddr": "\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.20",
+ "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.20",
"tipoMem": "FloatABCD",
"factor": 1
},
"OPC_SP_Temp_Burner7": {
"name": "OPC_SP_Temp_Burner7",
"description": "Burner 7",
- "memAddr": "\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.24",
+ "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.24",
"tipoMem": "FloatABCD",
"factor": 1
},
"OPC_SP_Temp_Burner8": {
"name": "OPC_SP_Temp_Burner8",
"description": "Burner 8",
- "memAddr": "\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.28",
+ "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.28",
"tipoMem": "FloatABCD",
"factor": 1
},
"OPC_SP_Temp_Burner9": {
"name": "OPC_SP_Temp_Burner9",
"description": "Burner 9",
- "memAddr": "\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.32",
+ "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Temperature\"#GEN.Float.32",
"tipoMem": "FloatABCD",
"factor": 1
},
"OPC_SP_Termoset_ThermoTime": {
"name": "OPC_SP_Termoset_ThermoTime",
"description": "Thermoset Time",
- "memAddr": "\"Recipe_Table_DB_RW\".\"Thermoset\"#GEN.Float.0",
+ "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Thermoset\"#GEN.Float.0",
"tipoMem": "FloatABCD",
"factor": 1
},
"OPC_SP_Termoset_ThermoTemp": {
"name": "OPC_SP_Termoset_ThermoTemp",
"description": "Thermoset Temperature",
- "memAddr": "\"Recipe_Table_DB_RW\".\"Thermoset\"#GEN.Float.4",
+ "memAddr": "ns=3;s=\"Recipe_Table_DB_RW\".\"Thermoset\"#GEN.Float.4",
"tipoMem": "FloatABCD",
"factor": 1
}
diff --git a/IOB-WIN-NEXT/DATA/IobOpcUaClient.Config.xml b/IOB-WIN-NEXT/DATA/IobOpcUaClient.Config.xml
index e4d2b0b7..17669aa0 100644
--- a/IOB-WIN-NEXT/DATA/IobOpcUaClient.Config.xml
+++ b/IOB-WIN-NEXT/DATA/IobOpcUaClient.Config.xml
@@ -55,14 +55,14 @@
- 60000
+ 600000
opc.tcp://{0}:4840
http://{0}:52601/UADiscovery
http://{0}/UADiscovery/Default.svc
- 10000
+ 120000
diff --git a/IOB-WIN-NEXT/Iob/Generic.cs b/IOB-WIN-NEXT/Iob/Generic.cs
index 4b31087f..630c5b69 100644
--- a/IOB-WIN-NEXT/Iob/Generic.cs
+++ b/IOB-WIN-NEXT/Iob/Generic.cs
@@ -635,6 +635,26 @@ namespace IOB_WIN_NEXT.Iob
}
}
+ ///
+ /// URL per recupero PODL NEXT = ATTIVABILI x macchina...
+ ///
+ public string urlGetActPODL
+ {
+ get
+ {
+ string answ = "";
+ try
+ {
+ answ = $@"{cIobConf.serverData.TRANSP}://{cIobConf.serverData.MPIP}{cIobConf.serverData.MPURL}{cIobConf.serverData.CMDALIVE}/getPOdlAct/{cIobConf.codIOB}";
+ }
+ catch (Exception exc)
+ {
+ lgError(exc, "Errore in composizione urlGetActPODL");
+ }
+ return answ;
+ }
+ }
+
///
/// URL per recupero ARTICOLI correnti x macchina...
///
@@ -696,8 +716,9 @@ namespace IOB_WIN_NEXT.Iob
}
///
- /// URL per recupero PODL correnti x macchina...
+ /// URL per recupero PODL ATTIVABILI (quindi correnti in senso di pronti) x macchina...
///
+ [Obsolete("Metodo obsoleto (dubbia interpretazione): sostituire con urlGetNextPODL se si vogliono PROSSIMI POdl attivabili (significato originale) o con urlGetActPODL x il POdl attualmente in produzione (per casi come Rama OPC-UA Siemens)")]
public string urlGetCurrPODL
{
get
@@ -735,6 +756,26 @@ namespace IOB_WIN_NEXT.Iob
}
}
+ ///
+ /// URL per recupero PODL NEXT = ATTIVABILI x macchina...
+ ///
+ public string urlGetNextPODL
+ {
+ get
+ {
+ string answ = "";
+ try
+ {
+ answ = $@"{cIobConf.serverData.TRANSP}://{cIobConf.serverData.MPIP}{cIobConf.serverData.MPURL}{cIobConf.serverData.CMDALIVE}/getPOdlNext/{cIobConf.codIOB}";
+ }
+ catch (Exception exc)
+ {
+ lgError(exc, "Errore in composizione urlGetNextPODL");
+ }
+ return answ;
+ }
+ }
+
///
/// URL per recupero traduzione CodArt in numerico...
///
@@ -4113,8 +4154,11 @@ namespace IOB_WIN_NEXT.Iob
currProdData.Add(chiave, valore);
done = true;
}
- // salvo in redis...
- redisMan.redSaveHashDict(rKeyCurrProdData, currProdData);
+ if (done)
+ {
+ // salvo in redis...
+ redisMan.redSaveHashDict(rKeyCurrProdData, currProdData);
+ }
return done;
}
diff --git a/IOB-WIN-NEXT/IobOpc/OpcUa.cs b/IOB-WIN-NEXT/IobOpc/OpcUa.cs
index 0db84258..8db14fbe 100644
--- a/IOB-WIN-NEXT/IobOpc/OpcUa.cs
+++ b/IOB-WIN-NEXT/IobOpc/OpcUa.cs
@@ -3,6 +3,7 @@ using MapoSDK;
using Newtonsoft.Json;
using NLog.Time;
using Opc.Ua;
+using Opc.Ua.Client;
using Opc.Ua.Configuration;
using S7.Net.Types;
using System;
@@ -14,6 +15,7 @@ using System.Security.AccessControl;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using System.Web.Util;
using System.Windows.Forms;
using static IOB_UT_NEXT.ByteDataConverter;
@@ -172,7 +174,7 @@ namespace IOB_WIN_NEXT.IobOpc
string varDef = opcUaParams.keyPartCount.Substring(iPos + 1);
// recupero byte
byte[] bArray = getDataItemValueBytes(kRef);
- answ = ConvBArr(bArray, varDef, opcUaParams.memDelim);
+ answ = ConvFromBArr(bArray, varDef, opcUaParams.memDelim);
}
else
{
@@ -483,7 +485,7 @@ namespace IOB_WIN_NEXT.IobOpc
string varDef = opcUaParams.keyPartCount.Substring(iPos + 1);
// recupero byte
byte[] bArray = getDataItemValueBytes(kRef);
- currPzCount = ConvBArr(bArray, varDef, opcUaParams.memDelim);
+ currPzCount = ConvFromBArr(bArray, varDef, opcUaParams.memDelim);
}
else
{
@@ -912,11 +914,11 @@ namespace IOB_WIN_NEXT.IobOpc
var rByte = dataItemMem[uuid].rawByte;
int iPos = item.Value.memAddr.IndexOf(opcUaParams.kvDelim);
string varDef = item.Value.memAddr.Substring(iPos + 1);
- string convVal = ConvBArr(rByte, varDef, opcUaParams.memDelim);
+ string convVal = ConvFromBArr(rByte, varDef, opcUaParams.memDelim);
// verifica SE ci sia deadBand da validare...
if (valueOverDBand(item.Key, convVal))
{
- // metto in array currData...
+ // metto in array memData...
if (upsertKey(item.Key, convVal))
{
// accodo se variato!
@@ -946,11 +948,11 @@ namespace IOB_WIN_NEXT.IobOpc
var rByte = dataItemMem[uuid].rawByte;
int iPos = item.Value.memAddr.IndexOf(opcUaParams.kvDelim);
string varDef = item.Value.memAddr.Substring(iPos + 1);
- string convVal = ConvBArr(rByte, varDef, opcUaParams.memDelim);
+ string convVal = ConvFromBArr(rByte, varDef, opcUaParams.memDelim);
// verifica SE ci sia deadBand da validare...
if (valueOverDBand(item.Key, convVal))
{
- // metto in array currData...
+ // metto in array memData...
if (upsertKey(item.Key, convVal))
{
// accodo se variato!
@@ -1735,7 +1737,7 @@ namespace IOB_WIN_NEXT.IobOpc
try
{
var wrapVal = ((DataValue)obj).WrappedValue;
- //rawByte = ObjectToByteArray(rawVal);
+ //rawByte = ObjectToByteArray(sVal);
var bodyVal = ((Opc.Ua.ExtensionObject)wrapVal.Value).Body;
rawByte = (byte[])bodyVal;
}
@@ -1744,6 +1746,31 @@ namespace IOB_WIN_NEXT.IobOpc
}
return rawByte;
}
+#if false
+ protected DataValue setByteRaw(DataValue obj, byte[] newData, int startPos)
+ {
+ if (obj != null)
+ {
+ byte[] rawByte = new byte[1];
+ if (obj != null)
+ {
+ try
+ {
+ var wrapVal = ((DataValue)obj).WrappedValue;
+ var bodyVal = ((Opc.Ua.ExtensionObject)wrapVal.Value).Body;
+ rawByte = (byte[])bodyVal;
+ // sostituisco
+ Array.Copy(newData, 0, rawByte, startPos, newData.Length);
+ // aggiorno oggetto originale...
+ ((Opc.Ua.ExtensionObject)wrapVal.Value).Body = rawByte;
+ }
+ catch
+ { }
+ }
+ }
+ return obj;
+ }
+#endif
///
/// Effettua traduzione ITEM da LUT parametrica (key: tipo+id) del file di conf, se non
@@ -1984,7 +2011,7 @@ namespace IOB_WIN_NEXT.IobOpc
/// Stringa definizione variabile
/// Separatore nella definizione
///
- private string ConvBArr(byte[] bArray, string varDef, char pSep)
+ private string ConvFromBArr(byte[] bArray, string varDef, char pSep)
{
string answ = "";
// converto prendendo solo parte richiesta...
@@ -2093,6 +2120,123 @@ namespace IOB_WIN_NEXT.IobOpc
return answ;
}
+ ///
+ /// Conversione da valore string a corrispettivo byteArray nel tipo obj richiesto
+ ///
+ /// Valore da inviare come string
+ /// Stringa definizione variabile
+ /// Separatore nella definizione
+ ///
+ private byte[] ConvToBArr(string sVal, string varDef, char pSep)
+ {
+ byte[] answ = new byte[1];
+ // converto prendendo solo parte richiesta...
+ if (!string.IsNullOrEmpty(sVal))
+ {
+ // splitto in primis la definizione
+ MemStruct currMem = new MemStruct(varDef, pSep);
+
+ // S7.Double.B0 ora eseguo riconoscimento (da portare in base? FixMe ToDo...)
+ if (currMem.Product == "S7")
+ {
+#if false
+ // converto!
+ plcDataType tVal = plcDataType.Int;
+ Enum.TryParse(currMem.Type, out tVal);
+ // ora gestisco seconda parte...
+ switch (tVal)
+ {
+ case plcDataType.Boolean:
+ var boolVal = S7.Net.Types.Boolean.GetValue(bArray[currMem.Idx], currMem.Num);
+ answ = $"{boolVal}";
+ break;
+
+ case plcDataType.Int:
+ var intVal = S7.Net.Types.Int.FromByteArray(bArray.Skip(currMem.Idx).Take(2).ToArray());
+ answ = $"{intVal}";
+ break;
+ //case plcDataType.IntLH:
+ // break;
+ case plcDataType.DInt:
+ var dIntVal = S7.Net.Types.Int.FromByteArray(bArray.Skip(currMem.Idx).Take(4).ToArray());
+ answ = $"{dIntVal}";
+ break;
+ //case plcDataType.DIntLH:
+ // break;
+ case plcDataType.Word:
+ var wordVal = S7.Net.Types.Word.FromByteArray((bArray.Skip(currMem.Idx).Take(2).ToArray()));
+ answ = $"{wordVal}";
+ break;
+
+ case plcDataType.DWord:
+ var dWordVal = S7.Net.Types.Word.FromByteArray((bArray.Skip(currMem.Idx).Take(4).ToArray()));
+ answ = $"{dWordVal}";
+ break;
+
+ case plcDataType.Real:
+ var dblVal = S7.Net.Types.Double.FromByteArray(bArray.Skip(currMem.Idx).Take(4).ToArray());
+ answ = $"{dblVal:N3}";
+ break;
+ //case plcDataType.RealHL:
+ // break;
+ //case plcDataType.RealLH:
+ // break;
+ case plcDataType.String:
+ answ = S7.Net.Types.String.FromByteArray(bArray.Skip(currMem.Idx).Take(currMem.Num).ToArray());
+ break;
+ //case plcDataType.HLPInt:
+ // break;
+ //case plcDataType.FloatABCD:
+ // break;
+ //case plcDataType.FloatBADC:
+ // break;
+ //case plcDataType.FloatCDAB:
+ // break;
+ //case plcDataType.FloatDCBA:
+ // break;
+ //case plcDataType.BitMap:
+ // break;
+ //case plcDataType.Byte:
+ // break;
+ //case plcDataType.UInt:
+ // break;
+ //case plcDataType.UDInt:
+ // break;
+ default:
+ break;
+ }
+#endif
+ }
+ else if (currMem.Product == "GEN")
+ {
+ // ora gestisco seconda parte...
+ switch (currMem.Type)
+ {
+ case "Byte":
+ answ = new byte[1];
+ bool bVal = false;
+ bool.TryParse(sVal, out bVal);
+ answ[0] = bVal ? (byte)1 : (byte)0;
+ break;
+
+ case "Float":
+ float fVal = 0;
+ float.TryParse(sVal, out fVal);
+ answ = BitConverter.GetBytes(fVal);
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // gestire casi NON S7...
+ }
+ }
+ return answ;
+ }
+
///
/// Vera connessione ad OpcUa
///
@@ -2117,6 +2261,11 @@ namespace IOB_WIN_NEXT.IobOpc
// load the application configuration.
string confPath = $"{Application.StartupPath}\\DATA\\IobOpcUaClient.Config.xml";
await application.LoadApplicationConfiguration(confPath, silent: false).ConfigureAwait(false);
+#if false
+ // impostazioni speciali client
+ application.ApplicationConfiguration.ClientConfiguration.DefaultSessionTimeout = 1000 * 60 * 60;
+ application.ApplicationConfiguration.ClientConfiguration.MinSubscriptionLifetime = 1000 * 60;
+#endif
// check the application certificate.
await application.CheckApplicationInstanceCertificate(silent: false, minimumKeySize: 0).ConfigureAwait(false);
@@ -2424,6 +2573,205 @@ namespace IOB_WIN_NEXT.IobOpc
readErrorCurr = 0;
}
+
+ ///
+ /// 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)
+ {
+ // cache dei valori da scrivere in memoria x i valori composti come byte[]
+ Dictionary memWriteCache = new Dictionary();
+ Dictionary nodes2Write = new Dictionary();
+ // controllo i parametri... ne gestisco 4...
+ foreach (var item in updatedPar)
+ {
+ if (connectionOk)
+ {
+ 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 isByteArr = memAddrWrite.Contains(opcUaParams.kvDelim);
+ byte[] memData = new byte[0];
+ byte[] newData = new byte[0];
+ if (isByteArr)
+ {
+ // ciclo e calcolo valore
+ int iPos = memAddrWrite.IndexOf(opcUaParams.kvDelim);
+ string memName = memAddrWrite.Substring(0, iPos);
+ string varDef = memAddrWrite.Substring(iPos + 1);
+ // verifico se ho in array..
+ if (!memWriteCache.ContainsKey(memName))
+ {
+ // leggo come byte[]
+ NodeId reqNode = new NodeId(memName);
+ var rawVal = UA_ref.ReadNodeRaw(reqNode);
+ if (rawVal != null)
+ {
+ memData = getByteRaw((DataValue)rawVal);
+ }
+ else
+ {
+ // registro x uscire subito!
+#if false
+ numErroriCheck = maxErroriCheck;
+#endif
+ numErroriCheck += 10;
+ }
+ }
+ // sennò leggo da server...
+ else
+ {
+ memData = memWriteCache[memName];
+ }
+
+ // se ho dati scrivo e salvo in memoria
+ if (memData != null && memData.Length > 0)
+ {
+ // recupero il valore come byte[]
+ MemStruct mStruc = new MemStruct(varDef, opcUaParams.memDelim);
+ newData = ConvToBArr(item.reqValue, varDef, opcUaParams.memDelim);
+ // sostituisco blocco new in byte[]
+ Array.Copy(newData, 0, memData, mStruc.Num, newData.Length);
+
+ // scrittura nell'oggetto OPC-UA direttamente
+ commWriteVal.NodeId = new NodeId(memName);
+ //commWriteVal.Value.Value = memData;
+ //commWriteVal.Value.WrappedValue = memData;
+
+ // impacchetto
+ ExtensionObject extObject = new ExtensionObject
+ {
+ Body = memData
+ };
+
+ commWriteVal.Value.Value = extObject;
+
+ //((Opc.Ua.ExtensionObject)commWriteVal.Value.WrappedValue.Value).Body = memData;
+ // salvo!
+ memWriteCache.Add(memName, memData);
+ }
+ }
+ 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 > 0)
+ {
+ List listWriteReq = nodes2Write.Select(x => x.Value).ToList();
+ UA_ref.WriteNodes(listWriteReq);
+ }
+ }
+ }
+ }
+
#endregion Private Methods
}
}
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/IobOpc/OpcUaKpwRama.cs b/IOB-WIN-NEXT/IobOpc/OpcUaKpwRama.cs
index 52cc93f4..89f993a8 100644
--- a/IOB-WIN-NEXT/IobOpc/OpcUaKpwRama.cs
+++ b/IOB-WIN-NEXT/IobOpc/OpcUaKpwRama.cs
@@ -71,9 +71,9 @@ namespace IOB_WIN_NEXT.IobOpc
* - recupero elenco DOSSIER last x macchina (legato ai PODL attivi)
* - prendo SOLO PODL attivi, e prendo il + vecchio
* - se trovo dossier x articolo del PODL + vecchio (e dovrebbe...) procedo
- * - uso Dictionary RecipeKeyTranslate x tradurre l'elenco fluxLog in nuovi valori
+ * - uso Dictionary dei memWrite x tradurre l'elenco fluxLog in nuovi valori
* - preparo il set di valori da scrivere con traduzione
- * - invio scritture (sim test --> scrivo su file?)
+ * - invio scritture
* - aggiungo info articolo (+ ODL...)
* - aggiungo il valore di "scrittura effettuata"
*----------------------------------------- */
@@ -87,7 +87,8 @@ namespace IOB_WIN_NEXT.IobOpc
// recupera dati da server tramite chiamate REST a MP/IO/IOB...
var rawListArt = callUrl(urlGetCurrArt, false);
var rawListDOSS = callUrl(urlGetCurrDOSS, false);
- var rawListPODL = callUrl(urlGetCurrPODL, false);
+ // fixme todo verificare se usare urlGetActPODL
+ var rawListPODL = callUrl(urlGetNextPODL, false);
if (!string.IsNullOrEmpty(rawListArt))
{
try
@@ -134,7 +135,7 @@ namespace IOB_WIN_NEXT.IobOpc
}
else
{
- lg.Error($"Errore: chiamata elenco PODL ({urlGetCurrPODL}) ha restituito valore vuoto");
+ lg.Error($"Errore: chiamata elenco PODL ({urlGetNextPODL}) ha restituito valore vuoto");
}
answ = okArt && okPodl && okDoss;
@@ -187,129 +188,7 @@ namespace IOB_WIN_NEXT.IobOpc
return answ;
}
- ///
- /// Recupera da server set di dati specifici x IOB : qui per compilare ricette via OPC-UA
- ///
- ///
- protected override bool iobGetDataFromServer()
- {
- bool answ = false;
- bool okArt = false;
- bool okDoss = false;
- bool okPodl = false;
- bool okLVFasi = false;
- List listaPODL = new List();
- List listaDoss = new List();
- List listaArt = new List();
- List anagLVFasi = new List();
- Dictionary dictAF = new Dictionary();
- // recupera dati da server tramite chiamate REST a MP/IO/IOB...
- var rawListArt = callUrl(urlGetCurrArt, false);
- var rawListDOSS = callUrl(urlGetCurrDOSS, false);
- var rawListPODL = callUrl(urlGetCurrPODL, false);
- var rawLVFasi = callUrl(urlGetListValFasiPodl, false);
- if (!string.IsNullOrEmpty(rawListArt))
- {
- try
- {
- listaArt = JsonConvert.DeserializeObject>(rawListArt);
- okArt = listaArt.Count > 0;
- }
- catch (Exception exc)
- {
- lg.Error($"Errore: chiamata elenco ART ha restituito errore{Environment.NewLine}{exc}");
- }
- }
- else
- {
- lg.Error($"Errore: chiamata elenco ART ({urlGetCurrArt}) ha restituito valore vuoto");
- }
- if (!string.IsNullOrEmpty(rawListDOSS))
- {
- try
- {
- listaDoss = JsonConvert.DeserializeObject>(rawListDOSS);
- okDoss = listaDoss.Count > 0;
- }
- catch (Exception exc)
- {
- lg.Error($"Errore: chiamata elenco DOSSIER ha restituito errore{Environment.NewLine}{exc}");
- }
- }
- else
- {
- lg.Error($"Errore: chiamata elenco DOSSIER ({urlGetCurrDOSS}) ha restituito valore vuoto");
- }
- if (!string.IsNullOrEmpty(rawListPODL))
- {
- try
- {
- listaPODL = JsonConvert.DeserializeObject>(rawListPODL);
- okPodl = listaPODL.Count > 0;
- }
- catch (Exception exc)
- {
- lg.Error($"Errore: chiamata elenco PODL ha restituito errore{Environment.NewLine}{exc}");
- }
- }
- else
- {
- lg.Error($"Errore: chiamata elenco PODL ({urlGetCurrPODL}) ha restituito valore vuoto");
- }
- if (!string.IsNullOrEmpty(rawLVFasi))
- {
- try
- {
- anagLVFasi = JsonConvert.DeserializeObject>(rawLVFasi);
- dictAF = anagLVFasi.ToDictionary(x => x.value, x => x.label);
- okLVFasi = listaArt.Count > 0;
- }
- catch (Exception exc)
- {
- lg.Error($"Errore: chiamata elenco ListVal ha restituito errore{Environment.NewLine}{exc}");
- }
- }
- else
- {
- lg.Error($"Errore: chiamata elenco ListVal ({urlGetListValFasiPodl}) ha restituito valore vuoto");
- }
- answ = okPodl && okDoss && okArt && okLVFasi;
- if (answ)
- {
- // predispongo dati PODL
- ListaJobs = listaPODL
- .Select(x => new JobRow() { Matricola = x.CodArticolo, Commessa = $"PODL{x.IdxPromessa:00000000}", Articolo = x.CodArticolo, Descrizione = x.CodArticolo, DataIns = $"{x.InsertDate:dd/MM/yyyy}", OraIns = $"{x.InsertDate:HH:mm}", Lavorazione = $"{getLV(dictAF, x.KeyRichiesta)} {x.Note}".Trim() })
- .ToList();
-
- // predispongo dati articoli
- ListaArticoli = listaArt
- .Select(a => new ArtRow() { Matricola = a.CodArticolo, Articolo = a.Disegno, Descrizione = a.DescArticolo, LimiteVel = 100 })
- .Distinct()
- .ToList();
-
- // completo con dati DOSSIER
- foreach (var item in ListaArticoli)
- {
- string codArt = item.Matricola;
- var currDoss = listaDoss.Where(x => x.CodArticolo == codArt).FirstOrDefault();
- if (currDoss != null)
- {
- DossierFluxLogDTO resultSet = JsonConvert.DeserializeObject(currDoss.Valore);
- // traduco AD MENTULAM...
- item.Peso_01 = getFluxValInt(resultSet, "OPC_PLC/DB231/peso1");
- item.Peso_02 = getFluxValInt(resultSet, "OPC_PLC/DB231/peso2");
- item.Peso_03 = getFluxValInt(resultSet, "OPC_PLC/DB231/peso3");
- item.Peso_04 = getFluxValInt(resultSet, "OPC_PLC/DB231/peso4");
- item.PosizCarrello_01 = getFluxValInt(resultSet, "OPC_PLC/DB231/PosCarr1");
- item.PosizCarrello_02 = getFluxValInt(resultSet, "OPC_PLC/DB231/PosCarr2");
- item.PosizCarrello_03 = getFluxValInt(resultSet, "OPC_PLC/DB231/PosCarr3");
- item.PosizCarrello_04 = getFluxValInt(resultSet, "OPC_PLC/DB231/PosCarr4");
- }
- }
- }
- return answ;
- }
-
+
#endregion Public Constructors
}
diff --git a/IOB-WIN-NEXT/IobOpc/OpcUaSiemens.cs b/IOB-WIN-NEXT/IobOpc/OpcUaSiemens.cs
index f7964f60..c9be612c 100644
--- a/IOB-WIN-NEXT/IobOpc/OpcUaSiemens.cs
+++ b/IOB-WIN-NEXT/IobOpc/OpcUaSiemens.cs
@@ -291,6 +291,7 @@ namespace IOB_WIN_NEXT.IobOpc
}
}
+#if false
///
/// Effettua vera scrittura parametri
///
@@ -303,6 +304,8 @@ namespace IOB_WIN_NEXT.IobOpc
string serObj = "";
if (updatedPar != null)
{
+ // cache dei valori da scrivere in memoria x i valori composti come byte[]
+ Dictionary memWriteCache = new Dictionary();
List nodes2Write = new List();
// controllo i parametri... ne gestisco 4...
foreach (var item in updatedPar)
@@ -320,6 +323,8 @@ namespace IOB_WIN_NEXT.IobOpc
byteSize = currMem.size;
memAddrWrite = currMem.memAddr;
+ // rifare: se è "Recipe_Table_DB_RW"."Thermoset"#GEN.Float.4 --> devo leggere un datablock di byte, aggiornare solo un pezzo... POI scrivere l'intero datablock...
+
WriteValue commWriteVal = new WriteValue();
commWriteVal.NodeId = new NodeId(memAddrWrite);
commWriteVal.AttributeId = Attributes.Value;
@@ -388,7 +393,8 @@ namespace IOB_WIN_NEXT.IobOpc
UA_ref.WriteNodes(nodes2Write);
}
}
- }
+ }
+#endif
#endregion Protected Methods
}
diff --git a/IOB-WIN-NEXT/IobOpc/OpcUaSiemensRama.cs b/IOB-WIN-NEXT/IobOpc/OpcUaSiemensRama.cs
index e8975e43..6f8e3bc9 100644
--- a/IOB-WIN-NEXT/IobOpc/OpcUaSiemensRama.cs
+++ b/IOB-WIN-NEXT/IobOpc/OpcUaSiemensRama.cs
@@ -36,23 +36,6 @@ namespace IOB_WIN_NEXT.IobOpc
* QUANDO FUNZIONA verificare se e come rendere parametrica la gestione oggetti/byte configurabili
*
*-------------------------------------------*/
-#if false
- // inizializzo classe base...
- if (!string.IsNullOrEmpty(getOptPar("CHANGE_ODL_MODE")))
- {
- CHANGE_ODL_MODE = getOptPar("CHANGE_ODL_MODE");
- }
- // gestione restart OpcUa client...
- if (!string.IsNullOrEmpty(getOptPar("ENABLE_CLI_RESTART")))
- {
- bool.TryParse(getOptPar("ENABLE_CLI_RESTART"), out enableCliRestart);
- }
- // init lastCurrentMaxElapsed
- if (!string.IsNullOrEmpty(getOptPar("MAX_ELAPSED_TIME_SEC")))
- {
- int.TryParse(getOptPar("MAX_ELAPSED_TIME_SEC"), out lastCurrentMaxElapsed);
- }
-#endif
sendKeyRichiesta = true;
}
@@ -70,14 +53,15 @@ namespace IOB_WIN_NEXT.IobOpc
}
///
- /// Recupero dati da server x invio dati ricetta a KepWare (Ex RAMA x TFT)
+ /// Recupero dati da server x invio dati ricetta a OPC-UA Siemens (RAMA x Tenditalia)
+ /// NB: modificato rispetto a TFT: invia PODL correntemente in esecuzione (SE DISPONIBILE) oppure il PRIMO di quelli attivabili...
///
///
private bool iobGetSendDossierKepware()
{
bool answ;
- lg.Info("iobGetSendDossierKepware: Inizio scrittura dati a KepWare");
+ lgInfo("iobGetSendDossierKepware: Inizio scrittura dati a KepWare");
/*-----------------------------------------
* STEPS processo:
* - recupero ARTICOLI (solo quelli dei PODL attivi)
@@ -85,11 +69,11 @@ namespace IOB_WIN_NEXT.IobOpc
* - recupero elenco DOSSIER last x macchina (legato ai PODL attivi)
* - prendo SOLO PODL attivi, e prendo il + vecchio
* - se trovo dossier x articolo del PODL + vecchio (e dovrebbe...) procedo
- * - uso Dictionary RecipeKeyTranslate x tradurre l'elenco fluxLog in nuovi valori
+ * - uso Dictionary dei memWrite x tradurre l'elenco fluxLog in nuovi valori
* - preparo il set di valori da scrivere con traduzione
- * - invio scritture (sim test --> scrivo su file?)
+ * - invio scritture
* - aggiungo info articolo (+ ODL...)
- * - aggiungo il valore di "scrittura effettuata"
+ * - aggiungo i valori BIT di "reset contapezzi " + "nuova ricetta"
*----------------------------------------- */
bool okArt = false;
@@ -101,7 +85,7 @@ namespace IOB_WIN_NEXT.IobOpc
// recupera dati da server tramite chiamate REST a MP/IO/IOB...
var rawListArt = callUrl(urlGetCurrArt, false);
var rawListDOSS = callUrl(urlGetCurrDOSS, false);
- var rawListPODL = callUrl(urlGetCurrPODL, false);
+ var rawListPODL = callUrl(urlGetActPODL, false);
if (!string.IsNullOrEmpty(rawListArt))
{
try
@@ -148,7 +132,7 @@ namespace IOB_WIN_NEXT.IobOpc
}
else
{
- lg.Error($"Errore: chiamata elenco PODL ({urlGetCurrPODL}) ha restituito valore vuoto");
+ lg.Error($"Errore: chiamata elenco PODL ({urlGetActPODL}) ha restituito valore vuoto");
}
answ = okArt && okPodl && okDoss;
@@ -184,6 +168,14 @@ namespace IOB_WIN_NEXT.IobOpc
ListaCalcParams.Add(currData);
lgInfo($"Add param: {currData.uid} | reqVal: {currData.reqValue}");
}
+ // aggiungo ultimo parametro di resetCounter...
+ objItem resetCnt = new objItem()
+ {
+ uid = "ResetCounter",
+ reqValue = "true",
+ name = "ResetCounter"
+ };
+ ListaCalcParams.Add(resetCnt);
// aggiungo ultimo parametro di newRecipe...
objItem newRecipeData = new objItem()
{
@@ -201,129 +193,7 @@ namespace IOB_WIN_NEXT.IobOpc
return answ;
}
- ///
- /// Recupera da server set di dati specifici x IOB : qui per compilare ricette via OPC-UA
- ///
- ///
- protected override bool iobGetDataFromServer()
- {
- bool answ = false;
- bool okArt = false;
- bool okDoss = false;
- bool okPodl = false;
- bool okLVFasi = false;
- List listaPODL = new List();
- List listaDoss = new List();
- List listaArt = new List();
- List anagLVFasi = new List();
- Dictionary dictAF = new Dictionary();
- // recupera dati da server tramite chiamate REST a MP/IO/IOB...
- var rawListArt = callUrl(urlGetCurrArt, false);
- var rawListDOSS = callUrl(urlGetCurrDOSS, false);
- var rawListPODL = callUrl(urlGetCurrPODL, false);
- var rawLVFasi = callUrl(urlGetListValFasiPodl, false);
- if (!string.IsNullOrEmpty(rawListArt))
- {
- try
- {
- listaArt = JsonConvert.DeserializeObject>(rawListArt);
- okArt = listaArt.Count > 0;
- }
- catch (Exception exc)
- {
- lg.Error($"Errore: chiamata elenco ART ha restituito errore{Environment.NewLine}{exc}");
- }
- }
- else
- {
- lg.Error($"Errore: chiamata elenco ART ({urlGetCurrArt}) ha restituito valore vuoto");
- }
- if (!string.IsNullOrEmpty(rawListDOSS))
- {
- try
- {
- listaDoss = JsonConvert.DeserializeObject>(rawListDOSS);
- okDoss = listaDoss.Count > 0;
- }
- catch (Exception exc)
- {
- lg.Error($"Errore: chiamata elenco DOSSIER ha restituito errore{Environment.NewLine}{exc}");
- }
- }
- else
- {
- lg.Error($"Errore: chiamata elenco DOSSIER ({urlGetCurrDOSS}) ha restituito valore vuoto");
- }
- if (!string.IsNullOrEmpty(rawListPODL))
- {
- try
- {
- listaPODL = JsonConvert.DeserializeObject>(rawListPODL);
- okPodl = listaPODL.Count > 0;
- }
- catch (Exception exc)
- {
- lg.Error($"Errore: chiamata elenco PODL ha restituito errore{Environment.NewLine}{exc}");
- }
- }
- else
- {
- lg.Error($"Errore: chiamata elenco PODL ({urlGetCurrPODL}) ha restituito valore vuoto");
- }
- if (!string.IsNullOrEmpty(rawLVFasi))
- {
- try
- {
- anagLVFasi = JsonConvert.DeserializeObject>(rawLVFasi);
- dictAF = anagLVFasi.ToDictionary(x => x.value, x => x.label);
- okLVFasi = listaArt.Count > 0;
- }
- catch (Exception exc)
- {
- lg.Error($"Errore: chiamata elenco ListVal ha restituito errore{Environment.NewLine}{exc}");
- }
- }
- else
- {
- lg.Error($"Errore: chiamata elenco ListVal ({urlGetListValFasiPodl}) ha restituito valore vuoto");
- }
- answ = okPodl && okDoss && okArt && okLVFasi;
- if (answ)
- {
- // predispongo dati PODL
- ListaJobs = listaPODL
- .Select(x => new JobRow() { Matricola = x.CodArticolo, Commessa = $"PODL{x.IdxPromessa:00000000}", Articolo = x.CodArticolo, Descrizione = x.CodArticolo, DataIns = $"{x.InsertDate:dd/MM/yyyy}", OraIns = $"{x.InsertDate:HH:mm}", Lavorazione = $"{getLV(dictAF, x.KeyRichiesta)} {x.Note}".Trim() })
- .ToList();
-
- // predispongo dati articoli
- ListaArticoli = listaArt
- .Select(a => new ArtRow() { Matricola = a.CodArticolo, Articolo = a.Disegno, Descrizione = a.DescArticolo, LimiteVel = 100 })
- .Distinct()
- .ToList();
-
- // completo con dati DOSSIER
- foreach (var item in ListaArticoli)
- {
- string codArt = item.Matricola;
- var currDoss = listaDoss.Where(x => x.CodArticolo == codArt).FirstOrDefault();
- if (currDoss != null)
- {
- DossierFluxLogDTO resultSet = JsonConvert.DeserializeObject(currDoss.Valore);
- // traduco AD MENTULAM...
- item.Peso_01 = getFluxValInt(resultSet, "OPC_PLC/DB231/peso1");
- item.Peso_02 = getFluxValInt(resultSet, "OPC_PLC/DB231/peso2");
- item.Peso_03 = getFluxValInt(resultSet, "OPC_PLC/DB231/peso3");
- item.Peso_04 = getFluxValInt(resultSet, "OPC_PLC/DB231/peso4");
- item.PosizCarrello_01 = getFluxValInt(resultSet, "OPC_PLC/DB231/PosCarr1");
- item.PosizCarrello_02 = getFluxValInt(resultSet, "OPC_PLC/DB231/PosCarr2");
- item.PosizCarrello_03 = getFluxValInt(resultSet, "OPC_PLC/DB231/PosCarr3");
- item.PosizCarrello_04 = getFluxValInt(resultSet, "OPC_PLC/DB231/PosCarr4");
- }
- }
- }
- return answ;
- }
-
+
#endregion Public Constructors
}
diff --git a/IOB-WIN-NEXT/UAClient.cs b/IOB-WIN-NEXT/UAClient.cs
index 2c00176c..29397116 100644
--- a/IOB-WIN-NEXT/UAClient.cs
+++ b/IOB-WIN-NEXT/UAClient.cs
@@ -334,7 +334,7 @@ namespace IOB_WIN_NEXT
Session session = await Session.Create(
m_configuration,
endpoint,
- false,
+ true,
false,
m_configuration.ApplicationName,
60 * 60 * 1000,
@@ -342,6 +342,20 @@ namespace IOB_WIN_NEXT
null
);
+
+#if false
+ Session session = await Session.Create(
+ m_configuration,
+ endpoint,
+ false,
+ false,
+ m_configuration.ApplicationName,
+ 60 * 60 * 1000,
+ CurrUserIdentity,
+ null
+ );
+#endif
+
// Assign the created session
if (session != null && session.Connected)
{
@@ -484,6 +498,7 @@ namespace IOB_WIN_NEXT
if (m_session == null || m_session.Connected == false)
{
lgError("Session not connected!");
+ numErrors++;
return answ;
}
@@ -500,6 +515,14 @@ namespace IOB_WIN_NEXT
{
// Log Error
lgError($"ReadNodeRaw Error 01: {Environment.NewLine}{exc}");
+ numErrors++;
+
+ // provare disconnect?!?
+ if (numErrors >= maxErrors)
+ {
+ numErrors = 0;
+ Disconnect();
+ }
}
#endregion Read the Value attribute of a node by calling the Session.ReadValue method
@@ -678,6 +701,14 @@ namespace IOB_WIN_NEXT
{
// Log Error
lgError($"Write Nodes Error : {ex.Message}");
+ numErrors++;
+
+ // provare disconnect?!?
+ if (numErrors >= maxErrors)
+ {
+ numErrors = 0;
+ Disconnect();
+ }
}
}
}