opcua-asyncio icon indicating copy to clipboard operation
opcua-asyncio copied to clipboard

get_children may return duplicated nodes

Open sardware opened this issue 3 years ago • 4 comments

Hi all, Thank you for developing this library, I hope I can contribute to it in the future. I have been building a scraper, OPC UA client, since the last two weeks. I noticed that, by connecting to a machine, I get some of the children more than one time. These nodes have the same namespace and node type of their clones. I wonder if obtaining multiple clone children is a normal behavior, or if there is something wrong with the client, or it is something wrong with the server (I lack experience and I cannot figure out alone ^_^").

My solution node_list = set(await base_node.get_children())

Describe the bug
Calling get_children may return the same object multiple times.

To Reproduce

node_list = await base_node.get_children()
assert len(node_list) == len(set(node_list))

It triggers the assertion error on my machine

Expected behavior
I expect to scrape only different nodes.

Screenshots
Output of: print(node_list)
I put in bold the duplicated nodes. The duplicated nodes are fixed.

[Node(NodeId(Identifier='BaseObject.A', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>)),

Node(NodeId(Identifier='BaseObject.B', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>)),

Node(NodeId(Identifier='BaseObject.C', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>)),

Node(NodeId(Identifier='BaseObject.D', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>)),

Node(NodeId(Identifier='BaseObject.E', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>)),

Node(NodeId(Identifier='BaseObject.F', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>)),

Node(NodeId(Identifier='BaseObject.G', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>)),

Node(NodeId(Identifier='BaseObject.H', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>)),

Node(NodeId(Identifier='BaseObject.I', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>)),

Node(NodeId(Identifier='BaseObject.L', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>)),

Node(NodeId(Identifier='BaseObject.F', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>)),

Node(NodeId(Identifier='BaseObject.B', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>)),

Node(NodeId(Identifier='BaseObject.L', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>)),

Node(NodeId(Identifier='BaseObject.G', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>)),

Node(NodeId(Identifier='Extension', NamespaceIndex=6, NodeIdType=<NodeIdType.String: 3>)),

Node(NodeId(Identifier='HistoricalEventFilter', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>))]

The problem also affects the children of not duplicated nodes (e.g. BaseObject.A).

[Node(NodeId(Identifier='BaseObject.A.N', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>)), Node(NodeId(Identifier='BaseObject.A.M', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>)), Node(NodeId(Identifier='BaseObject.A.M', NamespaceIndex=5, NodeIdType=<NodeIdType.String: 3>))]

Version
Python-Version: 3.7.11
opcua-asyncio Version: master, 0.9.90 (installed by pip)

Thank you

sardware avatar Nov 04 '21 15:11 sardware

The Idea with set() would be a workaround.

Could you tell us how your base_node looks like? What references does base_node got?

swamper123 avatar Nov 04 '21 15:11 swamper123

Thank you for the prompt reply.

Yes, I know that it would be a workaround.

base_node is an instance of a subtype of BaseObjectType, which has 10 ObjectType components (plus other things). Every ObjectType is different, and I expect only 1 from each. In UA Expert I see only one of each.
I do not know if I answered fully your question.

sardware avatar Nov 04 '21 15:11 sardware

Anything is possible. In UA you can create links in all directions. Uaexpert probably does a filtering to remove duplicates. Get_children returns what the server returns so in that case the server returned duplicates

oroulet avatar Nov 04 '21 17:11 oroulet

Thank you for your answer. Probably I should filter out some kind of cross-reference between the components, I'll do some experiment on the next week and eventually share some insights.

sardware avatar Nov 05 '21 00:11 sardware