Gestione null read con errori e disconnessione

This commit is contained in:
Samuele Locatelli
2023-11-30 19:27:55 +01:00
parent 7b3a73f5b9
commit 9dfe40cefa
3 changed files with 67 additions and 123 deletions
+5
View File
@@ -632,6 +632,11 @@ namespace IOB_UT_NEXT
/// </summary>
public bool UseFullId { get; set; } = false;
/// <summary>
/// Numero massimo di letture null prima di disconnettere il client
/// </summary>
public int maxNullRead { get; set; } = 1000;
/// <summary>
/// Base del NameSpace usato per le funzionalità di translate (parametri ACT --> SET)
/// </summary>
+19 -3
View File
@@ -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;
}
/// <summary>
/// Ricevuto troppi null --> disconnetto e traccio
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <exception cref="NotImplementedException"></exception>
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;
}
/// <summary>
/// Formatta un dataitem x salvataggio in memoria locale
/// </summary>
+43 -120
View File
@@ -72,8 +72,17 @@ namespace IOB_WIN_NEXT
/// <summary>
/// Initializes a new instance of the UAClient class.
/// </summary>
public UAClient(ApplicationConfiguration configuration, string codIOB, string user, string pwd, bool verboseLog, Action<IList, IList> validateResponse)
/// <param name="configuration"></param>
/// <param name="codIOB"></param>
/// <param name="user"></param>
/// <param name="pwd"></param>
/// <param name="verboseLog"></param>
/// <param name="validateResponse"></param>
/// <param name="maxNullRead">Numero massimo di risposte nulle in browsing prima di disconnettersi</param>
public UAClient(ApplicationConfiguration configuration, string codIOB, string user, string pwd, bool verboseLog, Action<IList, IList> validateResponse, int maxNullRead)
{
currNullReceiv = 0;
maxNullAllowed = maxNullRead;
m_validateResponse = validateResponse;
currIob = codIOB;
lg = LogManager.GetCurrentClassLogger();
@@ -99,6 +108,11 @@ namespace IOB_WIN_NEXT
/// </summary>
public event EventHandler<opcUaMonitItemChange> eh_MonItChange;
/// <summary>
/// Evento notifica superamento numero letture null
/// </summary>
public event EventHandler<int> 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;
/// <summary>
/// Read a SINGLE of nodes value (RAW) from Server
/// </summary>
@@ -507,8 +511,6 @@ namespace IOB_WIN_NEXT
return answ;
}
protected int numErrors = 0;
/// <summary>
/// Read a list of nodes from Server
/// </summary>
@@ -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
}
/// <summary>
/// Write a list of nodes to the Server
/// Write a list of nodes to the Server
/// </summary>
/// <param name="node2Write"></param>
public void WriteNodes(List<WriteValue> 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)
{