Bozza x aggiunta OPC-UA Omron di ICOEL
This commit is contained in:
@@ -355,6 +355,11 @@ namespace IOB_UT_NEXT
|
||||
/// </summary>
|
||||
OpcUaEwonMecolpress,
|
||||
|
||||
/// <summary>
|
||||
/// Adapter OMRON (es ICOEL)
|
||||
/// </summary>
|
||||
OpcUaOmron,
|
||||
|
||||
/// <summary>
|
||||
/// Adapter OSAI CNDEX (Cndex)
|
||||
/// </summary>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -184,6 +184,7 @@
|
||||
</Compile>
|
||||
<Compile Include="IobModbusTCPHelpi.cs" />
|
||||
<Compile Include="IobModbusTCPCedax.cs" />
|
||||
<Compile Include="IobOpcUaOmron.cs" />
|
||||
<Compile Include="IobOpcUaEwonBLM.cs" />
|
||||
<Compile Include="IobOpcUaEwonMecolpress.cs" />
|
||||
<Compile Include="IobOpcUaEwonMonti.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
|
||||
|
||||
/// <summary>
|
||||
/// Modalità cambio ODL
|
||||
/// </summary>
|
||||
protected string CHANGE_ODL_MODE = "";
|
||||
|
||||
protected bool testDone = false;
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Public Constructors
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
/// <param name="caller"></param>
|
||||
/// <param name="IOBConf"></param>
|
||||
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
|
||||
|
||||
/// <summary>
|
||||
/// Effettua decodifica aree memoria alla bitmap usata x MAPO
|
||||
/// </summary>
|
||||
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<WriteValue> nodes2Write = new List<WriteValue>();
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua vera scrittura parametri
|
||||
/// </summary>
|
||||
/// <param name="updatedPar"></param>
|
||||
protected override void plcWriteParams(ref List<objItem> updatedPar)
|
||||
{
|
||||
dataConf currMem = null;
|
||||
int byteSize = 0;
|
||||
string memAddrWrite = "";
|
||||
string serObj = "";
|
||||
if (updatedPar != null)
|
||||
{
|
||||
List<WriteValue> nodes2Write = new List<WriteValue>();
|
||||
// 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
|
||||
|
||||
/// <summary>
|
||||
/// Processo i task richiesti e li elimino dalla coda 1:1
|
||||
/// </summary>
|
||||
/// <param name="task2exe"></param>
|
||||
public override Dictionary<string, string> executeTasks(Dictionary<string, string> task2exe)
|
||||
{
|
||||
// uso metodo base x ora
|
||||
return base.executeTasks(task2exe);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua vero processing contapezzi
|
||||
/// </summary>
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua reset del contapezzi, NON POSSIBILE in questa versione
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override bool resetcontapezziPLC()
|
||||
{
|
||||
bool answ = false;
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua IMPOSTAZIONE FORZATA del contapezzi, NON POSSIBILE in questa versione
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override bool setcontapezziPLC(int newPzCount)
|
||||
{
|
||||
bool answ = false;
|
||||
return answ;
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user