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.
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:
Contents
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
- it is called on:
- 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:
- make the sample servers use a more complete nodeset than
Opc.Ua.NodeSet2.Reduced.xml
- write a custom CMake file as mentioned at https://open62541.org/doc/current/nodeset_compiler.html#getting-started
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
Continue with Step 10
First of all thanks a lot for your work on these tutorials.
I have been looking for a long time instructions to build an OPC UA server from a nodeset2.xml file. In fact, I am trying to implement the Openfuncdation Robotics and automation Companion.
I followed the instructions from the Step 1 of the “OPC UA Information Model Tutorial”.I tried to implement the FooFlt example, but I got problems using the CMake for building the server:
CMake Error at /usr/local/lib/cmake/open62541/open62541Macros.cmake:488 (message):
ua_generate_nodeset_and_datatypes function requires NAMESPACE_MAP argument
if any of FILE_CSV or FILE_BSD are set
Call Stack (most recent call first):
CMakeLists.txt:10 (ua_generate_nodeset_and_datatypes)
— Configuring incomplete, errors occurred!
It looks like there was a problem to find the .bsd, and .csv files, but I verified the path and the files many times.
Then I decided to use the nodeset_compiler.py script:
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
and
gcc -std=c99 -I$HOME/install/include -L$HOME/install/lib main.c FooFlt.c -lopen62541 -lmbedtls -lmbedx509 -lmbedcrypto -o myServer
(the manual, hard way)
Then I launched the executable an I got:
~/FooServer$ ./myServer
[2020-11-03 11:30:29.761 (UTC+0100)] warn/server AccessControl: Unconfigured AccessControl. Users have all permissions.
[2020-11-03 11:30:29.761 (UTC+0100)] info/server AccessControl: Anonymous login is enabled
[2020-11-03 11:30:29.761 (UTC+0100)] warn/server Username/Password configured, but no encrypting SecurityPolicy. This can leak credentials on the network.
[2020-11-03 11:30:29.761 (UTC+0100)] warn/userland AcceptAll Certificate Verification. Any remote certificate will be accepted.
[2020-11-03 11:30:29.762 (UTC+0100)] error/server Could not add the Foo FLT nodeset. Check previous output for any error.
if anyone can help me solve the bug or tell me where I can find information related to the error, I would be very grateful.
Hi Sebastian,
regarding your first error message:
CMake Error at /usr/local/lib/cmake/open62541/open62541Macros.cmake:488 (message):
ua_generate_nodeset_and_datatypes function requires NAMESPACE_MAP argument
if any of FILE_CSV or FILE_BSD are set
This is NOT about missing csv or bsd files. They are fine.
This is about the CMake function ua_generate_nodeset_and_datatypes wich requires NAMESPACE_MAP as argument BECAUSE you are using FILE_CSV and FILE_BSD.
1) If you google for “NAMESPACE_MAP open62541”, your first result will be the official documentation
https://open62541.org/doc/current/nodeset_compiler.html
Look at how they are using it. My first attempt would be to replace NAMESPACE_IDX with NAMESPACE_MAP (and respective values).
2) What is the console output of
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
3) What is the console output of
gcc -std=c99 -I$HOME/install/include -L$HOME/install/lib main.c FooFlt.c -lopen62541 -lmbedtls -lmbedx509 -lmbedcrypto -o myServer
Hi!
Thanks for these tutorials. Helped me a lot in my journey on OPCUA.
I have developed an information model for a Robot and i am building the CMakeLists.txt file for my project. My model consists of multiple namespaces. For example my model built on (NS4) is dependent on OPCUA Robotics namespace (NS2) and another custom namespace (NS3).
Since there is no official bsd file for OPCUA Robotics, the issue arises when using the (ua_generate_nodeset_and_datatypes) function with NAMESPACE_MAP variable in CMake. ( The error requires both csv and bsd file if NAMESPACE_MAP is used)
To work around, it I created my own bsd & csv files for OPCUA Robotics, however it resulted in makefile execution issues.
I am working on this issue concurrently, any suggestions on how to include the Robotics NS as an intermediate NS with ua_generate_nodeset_and_datatypes) function & NAMESPACE_MAP would be helpful.
Thanks in advance.
Hi,
please have look at the notice at the very beginning of this article:
It shows how to manage dependencies between several namespaces. Have a look at the CMakeLists.txt files in the subdirectories as well.
I recommend you post your error messages when looking for help. Without those, I doubt anyone can or will help you in a meaningful way.
Kind regards
PS: The CSV and BSD files are optional. Here is their use case:
If you compile your model for the first time, the compiler will generate a CSV and BSD file. Those files will document the types and node IDs assigned to the nodes of your model. This ID assignment is somewhat arbitrary. Let us assume that node ‘foo’ received ID ‘123’.
If you change your model and recompile WITHOUT taking into account the CSV and BSD files, node ‘foo’ may now be assigned a different ID ‘234’.
If you change your model and recompile WITH taking into account the CSV and BSD files, they make sure that nodes will be assigned the SAME ID they have been assigned initially. That is important, because OPC UA depends on those IDs during runtime. If your node changes its ID with a new release of your model, OPC UA clients will not be able to successfully recognize that node as the same node they used before.
Hope that helps.
Thank you for your quick answer.
I applied your suggestion about using the NAMESPACE_MAP flag. It solved my bug.
I was able to successfully build the FOOFLT server example and running it.
Then I applied the same procedure with the Opc.Ua.Robotics.NodeSet2.xml, which I recovered from the official site:
https://opcfoundation.org/developer-tools/specifications-opc-ua-information-models/opc-unified-architecture-for-robotics/#:~:text=The%20OPC%20UA%20Robotics%20Companion,Industrial%20robots
(Link to the nodeset2.xml and nodels.cvs in the annexe A ).
For building the server I used the Cmake function:
ua_generate_nodeset_and_datatypes(
NAME “Robotics”
TARGET_PREFIX “${PROJECT_NAME}”
FILE_NS “${PROJECT_SOURCE_DIR}/Opc.Ua.Robotics.NodeSet2.xml”
# FILE_CSV “${PROJECT_SOURCE_DIR}/NodeIds.csv”
# NAMESPACE_MAP “1:http://opcfoundation.org/UA/Robotics/”
OUTPUT_DIR “${GENERATE_OUTPUT_DIR}”
INTERNAL
)
Called by:
cmake -DCMAKE_PREFIX_PATH=$USER/install ..
the console output:
— The C compiler identification is GNU 7.5.0
— The CXX compiler identification is GNU 7.5.0
— Check for working C compiler: /usr/bin/cc
— Check for working C compiler: /usr/bin/cc — works
— Detecting C compiler ABI info
— Detecting C compiler ABI info – done
— Detecting C compile features
— Detecting C compile features – done
— Check for working CXX compiler: /usr/bin/c++
— Check for working CXX compiler: /usr/bin/c++ — works
— Detecting CXX compiler ABI info
— Detecting CXX compiler ABI info – done
— Detecting CXX compile features
— Detecting CXX compile features – done
— Found PythonInterp: /usr/bin/python (found version “3.6.9”)
— Configuring done
— Generating done
— Build files have been written to: /home/ubuntu18ros/OPC-UA-Robotics-Model-Server/build
However, when I ran the Makefile I got:
Scanning dependencies of target opcua-Robotics-server-ns-Robotics
[ 20%] Generating src_generated/namespace_Robotics_generated.c, src_generated/namespace_Robotics_generated.h
INFO:__main__:Preprocessing (existing) /usr/local/share/open62541/tools/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml
INFO:__main__:Preprocessing /home/ubuntu18ros/OPC-UA-Robotics-Model-Server/Opc.Ua.Robotics.NodeSet2.xml
[‘http://opcfoundation.org/UA/’, ‘http://opcfoundation.org/UA/Robotics/’, ‘http://opcfoundation.org/UA/DI/’]
Traceback (most recent call last):
File “/usr/local/share/open62541/tools/nodeset_compiler/nodeset_compiler.py”, line 154, in
ns.sanitize()
File “/usr/local/share/open62541/tools/nodeset_compiler/nodeset.py”, line 131, in sanitize
raise Exception(“Reference ” + str(ref) + ” has an unknown target”)
Exception: Reference ns=1;i=1002<–[ns=0;i=45]–ns=2;i=15063 has an unknown target
CMakeFiles/opcua-Robotics-server-ns-Robotics.dir/build.make:69: recipe for target 'src_generated/namespace_Robotics_generated.c' failed
make[2]: *** [src_generated/namespace_Robotics_generated.c] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/opcua-Robotics-server-ns-Robotics.dir/all' failed
make[1]: *** [CMakeFiles/opcua-Robotics-server-ns-Robotics.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
I didn't use FILE_CSV , nether the NAMESPACE_MAP on the ua_generate_nodeset_and_datatypes() method, car the OPC UA Companion Specification doesn't provides a .BSD file.
I appreciate a lot the help to solve this problem. I'm beginner on OPC UA.
My complete project:
https://github.com/scepedaesp2018/OPC-UA-Robotics-Model-Server
Hi Sebastian,
The key information of your error is provided by the following line
Exception: Reference ns=1;i=1002<–[ns=0;i=45]–ns=2;i=15063 has an unknown target
I hope you notice, that this error message and its solution is discussed in this _very_ article.
https://opcua.rocks/step-9-using-a-custom-uanodeset-with-open62541/#Exception_Reference_ns1i151038211ns0i408211gtns0i2368_has_an_unknown_target
Thanks,
I also thought it was the error of this post the first time, so I used Opc.Ua.NodeSet2.xml as you can see in the Makefile’s results.
Hi Sebastian,
you have different namespaces and indices in your error message. Applying the specific solution from the article (use full nodeset instead of reduced nodeset) to your problem will most likely _not_ help. You have to follow the presented _method_
That is:
Research what nodes are represented by the indices in your error message and deduce the adequate solution for your problem.
Hi,
I am trying to compile my Nodeset consisting of 5 Namespaces using CMakeLists.txt. I have been successful in building the files using CMAKE command.
However, when I run the MAKE command, this is the encountering this error. The error is shown below.
[ 63%] Linking CXX executable opcua_server
c++: fatal error: Killed signal terminated program lto1
compilation terminated.
lto-wrapper: fatal error: /usr/bin/c++ returned 1 exit status
compilation terminated.
/usr/bin/ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/opcua_server.dir/build.make:346: opcua_server] Error 1
make[1]: *** [CMakeFiles/Makefile2:419: CMakeFiles/opcua_server.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
I am trying to understand this error. Any suggestions from your end would be helpful.
Thanks in advance.
Hi,
please see a related comment over at
https://opcua.rocks/step-1-setup-open62541-on-linux-build-first-server/
Search for “-fno-lto” but read the rest of the comment too.
Good luck!
Hi,
I am trying to compile the IO-Link nodeset to c on linux but it fails and maybe you can help me.
I changed the example like this:
—————————————————————————————–
# Generate types and namespace for DI
ua_generate_nodeset_and_datatypes(
NAME “di”
TARGET_PREFIX “${PROJECT_NAME}”
FILE_CSV “${PROJECT_SOURCE_DIR}/model/Published/DI/OpcUaDiModel.csv”
FILE_BSD “${PROJECT_SOURCE_DIR}/model/Published/DI/Opc.Ua.Di.Types.bsd”
OUTPUT_DIR “${GENERATE_OUTPUT_DIR}”
NAMESPACE_MAP “2:http://opcfoundation.org/UA/DI/”
FILE_NS “${PROJECT_SOURCE_DIR}/model/Published/DI/Opc.Ua.Di.NodeSet2.xml”
INTERNAL
)
ua_generate_nodeset_and_datatypes(
NAME “iolink”
TARGET_PREFIX “${PROJECT_NAME}”
OUTPUT_DIR “${GENERATE_OUTPUT_DIR}”
NAMESPACE_IDX 3
FILE_NS “${PROJECT_SOURCE_DIR}/model/Published/IOLink/Opc.Ua.IOLink.NodeSet2.xml”
DEPENDS “di”
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_DI_SOURCES}
${UA_NODESET_IOLINK_SOURCES}
${UA_TYPES_DI_SOURCES}
${UA_TYPES_IOLINK_SOURCES}
main.c
)
# Make sure the nodeset compiler is execute before compiling the main file
add_dependencies(opcua-modeling-tutorial-server
${PROJECT_NAME}-ns-di
${PROJECT_NAME}-ns-iolink
)
——————–
However I am getting this error:
——————————–
INFO:__main__:Preprocessing /home/ioan/test/opcua-modeling-tutorial-server/model/Published/IOLink/Opc.Ua.IOLink.NodeSet2.xml
INFO:__main__:Generating Code for Backend: open62541
Traceback (most recent call last):
File “/usr/local/share/open62541/tools/nodeset_compiler/nodeset_compiler.py”, line 189, in
generateOpen62541Code(ns, args.outputFile, args.internal_headers, args.typesArray)
File “/usr/local/share/open62541/tools/nodeset_compiler/backend_open62541.py”, line 230, in generateOpen62541Code
code = generateNodeCode_begin(node, nodeset, code_global)
File “/usr/local/share/open62541/tools/nodeset_compiler/backend_open62541_nodes.py”, line 493, in generateNodeCode_begin
[code1, codeCleanup1, codeGlobal1] = generateVariableNodeCode(node, nodeset)
File “/usr/local/share/open62541/tools/nodeset_compiler/backend_open62541_nodes.py”, line 231, in generateVariableNodeCode
[code1, codeCleanup1, codeGlobal1] = generateCommonVariableCode(node, nodeset)
File “/usr/local/share/open62541/tools/nodeset_compiler/backend_open62541_nodes.py”, line 195, in generateCommonVariableCode
[code1, codeCleanup1, codeGlobal1] = generateValueCode(node.value, nodeset.nodes[node.id], nodeset)
File “/usr/local/share/open62541/tools/nodeset_compiler/backend_open62541_nodes.py”, line 406, in generateValueCode
valueName + “[” + str(idx) + “]” , v, instanceName, valueName, codeGlobal))
File “/usr/local/share/open62541/tools/nodeset_compiler/backend_open62541_datatypes.py”, line 121, in generateNodeValueCode
return prepend + ” = ” + generateLocalizedTextCode(node, alloc=asIndirect) + “;”
File “/usr/local/share/open62541/tools/nodeset_compiler/backend_open62541_datatypes.py”, line 72, in generateLocalizedTextCode
vt = makeCLiteral(value.text)
File “/usr/local/share/open62541/tools/nodeset_compiler/backend_open62541_datatypes.py”, line 24, in makeCLiteral
return re.sub(r'(?<!\\)"', r'\\"', value.replace('\\', r'\\').replace('"', r'\"').replace('\n', r'\\n').replace('\r', r''))
AttributeError: 'NoneType' object has no attribute 'replace'
make[2]: *** [CMakeFiles/opcua-modeling-tutorial-server-ns-iolink.dir/build.make:71: src_generated/namespace_iolink_generated.c] Error 1
make[1]: *** [CMakeFiles/Makefile2:163: CMakeFiles/opcua-modeling-tutorial-server-ns-iolink.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
————–
I get the same error if I try to compile it directly with this command:
python ~/bdn/open62541/tools/nodeset_compiler/nodeset_compiler.py –types-array=UA_TYPES -e ../open62541/deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml -e ~/bdn/open62541/deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml -x ~/bdn/open62541/deps/ua-nodeset/IOLink/Opc.Ua.IOLink.NodeSet2.xml test
Thanks!
Fixed!
There seems to be some errors in the IO-Link NodeSet2 file.