-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom/Aliased UADataTypes and UAVariableTypes not supported #253
Comments
Weirdly enough, if I read the data type of an imported variable (that should have dataType= I was hoping to use |
@matkonnerth Here's a working example in C along with the full XML nodeset. It tries to get the data type of #include <open62541/plugin/log_stdout.h>
#include <open62541/server.h>
#include <open62541/server_config_default.h>
#include <open62541/plugin/nodesetloader.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
UA_Boolean running = true;
static void stopHandler(int sign) {
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c");
running = false;
}
static void
testCallback(UA_Server *server, void *data) {
UA_StatusCode rc;
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "testcallback");
size_t index;
rc = UA_Server_getNamespaceByName(server, UA_STRING("http://foobar.example.com/Instances"), &index);
if (rc != UA_STATUSCODE_GOOD) {
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "could not determine namespace index for namespace URI");
abort();
}
UA_Guid guid;
UA_Guid_parse(&guid, UA_STRING("16001624-6a1d-42d5-81d1-f54af84f5325"));
UA_NodeId nodeId = UA_NODEID_GUID(index, guid);
UA_NodeId typeNodeId;
rc = UA_Server_readDataType(server, nodeId, &typeNodeId);
if (rc != UA_STATUSCODE_GOOD) {
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "could not read data type node id");
abort();
}
UA_String typeNodeIdString;
UA_String_init(&typeNodeIdString);
UA_NodeId_print(&typeNodeId, &typeNodeIdString);
UA_DataType *nodeDataType = UA_findDataType(&typeNodeId);
/* const UA_DataTypeArray *customTypes = UA_Server_getConfig(server)->customDataTypes; */
/* UA_DataType *nodeDataType = UA_findDataTypeWithCustom(&typeNodeId, customTypes); */
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "found data type node ID: %.*s", typeNodeIdString.length, typeNodeIdString.data);
UA_NodeClass outNodeClass;
rc = UA_Server_readNodeClass(server, typeNodeId, &outNodeClass);
if (rc != UA_STATUSCODE_GOOD) {
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "could not read node class of data type node");
abort();
}
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "data type node class: %i (is UA_NODECLASS_DATATYPE=%s)", outNodeClass, outNodeClass == UA_NODECLASS_DATATYPE ? "True" : "False");
if (nodeDataType) {
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "found data type: %s, typeKind=%i", nodeDataType->typeName, nodeDataType->typeKind);
}
else {
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "could not look up data type");
/* abort(); */
return;
}
}
int main(int argc, const char *argv[]) {
signal(SIGINT, stopHandler);
signal(SIGTERM, stopHandler);
UA_Server *server = UA_Server_new();
UA_ServerConfig_setDefault(UA_Server_getConfig(server));
UA_Server_run_startup(server);
/* Add a repeated callback to the server */
UA_Server_addRepeatedCallback(server, testCallback, NULL, 2000, NULL); /* call every 2 sec */
for (int cnt = 1; cnt < argc; cnt++) {
if (UA_StatusCode_isGood(UA_Server_loadNodeset(server, argv[cnt], NULL))) {
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Nodeset %s loaded.", argv[cnt]);
}
else {
printf("Nodeset %s could not be loaded, exit\n", argv[cnt]);
return EXIT_FAILURE;
}
}
UA_Boolean waitInternal = true;
while(running) {
UA_Server_run_iterate(server, waitInternal);
}
/* UA_StatusCode retval = UA_Server_run(server, &running); */
UA_Server_run_shutdown(server);
UA_Server_delete(server);
return EXIT_SUCCESS;
} Compile with:
Run with:
Local output:
Open62541 configured and installed with:
The XML nodeset (gzipped): |
@paddor : thank you for the detailled issue report, do you the result with the nodesetcompiler? |
@matkonnerth Sorry, I didn't understand the question. The nodeset itself works, in another UA stack and also in this UA stack, at least when checked via UaExpert. What doesn't work is getting the real data type of the variable node. |
sry, the open62541 has also the ability to generate c code for the information model (done with the nodesetcompiler). Would be interesting if the issue preserves with that method. |
Here's the output:
What does this mean? |
oh, seems that NodeIds with type ByteString or Guid are not supported by the nodesetcompiler |
I've added support for GUID node IDs in a PR: open62541/open62541#6355 The script completes successfully and gives me two files. |
Generated header file: /* WARNING: This is a generated file.
* Any manual changes will be overwritten. */
#ifndef MYNS_H_
#define MYNS_H_
#ifdef UA_ENABLE_AMALGAMATION
# include "open62541.h"
#else
# include <open62541/server.h>
#endif
_UA_BEGIN_DECLS
extern UA_StatusCode myNS(UA_Server *server);
_UA_END_DECLS
#endif /* MYNS_H_ */ Generated C file is attached as myNS.c.gz. Using the two new files in this program: #include <open62541/plugin/log_stdout.h>
#include <open62541/server.h>
#include <open62541/server_config_default.h>
#include <open62541/plugin/nodesetloader.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include "myNS.h"
UA_Boolean running = true;
static void stopHandler(int sign) {
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c");
running = false;
}
static void
testCallback(UA_Server *server, void *data) {
UA_StatusCode rc;
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "testcallback");
size_t index;
rc = UA_Server_getNamespaceByName(server, UA_STRING("http://foobar.example.com/Instances"), &index);
if (rc != UA_STATUSCODE_GOOD) {
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "could not determine namespace index for namespace URI");
abort();
}
UA_Guid guid;
UA_Guid_init(&guid);
UA_Guid_parse(&guid, UA_STRING("16001624-6a1d-42d5-81d1-f54af84f5325"));
UA_NodeId nodeId = UA_NODEID_GUID(index, guid);
UA_NodeId typeNodeId;
UA_NodeId_init(&typeNodeId);
rc = UA_Server_readDataType(server, nodeId, &typeNodeId);
if (rc != UA_STATUSCODE_GOOD) {
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "could not read data type node id");
abort();
}
UA_NodeClass outNodeClass;
UA_NodeClass_init(&outNodeClass);
rc = UA_Server_readNodeClass(server, typeNodeId, &outNodeClass);
if (rc != UA_STATUSCODE_GOOD) {
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "could not read node class of data type node");
abort();
}
UA_String typeNodeIdString;
UA_String_init(&typeNodeIdString);
UA_NodeId_print(&typeNodeId, &typeNodeIdString);
UA_DataType *nodeDataType = UA_findDataType(&typeNodeId);
/* const UA_DataTypeArray *customTypes = UA_Server_getConfig(server)->customDataTypes; */
/* UA_DataType *nodeDataType = UA_findDataTypeWithCustom(&typeNodeId, customTypes); */
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "found data type node ID: %.*s", typeNodeIdString.length, typeNodeIdString.data);
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "data type node class: %i (is UA_NODECLASS_DATATYPE=%s)", outNodeClass, outNodeClass == UA_NODECLASS_DATATYPE ? "True" : "False");
if (nodeDataType) {
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "found data type: %s, typeKind=%i", nodeDataType->typeName, nodeDataType->typeKind);
}
else {
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "could not look up data type");
/* abort(); */
return;
}
}
int main(int argc, const char *argv[]) {
signal(SIGINT, stopHandler);
signal(SIGTERM, stopHandler);
UA_Server *server = UA_Server_new();
UA_ServerConfig_setDefault(UA_Server_getConfig(server));
UA_Server_run_startup(server);
/* Add a repeated callback to the server */
UA_Server_addRepeatedCallback(server, testCallback, NULL, 2000, NULL); /* call every 2 sec */
UA_StatusCode retval = myNS(server);
/* Create nodes from nodeset */
if(retval != UA_STATUSCODE_GOOD) {
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Could not add the example nodeset. "
"Check previous output for any error.");
abort();
}
/* for (int cnt = 1; cnt < argc; cnt++) { */
/* if (UA_StatusCode_isGood(UA_Server_loadNodeset(server, argv[cnt], NULL))) { */
/* UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Nodeset %s loaded.", argv[cnt]); */
/* } */
/* else { */
/* printf("Nodeset %s could not be loaded, exit\n", argv[cnt]); */
/* return EXIT_FAILURE; */
/* } */
/* } */
UA_Boolean waitInternal = true;
while(running) {
UA_Server_run_iterate(server, waitInternal);
}
/* UA_StatusCode retval = UA_Server_run(server, &running); */
UA_Server_run_shutdown(server);
UA_Server_delete(server);
return EXIT_SUCCESS;
} Compiled with:
Output:
It seems the compiled nodeset tries to create the same node twice? |
@matkonnerth I've added logging to the generated code so I can see which node ID causes trouble.
It is always the same: |
I've fixed the issue with missing leading zeroes. See open62541/open62541#6355. The server with the compiled nodeset now imports many more variables before aborting:
If that error message is correct, a default value is missing (originally in the XML nodeset, but here in the compiled nodeset). That would mean the nodesetLoader should complain about the missing default value too, instead of silently importing the nodeset without warnings/errors. Correct? |
To reproduce, use issue_253.tgz with the following content:
|
I noticed that
UA_findDataTypeWithCustom()
can't find the data types of imported UAVariables with custom/aliased UADataTypes.Given the following namespaces:
Given these Aliases:
And this UADataType:
And this
UAVariableType
:And this
UAVariable
:(Sorry, I can't provide a full XML nodeset right now. But maybe this info is already enough.)
As preparation for
UA_Server_writeDataValue()
, my code can't find the data type by the type nodeIdAlarmStateStates
nor the type nodeIdns=2;s=af28ed20-dbb6-5624-aa65-4b42023ab1c4
(adjusted for runtime NS index) usingUA_findDataTypeWithCustom()
. Any ideas?The text was updated successfully, but these errors were encountered: