diff --git a/IOB-UT-NEXT/ToMapo.cs b/IOB-UT-NEXT/ToMapo.cs
index 776a6063..0e80d735 100644
--- a/IOB-UT-NEXT/ToMapo.cs
+++ b/IOB-UT-NEXT/ToMapo.cs
@@ -632,6 +632,11 @@ namespace IOB_UT_NEXT
///
public bool UseFullId { get; set; } = false;
+ ///
+ /// Numero massimo di letture null prima di disconnettere il client
+ ///
+ public int maxNullRead { get; set; } = 1000;
+
///
/// Base del NameSpace usato per le funzionalità di translate (parametri ACT --> SET)
///
diff --git a/IOB-WIN-NEXT/IobOpc/OpcUa.cs b/IOB-WIN-NEXT/IobOpc/OpcUa.cs
index 7cb11745..a7187c27 100644
--- a/IOB-WIN-NEXT/IobOpc/OpcUa.cs
+++ b/IOB-WIN-NEXT/IobOpc/OpcUa.cs
@@ -533,7 +533,7 @@ namespace IOB_WIN_NEXT.IobOpc
}
else
{
- lgTrace($"checkAndSend ERROR | MonIt: {MonIt.DisplayName} | NotifyValue Null!!!");
+ lgError($"checkAndSend ERROR | MonIt: {MonIt.DisplayName} | NotifyValue Null!!!");
}
}
else
@@ -1452,7 +1452,7 @@ namespace IOB_WIN_NEXT.IobOpc
lgInfo($"Chiamata UAClient con configurazione standard: {application.ApplicationConfiguration.ApplicationName}");
string userName = opcUaParams == null || opcUaParams.Identity == null ? "" : opcUaParams.Identity.UserName;
string passwd = opcUaParams == null || opcUaParams.Identity == null ? "" : opcUaParams.Identity.Passwd;
- UA_ref = new UAClient(application.ApplicationConfiguration, cIobConf.codIOB, userName, passwd, isVerboseLog, ClientBase.ValidateResponse);
+ UA_ref = new UAClient(application.ApplicationConfiguration, cIobConf.codIOB, userName, passwd, isVerboseLog, ClientBase.ValidateResponse, opcUaParams.maxNullRead);
lgInfo($"Chiamata apertura OpcUa Client: {cIobConf.cncIpAddr}:{port}");
UA_ref.ServerUrl = $"opc.tcp://{cIobConf.cncIpAddr}:{port}";
@@ -1594,6 +1594,8 @@ namespace IOB_WIN_NEXT.IobOpc
}
}
}
+ // gestione ricezione null
+ UA_ref.eh_nullExceed += UA_ref_eh_nullExceed;
// gestione eventi change
UA_ref.eh_MonItChange += UA_ref_eh_MonItChange;
lgInfo("eh_MonItChange event registered");
@@ -1614,7 +1616,7 @@ namespace IOB_WIN_NEXT.IobOpc
// controllo read error ed eventuale disconnect
if (readErrorCurr > readErrorMax)
{
- lgError($"Effettuo disconnessione x superamento errori lettura UA_ref.ReadNode, sleetp 15 sec");
+ lgError($"Effettuo disconnessione x superamento errori lettura UA_ref.ReadNode, sleep {readErrorSleepTime}msec");
tryDisconnect();
Thread.Sleep(readErrorSleepTime);
readErrorCurr = 0;
@@ -1622,6 +1624,20 @@ namespace IOB_WIN_NEXT.IobOpc
return esitoLink;
}
+ ///
+ /// Ricevuto troppi null --> disconnetto e traccio
+ ///
+ ///
+ ///
+ ///
+ private void UA_ref_eh_nullExceed(object sender, int e)
+ {
+ lgError($"Effettuo disconnessione x superamento letture UA_ref.ReadNode a NULL ({e}), sleep {2 * readErrorSleepTime}msec");
+ tryDisconnect();
+ Thread.Sleep(2 * readErrorSleepTime);
+ readErrorCurr = 0;
+ }
+
///
/// Formatta un dataitem x salvataggio in memoria locale
///
diff --git a/IOB-WIN-NEXT/UAClient.cs b/IOB-WIN-NEXT/UAClient.cs
index 1d6fc593..2d32b013 100644
--- a/IOB-WIN-NEXT/UAClient.cs
+++ b/IOB-WIN-NEXT/UAClient.cs
@@ -72,8 +72,17 @@ namespace IOB_WIN_NEXT
///
/// Initializes a new instance of the UAClient class.
///
- public UAClient(ApplicationConfiguration configuration, string codIOB, string user, string pwd, bool verboseLog, Action validateResponse)
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// Numero massimo di risposte nulle in browsing prima di disconnettersi
+ public UAClient(ApplicationConfiguration configuration, string codIOB, string user, string pwd, bool verboseLog, Action validateResponse, int maxNullRead)
{
+ currNullReceiv = 0;
+ maxNullAllowed = maxNullRead;
m_validateResponse = validateResponse;
currIob = codIOB;
lg = LogManager.GetCurrentClassLogger();
@@ -99,6 +108,11 @@ namespace IOB_WIN_NEXT
///
public event EventHandler eh_MonItChange;
+ ///
+ /// Evento notifica superamento numero letture null
+ ///
+ public event EventHandler eh_nullExceed;
+
#endregion Public Events
#region Public Properties
@@ -393,8 +407,6 @@ namespace IOB_WIN_NEXT
try
{
- //#region Read a node by calling the Read Service
-
//// build a list of nodes to be read
//ReadValueIdCollection nodesToRead = new ReadValueIdCollection()
//{
@@ -427,10 +439,6 @@ namespace IOB_WIN_NEXT
// lgInfo("Read Value = {0} , StatusCode = {1}", result.Value, result.StatusCode);
//}
- //#endregion Read a node by calling the Read Service
-
- #region Read the Value attribute of a node by calling the Session.ReadValue method
-
try
{
DataValue resp = m_session.ReadValue(reqNodeId);
@@ -447,8 +455,6 @@ namespace IOB_WIN_NEXT
numErrors++;
lgTrace($"ReadValue Error | reqNodeId: {reqNodeId} | numErrors: {numErrors}{Environment.NewLine}{exc}");
}
-
- #endregion Read the Value attribute of a node by calling the Session.ReadValue method
}
catch (Exception ex)
{
@@ -466,8 +472,6 @@ namespace IOB_WIN_NEXT
return answ;
}
- protected int maxErrors = 20;
-
///
/// Read a SINGLE of nodes value (RAW) from Server
///
@@ -507,8 +511,6 @@ namespace IOB_WIN_NEXT
return answ;
}
- protected int numErrors = 0;
-
///
/// Read a list of nodes from Server
///
@@ -618,83 +620,6 @@ namespace IOB_WIN_NEXT
monItList.Add(currMonIt);
}
-#if false
- MonitoredItem IO_120_00_MonitoredItem = new MonitoredItem(subscription.DefaultItem);
- // Int32 Node - Objects\CTT\Scalar\Simulation\Int32
- IO_120_00_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_120.00");
- IO_120_00_MonitoredItem.AttributeId = Attributes.Value;
- IO_120_00_MonitoredItem.DisplayName = "IO_120 Variable";
- IO_120_00_MonitoredItem.SamplingInterval = 1000;
- IO_120_00_MonitoredItem.Notification += OnMonitoredItemNotification;
- subscription.AddItem(IO_120_00_MonitoredItem);
-
- MonitoredItem IO_120_01_MonitoredItem = new MonitoredItem(subscription.DefaultItem);
- // Int32 Node - Objects\CTT\Scalar\Simulation\Int32
- IO_120_01_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_120.01");
- IO_120_01_MonitoredItem.AttributeId = Attributes.Value;
- IO_120_01_MonitoredItem.DisplayName = "IO_120_01 Variable";
- IO_120_01_MonitoredItem.SamplingInterval = 1000;
- IO_120_01_MonitoredItem.Notification += OnMonitoredItemNotification;
- subscription.AddItem(IO_120_01_MonitoredItem);
-
- MonitoredItem IO_130_MonitoredItem = new MonitoredItem(subscription.DefaultItem);
- // Int32 Node - Objects\CTT\Scalar\Simulation\Int32
- IO_130_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_130");
- IO_130_MonitoredItem.AttributeId = Attributes.Value;
- IO_130_MonitoredItem.DisplayName = "IO_130 Variable";
- IO_130_MonitoredItem.SamplingInterval = 1000;
- IO_130_MonitoredItem.Notification += OnMonitoredItemNotification;
- subscription.AddItem(IO_130_MonitoredItem);
-
- MonitoredItem IO_135_MonitoredItem = new MonitoredItem(subscription.DefaultItem);
- // Int32 Node - Objects\CTT\Scalar\Simulation\Int32
- IO_135_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_135");
- IO_135_MonitoredItem.AttributeId = Attributes.Value;
- IO_135_MonitoredItem.DisplayName = "IO_135 Variable";
- IO_135_MonitoredItem.SamplingInterval = 1000;
- IO_135_MonitoredItem.Notification += OnMonitoredItemNotification;
- subscription.AddItem(IO_135_MonitoredItem);
-
- MonitoredItem IO_140_MonitoredItem = new MonitoredItem(subscription.DefaultItem);
- // Int32 Node - Objects\CTT\Scalar\Simulation\Int32
- IO_140_MonitoredItem.StartNodeId = new NodeId("ns=4;s=IO_140");
- IO_140_MonitoredItem.AttributeId = Attributes.Value;
- IO_140_MonitoredItem.DisplayName = "IO_140 Variable";
- IO_140_MonitoredItem.SamplingInterval = 1000;
- IO_140_MonitoredItem.Notification += OnMonitoredItemNotification;
- subscription.AddItem(IO_140_MonitoredItem);
-
- //MonitoredItem intMonitoredItem = new MonitoredItem(subscription.DefaultItem);
- //// Int32 Node - Objects\CTT\Scalar\Simulation\Int32
- //intMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_Int32");
- //intMonitoredItem.AttributeId = Attributes.Value;
- //intMonitoredItem.DisplayName = "Int32 Variable";
- //intMonitoredItem.SamplingInterval = 1000;
- //intMonitoredItem.Notification += OnMonitoredItemNotification;
-
- //subscription.AddItem(intMonitoredItem);
-
- //MonitoredItem floatMonitoredItem = new MonitoredItem(subscription.DefaultItem);
- //// Float Node - Objects\CTT\Scalar\Simulation\Float
- //floatMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_Float");
- //floatMonitoredItem.AttributeId = Attributes.Value;
- //floatMonitoredItem.DisplayName = "Float Variable";
- //floatMonitoredItem.SamplingInterval = 1000;
- //floatMonitoredItem.Notification += OnMonitoredItemNotification;
-
- //subscription.AddItem(floatMonitoredItem);
-
- //MonitoredItem stringMonitoredItem = new MonitoredItem(subscription.DefaultItem);
- //// String Node - Objects\CTT\Scalar\Simulation\String
- //stringMonitoredItem.StartNodeId = new NodeId("ns=2;s=Scalar_Simulation_String");
- //stringMonitoredItem.AttributeId = Attributes.Value;
- //stringMonitoredItem.DisplayName = "String Variable";
- //stringMonitoredItem.SamplingInterval = 1000;
- //stringMonitoredItem.Notification += OnMonitoredItemNotification;
-
- //subscription.AddItem(stringMonitoredItem);
-#endif
-
// Create the monitored items on Server side
subscription.ApplyChanges();
lgInfo($"MonitoredItems created for SubscriptionId = {subscription.Id}");
@@ -707,7 +632,7 @@ namespace IOB_WIN_NEXT
}
///
- /// Write a list of nodes to the Server
+ /// Write a list of nodes to the Server
///
///
public void WriteNodes(List node2Write)
@@ -846,32 +771,6 @@ namespace IOB_WIN_NEXT
qtyWriteVal.Value.Value = (int)hhmm + 10;
nodesToWrite.Add(qtyWriteVal);
-#if false
- //// Int32 Node - Objects\CTT\Scalar\Scalar_Static\Int32
- //WriteValue intWriteVal = new WriteValue();
- //intWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_Int32");
- //intWriteVal.AttributeId = Attributes.Value;
- //intWriteVal.Value = new DataValue();
- //intWriteVal.Value.Value = (int)100;
- //nodesToWrite.Add(intWriteVal);
-
- //// Float Node - Objects\CTT\Scalar\Scalar_Static\Float
- //WriteValue floatWriteVal = new WriteValue();
- //floatWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_Float");
- //floatWriteVal.AttributeId = Attributes.Value;
- //floatWriteVal.Value = new DataValue();
- //floatWriteVal.Value.Value = (float)100.5;
- //nodesToWrite.Add(floatWriteVal);
-
- //// String Node - Objects\CTT\Scalar\Scalar_Static\String
- //WriteValue stringWriteVal = new WriteValue();
- //stringWriteVal.NodeId = new NodeId("ns=2;s=Scalar_Static_String");
- //stringWriteVal.AttributeId = Attributes.Value;
- //stringWriteVal.Value = new DataValue();
- //stringWriteVal.Value.Value = "String Test";
- //nodesToWrite.Add(stringWriteVal);
-#endif
-
// Write the node attributes
StatusCodeCollection results = null;
DiagnosticInfoCollection diagnosticInfos;
@@ -907,6 +806,10 @@ namespace IOB_WIN_NEXT
protected static bool isLogVerbose = false;
protected static Logger lg;
+ protected int currNullReceiv = 0;
+ protected int maxErrors = 20;
+ protected int maxNullAllowed = 100;
+ protected int numErrors = 0;
#endregion Protected Fields
@@ -1002,12 +905,32 @@ namespace IOB_WIN_NEXT
// Log MonitoredItem Notification event
MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification;
- // sollevo evento notifica vaziazione MonitoredItem
- if (eh_MonItChange != null)
+ // verifico se ricevo null, superata soglia genero eccezione
+ if ($"{notification.Value}" == "(null)")
{
- eh_MonItChange(this, new opcUaMonitItemChange(monitoredItem, notification));
+ currNullReceiv++;
+ }
+ else
+ {
+ currNullReceiv--;
+ currNullReceiv = currNullReceiv > 0 ? currNullReceiv : 0;
+ // sollevo evento notifica vaziazione MonitoredItem
+ if (eh_MonItChange != null)
+ {
+ eh_MonItChange(this, new opcUaMonitItemChange(monitoredItem, notification));
+ }
}
lgTrace($"Notification Received | Variable: {monitoredItem.DisplayName} | Value: {notification.Value}");
+ // se ho ricevuto troppi nul --> disconnetto
+ if (currNullReceiv > maxNullAllowed)
+ {
+ if (eh_nullExceed != null)
+ {
+ eh_nullExceed(this, currNullReceiv);
+ }
+ // reset
+ currNullReceiv = 0;
+ }
}
catch (Exception ex)
{