diff --git a/IOB-UT-NEXT/Enums.cs b/IOB-UT-NEXT/Enums.cs
index b5c20475..e2572b71 100644
--- a/IOB-UT-NEXT/Enums.cs
+++ b/IOB-UT-NEXT/Enums.cs
@@ -355,6 +355,11 @@ namespace IOB_UT_NEXT
///
OpcUaEwonMecolpress,
+ ///
+ /// Adapter OMRON (es ICOEL)
+ ///
+ OpcUaOmron,
+
///
/// Adapter OSAI CNDEX (Cndex)
///
diff --git a/IOB-WIN-NEXT/AdapterForm.cs b/IOB-WIN-NEXT/AdapterForm.cs
index 34e4d513..501ef25f 100644
--- a/IOB-WIN-NEXT/AdapterForm.cs
+++ b/IOB-WIN-NEXT/AdapterForm.cs
@@ -1271,6 +1271,11 @@ namespace IOB_WIN_NEXT
start.Enabled = true;
break;
+ case tipoAdapter.OpcUaOmron:
+ iobObj = new IobOpcUaOmron(this, IOBConf);
+ start.Enabled = true;
+ break;
+
case tipoAdapter.PingWatchdog:
iobObj = new IobPing(this, IOBConf);
start.Enabled = true;
diff --git a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj
index 1a148125..1d25aed5 100644
--- a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj
+++ b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj
@@ -184,6 +184,7 @@
+
diff --git a/IOB-WIN-NEXT/IobOpcUaOmron.cs b/IOB-WIN-NEXT/IobOpcUaOmron.cs
new file mode 100644
index 00000000..4ab8cadc
--- /dev/null
+++ b/IOB-WIN-NEXT/IobOpcUaOmron.cs
@@ -0,0 +1,369 @@
+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 IobOpcUaOmron : 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 Omron (es ICOEL)
+ /// https://github.com/OPCFoundation/UA-.NETStandard
+ ///
+ ///
+ ///
+ public IobOpcUaOmron(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf)
+ {
+ // inizializzo classe base...
+ if (!string.IsNullOrEmpty(getOptPar("CHANGE_ODL_MODE")))
+ {
+ CHANGE_ODL_MODE = getOptPar("CHANGE_ODL_MODE");
+ }
+ sendKeyRichiesta = true;
+ }
+
+ #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 / setup
+ * B7: emergenza ARMATA (1=ok, 0 = premuta)
+ ---------------------------------------------------- */
+
+ // se valido il check ping lo eseguo... altrimenti lo do x buono
+ bool checkPing = !opcUaParams.pingAsPowerOn;
+ string currRun = "N.A.";
+ 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...
+ if (!string.IsNullOrEmpty(opcUaParams.keyRunMode))
+ {
+ 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);
+ }
+ }
+ // se abilitato watchdog...
+ if (opcUaParams.WatchDog.IsEnabled)
+ {
+ if (adesso.Subtract(lastWatchDogPLC).TotalSeconds > 2)
+ {
+ lastWatchDogPLC = adesso;
+ WatchDog++;
+ WatchDog = WatchDog > opcUaParams.WatchDog.MaxVal ? 0 : WatchDog;
+
+ lgTrace($"WatchDog val: {WatchDog}");
+ try
+ {
+ WriteValue commWriteVal = new WriteValue();
+ commWriteVal.NodeId = new NodeId(opcUaParams.WatchDog.MemConfWrite);
+ commWriteVal.AttributeId = Attributes.Value;
+ commWriteVal.Value = new DataValue();
+ commWriteVal.Value.Value = WatchDog;
+
+ List nodes2Write = new List();
+ nodes2Write.Add(commWriteVal);
+
+ UA_ref.WriteNodes(nodes2Write);
+ }
+ catch (Exception exc)
+ {
+ lgError($"Eccezione in gestione WatchDog, valore attuale {WatchDog}{Environment.NewLine}{exc}");
+ }
+ }
+ }
+ else
+ {
+ lgTrace("WatchDog disabilitato");
+ }
+
+ // controllo se sono poweroff e se non ho dati buoni da > 2 minuti --> disconnetto
+ if (!powerOnOk && adesso.Subtract(lastCurrent).TotalMinutes > 2)
+ {
+ tryDisconnect();
+ }
+
+ // solo se non ho veto check
+ int vFactor = 2;
+ if (vetoCheckStatus < adesso)
+ {
+ lgDebug($"Stato variabili checkPing: {testPingMachine}");
+ // imposto veto per vetoSeconds...
+ vetoCheckStatus = adesso.AddSeconds(vetoSeconds * vFactor);
+ }
+
+ // log opzionale!
+ if (verboseLog)
+ {
+ lgDebug($"Trasformazione checkPing: {checkPing} | hasPowerOn: {hasPowerOn} | B_input: {B_input} | currRun = {currRun}");
+ }
+ }
+
+ ///
+ /// Effettua vera scrittura parametri
+ ///
+ ///
+ protected override void plcWriteParams(ref List updatedPar)
+ {
+ 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;
+ 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}---------------");
+
+ 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) || 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