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
Using Model Changed Events Correctly and Readding Deleted Nodes
June 22, 2017
16:23, EEST
Avatar
pbeylin
Member
Members
Forum Posts: 4
Member Since:
June 22, 2017
sp_UserOfflineSmall Offline

Hello everyone,

We are using the SDK server and client. There is no custom node manager, so as far as I understand the following explanation, calling initNodeVersion() on the Objects folder should be enough to trigger ModelChangedEvents, that can be received on the client side.
https://forum.prosysopc.com/forum/opc-ua-java-sdk/nodeversion-property-for-addressspace-changes/

Unfortunately the NodeVersion counter of the Objects folder is not increased when nodes are added and deleted in the address space and no events are sent out, so we resorted to calling begin-, add- and end model changed event on the NodeManagerRoot within an OnAddNode Listener, which works. But this means, that technically these events are fired before the nodes are actually added or removed from the address space. Theoretically a listener might throw an exception during the onAddNode call to prevent the address space modification, but the event might have been fired already and thereby misinformed the clients.

Is there something we are missing or misusing at this point?

The following observation might be unrelated but the preceding question came as a direct result of the investigation of the issue, so here it goes … đŸ™‚

As we were using the ModelChangedEvents in the aforementioned way I was testing the use case of deleting and recreating nodes, which worked fine with one exception. When the recreated node had the exact same node id of the previously deleted node, the first observation was, that it seemed like the first WriteRequest for this node had no effect. Further debugging revealed, that shortly after the creation of the node a direct ReadRequest returns the last value of the deleted node. This seems to be the case independent of the client in use. Even a freshly connected UaExpert, which did not have a previous session with the server and thereby has no way of retaining any old instance in its local cache, shows the value of the previously deleted node.
Interestingly a single ReadRequest on any node (by any of the connected clients) in the same namespace as the recreated node resolves this state and every client receives the new (initial) value and status code of the recreated node. This also explains the first observation. The WriteRequest that is “lost” also leads to the resolution of that undesired state. It seems like reading or writing in the namespace triggers some sort of refresh.

Another possibly relevant observation is that during that state the UaNode that can be retrieved from the NodeManagerRoot (via getNode) returns the current new Node with the correct initial status and value, so this mechanism seems to be independent from whatever is going on, that causes the described scenario.
We have spent some time investigating the possible causes but so far we have found nothing that would really explain where this old status and value is coming from and what causes this “refresh” for all connected clients (simultaneously SDK and UaExpert).
Is there something we can do?

June 22, 2017
17:24, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 983
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Hi,

(I’ll answer shortly and continue next week if needed, as tomorrow is national holiday here)

Please read UA Specification (v 1.03) Part 5 section 12.16 (Table 157) on the ModelChangeStructureDataType. It explains the possible “verbs”.
For node add/delete: the node in question must have the nodeversion property, i.e. the node that was added or deleted).
For reference add/delete: the node for which references are added/removed must have the nodeversion property (i.e. the node must be target or source of the reference).

Therefore calling initNodeVersion on Objects folder only triggers events if references are added/removed from it directly. If you want NodeAdded, then the node in question which was added must itself have the initNodeVersion called before adding it to the address space (e.g. NodeManagerUaNode.addNode triggers it if the node to be added has the NodeVersion property). You still need to call NodeManagerRoot.begin/endModelChange in order for the event to be sent to the client (normally you send one event for multiple operations in case they are done at the same time).

As for the second question, the default NodeManager.getNode implentation keeps a cache to the last asked node as often it is needed multiple times in a row. Deleting and adding the same node back is not a very common scenario, however we should probably add logic to invalidate the cache if the given node is removed. Thanks for noticing this đŸ™‚

– Bjarne

June 23, 2017
17:24, EEST
Avatar
pbeylin
Member
Members
Forum Posts: 4
Member Since:
June 22, 2017
sp_UserOfflineSmall Offline

Thank you very much for the quick reply!

So if I understand you correctly, calling begin/endModelChange is necessary in any case for the event to be actually sent to the client; by using the NodeVersion property we merely automate the event creation and addition, is that correct? If this is the case, I am still unsure about the right place to call the begin/end methods. The aforementioned onAddNode listener seems unfitting because at this point there is no way to be certain, that the node actually makes it to the address space in the end. Is there a better way?

Cheers

Pawel

June 27, 2017
12:11, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 983
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Yes that is correct.

Hmm.. I might have been misunderstanding the scenario. Do you mean about adding nodes from the client side via the AddNodes service call? As that is what the NodeManagerListener.onAddNode handler is for. If this is the case, then to my knowledge combining the model change events with AddNodes service calls is never done before (both of these features are used seldom). I suppose in this case the SDK could maybe in the future automatically create and trigger the event completely as there is clear starting and end points (start of adding the nodes and end after all nodes in the request have been added). IF this was the case, let me know, as workaround by overriding few methods should fix the issue.

Assuming you are adding the nodes in the server side, just call begin before calling NodeManagerUaNode.addNode and end after you have added all nodes.

June 28, 2017
12:48, EEST
Avatar
pbeylin
Member
Members
Forum Posts: 4
Member Since:
June 22, 2017
sp_UserOfflineSmall Offline

The scenario is that there are multiple OPC UA clients and one of them is adding / deleting nodes. The other clients need to be notified about this. The workaround (with the overridden methods), that you mentioned implies that we will need to implement a custom nodemanager, or do you mean something else?

June 29, 2017
13:43, EEST
Avatar
Bjarne Boström
Moderator
Moderators
Forum Posts: 983
Member Since:
April 3, 2012
sp_UserOfflineSmall Offline

Ok, then I had the right feeling about this..

I see at least 2 workaround options:

1)
For NodeManagerUaNode the AddNodes call routes to the following method which you could override in a subclass:
protected NodeId addNode(ServiceContext serviceContext, NodeId nodeId, NodeId parentNodeId,
QualifiedName browseName, NodeClass nodeClass, ExpandedNodeId typeDefinitionId, NodeAttributes attributes,
NodeId referenceTypeId) throws StatusException

You would call begin for the model change, then call the super implementation via super.addNode(…) and then end after. Note that since this method is called once per node to add in the request, so you would get one event per node. Also note that as-is this wont work for NodeAdded events, as the NodeVersion property does not exist for the node at this point. However the NodeManagerListener.onAddNode is called before the node is added internally calling addNode, therefore you could maybe init it there. Note that the super call is probably best to be done in a try-finally block in order to ensure end is called for the model change.

The node to be added is created is done in
protected UaNode createNodeForAddNode(NodeId nodeId, QualifiedName browseName, NodeClass nodeClass,
ExpandedNodeId typeDefinitionId, LocalizedText displayName)
therefore that would be another option (that is called before the listener onAddNode is called.

Also mentioning this just in case.. currently the way the AddNodes service is implemented, it creates 1:1 nodes of the ones requested, however this is one area where I’m not sure on the specification i.e. if node would be added via AddNodes and the TypeDefinition of the node is complex, i.e. has subnodes that are modelled as ModellingRule Mandatory. Currently it is assumed that client adds all the requested nodes, but the method can also be overridden to use createInstance or createNodeBuilder of the NodeManagerUaNode if it is desired that adding a single node with complex typedefinition would create all the nodes of that type.

You would need to override each NodeManagerUaNode for which nodes are added from the client side in order for this to work.

2)
There might be maybe easier way, assuming the ReferenceAdded/Deleted events are enough, however it would be a bit experimental as we don’t usually instruct to override these..

Create subclass of NodeManagementServiceHandler, with a constructor that passes values to the super constructor. Override
protected void addNodes(ServiceContext serviceContext, AddNodesRequest request, AddNodesResponse response)
throws ServiceException
similarly as in 1) with calling begin for model changes, then calling the super implemtation of the method and after that end. And like in 1), probably best to do in a try-finally block to ensure the end is called. Then create a subclass of UaServer, override:
protected NodeManagementServiceHandler createNodeManagementServiceHandler()
with creating the subclass of the NodeManagementServiceHandler done above (pass the sessionManager and nodeManagerTable protected fields as parameter). The events should then work and you should receive one event per AddNodes service call.

Sorry for the long post, please let me know if either did work. Probably we end up implementing something like 2) for the SDK in the future (directly to the existing class).

Also I suppose there is always option 3) IF your add operations are simple e.g. one kind of nodes to one place or something like that, you could also just create an Ua Method, and in the implementation of the method create the nodes (and call begin/end), and e.g. one Variable that would contain e.g. configuration timestamp which would be incremented and other clients would the rebrowse the address space as needed if they notice that the configuration timestamp has changed. Just mentioning this as an idea, as it probably is easier to implement anyway for both sides.

– Bjarne

August 23, 2017
13:12, EEST
Avatar
pbeylin
Member
Members
Forum Posts: 4
Member Since:
June 22, 2017
sp_UserOfflineSmall Offline

Sorry for the late update, but the project required our attention elsewhere đŸ™‚

We have now overidden the UaServer and the NodeManagerUaNode. In the UaServer we used the createNewNodeManager() method to instantiate our overridden NodeManagerUaNode which in turn has overridden addNode and deleteNode methods, that send the ModelChangedEvents after the operation has been actually completed.

So far this looks like a suitable solution. Thank you for your quick and helpful responses!

Pawel

Forum Timezone: Europe/Helsinki

Most Users Ever Online: 518

Currently Online:
19 Guest(s)

Currently Browsing this Page:
1 Guest(s)

Top Posters:

hbrackel: 135

pramanj: 86

Francesco Zambon: 81

rocket science: 77

Ibrahim: 76

Sabari: 62

kapsl: 57

gjevremovic: 49

Xavier: 43

TimK: 41

Member Stats:

Guest Posters: 0

Members: 682

Moderators: 16

Admins: 1

Forum Stats:

Groups: 3

Forums: 15

Topics: 1467

Posts: 6261

Newest Members:

karrimacvitie5, graciela2073, sagarchau, elviralangwell4, Donnavek, Eddiefauth, DonaldPooma, fidelduke938316, Jan-Pfizer, DavidROunc

Moderators: Jouni Aro: 1010, Otso Palonen: 32, Tuomas Hiltunen: 5, Pyry: 1, Petri: 0, Bjarne Boström: 983, Heikki Tahvanainen: 402, Jukka Asikainen: 1, moldzh08: 0, Jimmy Ni: 26, Teppo Uimonen: 21, Markus Johansson: 42, Niklas Nurminen: 0, Matti Siponen: 321, Lusetti: 0, Ari-Pekka Soikkeli: 5

Administrators: admin: 1