Avatar

Please consider registering
guest

sp_LogInOut Log In sp_Registration Register

Register | Lost password?
Advanced Search

— Forum Scope —




— Match —





— Forum Options —





Minimum search word length is 3 characters - maximum search word length is 84 characters

sp_Feed Topic RSS sp_TopicIcon
Get a Node (Variable) from KepWare KepServerEx
May 15, 2014
11:28, EEST
Avatar
oussamamz
New Member
Members
Forum Posts: 2
Member Since:
May 15, 2014
sp_UserOfflineSmall Offline

Hi,
I’m developping a Java Application that will extract some values from PLC, for that reason i’m using KepServerEx and Prosys SDK. I’ve read the Unified Architecture Book and tried to understund well the Code. I have made strategies to get one Node (Variable) : First approach, i tried to begin with a node with the nodeid= identifiers.rootFolder and then there are three Options that we have Types, objects and views, i used ReferenceDescription and after that it works for accessing Objects and getting _System, _server, Channel1 i want to browse also Channel1 Node and then Device1 (the same way) and the Tag Item that is located in the server but doesn’t work: Doesn’t print anything on a console. I guess because i can’t use ReferenceDescription for browsing it like a Node(RootFolder) and then getting other references. Otherway, i tried to access the tag directly, but it doesn’t work
Some Utils Informations:
– I did know the NodeId of one of the Tag : for Example : NodeId = ns=2;s=Channel1.Device1.Temperature
Please tell me if One of the Approach can lead me to a solution, or if i should try a different way. I know it’s so simple i think but i’m also new in Unified Architecture , and i work hard to achieve my goal
Best regards
Thank You

May 15, 2014
14:09, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 1032
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Did you try browsing with the SampleConsoleClient that comes with the SDK?, if the tag is configured correctly in KepServerEx, it should work and be visible. Can you see the tag using https://www.prosysopc.com/opc-ua-java-client.php or http://www.unified-automation……xpert.html (both are commonly used tools to view the address space of the server graphically)

If the tag is configured, its NodeId should be something like ns=2;ChannelName.DeviceName.TagName. In KEPServerEX configuration it should display Channels in left upper corner, devices under that and you can add tags on box on right if the device is selected.

May 15, 2014
15:17, EEST
Avatar
oussamamz
New Member
Members
Forum Posts: 2
Member Since:
May 15, 2014
sp_UserOfflineSmall Offline

Hi,
Thank you for answering. It works with KepServerEx with the line console, my aim is to put that in my application ( Protective Relay Simulation ), so i had problems concerning browsing and finding Values of Variables. At the moment i solved some problems and i’m trying a solution that i thought. If there isn’t a problem , we can keep in touch either here or at Gmail.

July 23, 2014
16:56, EEST
Avatar
OndrejBlazek
Member
Members
Forum Posts: 19
Member Since:
July 22, 2014
sp_UserOfflineSmall Offline

I am working on a UaSimpleClient which provides OPC DA like tag access to the address space without needing to concern yourself with NodeIds.

In a recent post, it was explained to me that while Kepware Server seems to use string NodeId which somewhat follow the tag convention, but other server may use integers, objects or arrays for NodeIds instead of the tag like strings.

For this purpose, my UaSimpleClient, upon connection, recursively runs through the address space of the server and creates a dictionary mapping between the Display Name hierarchy and node Ids. The UaSimpleClient then uses this dictionary to provide functions for reading and writing OPC tags using tag notation (as opposed to node Ids).

It is a work in progress since I only started today but I am already able to read any tag from the address space by using the corresponding tag (as opposed to node id). So far I am having a little trouble with writing because it keeps complaining about the data type not matching but I should be able to resolve that soon.

Currently subscriptions are not yet supported (next on the list) but you might want to have a look at my code if this is something that interests you.

Send me an e-mail (ondrej.blazek@ca.transport.bombardier.com) if you are interested.

July 24, 2014
6:19, EEST
Avatar
Otso Palonen
Espoo, Finland
Member
Members
Forum Posts: 32
Member Since:
December 21, 2011
sp_UserOfflineSmall Offline

Just a word of caution, the dictionary described by OndrejBlazek unfortunately doesn’t work with all servers (see http://forum.prosysopc.com/for…..deid/#p890 for a more thorough explanation), with the main issues being DisplayNames not being unique as well as the potentially huge number of Nodes on a server.

July 24, 2014
12:56, EEST
Avatar
OndrejBlazek
Member
Members
Forum Posts: 19
Member Since:
July 22, 2014
sp_UserOfflineSmall Offline

I would agree on the second part…if your OPC Server has a very large address space then the dictionary could get very large.

However, I would have to disagree on the first part. Yes, Display Name might not be unique but, as I said in my post, I am not using Display Name, I am using the Display Name hierarchy. This means, to build the “tag”, I am concatenating the Display Name of each level (as one would expect in an OPC DA style tag). For example, consider the following tiny name space:

Stations
– 01
– – Pumps
– – – 01
– – – – General Alarm
– – -02
– – – – General Alarm
– 02
– – Pumps
– – – 01
– – – – General Alarm
– – – 02
– – – – General Alarm

As we can see there are many nodes whose Display Name is not unique (e.g. “Pumps” show up under both the Stations.01 and Stations.02 branch. “01” shows up under the Stations branch as well as under each of the “Pumps” branches. And so on). However, when the SimpleUaClient recursively browses the address space to build the dictionary, it generates the unique tag name by concatenating all the parent levels. Thus, in the case, it would generate the following tags (with corresponding nodes) in the dictionary…

Stations.01.Pumps.01.General Alarm
Stations.01.Pumps.02.General Alarm
Stations.02.Pumps.01.General Alarm
Stations.02.Pumps.02.General Alarm

As can be seen, each of the resulting tags is unique and thus can be used in the dictionary to lookup the corresponding node. Nodes which don’t have attributes (i.e. are Object nodes corresponding to folders) are not included in the dictionary because, typically, one does not need to access these nodes when looking for the value of a specific tag (as opposed to traversing the nodes to get there).

I am thinking that for large address spaces, the SimpleUaClient could have an option where it traverses the nodes, on the fly, using the concatenated tag reference. Thus if the user supplied a tag like “Stations.01.Pumps.01.General Alarm”, the SimpleUaClient could start at the root and find the node whose Display Name is “Stations”. It would then advance to that node and look for the Display Name “01” (at that node). Advance to that node. Look for the node whose Display Name is “Pumps” and so on until it gets to the desired node. This would be slower, per tag access, since the address space would need to be traversed each time but would avoid having to store the entire address space in a dictionary.

July 24, 2014
13:29, EEST
Avatar
Otso Palonen
Espoo, Finland
Member
Members
Forum Posts: 32
Member Since:
December 21, 2011
sp_UserOfflineSmall Offline

Please note that you’re still assuming uniqueness of DisplayNames on the same hierarchy level. UA spec Part 3 defines DisplayName like this: “The DisplayName Attribute contains the localised name of the Node. Clients should use this Attribute if they want to display the name of the Node to the user.” So there is no guarantee that even on the same hierarchy level the DisplayNames are unique, since they’re simply the human-readable name of the Node. Uniqueness is guaranteed only for NodeIds.

The way you have described moving in the hierarchy based on DisplayNames is more appriopiate for using with BrowseNames, like I described in the other thread. BrowseNames are meant for resolving known type members and TranslateBrowsePathsToNodeIds is an optimized way of achieving just that instead of multiple Browses in a row. In any case, once the client has somehow resolved the NodeIds it needs, it can persist them in its configuration, so they won’t have to be searched for again.

While you’re of course free to choose the most appropiate strategy for your specific application, I’m simply trying to make the point that the way address spaces work in UA and DA are very different and applying DA logic to UA might not always work. It’s better to apply the UA way of thinking from the start to ensure full benefit from its rich information models.

July 24, 2014
15:24, EEST
Avatar
OndrejBlazek
Member
Members
Forum Posts: 19
Member Since:
July 22, 2014
sp_UserOfflineSmall Offline

With all due respect, I think sometimes programmers are looking too closely at the specifications and not the application. Yes, I am sure that the specification allows for Display Name to be repeated at the same level (hence the whole reason for having the nodes implementation) but it isn’t practical in real applications. I can’t speak for all servers but Kepware server won’t even allow it. If I create a Kepware server channel, then create a folder and then try to add more than one folder with the same folder name, Kepware will not allow it. Similarly when I try to add two signals with the same name, Kepware won’t allow it. Since it appears that these Kepware folder and signal names get stored as the Display Name in the address space, this means that, at least on a Kepware server, you can not have two Display Names with the same name at the same level.

Yes…yes…I am sure someone can find an OPC Server that allows it but why would you want to do it? Once again from a application point of view (not a specification point of view), you want your OPC tags to represent unique paths. If I have the address space:

Stations
– 01
– – Pump
– – – General Alarm
– – Pump
– – – General Alarm
– – Pump
– – – General Alarm
– 02
– – Pump
– – – General Alarm
– – Pump
– – – General Alarm
– – Pump
– – – General Alarm

While possibly acceptable by some OPC UA servers (but disallowed by Kepware Server), it would not make sense from a user point of view. If an operator saw the second pump General Alarm trip and she was relating it to the maintenance person, how would she related it? The second pump? Probably not since these results could be in the form of a Alarm Banner where the relation to the siblings might not be evident. This is why OPC tag are typically (yes, I am sure someone can find an exception) defined in such a way as to not use the same name at the same hierarchy level.

Now to address the other parts of your post. The Browse Names seem interesting. May Browse Name is what you would typically use (instead of Display Name) for navigation and I just assumed Display Name from the fact that the Kepware server places the folder/signal names in Display Names…but maybe is places the same names in Browse Names. I saw the TranslateBrowsePathsToNodeIds function but I didn’t immediately see how to use it. The only sample code that I have is the SimpleConsoleClient and while this shows how all the code comes together to create a client, it (in my opinion) isn’t the best learning tool. I actually found that the Client Tutorial documentation to be much more helpful in understanding the basics of the SDK. However, the client tutorial documentation did not cover TranslateBrowsePathsToNodeId. Is there some sample code I can get somewhere where I can see how to use this function. The javadoc describes the function but provides no examples.

With regards to the last statement, I can only partially agree. OPC UA and OPC DA are fundamentally different, under the hood, in the way that they are implemented but from a user point of view (barring things like a different style of connection endpoint) they are very much the same. When you configure folder and tags on an OPC Server the method is the same regardless if it is OPC DA or OPC UA. The end user still wants to use a human readable tag notation (typically based on the folders and signal names that are configured in the OPC server) which the OPC server interface needs to be able to accept and then change it into whatever notation it is using under the hood (in this case the node notation). I have yet to see (although I will not make the claim that it does not exist) an OPC Server where the user is expected to use some arbitrary node notation.

The functionality is very analogous to a PC hard drive. User use the file system to create folder and files using nice display names. All of the user references, to folder and files, are in terms of these nice display names but under the hood the file system takes the nice folder/file notation and converts it to some physical offset on the hard drive. The user never needs to know about these physical hard drive offsets but the file system does.

So it comes down to this…The OPC server will, most likely, be configure with a hierarchy of folders and (leaf) signals. The OPC sever on the other hand will store this configuration using the node implementation. Now if the user wants to write to the “Value” attribute of the (leaf) signal “WaterLevel” which is located in the folder “03” which is contained in the folder “Pumps” which is contained in the channel folder “Station01” (i.e. Stations01.Pumps.03.WaterLevel.Value) then what is the proper way, using the SDK, to locate the corresponding node? Can the TranslateBrowsePathToNodeId() function be passed a browse path such as “Stations01.Pumps.03.WaterLevel” to obtain the corresponding node?

Just my 2 cents.

July 25, 2014
7:06, EEST
Avatar
Otso Palonen
Espoo, Finland
Member
Members
Forum Posts: 32
Member Since:
December 21, 2011
sp_UserOfflineSmall Offline

If the dictionary works for your application and you’re targeting only KepServer, then it can be a viable strategy. The reason we look at specifications so closely is to ensure interoperability which is at the very heart of OPC UA, and we must ensure our SDK conforms to the specification and try to educate our customers to follow UA best practices.

Treating UA like DA works OK as long as you’re dealing with DA-like flat data. Assumptions like “Objects are typically folders” are plain wrong and will lead to trouble when you’re connecting to an OPC UA server with a rich address space with type information. NodeId’s haven’t been invented to annoy people, but to serve as an unique handle for the nodes. You’re right in that showing the NodeId’s to the user most often doesn’t make sense (especially if they’re numeric or GUIDs), in that sense they are like file handles. But they are the information that should be persisted in for example application configurations. Configurator UI’s can show the Address space to the user and type information used to make the configuring much less tedious, and handle NodeId’s in the background. As I understand at this point, testing the SDK, you’re working with flat DA-like data with only folders and variables and have only file-editing-based configuration for the application, and this is why UA seems tedious in this sense. Once you have a configurator UI for the system, it gets a lot easier and your users won’t have to see all the complexity.

You’re also right that OPC DA and OPC UA are very different under the hood. But also regarding application development, OPC DA lacks the type system and the complex address space of UA. While they are great tools to use, they also mean that some things (like this business regarding a Node’s NodeId/DisplayName/BrowseName) have to be a bit more complex.

I’m glad that you found the tutorial to be useful in learning about the SDK, unfortunately it doesn’t have anything on TranslateBrowsePathsToNodeIds (yet). TranslateBrowsePathsToNodeIds is not unique to our SDK, it’s one of the UA services and is meant to get NodeId’s if you know where in the hierarchy you want to start and which BrowseNames the Nodes have. Several paths can be resolved in one call to the server, making this very efficient. Note that since BrowseNames are not guaranteed to be unique, you can end up with several target Nodes. Here is a short example of using it in our SampleConsoleClient, so that it starts at Objects and finds MyLevel of MyDevice, in MyObjects.

try {
	int namespaceIndex = client
			.getAddressSpace()
			.getNamespaceTable()
			.getIndex(
					"http://www.prosysopc.com/OPCUA/SampleAddressSpace");
	BrowsePathTarget[] results = client
			.getAddressSpace()
			.translateBrowsePathToNodeId(
					Identifiers.ObjectsFolder,
					new RelativePathElement(
							Identifiers.HierarchicalReferences,
							false, true, new QualifiedName(namespaceIndex,
									"MyObjects")),
					new RelativePathElement(
							Identifiers.HierarchicalReferences,
							false, true, new QualifiedName(
									namespaceIndex, "MyDevice")),
					new RelativePathElement(
							Identifiers.HierarchicalReferences,
							false, true, new QualifiedName(
									namespaceIndex, "MyLevel")));
	// Assume a single target was returned
	ExpandedNodeId targetExpandedId = results[0].getTargetId();
	println("MyLevel has NodeId " + targetExpandedId.toString());
} catch (StatusException e1) {
	println("Error");
}
Forum Timezone: Europe/Helsinki

Most Users Ever Online: 1919

Currently Online:
20 Guest(s)

Currently Browsing this Page:
2 Guest(s)

Top Posters:

Heikki Tahvanainen: 402

hbrackel: 144

rocket science: 88

pramanj: 86

Francesco Zambon: 83

Ibrahim: 78

Sabari: 62

kapsl: 57

gjevremovic: 49

Xavier: 43

Member Stats:

Guest Posters: 0

Members: 730

Moderators: 7

Admins: 1

Forum Stats:

Groups: 3

Forums: 15

Topics: 1529

Posts: 6471

Newest Members:

rondawolinski7, Marypof5711, roycedelargie91, kourtneyquisenbe, ellis87832073466, zkxwilliemae, gabriellabachus, Deakin, KTP25Zof, Wojciech Kubala

Moderators: Jouni Aro: 1026, Pyry: 1, Petri: 0, Bjarne Boström: 1032, Jimmy Ni: 26, Matti Siponen: 349, Lusetti: 0

Administrators: admin: 1