UA_StatusCode UA_Server_addObjectNode(UA_Server *server, const UA_QualifiedName browseName, UA_NodeId nodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, const UA_NodeId typeDefinition) { UA_ObjectNode *node = UA_ObjectNode_new(); UA_NodeId_copy(&nodeId, &node->nodeId); UA_QualifiedName_copy(&browseName, &node->browseName); UA_String_copy(&browseName.name, &node->displayName.text); UA_ExpandedNodeId parentId; // we need an expandednodeid UA_ExpandedNodeId_init(&parentId); UA_NodeId_copy(&parentNodeId, &parentId.nodeId); UA_AddNodesResult res = UA_Server_addNodeWithSession(server, &adminSession, (UA_Node*)node, parentId, referenceTypeId); if(res.statusCode != UA_STATUSCODE_GOOD) { UA_ObjectNode_delete(node); } UA_AddNodesResult_deleteMembers(&res); if(!(UA_NodeId_isNull(&typeDefinition))){ UA_ExpandedNodeId typeDefid; // we need an expandednodeid UA_ExpandedNodeId_init(&typeDefid); UA_NodeId_copy(&typeDefinition, &typeDefid.nodeId); ADDREFERENCE(res.addedNodeId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION), typeDefid); } return res.statusCode; }
static UA_VariableNode* makeCompareSequence(void) { UA_VariableNode *node = UA_VariableNode_new(); UA_Variant *myIntegerVariant = UA_Variant_new(); UA_Int32 myInteger = 42; UA_Variant_setScalarCopy(myIntegerVariant, &myInteger, &UA_TYPES[UA_TYPES_INT32]); const UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer"); const UA_LocalizedText myIntegerDisplName = UA_LOCALIZEDTEXT("en_US", "the answer"); const UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer"); UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); //UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES); node->value.variant.value = *myIntegerVariant; UA_NodeId_copy(&myIntegerNodeId,&node->nodeId); UA_QualifiedName_copy(&myIntegerName,&node->browseName); UA_LocalizedText_copy(&myIntegerDisplName, &node->displayName); UA_LocalizedText_copy(&myIntegerDisplName, &node->description); UA_ExpandedNodeId parentId; UA_ExpandedNodeId_init(&parentId); UA_NodeId_copy(&parentNodeId,&parentId.nodeId); return node; }
UA_StatusCode UA_Server_addDataSourceVariableNode(UA_Server *server, UA_DataSource dataSource, const UA_QualifiedName browseName, UA_NodeId nodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId) { UA_VariableNode *node = UA_VariableNode_new(); node->valueSource = UA_VALUESOURCE_DATASOURCE; node->value.dataSource = dataSource; UA_NodeId_copy(&nodeId, &node->nodeId); UA_QualifiedName_copy(&browseName, &node->browseName); UA_String_copy(&browseName.name, &node->displayName.text); UA_ExpandedNodeId parentId; // dummy exapndednodeid UA_ExpandedNodeId_init(&parentId); UA_NodeId_copy(&parentNodeId, &parentId.nodeId); UA_AddNodesResult res = UA_Server_addNodeWithSession(server, &adminSession, (UA_Node*)node, parentId, referenceTypeId); ADDREFERENCE(res.addedNodeId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION), UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE)); if(res.statusCode != UA_STATUSCODE_GOOD) UA_VariableNode_delete(node); UA_AddNodesResult_deleteMembers(&res); return res.statusCode; }
UA_StatusCode 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_VariableNode *node = UA_VariableNode_new(); node->value.variant = *value; // copy content UA_NodeId_copy(&nodeId, &node->nodeId); UA_QualifiedName_copy(&browseName, &node->browseName); UA_String_copy(&browseName.name, &node->displayName.text); UA_ExpandedNodeId parentId; // we need an expandednodeid UA_ExpandedNodeId_init(&parentId); UA_NodeId_copy(&parentNodeId, &parentId.nodeId); UA_AddNodesResult res = UA_Server_addNodeWithSession(server, &adminSession, (UA_Node*)node, parentId, referenceTypeId); ADDREFERENCE(res.addedNodeId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION), UA_EXPANDEDNODEID_NUMERIC(0, value->type->typeId.identifier.numeric)); if(res.statusCode != UA_STATUSCODE_GOOD) { UA_Variant_init(&node->value.variant); UA_VariableNode_delete(node); } else UA_free(value); UA_AddNodesResult_deleteMembers(&res); return res.statusCode; }
UA_StatusCode UA_EXPORT UA_Server_addMethodNode(UA_Server *server, const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, const UA_MethodAttributes attr, UA_MethodCallback method, void *handle, UA_Int32 inputArgumentsSize, const UA_Argument* inputArguments, UA_Int32 outputArgumentsSize, const UA_Argument* outputArguments, UA_NodeId *outNewNodeId) { UA_AddNodesResult result; UA_AddNodesResult_init(&result); UA_AddNodesItem item; UA_AddNodesItem_init(&item); result.statusCode = UA_QualifiedName_copy(&browseName, &item.browseName); item.nodeClass = UA_NODECLASS_METHOD; result.statusCode |= UA_NodeId_copy(&parentNodeId, &item.parentNodeId.nodeId); result.statusCode |= UA_NodeId_copy(&referenceTypeId, &item.referenceTypeId); result.statusCode |= UA_NodeId_copy(&requestedNewNodeId, &item.requestedNewNodeId.nodeId); UA_MethodAttributes attrCopy; result.statusCode |= UA_MethodAttributes_copy(&attr, &attrCopy); if(result.statusCode != UA_STATUSCODE_GOOD) { UA_AddNodesItem_deleteMembers(&item); UA_MethodAttributes_deleteMembers(&attrCopy); return result.statusCode; } UA_MethodNode *node = UA_MethodNode_new(); if(!node) { result.statusCode = UA_STATUSCODE_BADOUTOFMEMORY; UA_AddNodesItem_deleteMembers(&item); UA_MethodAttributes_deleteMembers(&attrCopy); return result.statusCode; } copyStandardAttributes((UA_Node*)node, &item, (UA_NodeAttributes*)&attrCopy); node->executable = attrCopy.executable; node->userExecutable = attrCopy.executable; node->attachedMethod = method; node->methodHandle = handle; UA_AddNodesItem_deleteMembers(&item); UA_MethodAttributes_deleteMembers(&attrCopy); UA_Server_addExistingNode(server, &adminSession, (UA_Node*)node, &item.parentNodeId.nodeId, &item.referenceTypeId, &result); if(result.statusCode != UA_STATUSCODE_GOOD) { UA_MethodNode_delete(node); return result.statusCode; } UA_ExpandedNodeId parent; UA_ExpandedNodeId_init(&parent); parent.nodeId = result.addedNodeId; /* create InputArguments */ UA_VariableNode *inputArgumentsVariableNode = UA_VariableNode_new(); inputArgumentsVariableNode->nodeId.namespaceIndex = result.addedNodeId.namespaceIndex; inputArgumentsVariableNode->browseName = UA_QUALIFIEDNAME_ALLOC(0,"InputArguments"); inputArgumentsVariableNode->displayName = UA_LOCALIZEDTEXT_ALLOC("en_US", "InputArguments"); inputArgumentsVariableNode->description = UA_LOCALIZEDTEXT_ALLOC("en_US", "InputArguments"); inputArgumentsVariableNode->valueRank = 1; UA_Variant_setArrayCopy(&inputArgumentsVariableNode->value.variant.value, inputArguments, inputArgumentsSize, &UA_TYPES[UA_TYPES_ARGUMENT]); UA_AddNodesResult inputAddRes; const UA_NodeId hasproperty = UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY); UA_Server_addExistingNode(server, &adminSession, (UA_Node*)inputArgumentsVariableNode, &parent.nodeId, &hasproperty, &inputAddRes); // todo: check if adding succeeded UA_AddNodesResult_deleteMembers(&inputAddRes); /* create OutputArguments */ UA_VariableNode *outputArgumentsVariableNode = UA_VariableNode_new(); outputArgumentsVariableNode->nodeId.namespaceIndex = result.addedNodeId.namespaceIndex; outputArgumentsVariableNode->browseName = UA_QUALIFIEDNAME_ALLOC(0,"OutputArguments"); outputArgumentsVariableNode->displayName = UA_LOCALIZEDTEXT_ALLOC("en_US", "OutputArguments"); outputArgumentsVariableNode->description = UA_LOCALIZEDTEXT_ALLOC("en_US", "OutputArguments"); outputArgumentsVariableNode->valueRank = 1; UA_Variant_setArrayCopy(&outputArgumentsVariableNode->value.variant.value, outputArguments, outputArgumentsSize, &UA_TYPES[UA_TYPES_ARGUMENT]); UA_AddNodesResult outputAddRes; UA_Server_addExistingNode(server, &adminSession, (UA_Node*)outputArgumentsVariableNode, &parent.nodeId, &hasproperty, &outputAddRes); // todo: check if adding succeeded UA_AddNodesResult_deleteMembers(&outputAddRes); if(outNewNodeId) *outNewNodeId = result.addedNodeId; else UA_AddNodesResult_deleteMembers(&result); return result.statusCode; }
UA_StatusCode UA_EXPORT UA_Server_addMethodNode(UA_Server *server, const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, const UA_MethodAttributes attr, UA_MethodCallback method, void *handle, size_t inputArgumentsSize, const UA_Argument* inputArguments, size_t outputArgumentsSize, const UA_Argument* outputArguments, UA_NodeId *outNewNodeId) { UA_AddNodesResult result; UA_AddNodesResult_init(&result); UA_AddNodesItem item; UA_AddNodesItem_init(&item); result.statusCode = UA_QualifiedName_copy(&browseName, &item.browseName); item.nodeClass = UA_NODECLASS_METHOD; result.statusCode |= UA_NodeId_copy(&parentNodeId, &item.parentNodeId.nodeId); result.statusCode |= UA_NodeId_copy(&referenceTypeId, &item.referenceTypeId); result.statusCode |= UA_NodeId_copy(&requestedNewNodeId, &item.requestedNewNodeId.nodeId); UA_MethodAttributes attrCopy; result.statusCode |= UA_MethodAttributes_copy(&attr, &attrCopy); if(result.statusCode != UA_STATUSCODE_GOOD) { UA_AddNodesItem_deleteMembers(&item); UA_MethodAttributes_deleteMembers(&attrCopy); return result.statusCode; } UA_MethodNode *node = UA_NodeStore_newMethodNode(); if(!node) { result.statusCode = UA_STATUSCODE_BADOUTOFMEMORY; UA_AddNodesItem_deleteMembers(&item); UA_MethodAttributes_deleteMembers(&attrCopy); return result.statusCode; } copyStandardAttributes((UA_Node*)node, &item, (UA_NodeAttributes*)&attrCopy); node->executable = attrCopy.executable; node->userExecutable = attrCopy.executable; node->attachedMethod = method; node->methodHandle = handle; UA_AddNodesItem_deleteMembers(&item); UA_MethodAttributes_deleteMembers(&attrCopy); UA_RCU_LOCK(); UA_Server_addExistingNode(server, &adminSession, (UA_Node*)node, &item.parentNodeId.nodeId, &item.referenceTypeId, &result); UA_RCU_UNLOCK(); if(result.statusCode != UA_STATUSCODE_GOOD) return result.statusCode; UA_ExpandedNodeId parent; UA_ExpandedNodeId_init(&parent); parent.nodeId = result.addedNodeId; /* create InputArguments */ /* FIXME: The namespace compiler does currently not recognize the interdependancy between methods * and arguments - everything is treated as a standalone node. * In order to allow the compiler to create methods with arguments from an XML, this routine * must be coerced into *not* creating arguments, as these will be added by the compiler as * standalone nodes later. A semantic of inputArgumentsSize < 0 is used to signal this. * * This is not a production feature and should be fixed on the compiler side! (@ichrispa) */ const UA_NodeId hasproperty = UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY); UA_VariableNode *inputArgumentsVariableNode = UA_NodeStore_newVariableNode(); inputArgumentsVariableNode->nodeId.namespaceIndex = result.addedNodeId.namespaceIndex; inputArgumentsVariableNode->browseName = UA_QUALIFIEDNAME_ALLOC(0,"InputArguments"); inputArgumentsVariableNode->displayName = UA_LOCALIZEDTEXT_ALLOC("en_US", "InputArguments"); inputArgumentsVariableNode->description = UA_LOCALIZEDTEXT_ALLOC("en_US", "InputArguments"); inputArgumentsVariableNode->valueRank = 1; UA_Variant_setArrayCopy(&inputArgumentsVariableNode->value.variant.value, inputArguments, inputArgumentsSize, &UA_TYPES[UA_TYPES_ARGUMENT]); UA_AddNodesResult inputAddRes; UA_Server_addExistingNode(server, &adminSession, (UA_Node*)inputArgumentsVariableNode, &parent.nodeId, &hasproperty, &inputAddRes); // todo: check if adding succeeded UA_AddNodesResult_deleteMembers(&inputAddRes); /* create OutputArguments */ /* FIXME: See comment in inputArguments */ UA_VariableNode *outputArgumentsVariableNode = UA_NodeStore_newVariableNode(); outputArgumentsVariableNode->nodeId.namespaceIndex = result.addedNodeId.namespaceIndex; outputArgumentsVariableNode->browseName = UA_QUALIFIEDNAME_ALLOC(0,"OutputArguments"); outputArgumentsVariableNode->displayName = UA_LOCALIZEDTEXT_ALLOC("en_US", "OutputArguments"); outputArgumentsVariableNode->description = UA_LOCALIZEDTEXT_ALLOC("en_US", "OutputArguments"); outputArgumentsVariableNode->valueRank = 1; UA_Variant_setArrayCopy(&outputArgumentsVariableNode->value.variant.value, outputArguments, outputArgumentsSize, &UA_TYPES[UA_TYPES_ARGUMENT]); UA_AddNodesResult outputAddRes; UA_Server_addExistingNode(server, &adminSession, (UA_Node*)outputArgumentsVariableNode, &parent.nodeId, &hasproperty, &outputAddRes); // todo: check if adding succeeded UA_AddNodesResult_deleteMembers(&outputAddRes); if(outNewNodeId) *outNewNodeId = result.addedNodeId; // don't deleteMember the result else UA_AddNodesResult_deleteMembers(&result); return result.statusCode; }