OPCFoundation / UA-.NETStandard

OPC Unified Architecture .NET Standard
Other
1.96k stars 946 forks source link

Definitive solution for implementing/using custom types from nodeset2 files #676

Closed Ckath closed 5 years ago

Ckath commented 5 years ago

Here's the issue, I'm working with EUROMAP nodesets, they only supply nodeset2.xml, xsd and csv files, non of which are usable with the modelcompiler. Getting these imported seems to work just fine creating nodemanagers based on https://github.com/OPCFoundation/UA-.NETStandard/issues/546#issuecomment-425331836.

However implementing the custom datatypes seems to be a different issue, And multiple old issues come down to using the modelcompiler instead, which I cant use with the files I have. The code mentioned in https://github.com/OPCFoundation/UA-.NETStandard/issues/364#issuecomment-367349598 doesn't seem to add more functionality than the 'ImportXml' function from before either.

To make the issue more specific, what I have done is worked from the Reference Quickstart server in the hope I could create instances of the loaded in types with its ReferenceNodeManager. But they dont seem to be compatible and I don't understand where/if I can interface with my nodes and types added through AddPredefinedNodes out of the nodeset2 xml files.

I just need an instance of the datatype thats already in the ObjectTypes->BaseObjectType: image

to be added under the DeviceSet that was added automatically from importing the DI nodeset2 xml: image And possibly add some extra fields under the ExtrusionDeviceType structure.

Pretty new to this SDK and OPC UA in general so any possible solution suggestions would be nice.

MD-V commented 5 years ago

Hello @Ckath, I don't think there a definitive solution for this problem. I have found 2 approaches:

  1. Copy the complete NodeState and assign new NodeIds and references. An example of this method (not perfect). Can be found in the Softing OPC UA Toolkit Examples (Softing). Look for the method CreateInstanceFromType in the NodeSetImportNodeManager class.

  2. Try to build a ModelDesign file by reversing the NodeSet2.xml and run it through the C# ModelCompiler. (Error prone and costly for complicated object and data types)

Ckath commented 5 years ago

Thank you for the information @MD-V. The EUROMAP nodesets are quite complex, so I will try my luck with how far I can get using methods from Softing.

EDIT: which is what I thought, until I noticed the only trial offered is fully binary

MD-V commented 5 years ago

@Ckath the samples are also included in the binary version. Have a look in C:\ProgramData\Softing\OpcUaNetToolkit\V1.46\src\Samples\Server\Advanced\NodeSetImportServer

Ckath commented 5 years ago

Aha I see it now, thanks once again.

Ckath commented 5 years ago

Since importing nodes from XML seemed to work really well, I had hopes this would also work similarly well, however the node doesn't seem to be interpreted correctly. If anything I'm starting to doubt how it does work from xml as the node structures look exactly the same.

My current approach is as follows:

this leaves me with a very sorry excuse for a node on the addressspace: image

Debugging this for a while I'm somewhat lost what to blame at this point, CreateInstanceFromType seems to copy whatever information is in the typeDefinition node correctly, although it seems odd it doesn't have children even though it displays like that in the addressspace. This leads me to believe I'm either not getting the correct references to the nodes or I need to do more to initialize the new instance to be recognized as the correct datatype.

If anyone has an idea where to go from here I'd love to hear about it.

Ckath commented 5 years ago

Second day into this, I seem to have found a workable solution. As there are multiple issues regarding the importing of nodeset2 files and creation of types, I will try to explain my solution as clearly as possible. The main issue I was running into was incorrectly assigning nodeids, make sure nodeids are set on all nodes including references

What I did to get a working type from the nodeset2 files:

Though probably slightly convoluted, the following works out for my case:

// import nodesets required for EUROMAP
ImportXml(externalReferences, "./nodesets/Opc.Ua.Di.NodeSet2.xml");
ImportXml(externalReferences, "./nodesets/Opc_Ua.EUROMAP83.1_00_ext84_1_RC1_00_1.NodeSet2.xml");
ImportXml(externalReferences, "./nodesets/Opc_Ua.EUROMAP84_1.RC1_00_1.NodeSet2.xml");
ImportXml(externalReferences, "./nodesets/Opc_Ua.EUROMAP84_2.RC1_00_1.NodeSet2.xml");
ImportXml(externalReferences, "./nodesets/Opc_Ua.EUROMAP84_3.RC1_00_1.NodeSet2.xml");
ImportXml(externalReferences, "./nodesets/Opc_Ua.EUROMAP84_4.RC1_00_1.NodeSet2.xml");
ImportXml(externalReferences, "./nodesets/Opc_Ua.EUROMAP84_5.RC1_00_1.NodeSet2.xml");
ImportXml(externalReferences, "./nodesets/Opc_Ua.EUROMAP84_6.RC1_00_1.NodeSet2.xml");
ImportXml(externalReferences, "./nodesets/Opc_Ua.EUROMAP84_7.RC1_00_1.NodeSet2.xml");

// find required nodes
NodeState DeviceSet = null;
NodeState ExtruderType = null;
foreach (NodeState node in PredefinedNodes.Values)
{
    if (node.BrowseName.Name == "DeviceSet")
    {
        DeviceSet = node;
    }
    else if (node.BrowseName.Name == "Extruder_InterfaceType")
    {
        ExtruderType = node;
    }
    if (DeviceSet != null && ExtruderType != null) break;
}

// create the extrusion device
var line0 = CreateInstanceFromType(ExtruderType, "Extruder_1", 5, ExtruderType.NodeId);
line0.NodeId = new NodeId(Utils.IncrementIdentifier(ref m_lastUsedId), NamespaceIndex);
DeviceSet.AddChild(line0);
AddPredefinedNode(SystemContext, line0);

// ensure the reverse references exist.
AddReverseReferences(externalReferences);

and the result: image

Ofcourse this could be cleaned up, correctly assign a nodeid within the specified namespace from the functions, strip unused functionality from the softing implementations etc. but I just wanted to let people know it is possible to make instances of custom types from only a nodeset2.xml file. which is great since all these standards mostly only seem to provide them, and nearly all other opc ua servers fail to provide this functionality.

Thanks again @MD-V for the pointer in the right direction. for now this solution will do for what I have to implement, on that note I will mark this issue as solved.

rudoq32 commented 5 years ago

Hello all, just to not duplicate same topic. I am trying to create my OPCMES.Nodeset2.xml by using OPC Foundation ModelCompiler. In my OPCMES namespace I'd like to use object types defined in ISA95 model. So it is not possible to "include" Opc.ISA95.NodeSet2.xml into my ModelDesign.XML and run ModelCompiler?

MD-V commented 5 years ago

@rudoq32 Theres a possiblity. However I don't know how good this works. There is a project called OPC-UA-OOI that includes a tool called asp (its included in the latest release)

You can call the tool like this: asp "ISA-95\Opc.ISA95.NodeSet2.xml" -e "ISA-95\ModelDesign.xml" -s XMLstylesheet

This will produce a ModelDesign file for ISA-95.

rudoq32 commented 5 years ago

Thanks, I will try that. I already heard about it. The thing what is for me strange is, that in my understanding consists Information Models are key stone of the OPC UA interoperability. So by using reverse engineering external tools, to be able to use Information Model, this consistency could be broken. Or it is on purpose, that if I want ensure the interoperability by consistent model I have to become a subscribing member of OPC Foundation or have to buy a license of certified product? (just a rhetorical question).

Ckath commented 5 years ago

The thing what is for me strange is, that in my understanding consists Information Models are key stone of the OPC UA interoperability.

This is also something that never made sense to me, its supposed to be a standard yet barely anything has it implemented fully. And most of the time you rely on non standard or third party implementations to parse them.

rudoq32 commented 5 years ago

Hi @MD-V I used it as: .\asp.exe C:\Projects\UA-Nodeset\ISA-95\Opc.ISA95.NodeSet2.xml -e C:\Projects\UA-Nodeset\ISA-95\DesignModel.xml -s XMLstylesheet I am not sure about the output in sense that if it is what the tool should do.

image I was expected something else.

MD-V commented 5 years ago

@rudoq32,

What the tool does is converting NodeSet2.xml to a ModelDesign comaptible XML that can be used in the ModelCompiler.

So what were you expecting and what exactly are you trying to do?

mpostol commented 5 years ago

Hi @rudoq32,

In your example, the OPC UA Information Model is represented in the xml file

C:\Projects\UA-Nodeset\ISA-95\DesignModel.xml that is recovered from:

C:\Projects\UA-Nodeset\ISA-95\Opc.ISA95.NodeSet2.xml containing a description of an OPC UA Address Space instance.

The screen contains only diagnostic information. Anny issues and features requests shall be reported at:

Object Oriented Internet

You can use the DesignModel.xml to edit end expand the model as described in Information Models Development

To edit and compile the IM you can use Address Space Model Designer. The commercial license is available for free, but you must contact me on mpostol at cas.eu or using the OOI project contact information or Gitter chat.