- Posts: 20
- Thank you received: 1
Online Forums
Technical support is provided through Support Forums below. Anybody can view them; you need to Register/Login to our site (see links in upper right corner) in order to Post questions. You do not have to be a licensed user of our product.
Please read Rules for forum posts before reporting your issue or asking a question. OPC Labs team is actively monitoring the forums, and replies as soon as possible. Various technical information can also be found in our Knowledge Base. For your convenience, we have also assembled a Frequently Asked Questions page.
Do not use the Contact page for technical issues.
- Forum
- Discussions
- QuickOPC-UA in .NET
- Reading, Writing, Subscriptions
- A way to subscribe multi-items node that may change (add, delete, update each one) and get the list of change
A way to subscribe multi-items node that may change (add, delete, update each one) and get the list of change
the Vendor of server side has assured us that this function is supplied.
Thinking about this problem I found another workaround, since we're in contact with the vendor we can try to ask him if it's possible to supply a special node with the update list of AIS items. In this case we can subscrive this node and intercept every new entry or items deleting simply comparing with previous state.
I hope this work fine otherwise is hard work to find other partner with suitable functionality\specs .
Thank you
Please Log in or Create an account to join the conversation.
OPC UA, in general, allows to subscribe to events arising from changes in server's address space. But that only works if 1) the UA server supports it, and 2) the UA client supports it.
Unfortunately, QuickOPC dos not support it. And, I am not sure whether your server does - you will need to check with the vendor.
The EasyAEClient is for OPC "Classic" specs, therefore if you have an OPC UA server, it won't help you; in addition, normally the OPC-A&E clients do not report their address space changes through this interface anyway, its purpose is different.
The only workaround to his would be to periodically call the "browse" methods on parts of the address space you want to monitor, compare the old and new nodes, and act upon the differences. Obviously this is quite inefficient compared to change-based reporting. Whether or not such inefficiency would be acceptable, depends on the concrete application at hand.
Best regards
Please Log in or Create an account to join the conversation.
I found a pobable way that consist to use the "EasyAEClient" class but, for me, not enough documented.
public static void Main()
{
using (var easyAEClient = new EasyAEClient())
{
var eventHandler = new EventHandler<EasyAENotificationEventArgs>(easyAEClient_Notification);
easyAEClient.Notification += eventHandler;
int handle = easyAEClient.SubscribeEvents("", "OPCLabs.KitEventServer.2", 1000);
Console.WriteLine("Processing event notifications for 1 minute...");
Thread.Sleep(60 * 1000);
easyAEClient.UnsubscribeEvents(handle);
}
}
// Notification event handler
static void easyAEClient_Notification([NotNull] object sender, [NotNull] EasyAENotificationEventArgs e)
{
if (e.Event != null)
Console.WriteLine(e.Event.Message);
}
what kind of information I can supply to the second parameter of SubscribeEvents() method?
To satisfy our needed to got informations without subscribe we use "EasyUAClient" that we initialize with the following code:
public static EasyUAClient EasyUAClientInstance = new EasyUAClient()
{
Isolated = true,
IsolatedParameters =
{
Session =
{
CertificateAcceptancePolicy = { AcceptAnyCertificate = true, AllowUserAcceptCertificate = false },
EndpointSelectionPolicy =
{
AllowedMessageSecurityModes = UAMessageSecurityModes.SecurityNone,
EnforceSameSite = true
},
UserIdentity =
{
// Valori di default sovrascritti dopo
UserNameTokenInfo = { UserName = "gst", Password = "pw" }
},
SelectBestEndpoint = true,
// Valori di default sovrascritti dopo
SessionConnectTimeout = 20000
},
}
};
/*
serverURLAddress = opc.tcp://test.domainServer.com
port = 4123
*/
private static bool InstanziateEasyUAClient(string serverURLAddress, int port,
int sessionConnectTimeout, int threadRefreshMillisec,
string userName, string password)
{
bool ok = false;
int millisectoHoldOPCUAConnection = threadRefreshMillisec;
try
{
#region Assegnazione Parametri da configurazione
EasyUAClientInstance.IsolatedParameters.Session.UserIdentity.UserNameTokenInfo
= new UserNameTokenInfo()
{
UserName = userName,
Password = password
};
// Segue parametro: Tempo entro il quale NON VERRA' FATTO LogOut e si manterrà la connessione (aumentato del 60%)
millisectoHoldOPCUAConnection = millisectoHoldOPCUAConnection + (int)Math.Ceiling(millisectoHoldOPCUAConnection * 0.6);
EasyUAClientInstance.IsolatedParameters.Session.HoldPeriod = millisectoHoldOPCUAConnection;
if (sessionConnectTimeout > 0)
{
EasyUAClientInstance.IsolatedParameters.Session.SessionTimeout = sessionConnectTimeout;
}
m_ServerURLEasyUAClient = string.Format("{0}:{1}", serverURLAddress, port);
#endregion
// Event Handler di tutto quel che accade nell'interazione col Server OPC UA
EasyUAClient.LogEntry += EasyUAClient_LogEntry;
ok = true;
}
catch (Exception ex)
{
ok = false;
m_logger.Error("InstanziateEasyUAClient() '{0}'\r\n" +
"Other info: serverURLAddress= '{1}', OPCUA SessionTimeOut = '{2}', OPCUA HoldPeriod = '{3}'\r\n{4}\r\n",
ex.Message, serverURLAddress + ":" + port, sessionConnectTimeout, millisectoHoldOPCUAConnection, ex.StackTrace);
}
return ok;
}
// using the EasyUAClientInstance:
UANodeId nodeId = new UANodeId(CommonNamespaceURIString, strNodeIdIdentifier);
// Where: CommonNamespaceURIString="http://domainServer.com/UAComServer/"
// strNodeIdIdentifier = "IMO1234567/Meteorology/Wind/Angle";
UANodeElementCollection nodeElementCollection = EasyUAClientInstance.BrowseDataNodes(MainUAEndpointDescriptor, nodeId);
// Where: MainUAEndpointDescriptor="opc.tcp://test.domainServer.com:4123"
UANodeElementCollection nodeElementCollection = EasyUAClientInstance.BrowseDataNodes(MainUAEndpointDescriptor, nodeId);
Summarizing:
1. EasyAEClient is the way for our goals?
2. What parameter pass to SubscribeEvents() method?
Wainting your kindly replies
Thank you
Please Log in or Create an account to join the conversation.
is there a way to intercept Addition \ Deleting nodes ? In other words can I set an events handler and a callback to any add or delete nodes from server side information tree? If so I can filter for 'AIS' nodes changing (node\items added) and build subscription on this, it's a way that I can follow?
Thank you in advance
Please Log in or Create an account to join the conversation.
Now we use subscrition for reading single value information but now the situation become more complex.
Actually we handle changing in subscribed information values by a the Event change handler like in the following code:
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.AddressSpace;
using OpcLabs.EasyOpc.UA.OperationModel;
//... etc
bool okSubscription = StartSubscribe(strNodeIdIdentifier, Heading_ItemChanged);
// ... etc
private static bool StartSubscribe(string strNodeIdIdentifier, EasyUAMonitoredItemChangedEventHandler callBackMethodHandler)
{
bool ok = true;
UANodeId nodeId = new UANodeId("http://urlAddress.com/UAComServer/", "IMO1234567/NavigationalData/AIS");
object state = null;
int[] handleArray = OPCUACore.EasyUAClientInstance.SubscribeMultipleMonitoredItems(new[]
{
new EasyUAMonitoredItemArguments(callBackMethodHandler,
state,
"opc.tcp:ServerUrlAddress.com:4321",
nodeId,
m_configParams.MillisecSampleInterval)
});
return ok;
}
// This is an Example of Event Handler for change
private static void Heading_ItemChanged(object sender, EasyUAMonitoredItemChangedEventArgs e)
{
// ...
try
{
if (e.Exception != null)
{
// An error to log
}
else
{
// some previous operation
UAAttributeData item = e.AttributeData;
fullInfoItemValue = e.AttributeData.ToString();
itemValue = e.AttributeData.Value.ToString();
lastUpdateUTC = e.AttributeData.SourceTimestamp;
if (!string.IsNullOrEmpty(itemValue)
&& Monitor.TryEnter(ShipData.Instance.nauticalInfo, new TimeSpan(0, 0, 2)))
{
try
{
ShipData.Instance.nauticalInfo.heading.SetValue(double.Parse(itemValue), m_configParams.SourceName, lastUpdateUTC);
}
catch (Exception ex)
{
// Error to log
}
finally
{
Monitor.Exit(ShipData.Instance.nauticalInfo);
}
}
}
}
catch (Exception ex)
{
// Error to log
}
}
But now (see the following image from UA Expert client)
we need to read information from a node ,'AIS', with an undefined number of items (named like "M999999999"). This items may change ie some of them may be deleted other may be added and some items may have an update. Each item, like you can see in the image, have many information that can be single value variables or objects variables.
Actually we have "easly" implemented all we need to read 'AIS' informations but without subscription but, like you can understand, with the subscription the situation is more complex.
Your software may support this type of need?
Here the steps that for me must be satisfied:
1. How we can intercept events like: add, delete, update of items under 'AIS' node;
2. After intercept the events type of previous step, is there a way to have a list of items added, deleted or updated (I'm referring to the items named like 'M999999999')?
3. For each item in the list of (for example) added can I get the "UANodeElementCollection" so I can reuse my query methods that we've already implemented before the subscription?
I've just browsed the C# sample code but I just found two example that not match our need. All your informations are very very appreciated!
Thank you in advance!
Please Log in or Create an account to join the conversation.
- Forum
- Discussions
- QuickOPC-UA in .NET
- Reading, Writing, Subscriptions
- A way to subscribe multi-items node that may change (add, delete, update each one) and get the list of change