static UA_StatusCode instantiateObjectNode(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId, const UA_NodeId *typeId, UA_InstantiationCallback *instantiationCallback) { const UA_ObjectTypeNode *typenode = (const UA_ObjectTypeNode*)UA_NodeStore_get(server->nodestore, typeId); if(!typenode) return UA_STATUSCODE_BADNODEIDINVALID; if(typenode->nodeClass != UA_NODECLASS_OBJECTTYPE) return UA_STATUSCODE_BADNODECLASSINVALID; /* Add all the child nodes */ UA_BrowseDescription browseChildren; UA_BrowseDescription_init(&browseChildren); browseChildren.nodeId = *typeId; browseChildren.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_AGGREGATES); browseChildren.includeSubtypes = UA_TRUE; browseChildren.browseDirection = UA_BROWSEDIRECTION_FORWARD; browseChildren.nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_METHOD; browseChildren.resultMask = UA_BROWSERESULTMASK_REFERENCETYPEID | UA_BROWSERESULTMASK_NODECLASS; UA_BrowseResult browseResult; UA_BrowseResult_init(&browseResult); // todo: continuation points if there are too many results Service_Browse_single(server, session, NULL, &browseChildren, 100, &browseResult); for(size_t i = 0; i < browseResult.referencesSize; i++) { UA_ReferenceDescription *rd = &browseResult.references[i]; if(rd->nodeClass == UA_NODECLASS_METHOD) { /* add a reference to the method in the objecttype */ UA_AddReferencesItem item; UA_AddReferencesItem_init(&item); item.sourceNodeId = *nodeId; item.referenceTypeId = rd->referenceTypeId; item.isForward = UA_TRUE; item.targetNodeId = rd->nodeId; item.targetNodeClass = UA_NODECLASS_METHOD; Service_AddReferences_single(server, session, &item); } else if(rd->nodeClass == UA_NODECLASS_VARIABLE) copyExistingVariable(server, session, &rd->nodeId.nodeId, &rd->referenceTypeId, nodeId, instantiationCallback); else if(rd->nodeClass == UA_NODECLASS_OBJECT) copyExistingObject(server, session, &rd->nodeId.nodeId, &rd->referenceTypeId, nodeId, instantiationCallback); } /* add a hastypedefinition reference */ UA_AddReferencesItem addref; UA_AddReferencesItem_init(&addref); addref.sourceNodeId = *nodeId; addref.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION); addref.isForward = UA_TRUE; addref.targetNodeId.nodeId = *typeId; addref.targetNodeClass = UA_NODECLASS_OBJECTTYPE; Service_AddReferences_single(server, session, &addref); /* call the constructor */ const UA_ObjectLifecycleManagement *olm = &typenode->lifecycleManagement; if(olm->constructor) UA_Server_editNode(server, session, nodeId, (UA_EditNodeCallback)setObjectInstanceHandle, olm->constructor(*nodeId)); return UA_STATUSCODE_GOOD; }
static UA_StatusCode instantiateVariableNode(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId, const UA_NodeId *typeId) { const UA_ObjectTypeNode *type = (const UA_ObjectTypeNode*)UA_NodeStore_get(server->nodestore, typeId); if(!type) return UA_STATUSCODE_BADNODEIDINVALID; if(type->nodeClass != UA_NODECLASS_VARIABLETYPE) return UA_STATUSCODE_BADNODECLASSINVALID; /* get the references to child properties */ UA_BrowseDescription browseChildren; UA_BrowseDescription_init(&browseChildren); browseChildren.nodeId = *typeId; browseChildren.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY); browseChildren.includeSubtypes = UA_TRUE; browseChildren.browseDirection = UA_BROWSEDIRECTION_FORWARD; browseChildren.nodeClassMask = UA_NODECLASS_VARIABLE; browseChildren.resultMask = UA_BROWSERESULTMASK_REFERENCETYPEID | UA_BROWSERESULTMASK_NODECLASS; UA_BrowseResult browseResult; UA_BrowseResult_init(&browseResult); // todo: continuation points if there are too many results Service_Browse_single(server, session, NULL, &browseChildren, 100, &browseResult); /* add the child properties */ for(size_t i = 0; i < browseResult.referencesSize; i++) { UA_ReferenceDescription *rd = &browseResult.references[i]; copyExistingVariable(server, session, &rd->nodeId.nodeId, &rd->referenceTypeId, nodeId); } /* add a hastypedefinition reference */ UA_AddReferencesItem addref; UA_AddReferencesItem_init(&addref); addref.sourceNodeId = *nodeId; addref.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION); addref.isForward = UA_TRUE; addref.targetNodeId.nodeId = *typeId; addref.targetNodeClass = UA_NODECLASS_OBJECTTYPE; Service_AddReferences_single(server, session, &addref); return UA_STATUSCODE_GOOD; }