12:21, EEST
June 21, 2021
Hello,
I have two applications, one is an opc ua client and the other an opc ua server. Both use the same information model.
In this information model, I have a Machine type. I create the machine information in the client application. My wish is to use the opc ua client to connect and update the corresponding machine node in the opc ua server.
Is there any way to do this with the SDK?
Thanks
15:23, EEST
December 21, 2011
Well, yes there should be a way, although I didn’t quite understand what you expect to happen.
You can use the information model to generate code for both client and server side development. This will help you working with complete Java objects that represent the Machines.
But, there is no automatic way to create a new Machine object in the client and make it appear in the server. Or if you change the attributes of the client side object, they are not automatically copied to the server.
You will need to use the UaCliient.write (writeAttributes, etc) to modify attribute values to the server objects. And if you wish to add or remove objects, you need to
#1 enable node management
#2 call addNode/addNodes or deleteNode/deleteNodes from the client to add the objects to the server, one node at a time.
Does this answer your question?
18:13, EEST
December 21, 2011
The IOManager is responsible of responding to read and write requests. If you use the NodeManagerUaNode, it uses the default IoManagerUaNode that copies values directly to the nodes.
So, only if you have a custom NodeManager, should you need a custom IoManagaer as well.
You can still plug an IoManagerListener to the default IoManager to validate client requests, if you need to do so.
16:01, EEST
December 21, 2011
OK, you can test it like this.
Add the following Action to the SampleConsoleServer (beginning of the class), if you don’t have a server that supports NodeManagement yet:
@Override
ActionResult performAction(SampleConsoleServer s) {
boolean value = !s.getServer().getAddressSpace().getNodeManagementEnabled();
s.getServer().getAddressSpace().setNodeManagementEnabled(value);
println("NodeManagement " + (value ? "enabled" : "disabled"));
return ActionResult.NOTHING;
}
},
This adds a toggle ‘N’ that you can use to enable Node Management in the server.
then you can add the following method to SampleConsoleClient – or your own client without the ‘println’ and ‘prompt’ calls:
println("Adding a new node to the current node");
println("Name:");
String name = readInput(false);
NodeId typeDefinitionId = Identifiers.BaseObjectType;
NodeId referenceTypeId = Identifiers.HasComponent;
int ns = parentNodeId.getNamespaceIndex();
NodeId newNodeId = new NodeId(ns, parentNodeId.getValue().toString() + "/" + name);
QualifiedName browseName = new QualifiedName(ns, name);
LocalizedText displayName = new LocalizedText(name);
UnsignedInteger attributesMask = NodeAttributesMask.getMask(NodeAttributesMask.DisplayName);
ObjectAttributes nodeAttributes = new ObjectAttributes(attributesMask, displayName, null, null, null, null);
client.getAddressSpace().addNode(parentNodeId, referenceTypeId, newNodeId, browseName, NodeClass.Object,
nodeAttributes, typeDefinitionId);
}
‘prompt’ is actually a new method as well
This adds just a node of BaseObjectType to the server, but you can modify it to your needs.
Note that even when you have enabled Node Management, the server requires that you connect with a non-Anonymous UserIdentity. SampleConsoleClient takes the username (-u) and password (-p) from the command line, for example.
Also, you cannot add nodes to nodes that are in the standard Namespace, so you have to browse to MyObjects, for example, before it works.
So, this should help you to get started.
17:23, EEST
June 21, 2021
Thank you for your help.
Now, using the sample code you post, i can add new node of BaseObjectType on my server from client.
So have another question, to create a node with my custom type MachineType, how can i do that ?
In my client a have generated the informaion model and i have MachineType and MachineTypeImpl
Thanks you in advance
11:31, EEST
April 3, 2012
Hi,
Based on the above my assumption is that you are also using our SDK in the server side.
Assuming the information model is loaded in the server side, you basically change the typeDefinitionId in the code above to be the MachineType TypeDefinition node (the in the Types part, I’m assuming it is an ObjectType node).
Assuming NodeManagerUaNode is the manager handling the namespace on the server side, it will do the same thing as a (NodeManagerUaNode).createInstance(…) call would (see SampleConsoleServer + MyNodeManager for creating e.g. the alarm node), i.e. create all Mandatory nodes below that type. Any Optionals you would need to create yourself however, unless configured in the manager (basically the server would have then to be made to expect AddNodes to be done like this, see also the alarm creation in the MyNodeManager sample)
However, also note that this doesn’t “automatically” persist these changes in the server, unless the server reacts to it i.e. on a restart it would lose the changes.
You can note the AddNodes happening via a NodeManagerListener.onAddNode (or onAfterAddNode). The logic of making the node happens in ‘protected UaNode createNodeForAddNodesRequest(NodeId nodeId, QualifiedName browseName, NodeClass nodeClass, ExpandedNodeId typeDefinitionId, LocalizedText displayName)’, which can be overridden if needed. There is ‘createNodeForNodeSet2’ also when the nodes are loaded from a NodeSet2 file. Do note the difference is that when loading a NodeSet, it must contain all the nodes, but when the client calls AddNodes, the server shall make all Mandatory nodes below the type given (BaseObjectType has none, thus only that node was created). And also this behaviour was clarified at some point in the spec, i.e. some older servers might incorrectly just do the “top-lvl” node in types.
IF the server doesn’t even have the TypeDefinition, you can create that node-by-node via AddNodes (NodeClasses ObjectType+VariableType and for the structure other ones as well), and then use the NodeId of the Type later (the instantiation doesn’t need Codegen, just for the types to exist, and in the presense of Codegen classes those more-specific-uanode implementations would be used).
P.S. IMPORTANT
Also consider adding user validation via the NodeManagerListener to all NodeManagers, as otherwise any client that can make sessions on the server can e.g. delete the ‘Server’ node. Thus you should check that and throw a StatusException if the operation is not allowed (this is why the nodemanagement is by default disabled). If you trust and know all clients then this might not be needed.
16:29, EEST
April 3, 2012
Put the NodeId of the MachineType “type node” there. This is assuming my assumption was correct that the information model is loaded on the server side. If not you would need to load them first to the server.
Anyway, assuming the model is loaded in the Server, look with a graphical client such as our https://www.prosysopc.com/products/opc-ua-browser/ in the Types part of the server.
Alternatively, since you have generated the model in the client side, there is a XXXIds class, where XXX is the “prefix” in the configuration when generating. If no prefix was used the class is just ‘Ids’. IMPORTANT, the SDK already also includes an ‘Ids’ class internally, for the base namespace, thus be careful which class you import if this is the case (the prefix is preferred).
And technically com.prosysopc.ua.AnnotationUtils.readTypeDefinitionId(MachineType.class) would also give it, though the Ids-way would be the expected way instead of this.
Also for the first approach, we would recommend storing the NodeId as an ExpandedNodeId with the NamespaceUri instead of the NamespaceIndex (the number X in the NodeId ns=X;…) (the index points to Objects/Server/NamespaceArray the string at that index in the value is the NamespaceUri of that namespace), and then transforming it to NodeId in the context of (UaClient)client.getNamespaceTable(). This is also what you would do with the Ids output (since the generator cannot know which index it would be they are ExpandedNodeIds with the uri).
12:39, EEST
June 21, 2021
Hi,
Thanks, these explanations help me to create a MachineType node in my server.
To write values from my client, i used uaClient.writeValues(nodeIds, values).
Now I want to insert in database with my server application, the information of the written node.
I want this insertion in the database to happen only when the writing of the node opc ua has been successful.
My question is there a way to know that the writing of the node has been successful? Can I manage this behavior with an IOManagerListner?
16:16, EEST
April 3, 2012
Well, in general I would say you would want to do it the other way around: only set the value to the node once you have successfully written it to the DB. Otherwise the client would see the value, but if e.g. the server machine crashed just there before it was written to the DB on a restart that value would be lost. If done database-first it would not be.
Basically at the point when the IoManagerListener onXXX are being called, the accesslevel and datatype have been checked, so basically unless you prevent it in the listener it will be successful. Thus you could write it to the DB within the listener method.
Most Users Ever Online: 1919
Currently Online:
21 Guest(s)
Currently Browsing this Page:
1 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: 735
Moderators: 7
Admins: 1
Forum Stats:
Groups: 3
Forums: 15
Topics: 1523
Posts: 6449
Newest Members:
rust, christamcdowall, redaahern07571, nigelbdhmp, travistimmons, AnnelCib, dalenegettinger, howardkennerley, Thomassnism, biancacraft16Moderators: Jouni Aro: 1026, Pyry: 1, Petri: 0, Bjarne Boström: 1026, Jimmy Ni: 26, Matti Siponen: 346, Lusetti: 0
Administrators: admin: 1