Professional OPC
Development Tools

logos

Syntax of "SubscribeMultipleMonitoredItems" need overload with samplingInterval

More
24 Jan 2015 15:41 #2638 by support
Regarding the samplingInterval: If I take your example, you can simply add it as the last (fifth) argument to the constructor of EasyDAMonitoredItemArguments, like this (the sampling interval is 100 milliseconds in this example):
UANodeId nodeId = new UANodeId("http://serverDomain.it/UAServer/", "IMO2134567/NavigationalData/Course/Course");
object state = null;
int[] handleArray = DataHandlers.EasyUAClientInstance.SubscribeMultipleMonitoredItems(new[]
	{
		new EasyUAMonitoredItemArguments(
                    callBackMethodHandler, 
                    state, 
                    DataHandlers.MainUAEndpointDescriptor, 
                    nodeId,
                    100)
	});

This works, because effectively it is using this overload of the constructor:
public EasyUAMonitoredItemArguments(
            [CanBeNull] EasyUAMonitoredItemChangedEventHandler callback, 
            [CanBeNull] object state, 
            [NotNull] UAEndpointDescriptor endpointDescriptor,
            [NotNull] UANodeDescriptor nodeDescriptor, 
            [NotNull] UAMonitoringParameters monitoringParameters)
and there is an implicit conversion from an 'int' to UAMonitoringParameters. Of course you can also pass in "new UAMonitoringParameters(100)" and the result would be the same, or you can construct more complicated UAMonitoringParameters, with specifying data change filter, or queue size.

Note that you can also construct all of these objects differently: There is nothing that tells you that all values must be passed in as constructor arguments. You can create e.g. an empty EasyUAMonitoredItemArguments object, and then manipulate its properties individually. The resulting code will be longer, but perhaps more readable, because the property names would be clearly visible.
The following user(s) said Thank You: g.aino

Please Log in or Create an account to join the conversation.

More
23 Jan 2015 18:37 #2637 by support
A comment to your code: The try/catch around SubscribeMultipleMonitoredItems is unnecessary. This method (leaving aside async exceptions like OutOfMemory) will only throw an exception if you made a programming error, such passing it a null array or a null element in the array. Any other errors (such as unreachable OPC server, node Ids that do not exist in the server etc.) will be reported through the event notification.
The following user(s) said Thank You: g.aino

Please Log in or Create an account to join the conversation.

More
23 Jan 2015 18:31 #2636 by support
Regarding this part of your post:

Can you confirm that if the node inspected does not change is not generated the change event (I'm refering to "Heading_ItemChanged" in the following example)?

If I understand correctly, you are asking whether the event handler is only called when the underlying value changes. The answer to this is a "qualified Yes". We instruct the OPC server to send us notifications that are in accordance with the filter, and the default filter specifies that only when the value changes, the notification should be generated. We then process the notifications received from the OPC server, and ship them to you. Therefore you should not see notifications with the same value, but we ourselves do not explicitly "throw out" any duplicates: It is the server responsibility to correctly follow the instructions. Most servers I know about work well in this respect.

The answer to samplingInterval question will still be posted separately.
The following user(s) said Thank You: g.aino

Please Log in or Create an account to join the conversation.

More
23 Jan 2015 16:09 #2634 by support
Regarding the first part of the question: The constructor of EasyUAMonitoredItemArguments takes the last argument as UANodeDescriptor, and it works as it should. The reason why your first example does not work is because the UANodeDescriptor is probably not constructed as you expected or want: When you give it two strings, it will use the overload
public UANodeDescriptor([NotNull] UANodeId nodeId, [NotNull] UABrowsePath browsePath)
and, because there are implicit conversions, convert the first string to UANodeId (incomplete probably), and the second to a browse path (again, an incorrect one). If you have constructed a correct UANodeDescriptor, e.g. like below (but can also be done in many other ways), it should work:
new UANodeDescriptor("nsu=http://serverDomain.it/UAServer/;s=IMO2134567/NavigationalData/Course/Course")
In the second example (the one that works), in reality the argument that the EasyUAMonitoredItemArguments constructor receives is not a UANodeId. Because of implicit conversions, the UANodeId you create in the code gets (properly) converted to UANodeDescriptor, and that's what is used then.

I admit that it is sometimes difficult to figure out the conversions and overloads, but the reference documentation has them all.

Generally, the purpose of UANodeDescriptor is to describe which node your are interested in. It allows the nodes be specified using a node Id (UANodeId), using a browse path (UABrowsePath), or both. Therefore most our APIs accept a UANodeDescriptor on input, but it is possible to specify either UANodeId or UABrowsePath in place of it, and the implicit conversions will do the trick.

I will answer the other part of your question separately later.
The following user(s) said Thank You: g.aino

Please Log in or Create an account to join the conversation.

More
23 Jan 2015 15:48 - 23 Jan 2015 15:49 #2633 by g.aino
My application is a webservice client witch scope is only to read information from a Server via OPC UA architecture, my service is written in C# fwk 4.5 and use EasyUAClient Ver 5.3. Because the time to get information become critical now we need to change the approach an so I start to integrate our working service with the use of "subscription". I write this prelude because any suggestion beyond my specific question will be appreciate.

first, I had some problem to get the correct use how method "SubscribeMultipleMonitoredItems" because the last parameter is documented like "UANodeDescriptor" type but don't work I casually found that the type correct is "UANodeId".

this don't work:
UANodeDescriptor nodeDescriptor = new UANodeDescriptor("http://serverDomain.it/UAServer/", "IMO2134567/NavigationalData/Course/Course");
object state = null;
int[] handleArray = DataHandlers.EasyUAClientInstance.SubscribeMultipleMonitoredItems(new[]
	{
		new EasyUAMonitoredItemArguments(callBackMethodHandler, state, DataHandlers.MainUAEndpointDescriptor, nodeDescriptor)
	});
but this yes:
UANodeId nodeId = new UANodeId("http://serverDomain.it/UAServer/", "IMO2134567/NavigationalData/Course/Course");
object state = null;
int[] handleArray = DataHandlers.EasyUAClientInstance.SubscribeMultipleMonitoredItems(new[]
	{
		new EasyUAMonitoredItemArguments(callBackMethodHandler, state, DataHandlers.MainUAEndpointDescriptor, nodeId)
	});


Other question. We need to use a "samplingInterval" but I don't found the correct overload of "SubscribeMultipleMonitoredItems" that allow me to indicate: callBackMethodHandler, EndpointDescriptor, nodeId and in adding 'samplingInterval' that seems is not allowed to be passed.

Can you confirm that if the node inspected does not change is not generated the change event (I'm refering to "Heading_ItemChanged" in the following example)?
 
private static bool StartSubscribe(string strNodeIdIdentifier, EasyUAMonitoredItemChangedEventHandler callBackMethodHandler)
{
	bool ok = true;
 
	try
	{
		//--------------------------------- Parte che funziona !!! --------------------
		UANodeId nodeId = new UANodeId(DataHandlers.CommonNameSpaceURIString, strNodeIdIdentifier);
		object state = null;
		int[] handleArray = DataHandlers.EasyUAClientInstance.SubscribeMultipleMonitoredItems(new[]
			{
				new EasyUAMonitoredItemArguments(callBackMethodHandler, state, DataHandlers.MainUAEndpointDescriptor, nodeId)
			});
	}
	catch (Exception ex)
	{
		ok = false;
		m_logger.Error("StartSubscribe() NodeId='{0}', MethodHandler='{1}'\r\n'{2}'\r\n{3}\r\n",
					strNodeIdIdentifier, callBackMethodHandler, ex.Message, ex.StackTrace.ToString());
	}
 }
private static void Heading_ItemChanged(object sender, EasyUAMonitoredItemChangedEventArgs e)
{
	string itemValue = string.Empty;
	string fullInfoItemValue = string.Empty;
	DateTime lastUpdateUTC = DateTime.MinValue;
	string mappingKey = "#Heading";
	if (e.Exception != null)
	{
		m_dictKeySubscriptionState[mappingKey] = Enums.EnumSubscriptionState.Inactive;
		m_logger.Error("[{0}_ItemChanged] Error: '{1}'", mappingKey, e.ErrorMessage);
	}
	else
	{
		m_dictKeySubscriptionState[mappingKey] = Enums.EnumSubscriptionState.Active;                
		UAAttributeData item = e.AttributeData;
		fullInfoItemValue = e.AttributeData.ToString();
		itemValue = e.AttributeData.Value.ToString();
		lastUpdateUTC = e.AttributeData.SourceTimestamp;
 
		// ??? -> van inserite nel model
 
		m_dictKeyUpdateDate[mappingKey] = DateTime.UtcNow;
		m_logger.Debug("[{0}_ItemChanged] Updated value to '{1}'.", mappingKey, itemValue);
	}
}

thank you in advance
Last edit: 23 Jan 2015 15:49 by g.aino. Reason: revision

Please Log in or Create an account to join the conversation.

Moderators: support
Time to create page: 0.197 seconds

      

 Recommend this on Google