open62541/open62541-nodeset-loader

tests integration compiling

eziosella opened this issue · 14 comments

Dear all,
thanks for sharing this project.

How can I compile the test in the integration folder?
Here what I did:

git clone https://github.com/open62541/open62541-nodeset-loader.git
cd open62541-nodeset-loader
makdir build && cd build
cmake -DENABLE_TESTING=on -DENABLE_INTEGRATION_TEST=on -DENABLE_EXAMPLES=on ..

The project compiles properly but I cant see anything regarding the integration folder and the "start_test.sh" script.

Hi there's a comment in the root CMakeLists.txt:

set(ENABLE_INTEGRATION_TEST off)

Seems that the open ci is failing with the integration tests enabled

Thanks @matkonnerth,

you are right, the flag is forced OFF, sorry I didn't see it.

It wouldbe great to have a sequence of commands replicating this nodeset and datatypes compilation using the python scripts,
in order to compile the Euromap77 example.
That's my goal and what I am trying to do.
I will share my tests ASAP, in the meanwhile any suggest would be very aprecciated.

Yes thanks, I saw it, but
that needs the CMakeLists.txt working to generate the Makefile.

In the meanwhile the example cannot be compiled I was trying the corrisponding python commands one by one to generate the same conversion result.
For example, something like:

# test 2 on EUROMAP77 (WIP)
# datatypes generation
python3 ../../tools/generate_datatypes.py --namespaceMap="2:http://opcfoundation.org/UA/DI/" --type-csv=../../deps/ua-nodeset/DI/Opc.Ua.Di.NodeIds.csv --type-bsd=../../deps/ua-nodeset/DI/Opc.Ua.Di.Types.bsd --no-builtin types_di
python3 ../../tools/generate_datatypes.py --namespaceMap="3:http://opcfoundation.org/UA/PlasticsRubber/GeneralTypes/" --type-csv=../../deps/ua-nodeset/PlasticsRubber/GeneralTypes/1.03/NodeIds.csv --type-bsd=../../deps/ua-nodeset/PlasticsRubber/GeneralTypes/1.03/Opc.Ua.PlasticsRubber.GeneralTypes.NodeSet2.bsd --import=UA_TYPES#../../deps/ua-nodeset/Schema/Opc.Ua.Types.bsd --no-builtin types_gen
python3 ../../tools/generate_datatypes.py --namespaceMap="4:http://opcfoundation.org/UA/PlasticsRubber/IMM2MES/" --type-csv=../../deps/ua-nodeset/PlasticsRubber/IMM2MES/1.01/NodeIds.csv --type-bsd=../../deps/ua-nodeset/PlasticsRubber/IMM2MES/1.01/Opc.Ua.PlasticsRubber.IMM2MES.NodeSet2.bsd --import=UA_TYPES#../../deps/ua-nodeset/Schema/Opc.Ua.Types.bsd --no-builtin types_imm
# nodeset's compilation
python3 ../../tools/nodeset_compiler/nodeset_compiler.py --internal-headers --types-array=UA_TYPES --types-array=UA_TYPES_DI --existing ../../deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml --xml ../../deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml namespace_di
python3 ../../tools/nodeset_compiler/nodeset_compiler.py --internal-headers --types-array=UA_TYPES --types-array=UA_TYPES_DI --types-array=UA_TYPES_GEN --existing ../../deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml --existing ../../deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml --xml ../../deps/ua-nodeset/PlasticsRubber/GeneralTypes/1.03/Opc.Ua.PlasticsRubber.GeneralTypes.NodeSet2.xml namespace_gen
python3 ../../tools/nodeset_compiler/nodeset_compiler.py --internal-headers --types-array=UA_TYPES --types-array=UA_TYPES_DI --types-array=UA_TYPES_GEN --types-array=UA_TYPES_IMM --existing ../../deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml --existing ../../deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml --existing ../../deps/ua-nodeset/PlasticsRubber/GeneralTypes/1.03/Opc.Ua.PlasticsRubber.GeneralTypes.NodeSet2.xml --xml ../../deps/ua-nodeset/PlasticsRubber/IMM2MES/1.01/Opc.Ua.PlasticsRubber.IMM2MES.NodeSet2.xml namespace_imm
#test program compiling
gcc -std=c99 -I/opt/open62541/include -L/opt/open62541/lib types_di_generated.c types_gen_generated.c types_imm_generated.c namespace_di.c namespace_gen.c namespace_imm.c myServerIMM.c -lopen62541 -lmbedtls -lmbedx509 -lmbedcrypto -o myServerIMM

I am in a standstill situation now,
I mean, the compiling seems ok without problem, the server loads all the noded without apparently problem,
but I have to test properly the server if running OK.

Maybe someone could take a look if the python's steps are correct or something is missing.

Dear all,
at the end I was able to compile a similar test of https://github.com/open62541/open62541-nodeset-loader/blob/master/backends/open62541/tests/integration/reference_server/server.cpp without cmake but using directly the python scripts as below:

python3 ../../tools/generate_datatypes.py --namespaceMap="2:http://opcfoundation.org/UA/DI/" --type-csv=../../deps/ua-nodeset/DI/Opc.Ua.Di.NodeIds.csv --type-bsd=../../deps/ua-nodeset/DI/Opc.Ua.Di.Types.bsd --no-builtin types_di

python3 ../../tools/generate_datatypes.py --namespaceMap="3:http://opcfoundation.org/UA/PlasticsRubber/GeneralTypes/" --type-csv=../../deps/ua-nodeset/PlasticsRubber/GeneralTypes/1.03/NodeIds.csv --type-bsd=../../deps/ua-nodeset/PlasticsRubber/GeneralTypes/1.03/Opc.Ua.PlasticsRubber.GeneralTypes.NodeSet2.bsd --import=UA_TYPES#../../deps/ua-nodeset/Schema/Opc.Ua.Types.bsd --no-builtin types_gen

python3 ../../tools/generate_datatypes.py --namespaceMap="4:http://opcfoundation.org/UA/PlasticsRubber/IMM2MES/" --type-csv=../../deps/ua-nodeset/PlasticsRubber/IMM2MES/1.01/NodeIds.csv --type-bsd=../../deps/ua-nodeset/PlasticsRubber/IMM2MES/1.01/Opc.Ua.PlasticsRubber.IMM2MES.NodeSet2.bsd --import=UA_TYPES#../../deps/ua-nodeset/Schema/Opc.Ua.Types.bsd --no-builtin types_imm

python3 ../../tools/generate_datatypes.py --namespaceMap="5:http://yourorganisation.org/EuromapInstances/" --type-csv=../../deps/nodesetLoader/nodesets/euromap_instances/euromapinstances.csv --import=UA_TYPES#../../deps/ua-nodeset/Schema/Opc.Ua.Types.bsd --no-builtin types_eu77

python3 ../../tools/nodeset_compiler/nodeset_compiler.py --internal-headers --types-array=UA_TYPES --types-array=UA_TYPES_DI --existing ../../deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml --xml ../../deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml namespace_di

python3 ../../tools/nodeset_compiler/nodeset_compiler.py --internal-headers --types-array=UA_TYPES --types-array=UA_TYPES_DI --types-array=UA_TYPES_GEN --existing ../../deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml --existing ../../deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml --xml ../../deps/ua-nodeset/PlasticsRubber/GeneralTypes/1.03/Opc.Ua.PlasticsRubber.GeneralTypes.NodeSet2.xml namespace_gen

python3 ../../tools/nodeset_compiler/nodeset_compiler.py --internal-headers --types-array=UA_TYPES --types-array=UA_TYPES_DI --types-array=UA_TYPES_GEN --types-array=UA_TYPES_IMM --existing ../../deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml --existing ../../deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml --existing ../../deps/ua-nodeset/PlasticsRubber/GeneralTypes/1.03/Opc.Ua.PlasticsRubber.GeneralTypes.NodeSet2.xml --xml ../../deps/ua-nodeset/PlasticsRubber/IMM2MES/1.01/Opc.Ua.PlasticsRubber.IMM2MES.NodeSet2.xml namespace_imm

python3 ../../tools/nodeset_compiler/nodeset_compiler.py --internal-headers --types-array=UA_TYPES --types-array=UA_TYPES_DI --types-array=UA_TYPES_GEN --types-array=UA_TYPES_IMM  --types-array=UA_TYPES_EU77 --existing ../../deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml --existing ../../deps/ua-nodeset/DI/Opc.Ua.Di.NodeSet2.xml --existing ../../deps/ua-nodeset/PlasticsRubber/GeneralTypes/1.03/Opc.Ua.PlasticsRubber.GeneralTypes.NodeSet2.xml --existing ../../deps/ua-nodeset/PlasticsRubber/IMM2MES/1.01/Opc.Ua.PlasticsRubber.IMM2MES.NodeSet2.xml --xml ../../deps/nodesetLoader/nodesets/euromap_instances/euromapinstances.xml namespace_eu77

gcc -I/opt/open62541/include -L/opt/open62541/lib types_di_generated.c types_gen_generated.c types_imm_generated.c types_eu77_generated.c namespace_di.c namespace_gen.c namespace_imm.c namespace_eu77.c myServerEU77.cpp -lstdc++ -lopen62541 -lmbedtls -lmbedx509 -lmbedcrypto -o myServerEU77

This's wonderful for me thanks!
Now I was trying to use the NodesetLoader for loading the euromapinstances.xml without generate the source code with the python's scripts but something is not working:

gcc -std=c++11 -I/opt/open62541/include -L/opt/open62541/lib types_di_generated.c types_gen_generated.c types_imm_generated.c  namespace_di.c namespace_gen.c namespace_imm.c  myServerEU77b.cpp -lstdc++ -lopen62541 -lmbedtls -lmbedx509 -lmbedcrypto -lNodesetLoader -o myServerEU77b
cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C
cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C
cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C
cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C
cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C
cc1: warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C
/opt/open62541/lib/libNodesetLoader.a(Parser.c.o): nella funzione "Parser_run":
Parser.c:(.text+0x11d): riferimento non definito a "xmlInitParser"
Parser.c:(.text+0x149): riferimento non definito a "xmlCreatePushParserCtxt"
Parser.c:(.text+0x173): riferimento non definito a "xmlParseChunk"
Parser.c:(.text+0x192): riferimento non definito a "xmlParserError"
Parser.c:(.text+0x1eb): riferimento non definito a "xmlParseChunk"
Parser.c:(.text+0x1fa): riferimento non definito a "xmlFreeParserCtxt"
Parser.c:(.text+0x1ff): riferimento non definito a "xmlCleanupParser"
collect2: error: ld returned 1 exit status

Sorry for the Italian console output, anyway my NodesetLoader compiling steps were:

cd ~/open62541/deps/nodesetLoader
make build && cd build
cmake -DCMAKE_INSTALL_PREFIX=/opt/open62541 ..
sudo make install

the nodesetLoader compiling phase was OK.
Below myServerEU77b.cpp example

#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <open62541/server.h>
#include <open62541/plugin/log_stdout.h>
#include <open62541/server_config_default.h>
#include <open62541/types.h>
#include <NodesetLoader/backendOpen62541.h>
#include <NodesetLoader/dataTypes.h>

#include "namespace_di.h"
#include "namespace_gen.h"
#include "namespace_imm.h"

#include "types_di_generated.h"
#include "types_di_generated_handling.h"
#include "types_gen_generated.h"
#include "types_gen_generated_handling.h"
#include "types_imm_generated.h"
#include "types_imm_generated_handling.h"

UA_Boolean running = true;

using namespace std;

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

static UA_Boolean addDataTypeArray(UA_DataTypeArray *pDataTypeArray,
								   const UA_DataType *pNewDataTypes,
								   const size_t newDataTypesSize)
{
	if ((pDataTypeArray == nullptr) || (pNewDataTypes == nullptr))
	{
		UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
					 "Error AddDataTypeArray(): null pointer param");
		return UA_FALSE;
	}
	// copy the new types to the end of the array
	UA_DataType *newTypes = (UA_DataType *)realloc(
		const_cast<UA_DataType *>(pDataTypeArray->types),
		sizeof(UA_DataType) * (newDataTypesSize + pDataTypeArray->typesSize));
	if (!newTypes)
	{
		return UA_FALSE;
	}
	memcpy(newTypes + pDataTypeArray->typesSize, pNewDataTypes,
		   newDataTypesSize * sizeof(UA_DataType));

	// ugly
	size_t *typesSize = const_cast<size_t *>(&pDataTypeArray->typesSize);
	*typesSize += newDataTypesSize;

	pDataTypeArray->types = newTypes;
	return UA_TRUE;
}

void FreeDataTypeArray(UA_DataTypeArray *pDataTypeArray)
{
	UA_free(pDataTypeArray);
}

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));

	/* Create nodes from nodeset */
	UA_StatusCode retval = namespace_di(server);
	if(retval != UA_STATUSCODE_GOOD) {
		UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Adding the DI namespace failed. Please check previous error output.");
		UA_Server_delete(server);
		return (int)UA_STATUSCODE_BADUNEXPECTEDERROR;
	}

	retval |= namespace_gen(server);
	if(retval != UA_STATUSCODE_GOOD) {
		UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Adding the PlasticsRubber/GeneralTypes namespace failed. Please check previous error output.");
		UA_Server_delete(server);
		return (int)UA_STATUSCODE_BADUNEXPECTEDERROR;
	}

	retval |= namespace_imm(server);
	if(retval != UA_STATUSCODE_GOOD) {
		UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Adding the PlasticsRubber/IMM2MES namespace failed. Please check previous error output.");
		UA_Server_delete(server);
		return (int)UA_STATUSCODE_BADUNEXPECTEDERROR;
	}

	// retval |= namespace_eu77(server);
	// if(retval != UA_STATUSCODE_GOOD) {
	// 	UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Adding the Euromap instance namespace failed. Please check previous error output.");
	// 	UA_Server_delete(server);
	// 	return (int)UA_STATUSCODE_BADUNEXPECTEDERROR;
	// }
	if(!NodesetLoader_loadFile(server, "./eu77_instances.xml", NULL))
	{
		UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "importing the xml nodeset failed");
	}

	retval = UA_Server_run(server, &running);

	const UA_DataTypeArray *customTypes = UA_Server_getConfig(server)->customDataTypes;
	UA_Server_delete(server);
	NodesetLoader_cleanupCustomDataTypes(customTypes);
	return (int) retval;
}

Does anybody can help me why I get this error? What am I doing wrong?

include and link with libxml

@matkonnerth Thank you so much for you reply!

I did some tests after your suggestion and I found out a way to compile it and run it properly.

My final gcc commands has been:

gcc -std=c++11 -I/opt/open62541/include -I/usr/include/libxml2 -L/opt/open62541/lib -L/usr/lib/i386-linux-gnu types_di_generated.c types_gen_generated.c types_imm_generated.c  namespace_di.c namespace_gen.c namespace_imm.c  myServerEU77b.cpp -lstdc++ -lopen62541 -lmbedtls -lmbedx509 -lmbedcrypto  -o myServerEU77b -l:libNodesetLoader.a -lxml2

By my side I guess this question/issue can be closed. May I?

if the questions are resolved, please close the issue.

Good to see that EM77 specification gets implemented by more and more companies.

Sorry to bother again.
I am no able to modify node's values from server side.
I am following some code from an example on the docs but I always get the error code:

UA_STATUSCODE_BADNODEIDUNKNOWN 0x80340000

The code that I am using is

UA_NodeId myIntegerNodeId = UA_NODEID_STRING(5, "AverageCycleTime");

/* Write a different integer value */
UA_Int32 myInteger = 43;
UA_Variant myVar;
UA_Variant_init(&myVar);
UA_Variant_setScalar(&myVar, &myInteger, &UA_TYPES[UA_TYPES_INT32]);
UA_StatusCode retval = UA_Server_writeValue(server, myIntegerNodeId, myVar);
if (retval != UA_STATUSCODE_GOOD)
qDebug() << QString("[5] Writing value to OPCUA server error 0x%1").arg(retval, 0, 16);
else {
qDebug() << QString("[5] Written value to OPCUA properly");
return;
}

I am able to modify the same NodeId from UAExpert tool but not by the server API

immagine

What am I missing?

you have to use the numeric nodeid, nsidx=5, i=6099

It seems that the BrowseName AverageCycleTime in namespace 3 is (not 5).

I forgot to mention that I had already try with all the namespace numbers, I tried from 0 to 5 but no one works.

browseName is irrevalent for the NodeId

you have to use the numeric nodeid, nsidx=5, i=6099

OK, that's clear from the UAExpert image, but how can I access to that?
In my previous test I also use another example like below

double dval = 123.456;
UA_Variant value;
UA_Variant_setScalar(&value, &dval, &UA_TYPES[UA_TYPES_DOUBLE]);
UA_NodeId currentNodeId = UA_NODEID_STRING(5, (char *)"AverageCycleTime");
UA_StatusCode retval = UA_Server_writeValue(server, currentNodeId, value);
if (retval != UA_STATUSCODE_GOOD)
qDebug() << QString("[ns=5] Writing value to OPCUA server error 0x%1 currentNodeId=%2").arg(retval, 0, 16).arg(currentNodeId.namespaceIndex);
else {
qDebug() << QString("[ns=5] Written value to OPCUA properly");
}

Is it possible acces directly in some way or do I have to browse from the root path?

I did it using:

UA_StatusCode retval = UA_Server_writeValue(server, UA_NODEID_NUMERIC(5, 6099), value);

with UA_NODEID_NUMERIC function.
Thanks.