Skip to content

Step 9: Using a custom UANodeSet with open62541

Last updated on September 1, 2020


Compile open62541 with a custom UANodeSet using CMake. This step will use nodeset_compiler.py to convert the UANodeSet2.xml to C99 header and source files and then compile the complete open62541 C99 application into a single executable.

This Post is part of the OPC UA Information Model Tutorial.


Notice

You can use the open62541 Nodeset Compiler directly, or create a CMake project which is using the provided macros.
I strongly recommend to use the CMake approach.


Especially for more complex setups where you have multiple NodeSets based on each other, manually passing the parameters to the Nodeset Compiler is very cumbersome. CMake will do this for you.
Also, the CMake macro also calls the datatype generator (custom datatypes) and nodeid generator (header file with node ID defines) for you.

A more complete example with heavy use of heavy usage of ModelDesign files and dependencies between them is shown in this project:

https://github.com/opcua-skills/plug-and-produce

Building an OPC UA Server with a custom UANodeSet using CMake

The open62541 OPC UA Stack uses a Python Script (Nodeset Compiler) to generate compilable C99 Code out of NodeSet2.xml files.

The complete documentation on the Nodeset Compiler can be found here:
https://open62541.org/doc/current/nodeset_compiler.html

Over the last years the interface and parameters to this Python Script became somewhat complext and not as intuitive as they should be (shame on me (Stefan) as I’m the one who extended it).

Therefore I created a simpler to use CMake Macro which handles all the complex stuff for you, as shown in the following example:

# Generate types and namespace for DI
ua_generate_nodeset_and_datatypes(
    NAME "di"
    FILE_CSV "${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/OpcUaDiModel.csv"
    FILE_BSD "${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.Types.bsd"
    NAMESPACE_IDX 2
    FILE_NS "${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml"
)

# generate PLCopen namespace which is using DI
ua_generate_nodeset_and_datatypes(
    NAME "plc"
    # PLCopen does not define custom types. Only generate the nodeset
    FILE_NS "${PROJECT_SOURCE_DIR}/deps/ua-nodeset/PLCopen/Opc.Ua.Plc.NodeSet2.xml"
    # PLCopen depends on the di nodeset, which must be generated before
    DEPENDS "di"
)

As you can see, you need the following files of a NodeSet:

  • .csv: Used to generate the NodeID header to provide defines for specific node IDs instead of numbers
  • .bsd: Used to generate custom data types and struct definitions if you define your own Data Types in the nodeset
  • NodeSet2.xml: Contains the whole nodeset definition and is used to generate the initialization code for the open62541 server.

Create a new CMake Project

The first step is to create a new CMake project in a new folder, let’s name it FooServer. In this folder create a CMakeLists.txt file with the following content:

(see also: https://github.com/Pro/opcua-modeling-tutorial-server/blob/master/CMakeLists.txt)

cmake_minimum_required(VERSION 3.2)
project(opcua-modeling-tutorial-server)

# open62541 must be installed.
# If in custom path, then use -DCMAKE_PREFIX_PATH=/home/user/install
find_package(open62541 1.1 REQUIRED COMPONENTS FullNamespace)

# Output directory for Nodeset Compiler
set(GENERATE_OUTPUT_DIR "${CMAKE_BINARY_DIR}/src_generated/")

file(MAKE_DIRECTORY "${GENERATE_OUTPUT_DIR}")
include_directories("${GENERATE_OUTPUT_DIR}")

ua_generate_nodeset_and_datatypes(
        NAME "foo_flt"
        TARGET_PREFIX "${PROJECT_NAME}"
        FILE_CSV "${PROJECT_SOURCE_DIR}/model/Published/FooFlt/FooFltModel.csv"
        FILE_BSD "${PROJECT_SOURCE_DIR}/model/Published/FooFlt/FooFlt.Types.bsd"
        OUTPUT_DIR "${GENERATE_OUTPUT_DIR}"
	# This namespace index must match the order in which you are adding the nodeset in the source code
        NAMESPACE_IDX 2
        FILE_NS "${PROJECT_SOURCE_DIR}/model/Published/FooFlt/FooFlt.NodeSet2.xml"
        INTERNAL
)

# Previous macro automatically sets some variables which hold the generated source code files using the provided NAME
add_executable(opcua-modeling-tutorial-server
               ${UA_NODESET_FOO_FLT_SOURCES}
               ${UA_TYPES_FOO_FLT_SOURCES}
               main.c
               )

# Make sure the nodeset compiler is execute before compiling the main file
add_dependencies(opcua-modeling-tutorial-server
                 ${PROJECT_NAME}-ns-foo_flt
                 )

target_link_libraries(opcua-modeling-tutorial-server open62541::open62541)

And copy the previously generated NodeSet2 files into the model/Published subfolder:

tree ~/FooServer
.
└── CMakeLists.txt
└── model
    ├── FooFltModel.csv
    ├── FooFltModel.xml
    ├── Published
    │   └── FooFlt
    │       ├── FooFlt.Classes.cs
    │       ├── FooFlt.Constants.cs
    │       ├── FooFlt.DataTypes.cs
    │       ├── FooFltModel.csv
    │       ├── FooFltModel.xml
    │       ├── FooFlt.NodeSet2.xml
    │       ├── FooFlt.NodeSet.xml
    │       ├── FooFlt.PredefinedNodes.uanodes
    │       ├── FooFlt.PredefinedNodes.xml
    │       ├── FooFlt.Types.bsd
    │       └── FooFlt.Types.xsd

Create a custom Server Code which uses your Model

After you created a new CMake project in previous section, you now need to define your Source Code which is initializing an OPC UA Server with your model.

Therefore, create a new file called main.c in the FooServer directory with the following content:

(see also https://github.com/Pro/opcua-modeling-tutorial-server/blob/master/main.c)

#include <open62541/plugin/log_stdout.h>
#include <open62541/server.h>
#include <open62541/server_config_default.h>

/* Files namespace_foo_flt_generated.h and namespace_foo_flt_generated.c are created from FooFlt.NodeSet2.xml in the
 * /src_generated directory by CMake */
#include "foo_flt_nodeids.h"
#include "namespace_foo_flt_generated.h"

#include <signal.h>
#include <stdlib.h>

UA_Boolean running = true;

static void stopHandler(int sign) {
    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c");
    running = false;
}

int main(int argc, char** argv) {
    signal(SIGINT, stopHandler);
    signal(SIGTERM, stopHandler);
    
    UA_Server *server = UA_Server_new();
    UA_ServerConfig_setDefault(UA_Server_getConfig(server));

    UA_StatusCode retval;
    /* create nodes from nodeset */
    if(namespace_foo_flt_generated(server) != UA_STATUSCODE_GOOD) {
        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Could not add the Foo FLT nodeset. "
        "Check previous output for any error.");
        retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
    } else {

        // Do some additional stuff with the nodes

        // this will just get the namespace index, since it is already added to the server
        UA_UInt16 nsIdx = UA_Server_addNamespace(server, "https://new.foo.com/zebra-compression/flattening-and-subspacefolding/UA/");

        UA_NodeId testInstanceId = UA_NODEID_NUMERIC(nsIdx, UA_FOO_FLTID_APE);

        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "The Ape has ns=%d;id=%d",
                    testInstanceId.namespaceIndex, testInstanceId.identifier.numeric);

        retval = UA_Server_run(server, &running);
    }

    UA_Server_delete(server);
    return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}

Especially look at line 29 which is is calling the gererated Nodeset initialization. This call will create all the nodes defined in your NodeSet2.xml file inside the open62541 OPC UA server.

To build and run this server just use CMake and make. Note, if you installed open62541 in a custom location, you may need to use the CMAKE_PREFIX_PATH option:

cd ~/FooServer
mkdir build && cd build
cmake -DCMAKE_PREFIX_PATH=/home/user/install ..
make -j
# Then run the server:
./opcua-modeling-tutorial-server

Now you can connect any OPC UA Client to your server and browse it.

Here is an example output:

$ make -j
Scanning dependencies of target opcua-modeling-tutorial-server-ids-foo_flt
Scanning dependencies of target opcua-modeling-tutorial-server-types-foo_flt
[ 22%] Generating src_generated/types_foo_flt_generated.c, src_generated/types_foo_flt_generated.h, src_generated/types_foo_flt_generated_handling.h, src_generated/types_foo_flt_generated_encoding_binary.h
[ 22%] Generating src_generated/foo_flt_nodeids.h
[ 22%] Built target opcua-modeling-tutorial-server-ids-foo_flt
[ 22%] Built target opcua-modeling-tutorial-server-types-foo_flt
Scanning dependencies of target opcua-modeling-tutorial-server-ns-foo_flt
[ 33%] Generating src_generated/namespace_foo_flt_generated.c, src_generated/namespace_foo_flt_generated.h
INFO:__main__:Preprocessing (existing) /home/user/install/open62541/share/open62541/tools/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml
INFO:__main__:Preprocessing /home/user/FooServer/model/Published/FooFlt/FooFlt.NodeSet2.xml
INFO:__main__:Generating Code for Backend: open62541
INFO:__main__:NodeSet generation code successfully printed
[ 33%] Built target opcua-modeling-tutorial-server-ns-foo_flt
Scanning dependencies of target opcua-modeling-tutorial-server
[ 44%] Building C object CMakeFiles/opcua-modeling-tutorial-server.dir/src_generated/namespace_foo_flt_generated.c.o
[ 55%] Building C object CMakeFiles/opcua-modeling-tutorial-server.dir/src_generated/types_foo_flt_generated.c.o
[ 66%] Building C object CMakeFiles/opcua-modeling-tutorial-server.dir/main.c.o
[ 77%] Linking C executable opcua-modeling-tutorial-server
[100%] Built target opcua-modeling-tutorial-server

$ ls
CMakeFiles     CMakeCache.txt       Makefile
src_generated  cmake_install.cmake  opcua-modeling-tutorial-server

$ ./opcua-modeling-tutorial-server
[2020-08-31 14:26:27.897 (UTC+0200)] warn/server	AccessControl: Unconfigured AccessControl. Users have all permissions.
[2020-08-31 14:26:27.897 (UTC+0200)] info/server	AccessControl: Anonymous login is enabled
[2020-08-31 14:26:27.897 (UTC+0200)] warn/server	Username/Password configured, but no encrypting SecurityPolicy. This can leak credentials on the network.
[2020-08-31 14:26:27.897 (UTC+0200)] warn/userland	AcceptAll Certificate Verification. Any remote certificate will be accepted.
[2020-08-31 14:26:27.898 (UTC+0200)] info/server	The Ape has ns=2;id=15111
[2020-08-31 14:26:27.898 (UTC+0200)] info/network	TCP network layer listening on opc.tcp://localhost:4840/
^C[2020-08-31 14:26:32.597 (UTC+0200)] info/server	received ctrl-c
[2020-08-31 14:26:32.597 (UTC+0200)] info/network	Shutting down the TCP network layer
                                                                          

And the view in UaExpert:

Building an example server with a custom UANodeset and gcc (the manual, hard way)

Instead of blindly relying on the pre-existing examples and make files of open62541, a manual build of the custom UANodeSet and open62541 OPC UA server will yield additional insights.

Manual validation and compilation of an UANodeSet

The main reference is: https://open62541.org/doc/current/nodeset_compiler.html

Before compiling an open62541 OPC UA server, the target UANodeSet file must be validated and compiled to C99 source and header files.

A valid FOO UANodeSet file FooFltModel.xml is provided in the Github Repo of this tutorial, including the generated NodeSet2.xml files in the Published folder:

https://github.com/Pro/opcua-modeling-tutorial/tree/master-published/Published/FooFlt

Compile the UANodeSet according to the documentation in the folder created at the beginning of this post:

cd ~/FooServer
python ~/open62541/tools/nodeset_compiler/nodeset_compiler.py --types-array=UA_TYPES --existing ~/open62541/deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml --xml model/Published/FooFlt/FooFlt.NodeSet2.xml FooFlt

# INFO:__main__:Preprocessing (existing) /home/user/open62541/deps/ua-# nodeset/Schema/Opc.Ua.NodeSet2.xml
# INFO:__main__:Preprocessing model/Published/FooFlt/FooFlt.NodeSet2.xml
# INFO:__main__:Generating Code for Backend: open62541
# INFO:__main__:NodeSet generation code successfully printed

This will generate two source files, namely FooFlt.c and FooFlt.h.

At this point the UANodeSet is ready to be compiled into a open62541.

Building an open62541 OPC UA server with a custom UANodeset by hand

After manually creating the .c and .h file from the UANodeset, you need a main file which uses the generated source code.

Use this slightly adapted main.c file. Especially note the changed include files and that the Node IDs are not availalbe:

#include <open62541/plugin/log_stdout.h>
#include <open62541/server.h>
#include <open62541/server_config_default.h>

/* Files namespace_foo_flt_generated.h and namespace_foo_flt_generated.c are created from FooFlt.NodeSet2.xml in the
 * /src_generated directory by CMake */
#include "FooFlt.h"

#include <signal.h>
#include <stdlib.h>

UA_Boolean running = true;

static void stopHandler(int sign) {
    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c");
    running = false;
}

int main(int argc, char** argv) {
    signal(SIGINT, stopHandler);
    signal(SIGTERM, stopHandler);
    
    UA_Server *server = UA_Server_new();
    UA_ServerConfig_setDefault(UA_Server_getConfig(server));

    UA_StatusCode retval;
    /* create nodes from nodeset */
    if(FooFlt(server) != UA_STATUSCODE_GOOD) {
        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Could not add the Foo FLT nodeset. "
        "Check previous output for any error.");
        retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
    } else {

        // Do some additional stuff with the nodes

        // this will just get the namespace index, since it is already added to the server
        UA_UInt16 nsIdx = UA_Server_addNamespace(server, "https://new.foo.com/zebra-compression/flattening-and-subspacefolding/UA/");

	// UA_FOO_FLTID_APE = 15111 
        UA_NodeId testInstanceId = UA_NODEID_NUMERIC(nsIdx, 15111);

        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "The Ape has ns=%d;id=%d",
                    testInstanceId.namespaceIndex, testInstanceId.identifier.numeric);

        retval = UA_Server_run(server, &running);
    }

    UA_Server_delete(server);
    return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}

Then compile the server:

gcc -std=c99 -I$HOME/install/include -L$HOME/install/lib main_manual.c FooFlt.c -lopen62541 -lmbedtls -lmbedx509 -lmbedcrypto -o myServer

To execute the generated server, make sure to add your custom installation path to the LD_LIBRARY_PATH, otherwise the open62541 library is not found:

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/install/lib ./myServer

Success!

Troubleshooting

Exception: Reference ns=1;i=15103–[ns=0;i=40]–>ns=0;i=2368 has an unknown target

This exception is thrown because the example server is compiled with Opc.Ua.NodeSet2.Reduced.xml which does not support AnalogItemType .

Compiling the example server with a custom nodeset may fail as follows

[ 78%] Built target tutorial_client_firststeps
[ 78%] Generating ../../src_generated/open62541/namespace_example_generated.c, ../../src_generated/open62541/namespace_example_generated.h
INFO:__main__:Preprocessing (existing) /home/user/open62541/tools/schema/Opc.Ua.NodeSet2.Reduced.xml
INFO:__main__:Preprocessing /home/user/open62541/examples/nodeset/server_nodeset.xml
['http://opcfoundation.org/UA/', u'https://new.foo.com/zebra-compression/flattening-and-subspacefolding/UA/']
Traceback (most recent call last):
  File "/home/user/open62541/tools/nodeset_compiler/nodeset_compiler.py", line 154, in <module>
    ns.sanitize()
  File "/home/user/open62541/tools/nodeset_compiler/nodeset.py", line 131, in sanitize
    raise Exception("Reference " + str(ref) + " has an unknown target")
Exception: Reference ns=1;i=15103--[ns=0;i=40]-->ns=0;i=2368 has an unknown target
make[2]: *** [examples/nodeset/CMakeFiles/server_nodeset.dir/build.make:70: src_generated/open62541/namespace_example_generated.c] Error 1
make[1]: *** [CMakeFiles/Makefile2:2190: examples/nodeset/CMakeFiles/server_nodeset.dir/all] Error 2
make: *** [Makefile:152: all] Error 2

user@debian:~/open62541/build$

The output indicates:

  • calling nodeset_compiler.py is part of the compilation process and breaks it
    • it is called on:
      • open62541/tools/schema/Opc.Ua.NodeSet2.Reduced.xml
      • open62541/examples/nodeset/server_nodeset.xml the example nodeset that is replaced with the custom nodeset before compilation
  • and that Reference ns=1;i=15103--[ns=0;i=40]-->ns=0;i=2368 has an unknown target

The missing 2368 can be located in https://github.com/OPCFoundation/UA-Nodeset (which is a git submodule of https://github.com/OPCFoundation/UA-ModelCompiler)

johndoe@winpc MINGW64 /c/FLT_SW/UA-ModelCompiler/Published/Schema ((5bbf784...))
$ grep -r 2368
NodeIds.csv:AnalogItemType,2368,VariableType
Opc.Ua.Constants.cs:        public const uint AnalogItemType = 2368;
Opc.Ua.NodeSet.xml:            <Identifier>i=2368</Identifier>
Opc.Ua.NodeSet.xml:        <Identifier>i=2368</Identifier>
Opc.Ua.NodeSet.xml:            <Identifier>i=2368</Identifier>
Opc.Ua.NodeSet.xml:            <Identifier>i=2368</Identifier>
Opc.Ua.NodeSet.xml:            <Identifier>i=2368</Identifier>
Opc.Ua.NodeSet2.Part8.xml:  <UAVariableType NodeId="i=2368" BrowseName="AnalogItemType" DataType="Number" ValueRank="-2">
Opc.Ua.NodeSet2.Part8.xml:  <UAVariable NodeId="i=2370" BrowseName="InstrumentRange" ParentNodeId="i=2368" DataType="i=884">
Opc.Ua.NodeSet2.Part8.xml:      <Reference ReferenceType="HasProperty" IsForward="false">i=2368</Reference>
Opc.Ua.NodeSet2.Part8.xml:  <UAVariable NodeId="i=2369" BrowseName="EURange" ParentNodeId="i=2368" DataType="i=884">
Opc.Ua.NodeSet2.Part8.xml:      <Reference ReferenceType="HasProperty" IsForward="false">i=2368</Reference>
Opc.Ua.NodeSet2.Part8.xml:  <UAVariable NodeId="i=2371" BrowseName="EngineeringUnits" ParentNodeId="i=2368" DataType="i=887">
Opc.Ua.NodeSet2.Part8.xml:      <Reference ReferenceType="HasProperty" IsForward="false">i=2368</Reference>
Opc.Ua.NodeSet2.xml:  <UAVariableType NodeId="i=2368" BrowseName="AnalogItemType" DataType="Number" ValueRank="-2">
Opc.Ua.NodeSet2.xml:  <UAVariable NodeId="i=2370" BrowseName="InstrumentRange" ParentNodeId="i=2368" DataType="i=884">
Opc.Ua.NodeSet2.xml:      <Reference ReferenceType="HasProperty" IsForward="false">i=2368</Reference>
Opc.Ua.NodeSet2.xml:  <UAVariable NodeId="i=2369" BrowseName="EURange" ParentNodeId="i=2368" DataType="i=884">
Opc.Ua.NodeSet2.xml:      <Reference ReferenceType="HasProperty" IsForward="false">i=2368</Reference>
Opc.Ua.NodeSet2.xml:  <UAVariable NodeId="i=2371" BrowseName="EngineeringUnits" ParentNodeId="i=2368" DataType="i=887">
Opc.Ua.NodeSet2.xml:      <Reference ReferenceType="HasProperty" IsForward="false">i=2368</Reference>
Opc.Ua.PredefinedNodes.xml:      <uax:Identifier>i=2368</uax:Identifier>

Pay special attention to

Opc.Ua.NodeSet2.Part8.xml:  <UAVariableType NodeId="i=2368" BrowseName="AnalogItemType" DataType="Number" ValueRank="-2">
Opc.Ua.NodeSet2.xml:  <UAVariableType NodeId="i=2368" BrowseName="AnalogItemType" DataType="Number" ValueRank="-2">

This leads to the suspicion, that Opc.Ua.NodeSet2.Reduced.xml does not hold the required node. To verify that, call nodeset_compiler.py with the full Opc.Ua.NodeSet2.xml

user@debian:~/open62541/tools/nodeset_compiler$
python ./nodeset_compiler.py --types-array=UA_TYPES --existing ../../deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml --xml ../../examples/nodeset/server_nodeset.xml temporary_garbage_file
INFO:__main__:Preprocessing (existing) ../../deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml
INFO:__main__:Preprocessing ../../examples/nodeset/server_nodeset.xml
INFO:__main__:Generating Code for Backend: open62541
INFO:__main__:NodeSet generation code successfully printed

Consequently, one of the following solutions must be implemented:

The first solution is implemented by replacing the reduced nodeset with the full nodeset as indicated by the following diff:

user@debian:~/open62541$
git diff examples/nodeset/CMakeLists.txt
diff --git a/examples/nodeset/CMakeLists.txt b/examples/nodeset/CMakeLists.txt
index 073db5f0..49d23332 100644
--- a/examples/nodeset/CMakeLists.txt
+++ b/examples/nodeset/CMakeLists.txt
@@ -20,7 +20,7 @@ if(NOT CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
     ua_generate_nodeset_and_datatypes(
         NAME "example"
         FILE_NS "${FILE_NS_DIRPREFIX}/server_nodeset.xml"
-        DEPENDS "${CMAKE_SOURCE_DIR}/tools/schema/Opc.Ua.NodeSet2.Reduced.xml"
+        DEPENDS "${CMAKE_SOURCE_DIR}/deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml"
     )
 else()
     # standalone examples build expects already installed Opc.Ua.NodeSet2.Reduced.xml

This change allows to build the open62541 example server with AnalogItemTypes and EUInformation.

Note: Alternative reduced standard nodesets are available from folder open62541/tools/schema

KeyError: 65535 self.browseName.ns = nsMapping[self.browseName.ns]

Compilation of the UANodeSet may fail as follows:

user@debian:~/open62541/tools/nodeset_compiler$
python ./nodeset_compiler.py --types-array=UA_TYPES --existing ../../deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml --xml ../../examples/nodeset/server_nodeset.xml server_nodeset
INFO:__main__:Preprocessing (existing) ../../deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml
INFO:__main__:Preprocessing ../../examples/nodeset/server_nodeset.xml
Traceback (most recent call last):
  File "./nodeset_compiler.py", line 131, in <module>
    ns.addNodeSet(xmlfile, typesArray=getTypesArray(nsCount))
  File "/home/user/open62541/tools/nodeset_compiler/nodeset.py", line 296, in addNodeSet
    node.replaceNamespaces(namespaceMapping)
  File "/home/user/open62541/tools/nodeset_compiler/nodes.py", line 177, in replaceNamespaces
    self.browseName.ns = nsMapping[self.browseName.ns]
KeyError: 65535

Note: Be aware that in this example deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml is used, while the example servers of open62541 use reduced nodesets! This is relevant when using AnalogItemType or EUInformation types.

This is most likely caused by a missing namespace prefix like in the example below:

Insert the missing prefix to the ModelDesign, regenerate the UANodeSet with UA-ModelCompiler and rerun nodeset_compiler.py

Published inopen62541

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.