Просмотр исходного кода

UA_Server_add<Type>Node now takes an additional argument to return the nodeId of the actually created node, allowing userspace functions to create hierarchic instances of objects. Fixed an error in addMethodNode that prevented dynamic methods having arguments when using NODEID_NUMERIC(x,0).

ichrispa лет назад: 9
Родитель
Сommit
0fb4fd0f12
4 измененных файлов с 46 добавлено и 29 удалено
  1. 0 4
      CMakeLists.txt
  2. 13 12
      examples/server.c
  3. 9 4
      include/ua_server.h
  4. 24 9
      src/server/ua_server_addressspace.c

+ 0 - 4
CMakeLists.txt

@@ -5,10 +5,6 @@ project(open62541 C)
 
 
 FIND_PACKAGE(PythonInterp REQUIRED)
 FIND_PACKAGE(PythonInterp REQUIRED)
 
 
-set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -march=armv7-r")
-set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -march=armv7-r")
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-r")
-
 # Find Python-lxml
 # Find Python-lxml
 execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE)
 execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE)
 if(NOT EXISTS "${PYTHON_SITE_PACKAGES}/lxml")
 if(NOT EXISTS "${PYTHON_SITE_PACKAGES}/lxml")

+ 13 - 12
examples/server.c

@@ -208,7 +208,7 @@ int main(int argc, char** argv) {
 	UA_DataSource dateDataSource = (UA_DataSource) {.handle = NULL, .read = readTimeData, .write = NULL};
 	UA_DataSource dateDataSource = (UA_DataSource) {.handle = NULL, .read = readTimeData, .write = NULL};
 	const UA_QualifiedName dateName = UA_QUALIFIEDNAME(1, "current time");
 	const UA_QualifiedName dateName = UA_QUALIFIEDNAME(1, "current time");
 	UA_Server_addDataSourceVariableNode(server, dateDataSource, dateName, UA_NODEID_NULL,
 	UA_Server_addDataSourceVariableNode(server, dateDataSource, dateName, UA_NODEID_NULL,
-                                        UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
+                                        UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), NULL);
 
 
 #ifndef _WIN32
 #ifndef _WIN32
 	//cpu temperature monitoring for linux machines
 	//cpu temperature monitoring for linux machines
@@ -217,7 +217,7 @@ int main(int argc, char** argv) {
 		UA_DataSource temperatureDataSource = (UA_DataSource) {.handle = NULL, .read = readTemperature, .write = NULL};
 		UA_DataSource temperatureDataSource = (UA_DataSource) {.handle = NULL, .read = readTemperature, .write = NULL};
 		const UA_QualifiedName tempName = UA_QUALIFIEDNAME(1, "cpu temperature");
 		const UA_QualifiedName tempName = UA_QUALIFIEDNAME(1, "cpu temperature");
 		UA_Server_addDataSourceVariableNode(server, temperatureDataSource, tempName, UA_NODEID_NULL,
 		UA_Server_addDataSourceVariableNode(server, temperatureDataSource, tempName, UA_NODEID_NULL,
-                                            UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
+                                                    UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), NULL);
 	}
 	}
 
 
 	//LED control for rpi
 	//LED control for rpi
@@ -236,7 +236,7 @@ int main(int argc, char** argv) {
             const UA_QualifiedName statusName = UA_QUALIFIEDNAME(0, "status LED");
             const UA_QualifiedName statusName = UA_QUALIFIEDNAME(0, "status LED");
             UA_Server_addDataSourceVariableNode(server, ledStatusDataSource, statusName, UA_NODEID_NULL,
             UA_Server_addDataSourceVariableNode(server, ledStatusDataSource, statusName, UA_NODEID_NULL,
                                                 UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
                                                 UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
-                                                UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
+                                                UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), NULL);
         } else {
         } else {
             UA_LOG_WARNING(logger, UA_LOGCATEGORY_USERLAND, "[Raspberry Pi] LED file exist, but I have no access (try to run server with sudo)");
             UA_LOG_WARNING(logger, UA_LOGCATEGORY_USERLAND, "[Raspberry Pi] LED file exist, but I have no access (try to run server with sudo)");
         }
         }
@@ -252,7 +252,7 @@ int main(int argc, char** argv) {
     UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
     UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
     UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
     UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
     UA_Server_addVariableNode(server, myIntegerVariant, myIntegerName,
     UA_Server_addVariableNode(server, myIntegerVariant, myIntegerName,
-                              myIntegerNodeId, parentNodeId, parentReferenceNodeId);
+                              myIntegerNodeId, parentNodeId, parentReferenceNodeId, NULL);
 
 
    /**************/
    /**************/
    /* Demo Nodes */
    /* Demo Nodes */
@@ -260,19 +260,19 @@ int main(int argc, char** argv) {
 
 
 #define DEMOID 50000
 #define DEMOID 50000
    UA_Server_addObjectNode(server,UA_QUALIFIEDNAME(1, "Demo"), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
    UA_Server_addObjectNode(server,UA_QUALIFIEDNAME(1, "Demo"), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
-                           UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
+                           UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), NULL);
 
 
 #define SCALARID 50001
 #define SCALARID 50001
    UA_Server_addObjectNode(server,UA_QUALIFIEDNAME(1, "Scalar"), UA_NODEID_NUMERIC(1, SCALARID), UA_NODEID_NUMERIC(1, DEMOID),
    UA_Server_addObjectNode(server,UA_QUALIFIEDNAME(1, "Scalar"), UA_NODEID_NUMERIC(1, SCALARID), UA_NODEID_NUMERIC(1, DEMOID),
-                           UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
+                           UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), NULL);
 
 
 #define ARRAYID 50002
 #define ARRAYID 50002
    UA_Server_addObjectNode(server,UA_QUALIFIEDNAME(1, "Array"), UA_NODEID_NUMERIC(1, ARRAYID), UA_NODEID_NUMERIC(1, DEMOID),
    UA_Server_addObjectNode(server,UA_QUALIFIEDNAME(1, "Array"), UA_NODEID_NUMERIC(1, ARRAYID), UA_NODEID_NUMERIC(1, DEMOID),
-                           UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
+                           UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), NULL);
 
 
 #define MATRIXID 50003
 #define MATRIXID 50003
    UA_Server_addObjectNode(server,UA_QUALIFIEDNAME(1, "Matrix"), UA_NODEID_NUMERIC(1, MATRIXID), UA_NODEID_NUMERIC(1, DEMOID),
    UA_Server_addObjectNode(server,UA_QUALIFIEDNAME(1, "Matrix"), UA_NODEID_NUMERIC(1, MATRIXID), UA_NODEID_NUMERIC(1, DEMOID),
-                           UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
+                           UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), NULL);
 
 
    UA_UInt32 id = 51000; //running id in namespace 0
    UA_UInt32 id = 51000; //running id in namespace 0
    for(UA_UInt32 type = 0; UA_IS_BUILTIN(type); type++) {
    for(UA_UInt32 type = 0; UA_IS_BUILTIN(type); type++) {
@@ -286,13 +286,13 @@ int main(int argc, char** argv) {
         sprintf(name, "%02d", type);
         sprintf(name, "%02d", type);
         UA_QualifiedName qualifiedName = UA_QUALIFIEDNAME(1, name);
         UA_QualifiedName qualifiedName = UA_QUALIFIEDNAME(1, name);
         UA_Server_addVariableNode(server, variant, qualifiedName, UA_NODEID_NUMERIC(1, ++id),
         UA_Server_addVariableNode(server, variant, qualifiedName, UA_NODEID_NUMERIC(1, ++id),
-                                  UA_NODEID_NUMERIC(1, SCALARID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
+                                  UA_NODEID_NUMERIC(1, SCALARID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), NULL);
 
 
         //add an array node for every built-in type
         //add an array node for every built-in type
         UA_Variant *arrayvar = UA_Variant_new();
         UA_Variant *arrayvar = UA_Variant_new();
         UA_Variant_setArray(arrayvar, UA_Array_new(&UA_TYPES[type], 10), 10, &UA_TYPES[type]);
         UA_Variant_setArray(arrayvar, UA_Array_new(&UA_TYPES[type], 10), 10, &UA_TYPES[type]);
         UA_Server_addVariableNode(server, arrayvar, qualifiedName, UA_NODEID_NUMERIC(1, ++id),
         UA_Server_addVariableNode(server, arrayvar, qualifiedName, UA_NODEID_NUMERIC(1, ++id),
-                                  UA_NODEID_NUMERIC(1, ARRAYID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
+                                  UA_NODEID_NUMERIC(1, ARRAYID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), NULL);
 
 
         //add an matrix node for every built-in type
         //add an matrix node for every built-in type
         arrayvar = UA_Variant_new();
         arrayvar = UA_Variant_new();
@@ -305,7 +305,7 @@ int main(int argc, char** argv) {
         arrayvar->data = myMultiArray;
         arrayvar->data = myMultiArray;
         arrayvar->type = &UA_TYPES[type];
         arrayvar->type = &UA_TYPES[type];
         UA_Server_addVariableNode(server, arrayvar, qualifiedName, UA_NODEID_NUMERIC(1, ++id),
         UA_Server_addVariableNode(server, arrayvar, qualifiedName, UA_NODEID_NUMERIC(1, ++id),
-                                  UA_NODEID_NUMERIC(1, MATRIXID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
+                                  UA_NODEID_NUMERIC(1, MATRIXID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), NULL);
    }
    }
 
 
 
 
@@ -330,9 +330,10 @@ int main(int argc, char** argv) {
    outputArguments.name = UA_STRING("Input an integer");
    outputArguments.name = UA_STRING("Input an integer");
    outputArguments.valueRank = -1;
    outputArguments.valueRank = -1;
 
 
+   UA_NodeId methodId; // Retrieve the actual ID if this node if a random id as in UA_NODEID_NUMERIC(1,0) is used
    UA_Server_addMethodNode(server, UA_QUALIFIEDNAME(1,"ping"), UA_NODEID_NUMERIC(1,62541),
    UA_Server_addMethodNode(server, UA_QUALIFIEDNAME(1,"ping"), UA_NODEID_NUMERIC(1,62541),
                            UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
                            UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
-                           &getMonitoredItems, 1, &inputArguments, 1, &outputArguments);
+                           &getMonitoredItems, 1, &inputArguments, 1, &outputArguments, &methodId);
 #endif
 #endif
 	//start server
 	//start server
 	UA_StatusCode retval = UA_Server_run(server, 1, &running); //blocks until running=false
 	UA_StatusCode retval = UA_Server_run(server, 1, &running); //blocks until running=false

+ 9 - 4
include/ua_server.h

@@ -126,17 +126,21 @@ UA_StatusCode UA_EXPORT UA_Server_addReference(UA_Server *server, const UA_NodeI
 
 
 UA_StatusCode UA_EXPORT
 UA_StatusCode UA_EXPORT
 UA_Server_addVariableNode(UA_Server *server, UA_Variant *value, const UA_QualifiedName browseName, 
 UA_Server_addVariableNode(UA_Server *server, UA_Variant *value, const UA_QualifiedName browseName, 
-                          UA_NodeId nodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId);
+                          UA_NodeId nodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
+                          UA_NodeId *createdNodeId
+                         );
 
 
 UA_StatusCode UA_EXPORT
 UA_StatusCode UA_EXPORT
 UA_Server_addObjectNode(UA_Server *server, const UA_QualifiedName browseName,
 UA_Server_addObjectNode(UA_Server *server, const UA_QualifiedName browseName,
                         UA_NodeId nodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
                         UA_NodeId nodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
-                        const UA_NodeId typeDefinition);
+                        const UA_NodeId typeDefinition,
+                        UA_NodeId *createdNodeId);
 
 
 UA_StatusCode UA_EXPORT
 UA_StatusCode UA_EXPORT
 UA_Server_addDataSourceVariableNode(UA_Server *server, UA_DataSource dataSource,
 UA_Server_addDataSourceVariableNode(UA_Server *server, UA_DataSource dataSource,
                                     const UA_QualifiedName browseName, UA_NodeId nodeId,
                                     const UA_QualifiedName browseName, UA_NodeId nodeId,
-                                    const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId);
+                                    const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
+                                    UA_NodeId *createdNodeId);
 
 
 UA_StatusCode UA_EXPORT
 UA_StatusCode UA_EXPORT
 UA_Server_AddMonodirectionalReference(UA_Server *server, UA_NodeId sourceNodeId,
 UA_Server_AddMonodirectionalReference(UA_Server *server, UA_NodeId sourceNodeId,
@@ -153,7 +157,8 @@ UA_Server_addMethodNode(UA_Server *server, const UA_QualifiedName browseName, UA
                         const UA_ExpandedNodeId parentNodeId, const UA_NodeId referenceTypeId,
                         const UA_ExpandedNodeId parentNodeId, const UA_NodeId referenceTypeId,
                         UA_MethodCallback method, UA_Int32 inputArgumentsSize,
                         UA_MethodCallback method, UA_Int32 inputArgumentsSize,
                         const UA_Argument *inputArguments, UA_Int32 outputArgumentsSize,
                         const UA_Argument *inputArguments, UA_Int32 outputArgumentsSize,
-                        const UA_Argument *outputArguments);
+                        const UA_Argument *outputArguments,
+                        UA_NodeId *createdNodeId);
 #endif
 #endif
 
 
 /** Jobs describe work that is executed once or repeatedly. */
 /** Jobs describe work that is executed once or repeatedly. */

+ 24 - 9
src/server/ua_server_addressspace.c

@@ -3,7 +3,8 @@
 
 
 UA_StatusCode
 UA_StatusCode
 UA_Server_addVariableNode(UA_Server *server, UA_Variant *value, const UA_QualifiedName browseName, 
 UA_Server_addVariableNode(UA_Server *server, UA_Variant *value, const UA_QualifiedName browseName, 
-                          UA_NodeId nodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId) {
+                          UA_NodeId nodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
+                          UA_NodeId *createdNodeId) {
     UA_VariableNode *node = UA_VariableNode_new();
     UA_VariableNode *node = UA_VariableNode_new();
     node->value.variant = *value; // copy content
     node->value.variant = *value; // copy content
     UA_NodeId_copy(&nodeId, &node->nodeId);
     UA_NodeId_copy(&nodeId, &node->nodeId);
@@ -19,8 +20,10 @@ UA_Server_addVariableNode(UA_Server *server, UA_Variant *value, const UA_Qualifi
     if(res.statusCode != UA_STATUSCODE_GOOD) {
     if(res.statusCode != UA_STATUSCODE_GOOD) {
         UA_Variant_init(&node->value.variant);
         UA_Variant_init(&node->value.variant);
         UA_VariableNode_delete(node);
         UA_VariableNode_delete(node);
-    } else
+    } else 
         UA_free(value);
         UA_free(value);
+    if (createdNodeId != UA_NULL)
+      UA_NodeId_copy(&res.addedNodeId, createdNodeId);
     UA_AddNodesResult_deleteMembers(&res);
     UA_AddNodesResult_deleteMembers(&res);
     return res.statusCode;
     return res.statusCode;
 }
 }
@@ -28,7 +31,8 @@ UA_Server_addVariableNode(UA_Server *server, UA_Variant *value, const UA_Qualifi
 UA_StatusCode
 UA_StatusCode
 UA_Server_addObjectNode(UA_Server *server, const UA_QualifiedName browseName, UA_NodeId nodeId,
 UA_Server_addObjectNode(UA_Server *server, const UA_QualifiedName browseName, UA_NodeId nodeId,
                         const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
                         const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
-                        const UA_NodeId typeDefinition) {
+                        const UA_NodeId typeDefinition,
+                        UA_NodeId *createdNodeId) {
     UA_ObjectNode *node = UA_ObjectNode_new();
     UA_ObjectNode *node = UA_ObjectNode_new();
     UA_NodeId_copy(&nodeId, &node->nodeId);
     UA_NodeId_copy(&nodeId, &node->nodeId);
     UA_QualifiedName_copy(&browseName, &node->browseName);
     UA_QualifiedName_copy(&browseName, &node->browseName);
@@ -40,6 +44,8 @@ UA_Server_addObjectNode(UA_Server *server, const UA_QualifiedName browseName, UA
                                                          parentId, referenceTypeId);
                                                          parentId, referenceTypeId);
     if(res.statusCode != UA_STATUSCODE_GOOD)
     if(res.statusCode != UA_STATUSCODE_GOOD)
         UA_ObjectNode_delete(node);
         UA_ObjectNode_delete(node);
+    if (createdNodeId != UA_NULL)
+      UA_NodeId_copy(&res.addedNodeId, createdNodeId);
     UA_AddNodesResult_deleteMembers(&res);
     UA_AddNodesResult_deleteMembers(&res);
 
 
     if(!UA_NodeId_isNull(&typeDefinition)) {
     if(!UA_NodeId_isNull(&typeDefinition)) {
@@ -55,7 +61,8 @@ UA_Server_addObjectNode(UA_Server *server, const UA_QualifiedName browseName, UA
 UA_StatusCode
 UA_StatusCode
 UA_Server_addDataSourceVariableNode(UA_Server *server, UA_DataSource dataSource,
 UA_Server_addDataSourceVariableNode(UA_Server *server, UA_DataSource dataSource,
                                     const UA_QualifiedName browseName, UA_NodeId nodeId,
                                     const UA_QualifiedName browseName, UA_NodeId nodeId,
-                                    const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId) {
+                                    const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
+                                    UA_NodeId *createdNodeId) {
     UA_VariableNode *node = UA_VariableNode_new();
     UA_VariableNode *node = UA_VariableNode_new();
     node->valueSource = UA_VALUESOURCE_DATASOURCE;
     node->valueSource = UA_VALUESOURCE_DATASOURCE;
     node->value.dataSource = dataSource;
     node->value.dataSource = dataSource;
@@ -71,6 +78,8 @@ UA_Server_addDataSourceVariableNode(UA_Server *server, UA_DataSource dataSource,
                            UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
                            UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
     if(res.statusCode != UA_STATUSCODE_GOOD)
     if(res.statusCode != UA_STATUSCODE_GOOD)
         UA_VariableNode_delete(node);
         UA_VariableNode_delete(node);
+    if (createdNodeId != UA_NULL)
+      UA_NodeId_copy(&res.addedNodeId, createdNodeId);
     UA_AddNodesResult_deleteMembers(&res);
     UA_AddNodesResult_deleteMembers(&res);
     return res.statusCode;
     return res.statusCode;
 }
 }
@@ -373,7 +382,8 @@ UA_Server_addMethodNode(UA_Server *server, const UA_QualifiedName browseName, UA
                         const UA_ExpandedNodeId parentNodeId, const UA_NodeId referenceTypeId,
                         const UA_ExpandedNodeId parentNodeId, const UA_NodeId referenceTypeId,
                         UA_MethodCallback method, UA_Int32 inputArgumentsSize,
                         UA_MethodCallback method, UA_Int32 inputArgumentsSize,
                         const UA_Argument *inputArguments, UA_Int32 outputArgumentsSize,
                         const UA_Argument *inputArguments, UA_Int32 outputArgumentsSize,
-                        const UA_Argument *outputArguments) {
+                        const UA_Argument *outputArguments,
+                        UA_NodeId *createdNodeId) {
     UA_MethodNode *newMethod = UA_MethodNode_new();
     UA_MethodNode *newMethod = UA_MethodNode_new();
     UA_NodeId_copy(&nodeId, &newMethod->nodeId);
     UA_NodeId_copy(&nodeId, &newMethod->nodeId);
     UA_QualifiedName_copy(&browseName, &newMethod->browseName);
     UA_QualifiedName_copy(&browseName, &newMethod->browseName);
@@ -381,10 +391,6 @@ UA_Server_addMethodNode(UA_Server *server, const UA_QualifiedName browseName, UA
     newMethod->attachedMethod = method;
     newMethod->attachedMethod = method;
     newMethod->executable = UA_TRUE;
     newMethod->executable = UA_TRUE;
     newMethod->userExecutable = UA_TRUE;
     newMethod->userExecutable = UA_TRUE;
-
-    UA_ExpandedNodeId methodExpandedNodeId;
-    UA_ExpandedNodeId_init(&methodExpandedNodeId);
-    UA_NodeId_copy(&newMethod->nodeId, &methodExpandedNodeId.nodeId);
     
     
     UA_AddNodesResult addRes = UA_Server_addNode(server, (UA_Node*)newMethod, parentNodeId, referenceTypeId);
     UA_AddNodesResult addRes = UA_Server_addNode(server, (UA_Node*)newMethod, parentNodeId, referenceTypeId);
     if(addRes.statusCode != UA_STATUSCODE_GOOD) {
     if(addRes.statusCode != UA_STATUSCODE_GOOD) {
@@ -392,6 +398,13 @@ UA_Server_addMethodNode(UA_Server *server, const UA_QualifiedName browseName, UA
         return addRes.statusCode;
         return addRes.statusCode;
     }
     }
     
     
+    UA_ExpandedNodeId methodExpandedNodeId;
+    UA_ExpandedNodeId_init(&methodExpandedNodeId);
+    UA_NodeId_copy(&addRes.addedNodeId, &methodExpandedNodeId.nodeId);
+    
+    if (createdNodeId != UA_NULL)
+      UA_NodeId_copy(&addRes.addedNodeId, createdNodeId);
+    
     /* create InputArguments */
     /* create InputArguments */
     UA_NodeId argId = UA_NODEID_NUMERIC(nodeId.namespaceIndex, 0); 
     UA_NodeId argId = UA_NODEID_NUMERIC(nodeId.namespaceIndex, 0); 
     UA_VariableNode *inputArgumentsVariableNode  = UA_VariableNode_new();
     UA_VariableNode *inputArgumentsVariableNode  = UA_VariableNode_new();
@@ -409,6 +422,8 @@ UA_Server_addMethodNode(UA_Server *server, const UA_QualifiedName browseName, UA
         // TODO Remove node
         // TODO Remove node
         return addRes.statusCode;
         return addRes.statusCode;
     }
     }
+    if (createdNodeId != UA_NULL)
+      UA_NodeId_copy(&addRes.addedNodeId, createdNodeId);
     
     
     /* create OutputArguments */
     /* create OutputArguments */
     argId = UA_NODEID_NUMERIC(nodeId.namespaceIndex, 0);
     argId = UA_NODEID_NUMERIC(nodeId.namespaceIndex, 0);