Livetime / uniqueness of NodeId (How to manage NodeIds for dynamic nodes) - opc-ua

The Specification (Part 3: Address Space Model) of OPC UA says
5.2.2 NodeId
... A Server shall persist the NodeId of a Node, that is, it shall not
generate new NodeIds when rebooting.
but how can this be?
NodeId is a combination from a NamespceIndex and Identifier. NamespceIndex can be changed when the Server is restarting. see:
http://documentation.unified-automation.com/uasdkhp/1.0.0/html/_l2_ua_node_ids.html
For this reason, a Client should not persist the namespace index without storing the namespace URI as well, because a namespace URI represented by index “2” during one session could be represented by index “5” during the next session
Also the use of FolderType with e.g. "Files" as Items speak again this, or should the server store the NodeId it uses for File-X to assign it right again after restart?
What for is "GenericModelChangeEventType" if no NodeId can be created?
Client: I thought useing BrowsePath-Path (e.g. "Objects.Server.ServerStatus.CurrentTime" (* ) ) for addressing NodeIds and then using the NodeId while the clinet session to access the nodes is a good approach. Also because Companion Specifications defines the browsename so I might by save. Is this a good idea? ( *need attention on collisions caused by different namespaces)
Server: How should the Server behave when it needs to generate/create new NodeIds. Need the NodeIds to be unambiguous all the time or just for the Server runtime. I know some Servers are using NodeIds with String-Typed Identifiers and this String-Identifiers are made from the BrowsePath e.g. "ns=1;s=Server.ServerStatus.CurrentTime". But I don't like this...

What the OPC UA spec means when it says " A Server shall persist the NodeId of a Node, that is, it shall not generate new NodeIds when rebooting." is as follows: The NodeIds, when seen as a combination of namespace URI and identifier, must not change. The server may or may not reassign namespace indices after reboot - but the resulting namespaceURI/Identifier must not change. So, if on the first run I had a node with Identifier 1234 and namespace index 7, and that namespace index corresponded to "http://mynamespace.mycompany.com" in the namespace table, on the second run the same node may have Identifier 1234, but the namespace index 8, as long as in the new NamespaceTable index 8 now corresponds to "http://mynamespace.mycompany.com".

I think the Unified Automation SDK technically violates the spec in this regard. The recommendation it suggests is good practice for client implementations either way, but as you pointed out, shouldn't strictly be necessary.
Also the use of FolderType with e.g. "Files" as Items speak again this, or should the server store the NodeId it uses for File-X to assign it right again after restart?
I'm not sure what you're asking here.
What for is "GenericModelChangeEventType" if no NodeId can be created?
That's not what is being said here. Nodes can be created and deleted and the structure of objects and variables can change. All the spec is saying is that given Node "Foo" with NodeId "ns=1;s=Foo" it should have the same NodeId if the server reboots.
I thought useing BrowsePath-Path (e.g. "Objects.Server.ServerStatus.CurrentTime" (* ) ) for addressing NodeIds and then using the NodeId while the clinet session to access the nodes is a good approach.
Browse paths are for programming against types. The approach suggested by the Unified Automation SDK docs is the safe one for persisting NodeIds in your client.
How should the Server behave when it needs to generate/create new NodeIds. Need the NodeIds to be unambiguous all the time or just for the Server runtime. I know some Servers are using NodeIds with String-Typed Identifiers and this String-Identifiers are made from the BrowsePath e.g. "ns=1;s=Server.ServerStatus.CurrentTime". But I don't like this...
Create them however you like in the Namespaces you control, it's up to you. Using string-based NodeIds allows you to easily "derive" the NodeId from certain other sources, though, e.g. from the address of a variable in a PLC or something similar.

Related

How are OPC UA namespace used?

I'm very new to the OPC UA and would appreciate your help with stuff that seems to be basic but I can't grasp it in full.
I'm exploring a publicly available OPC UA server at opc.tcp://opcuaserver.com:48010.
Here's the tree of nodes it exposes:
I'm trying to figure out what's the logic behind assigning namespaces here.
Path
Node Id
Comment
Objects
i=85
(I understand ns=0 is the default one and is omitted)
Objects/Demo
ns=2;s=Demo
Objects/BuildingAutomation
ns=3;s=BuildingAutomation
Why is it in a different namespace while it's under same parent?
Objects/BuildingAutomation/ControllerConfigurations
ns=3;s=ControllerConfigurations
BuildingAutomation is not part of the prefix?
Objects/BuildingAutomation/AirConditioner_1
ns=3;s=AirConditioner_1
Why doesn't it have BuildingAutomation in the prefix?
Objects/BuildingAutomation/AirConditioner_1/Temperature
ns=3;s=AirConditioner_1.Temperature
Why does it have AirConditioner_1 in the prefix?
Is it that we see multiple trees (each having its own namespace) merged here? Where do these trees come from? How namespace is assigned?
What's the logic behind node IDs without prefixes (ex. ControllerConfigurations ) vs with prefixes (ex. AirConditioner_1.Temperature) (as both seem to be attributes?)
Here is a great explanation.
Each namespace is a different model (tree of data):
Namespace 0 is defined by the OPC Foundation and contains OPC Core nodes that you cannot modify.
Namespace 1 is specific to your server can contains server info like certificates and open connections.
Namespace 2 ... n is where your business objects are.

OPC UA TranslateBrowsePathsToNodeIds: How stable/volatile are resolved NodeIDs

there is a OPC UA service TranslateBrowsePathsToNodeIds.
How volatile or stable are the NodeIDs results returned by the service ---
Is it possible that NodeIDs resolved by the service alter while server runtime?
In our Case we are running our client against a server, which enumerates NodeIDs differently on every server restart. So we decide to resolve IDs by BrowsePath once after each (re)connect to the server. So far so good. But now there is a Problem when the server is restartet and after the first client reconnect no paths can't resolved.. it seems the server is not ready for the job (...).
I am wondering how often I have to update the resolved Node IDs (all or just the onces which was not resolved correctly?).
We are reading data by polling in this case.
I don't know your server, but it seems, you do address an OPC UA Server with a very dynamic behaviour, But I think, it's within the OPC UA spec.
It depends on the OPC UA objects, this server offers and what a client should or wants do with them.
Is it possible that NodeIDs resolved by the service alter while server runtime?
Yes!
Many servers do offer a static node set from the device configuration. In this case, the client will always get the same node ids from TranslateBrowsePathsToNodeIds, the client may use the node ids directly without translation (but has always to resolve the namespace index after connecting to the server). But obviously it's not your kind of server.
Another use case are dynamic objects, with a restricted lifetime, coming and going on any time they want to come an go. Imagine a warehouse in which goods are received and delivered. So a good will be representent with an individual OPC UA object instance, created on receive and removed on delivery. As long the good exists in the warehouse, you may browse to the object, translate its browse pathes to node ids and use them (reading, writing, monitoring). Of course, when the good delivers, the UA object will no longer be needed and could be removed by the server. The node ids removed now could be used later in an other context for another object instance.
Alternatively, the server could offer an interface to create or remove objects with a client.
The question is, how the server deals with the creation or removal of it's objects, how does it announce the changes? There should be a kind of configuration change event you want to monitor with your client. When your client receives an event, it may decide which actions to do, e.g. rebrowse the object and translate the browse pathes. Read the manual!
By the way: TranslateBrowsPathsToNodeIds is widly used to adress subnodes of object instances with a known object type. Once you know the node id for the entire object, you easily get the node ids for the subnodes with their browse pathes.

Retrieving a node solely based on its Tag

A customer has implemented an OPC-UA server and has provided some documentation for us to access it. The only information we have is the endpoint to contact the server at and the tags that the data points are linked to.
I have to implement a client without having access to the server to test it with. Is this enough information to go by? I imagine we would at least need some namespace uri. From what I understand, in order to use a function such as translateBrowsePathsToNodeIds I would also need to know some namespace ID's.
For instance, in python-opcua it would be something like:
mynode = client.uaclient.translate_browsepaths_to_nodeids(ua.QualifiedName("StaticData", 3)) (which somehow is not working but that's another question)
It doesn't help that the client examples I find somehow all use hardcoded namespace ID's.
TranslateBrowsePathToNodeIds is generally used when programming against type definitions where you know what the path of BrowseNames will be because they are defined by the type definition of each node in the path.
If this doesn't sound like your situation then you should push back for the documentation to include the NodeIds of all the Nodes you need to access.

OPC UA unique ID

I'm trying to build a OPC UA client application.
I'd like to be able to identify a UA node uniquely in the OPC tree.
I know that in OPC DA, a standard node id is a string with a '.' as a delimeter that I can use in order to identify a node.
In OPC UA, the node ID doesn't have to be a string, but I'd still like to be able to build a unique string that maps to a particular node.
I'm thinking about basing it on the the nodes names. e.g.: Demo.MyNode.MyValue.
but I'm afraid that the node name can contain characters such as "." and this will make my IDs not unique.
Is there a character I can use as a delimeter?
Is there a better way to represent the node ID as a string (including its path)?
OPC-UA offers the concept of a unique "BrowsePath" for each and every node, and a client could opt to store BrowsePaths instead of NodeIds, and then upon startup call the TranslateBrowsePathsToNodeIds service.
In fact, I believe this may be the intended behavior, as there's no requirement that a server use the same NodeId for any given Node after restarting, even if in practice that's how it's done.
I was wrong about NodeId being allowed to change. The spec says: "A Server shall persist the NodeId of a Node, that is, it shall not generate new NodeIds when rebooting."
I now believe its best to store NodeIds and only use BrowsePaths to aid in programming against type definitions.
One of the features of OPC UA is that the server can offer different menu trees to different users. It may not matter for your client, since any given user will only see the one tree, and the BrowsePath will be unique for that user.
In v1.03 of Part 3 of the OPC UA spec, "OPC UA Part 3 - Address Space Model 1.03 Specification.pdf", section 5.2.2 says a server should not change a node's NodeId when it reboots. (The spec is available from the OPC Foundation at https://opcfoundation.org. You can register and download it for free.)
Of course, some UA servers might not maintain their NodeIDs across a reboot. Which is another reason to use Kevin's suggestion to use the BrowsePath to make a unique string for each node. The string can make it clearer to the user which node they're accessing. Good idea!
The OPC Foundation announced their “OPC UA Open Shared Source” Strategy (04/14/2015).
The stack for .NET including lots of samples for DA, Historie... clients and servers can freely be downloaded here OPCFoundation/UA-.NET on GitHub.
Also Build OPC UA .NET applications using C#, VB.NET
You can take a look at the samples in the "SampleApplications" directory and see how they do things...

Neo4j merge statement with id

I'm trying to do a merge statement. I'm trying to get the node with his node id, the problem that merging doesn't allow me to use 'where id(node)=nodeId'.
Something like:
merge( user:User) where id(user)=111
on create set user =
{facebookId:"13",name:"",gender:"",pushId:"", picoAccessToken:"",
accessTokenExpires:""}
on match set user +=
{facebookId:"13",name:"",gender:"",pushId:"",picoAccessToken:"",
accessTokenExpires:""}
return user
General question, should I use the node id to retrieve nodes? or should I add an id property to the node.
You can't use the "ID()" function with MERGE because it behaves as "MATCH or CREATE" and you can't assign internal ids manually to nodes.
On the other hand, YES! it is better to use an id generation at the application level that you will assign to nodes OR use the GraphAware UUID plugin that will do it for you https://github.com/graphaware/neo4j-uuid/tree/master.
Relying on nodes internal ids is considered as bad practice as ids of deleted nodes are reused in the database lifecycle.
Michael Hunger from Neo Technology has already answered the question regarding internal ids here on StackOverflow.
The bottom line is that the node id should not be used, rather they should be considered an implementation detail.
So, the recommended approach is to use your own id property*. This can be a UUID, some kind of counter or whatever id that is suitable for your project.
Personally I like the UUID-approach. They are easy to generate from any language (e.g. the UUID-class in Java). The are unique and it is obvious that the are generated.