open62541 / open62541-nodeset-loader

Library for loading opc ua nodesets from xml and sorting the nodes
Mozilla Public License 2.0
26 stars 23 forks source link

Problem adding UA_VARIABLE nodes of abstract type. #262

Open xydan83 opened 1 month ago

xydan83 commented 1 month ago

Hi! Sometimes (in practice) situations occur when some OPC UA servers contain variable nodes of abstract types. For example, these nodes have a HasTypeDefinition reference type for nodeId i=2372. <Reference ReferenceType="HasTypeDefinition">i=2372</Reference> But in the open62541 library you can add nodes of this type only if you apply some rules: image

image

We can use it and import that nodeset with this xml. For example:

...
    <UAObject NodeId="ns=2;s=Some.Node" BrowseName="2:Some.Node" ParentNodeId="i=85">
        <DisplayName>Some.Node</DisplayName>
        <References>
            <Reference ReferenceType="Organizes" IsForward="false">i=85</Reference>
            <Reference ReferenceType="HasComponent" IsForward="false">i=63</Reference>
            <Reference ReferenceType="HasComponent" IsForward="false">i=58</Reference>
            <Reference ReferenceType="HasTypeDefinition">i=61</Reference>
        </References>
    </UAObject>
    <UAVariable NodeId="ns=2;s=abstract.node" BrowseName="2:abstract.node" ParentNodeId="ns=2;s=Some.Node" DataType="Boolean"">
        <DisplayName>abstract.node</DisplayName>
        <References>
            <Reference ReferenceType="Organizes" IsForward="false">ns=2;s=Some.Node</Reference>
            <Reference ReferenceType="HasTypeDefinition">i=2372</Reference>
        </References>
    </UAVariable>  
...

All we need is to add two references to the parent node (ns=2;s=Some.Node):

            <Reference ReferenceType="HasComponent" IsForward="false">i=63</Reference>
            <Reference ReferenceType="HasComponent" IsForward="false">i=58</Reference>

And we can add it to the node space.

If I try to add it using Python's nodeset_compiler - everything is fine. But if I try to add xml using nodesetloader - I can’t do this, because processing of additional references occurs after adding all the nodes, but without these references - the library will not be able to add such nodes and will throw an error.

image

But I found a quick solution using the "second chance algorithm". We can add a cycle of adding additional references before the "second chance algorithm", if unadded nodes are found, after cycle then this algorithm will add problematic nodes, and after that the cycle of adding additional references "addNonHierachicalRefs" will run again and it will add references to those already nodes that were added after the "second chance algorithm" was worked out.

In code it looks like this: image

I tried this and it works. Perhaps there is another way...

What do you think of this solution?