Merge branch 'release/BetaOpcUaCMS'
This commit is contained in:
@@ -294,6 +294,16 @@ namespace IOB_UT_NEXT
|
||||
/// </summary>
|
||||
OpcUa,
|
||||
|
||||
/// <summary>
|
||||
/// Adapter OPC-UA CMS
|
||||
/// </summary>
|
||||
OpcUaCMS,
|
||||
|
||||
/// <summary>
|
||||
/// Adapter OPC-UA SCM
|
||||
/// </summary>
|
||||
OpcUaSCM,
|
||||
|
||||
/// <summary>
|
||||
/// Adapter OPC-UA per Ewon
|
||||
/// </summary>
|
||||
|
||||
@@ -458,6 +458,16 @@ namespace IOB_UT_NEXT
|
||||
/// </summary>
|
||||
public Dictionary<string, dataConf> mMapWrite { get; set; } = new Dictionary<string, dataConf>();
|
||||
|
||||
/// <summary>
|
||||
/// Elenco dei SOLI item sottoscritti (se vuoto TUTTI)
|
||||
/// </summary>
|
||||
public List<string> subscribedItems { get; set; } = new List<string>();
|
||||
|
||||
/// <summary>
|
||||
/// Elenco dei NodeId da ignorare intesi come interi rami (se vuoto NON filtro)
|
||||
/// </summary>
|
||||
public List<string> filterItemsNodeId { get; set; } = new List<string>();
|
||||
|
||||
#endregion Public Properties
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
@@ -71,6 +71,5 @@ CLI_INST=SteamWareSim
|
||||
;STARTLIST=OPC_UA
|
||||
;STARTLIST=SIM_PIZ03
|
||||
;STARTLIST=FOV062
|
||||
STARTLIST=3013
|
||||
|
||||
STARTLIST=FP_TR2
|
||||
MAXCNC=10
|
||||
@@ -182,6 +182,7 @@
|
||||
<Compile Include="IobOpcUa.cs" />
|
||||
<Compile Include="IobMTC.cs" />
|
||||
<Compile Include="IobOmron.cs" />
|
||||
<Compile Include="IobOpcUaCMS.cs" />
|
||||
<Compile Include="IobOpcUaEwon.cs" />
|
||||
<Compile Include="IobSiemensAt2001.cs" />
|
||||
<Compile Include="IobSiemensComeca.cs" />
|
||||
@@ -340,6 +341,12 @@
|
||||
<None Include="DATA\CONF\GT576.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="DATA\CONF\FP_TR2.ini">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="DATA\CONF\FP_TR2.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="DATA\CONF\OPC_UA.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
||||
+62
-25
@@ -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<string, string> nodeIdNameList = new Dictionary<string, string>();
|
||||
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<Opc.Ua.Client.MonitoredItem> 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<OpcUaParamConf>(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<OpcUaParamConf>(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
|
||||
|
||||
@@ -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
|
||||
|
||||
/// <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 CMS/SCM (es. Eidos termoformatrice)
|
||||
/// https://github.com/OPCFoundation/UA-.NETStandard
|
||||
/// </summary>
|
||||
/// <param name="caller"></param>
|
||||
/// <param name="IOBConf"></param>
|
||||
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
|
||||
|
||||
/// <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 (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}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua vera scrittura parametri
|
||||
/// </summary>
|
||||
/// <param name="updatedPar"></param>
|
||||
protected override void plcWriteParams(ref List<objItem> 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<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;
|
||||
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
|
||||
|
||||
/// <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.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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <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
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ namespace IOB_WIN_NEXT
|
||||
/// <param name="IOBConf"></param>
|
||||
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");
|
||||
|
||||
@@ -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<string, string> lastReadAlarms = new Dictionary<string, string>();
|
||||
|
||||
#endregion Protected Fields
|
||||
|
||||
#region Public Constructors
|
||||
|
||||
/// <summary>
|
||||
@@ -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
|
||||
|
||||
/// <summary>
|
||||
@@ -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<string, string> lastReadAlarms = new Dictionary<string, string>();
|
||||
|
||||
#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;
|
||||
|
||||
+37
-10
@@ -180,13 +180,13 @@ namespace IOB_WIN_NEXT
|
||||
/// <summary>
|
||||
/// Browse Server nodes
|
||||
/// </summary>
|
||||
public Dictionary<string, string> Browse(ushort startNodeNS, uint startNodeVal)
|
||||
public bool Browse(ushort startNodeNS, uint startNodeVal, List<string> vetoBrowse, ref Dictionary<string, string> nodeIdNameList)
|
||||
{
|
||||
Dictionary<string, string> nodeIdNameList = new Dictionary<string, string>();
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Browse Server nodes
|
||||
/// </summary>
|
||||
public Dictionary<string, string> Browse(string browsePath)
|
||||
public bool Browse(string browsePath, List<string> vetoBrowse, ref Dictionary<string, string> nodeIdNameList)
|
||||
{
|
||||
Dictionary<string, string> nodeIdNameList = new Dictionary<string, string>();
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user