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; }
/* copy an existing variable under the given parent. then instantiate the variable for all hastypedefinitions of the original version. */ static UA_StatusCode copyExistingVariable(UA_Server *server, UA_Session *session, const UA_NodeId *variable, const UA_NodeId *referenceType, const UA_NodeId *parent) { const UA_VariableNode *node = (const UA_VariableNode*)UA_NodeStore_get(server->nodestore, variable); if(!node) return UA_STATUSCODE_BADNODEIDINVALID; if(node->nodeClass != UA_NODECLASS_VARIABLE) return UA_STATUSCODE_BADNODECLASSINVALID; // copy the variable attributes UA_VariableAttributes attr; UA_VariableAttributes_init(&attr); UA_LocalizedText_copy(&node->displayName, &attr.displayName); UA_LocalizedText_copy(&node->description, &attr.description); attr.writeMask = node->writeMask; attr.userWriteMask = node->userWriteMask; // todo: handle data sources!!!! UA_Variant_copy(&node->value.variant.value, &attr.value); // datatype is taken from the value // valuerank is taken from the value // array dimensions are taken from the value attr.accessLevel = node->accessLevel; attr.userAccessLevel = node->userAccessLevel; attr.minimumSamplingInterval = node->minimumSamplingInterval; attr.historizing = node->historizing; UA_AddNodesItem item; UA_AddNodesItem_init(&item); UA_NodeId_copy(parent, &item.parentNodeId.nodeId); UA_NodeId_copy(referenceType, &item.referenceTypeId); UA_QualifiedName_copy(&node->browseName, &item.browseName); item.nodeClass = UA_NODECLASS_VARIABLE; item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE; item.nodeAttributes.content.decoded.type = &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES]; item.nodeAttributes.content.decoded.data = &attr; // don't add a typedefinition here. // add the new variable UA_AddNodesResult res; UA_AddNodesResult_init(&res); Service_AddNodes_single(server, session, &item, &res); UA_VariableAttributes_deleteMembers(&attr); UA_AddNodesItem_deleteMembers(&item); // now instantiate the variable for all hastypedefinition references for(size_t i = 0; i < node->referencesSize; i++) { UA_ReferenceNode *rn = &node->references[i]; if(rn->isInverse) continue; const UA_NodeId hasTypeDef = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION); if(!UA_NodeId_equal(&rn->referenceTypeId, &hasTypeDef)) continue; instantiateVariableNode(server, session, &res.addedNodeId, &rn->targetId.nodeId); } UA_AddNodesResult_deleteMembers(&res); return UA_STATUSCODE_GOOD; }
UA_StatusCode UA_EXPORT UA_Server_addDataSourceVariableNode(UA_Server *server, const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, const UA_NodeId typeDefinition, const UA_VariableAttributes attr, const UA_DataSource dataSource, 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_VARIABLE; 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); result.statusCode |= UA_NodeId_copy(&typeDefinition, &item.typeDefinition.nodeId); UA_VariableAttributes attrCopy; result.statusCode |= UA_VariableAttributes_copy(&attr, &attrCopy); if(result.statusCode != UA_STATUSCODE_GOOD) { UA_AddNodesItem_deleteMembers(&item); UA_VariableAttributes_deleteMembers(&attrCopy); return result.statusCode; } UA_VariableNode *node = UA_VariableNode_new(); if(!node) { UA_AddNodesItem_deleteMembers(&item); UA_VariableAttributes_deleteMembers(&attrCopy); return UA_STATUSCODE_BADOUTOFMEMORY; } copyStandardAttributes((UA_Node*)node, &item, (UA_NodeAttributes*)&attrCopy); node->valueSource = UA_VALUESOURCE_DATASOURCE; node->value.dataSource = dataSource; node->accessLevel = attr.accessLevel; node->userAccessLevel = attr.userAccessLevel; node->historizing = attr.historizing; node->minimumSamplingInterval = attr.minimumSamplingInterval; node->valueRank = attr.valueRank; UA_Server_addExistingNode(server, &adminSession, (UA_Node*)node, &item.parentNodeId.nodeId, &item.referenceTypeId, &result); UA_AddNodesItem_deleteMembers(&item); UA_VariableAttributes_deleteMembers(&attrCopy); if(result.statusCode != UA_STATUSCODE_GOOD) UA_VariableNode_delete(node); if(outNewNodeId && result.statusCode == UA_STATUSCODE_GOOD) *outNewNodeId = result.addedNodeId; else UA_AddNodesResult_deleteMembers(&result); return result.statusCode; }
/* copy an existing object under the given parent. then instantiate the variable for all hastypedefinitions of the original version. */ static UA_StatusCode copyExistingObject(UA_Server *server, UA_Session *session, const UA_NodeId *variable, const UA_NodeId *referenceType, const UA_NodeId *parent, UA_InstantiationCallback *instantiationCallback) { const UA_ObjectNode *node = (const UA_ObjectNode*)UA_NodeStore_get(server->nodestore, variable); if(!node) return UA_STATUSCODE_BADNODEIDINVALID; if(node->nodeClass != UA_NODECLASS_OBJECT) return UA_STATUSCODE_BADNODECLASSINVALID; // copy the variable attributes UA_ObjectAttributes attr; UA_ObjectAttributes_init(&attr); UA_LocalizedText_copy(&node->displayName, &attr.displayName); UA_LocalizedText_copy(&node->description, &attr.description); attr.writeMask = node->writeMask; attr.userWriteMask = node->userWriteMask; attr.eventNotifier = node->eventNotifier; UA_AddNodesItem item; UA_AddNodesItem_init(&item); UA_NodeId_copy(parent, &item.parentNodeId.nodeId); UA_NodeId_copy(referenceType, &item.referenceTypeId); UA_QualifiedName_copy(&node->browseName, &item.browseName); item.nodeClass = UA_NODECLASS_OBJECT; item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE; item.nodeAttributes.content.decoded.type = &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES]; item.nodeAttributes.content.decoded.data = &attr; // don't add a typedefinition here. // add the new object UA_AddNodesResult res; UA_AddNodesResult_init(&res); Service_AddNodes_single(server, session, &item, &res, instantiationCallback); UA_ObjectAttributes_deleteMembers(&attr); UA_AddNodesItem_deleteMembers(&item); // now instantiate the object for all hastypedefinition references for(size_t i = 0; i < node->referencesSize; i++) { UA_ReferenceNode *rn = &node->references[i]; if(rn->isInverse) continue; const UA_NodeId hasTypeDef = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION); if(!UA_NodeId_equal(&rn->referenceTypeId, &hasTypeDef)) continue; instantiateObjectNode(server, session, &res.addedNodeId, &rn->targetId.nodeId, instantiationCallback); } if (instantiationCallback != NULL) instantiationCallback->method(res.addedNodeId, node->nodeId, instantiationCallback->handle); UA_AddNodesResult_deleteMembers(&res); return UA_STATUSCODE_GOOD; }
UA_StatusCode UA_Client_forEachChildNodeCall(UA_Client *client, UA_NodeId parentNodeId, UA_NodeIteratorCallback callback, void *handle) { UA_StatusCode retval = UA_STATUSCODE_GOOD; UA_BrowseRequest bReq; UA_BrowseRequest_init(&bReq); bReq.requestedMaxReferencesPerNode = 0; bReq.nodesToBrowse = UA_BrowseDescription_new(); bReq.nodesToBrowseSize = 1; UA_NodeId_copy(&parentNodeId, &bReq.nodesToBrowse[0].nodeId); bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; //return everything bReq.nodesToBrowse[0].browseDirection = UA_BROWSEDIRECTION_BOTH; UA_BrowseResponse bResp = UA_Client_Service_browse(client, bReq); if(bResp.responseHeader.serviceResult == UA_STATUSCODE_GOOD) { for (size_t i = 0; i < bResp.resultsSize; ++i) { for (size_t j = 0; j < bResp.results[i].referencesSize; ++j) { UA_ReferenceDescription *ref = &(bResp.results[i].references[j]); retval |= callback(ref->nodeId.nodeId, ! ref->isForward, ref->referenceTypeId, handle); } } } else retval = bResp.responseHeader.serviceResult; UA_BrowseRequest_deleteMembers(&bReq); UA_BrowseResponse_deleteMembers(&bResp); return retval; }
static void requestHistory(UA_DateTime start, UA_DateTime end, UA_HistoryReadResponse * response, UA_UInt32 numValuesPerNode, UA_Boolean returnBounds, UA_ByteString *continuationPoint) { UA_ReadRawModifiedDetails *details = UA_ReadRawModifiedDetails_new(); details->startTime = start; details->endTime = end; details->isReadModified = false; details->numValuesPerNode = numValuesPerNode; details->returnBounds = returnBounds; UA_HistoryReadValueId *valueId = UA_HistoryReadValueId_new(); UA_NodeId_copy(&outNodeId, &valueId->nodeId); if (continuationPoint) UA_ByteString_copy(continuationPoint, &valueId->continuationPoint); UA_HistoryReadRequest request; UA_HistoryReadRequest_init(&request); request.historyReadDetails.encoding = UA_EXTENSIONOBJECT_DECODED; request.historyReadDetails.content.decoded.type = &UA_TYPES[UA_TYPES_READRAWMODIFIEDDETAILS]; request.historyReadDetails.content.decoded.data = details; request.timestampsToReturn = UA_TIMESTAMPSTORETURN_BOTH; request.nodesToReadSize = 1; request.nodesToRead = valueId; Service_HistoryRead(server, &server->adminSession, &request, response); UA_HistoryReadRequest_deleteMembers(&request); }
static UA_NodeId findSingleChildNode(UA_QualifiedName targetName, UA_NodeId referenceTypeId, UA_NodeId startingNode){ UA_NodeId resultNodeId; UA_RelativePathElement rpe; UA_RelativePathElement_init(&rpe); rpe.referenceTypeId = referenceTypeId; rpe.isInverse = false; rpe.includeSubtypes = false; rpe.targetName = targetName; UA_BrowsePath bp; UA_BrowsePath_init(&bp); bp.startingNode = startingNode; bp.relativePath.elementsSize = 1; bp.relativePath.elements = &rpe; UA_BrowsePathResult bpr = UA_Server_translateBrowsePathToNodeIds(server, &bp); if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) return UA_NODEID_NULL; if(UA_NodeId_copy(&bpr.targets[0].targetId.nodeId, &resultNodeId) != UA_STATUSCODE_GOOD){ UA_BrowsePathResult_deleteMembers(&bpr); return UA_NODEID_NULL; } UA_BrowsePathResult_deleteMembers(&bpr); return resultNodeId; }
UA_StatusCode __UA_Client_writeAttribute(UA_Client *client, UA_NodeId nodeId, UA_AttributeId attributeId, void *in, const UA_DataType *inDataType) { if(in == NULL) return UA_STATUSCODE_BADTYPEMISMATCH; UA_Variant *tmp = (UA_Variant *) in; if (tmp == NULL) return 1; UA_WriteRequest *wReq = UA_WriteRequest_new(); wReq->nodesToWrite = UA_WriteValue_new(); wReq->nodesToWriteSize = 1; UA_NodeId_copy(&nodeId, &wReq->nodesToWrite[0].nodeId); wReq->nodesToWrite[0].attributeId = attributeId; if (attributeId == UA_ATTRIBUTEID_VALUE) { UA_Variant_copy((UA_Variant *) in, &wReq->nodesToWrite[0].value.value); wReq->nodesToWrite[0].value.hasValue = true; } else { if( ! UA_Variant_setScalarCopy(&wReq->nodesToWrite[0].value.value, in, inDataType) ) wReq->nodesToWrite[0].value.hasValue = true; } UA_WriteResponse wResp = UA_Client_Service_write(client, *wReq); UA_StatusCode retval = wResp.responseHeader.serviceResult; UA_WriteRequest_delete(wReq); UA_WriteResponse_deleteMembers(&wResp); return retval; }
UaNodeId::UaNodeId ( const UaNodeId & other) { UA_NodeId_init( &m_impl ); UA_StatusCode status = UA_NodeId_copy( other.pimpl(), &this->m_impl ); if (status != UA_STATUSCODE_GOOD) throw alloc_error(); }
static void addNodeFromAttributes(UA_Server *server, UA_Session *session, UA_AddNodesItem *item, UA_AddNodesResult *result) { // adding nodes to ns0 is not allowed over the wire if(item->requestedNewNodeId.nodeId.namespaceIndex == 0) { result->statusCode = UA_STATUSCODE_BADNODEIDREJECTED; return; } // parse the node UA_Node *node = UA_NULL; switch (item->nodeClass) { case UA_NODECLASS_OBJECT: result->statusCode = parseObjectNode(&item->nodeAttributes, &node); break; case UA_NODECLASS_OBJECTTYPE: result->statusCode = parseObjectTypeNode(&item->nodeAttributes, &node); break; case UA_NODECLASS_REFERENCETYPE: result->statusCode = parseReferenceTypeNode(&item->nodeAttributes, &node); break; case UA_NODECLASS_VARIABLE: result->statusCode = parseVariableNode(&item->nodeAttributes, &node); break; default: result->statusCode = UA_STATUSCODE_BADNOTIMPLEMENTED; } if(result->statusCode != UA_STATUSCODE_GOOD) return; // The BrowseName was not included with the NodeAttribute ExtensionObject UA_QualifiedName_init(&(node->browseName)); UA_QualifiedName_copy(&(item->browseName), &(node->browseName)); UA_NodeId_copy(&item->requestedNewNodeId.nodeId, &node->nodeId); // add the node *result = UA_Server_addNodeWithSession(server, session, node, item->parentNodeId, item->referenceTypeId); if(result->statusCode != UA_STATUSCODE_GOOD) { switch (node->nodeClass) { case UA_NODECLASS_OBJECT: UA_ObjectNode_delete((UA_ObjectNode*)node); break; case UA_NODECLASS_OBJECTTYPE: UA_ObjectTypeNode_delete((UA_ObjectTypeNode*)node); break; case UA_NODECLASS_REFERENCETYPE: UA_ReferenceTypeNode_delete((UA_ReferenceTypeNode*)node); break; case UA_NODECLASS_VARIABLE: UA_VariableNode_delete((UA_VariableNode*)node); break; default: UA_assert(UA_FALSE); } } }
void UaNodeId::copyTo( UA_NodeId* other) const { if (!other) throw std::runtime_error("passed a nullptr"); UA_StatusCode status = UA_NodeId_copy( &this->m_impl, other ); if (status != UA_STATUSCODE_GOOD) throw alloc_error(); }
UA_StatusCode UA_Node_copyAnyNodeClass(const UA_Node *src, UA_Node *dst) { if(src->nodeClass != dst->nodeClass) return UA_STATUSCODE_BADINTERNALERROR; /* copy standard content */ UA_StatusCode retval = UA_NodeId_copy(&src->nodeId, &dst->nodeId); dst->nodeClass = src->nodeClass; retval |= UA_QualifiedName_copy(&src->browseName, &dst->browseName); retval |= UA_LocalizedText_copy(&src->displayName, &dst->displayName); retval |= UA_LocalizedText_copy(&src->description, &dst->description); dst->writeMask = src->writeMask; dst->userWriteMask = src->userWriteMask; if(retval != UA_STATUSCODE_GOOD) { UA_Node_deleteMembersAnyNodeClass(dst); return retval; } retval |= UA_Array_copy(src->references, src->referencesSize, (void**)&dst->references, &UA_TYPES[UA_TYPES_REFERENCENODE]); if(retval != UA_STATUSCODE_GOOD) { UA_Node_deleteMembersAnyNodeClass(dst); return retval; } dst->referencesSize = src->referencesSize; /* copy unique content of the nodeclass */ switch(src->nodeClass) { case UA_NODECLASS_OBJECT: retval = UA_ObjectNode_copy((const UA_ObjectNode*)src, (UA_ObjectNode*)dst); break; case UA_NODECLASS_VARIABLE: retval = UA_VariableNode_copy((const UA_VariableNode*)src, (UA_VariableNode*)dst); break; case UA_NODECLASS_METHOD: retval = UA_MethodNode_copy((const UA_MethodNode*)src, (UA_MethodNode*)dst); break; case UA_NODECLASS_OBJECTTYPE: retval = UA_ObjectTypeNode_copy((const UA_ObjectTypeNode*)src, (UA_ObjectTypeNode*)dst); break; case UA_NODECLASS_VARIABLETYPE: retval = UA_VariableTypeNode_copy((const UA_VariableTypeNode*)src, (UA_VariableTypeNode*)dst); break; case UA_NODECLASS_REFERENCETYPE: retval = UA_ReferenceTypeNode_copy((const UA_ReferenceTypeNode*)src, (UA_ReferenceTypeNode*)dst); break; case UA_NODECLASS_DATATYPE: retval = UA_DataTypeNode_copy((const UA_DataTypeNode*)src, (UA_DataTypeNode*)dst); break; case UA_NODECLASS_VIEW: retval = UA_ViewNode_copy((const UA_ViewNode*)src, (UA_ViewNode*)dst); break; default: break; } if(retval != UA_STATUSCODE_GOOD) UA_Node_deleteMembersAnyNodeClass(dst); return retval; }
const UaNodeId& UaNodeId::operator=(const UaNodeId & other) { UA_NodeId_deleteMembers( &m_impl ); UA_NodeId_init( &m_impl ); UA_StatusCode status = UA_NodeId_copy( other.pimpl(), &this->m_impl ); if (status != UA_STATUSCODE_GOOD) throw alloc_error(); return *this; }
static void responseSessionCallback(UA_Client *client, void *userdata, UA_UInt32 requestId, void *response) { UA_CreateSessionResponse *sessionResponse = (UA_CreateSessionResponse *)response; UA_NodeId_copy(&sessionResponse->authenticationToken, &client->authenticationToken); requestActivateSession(client, &requestId); }
void UA_Server_addExistingNode(UA_Server *server, UA_Session *session, UA_Node *node, const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId, UA_AddNodesResult *result) { if(node->nodeId.namespaceIndex >= server->namespacesSize) { result->statusCode = UA_STATUSCODE_BADNODEIDINVALID; UA_NodeStore_deleteNode(node); return; } const UA_Node *parent = UA_NodeStore_get(server->nodestore, parentNodeId); if(!parent) { result->statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID; UA_NodeStore_deleteNode(node); return; } const UA_ReferenceTypeNode *referenceType = (const UA_ReferenceTypeNode *)UA_NodeStore_get(server->nodestore, referenceTypeId); if(!referenceType) { result->statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID; UA_NodeStore_deleteNode(node); return; } if(referenceType->nodeClass != UA_NODECLASS_REFERENCETYPE) { result->statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID; UA_NodeStore_deleteNode(node); return; } if(referenceType->isAbstract == UA_TRUE) { result->statusCode = UA_STATUSCODE_BADREFERENCENOTALLOWED; UA_NodeStore_deleteNode(node); return; } // todo: test if the referencetype is hierarchical // todo: namespace index is assumed to be valid result->statusCode = UA_NodeStore_insert(server->nodestore, node); if(result->statusCode == UA_STATUSCODE_GOOD) result->statusCode = UA_NodeId_copy(&node->nodeId, &result->addedNodeId); else return; // reference back to the parent UA_AddReferencesItem item; UA_AddReferencesItem_init(&item); item.sourceNodeId = node->nodeId; item.referenceTypeId = *referenceTypeId; item.isForward = UA_FALSE; item.targetNodeId.nodeId = *parentNodeId; Service_AddReferences_single(server, session, &item); // todo: error handling. remove new node from nodestore }
/** * Gets a list of nodeIds which are referenced by this node. * Hereby the list will be filtered to only include references * which are of the given `references` types. */ static UA_StatusCode getReferencedNodesWithReferenceType(UA_NodeId **results_ptr, size_t *results_count, size_t *results_size, const UA_Node *node, const UA_NodeReferenceKind *references, size_t referencesSize) { UA_NodeId *results = *results_ptr; for(size_t i = 0; i < node->referencesSize; ++i) { /* Is the reference kind relevant? */ UA_NodeReferenceKind *refs = &node->references[i]; bool referenceInList = false; for (size_t j=0; j<referencesSize && !referenceInList; j++) { referenceInList = refs->isInverse == references[j].isInverse && UA_NodeId_equal(&references[j].referenceTypeId, &refs->referenceTypeId); } if (!referenceInList) continue; /* Append all targets of the reference kind .. if not a duplicate */ for(size_t j = 0; j < refs->targetIdsSize; ++j) { /* Is the target a duplicate? (multi-inheritance) */ UA_NodeId *targetId = &refs->targetIds[j].nodeId; UA_Boolean duplicate = false; for(size_t k = 0; k < *results_count; ++k) { if(UA_NodeId_equal(targetId, &results[k])) { duplicate = true; break; } } if(duplicate) continue; /* Increase array length if necessary */ if(*results_count >= *results_size) { size_t new_size = sizeof(UA_NodeId) * (*results_size) * 2; UA_NodeId *new_results = (UA_NodeId*)UA_realloc(results, new_size); if(!new_results) { UA_Array_delete(results, *results_count, &UA_TYPES[UA_TYPES_NODEID]); return UA_STATUSCODE_BADOUTOFMEMORY; } results = new_results; *results_ptr = results; *results_size *= 2; } /* Copy new nodeid to the end of the list */ UA_StatusCode retval = UA_NodeId_copy(targetId, &results[*results_count]); if(retval != UA_STATUSCODE_GOOD) { UA_Array_delete(results, *results_count, &UA_TYPES[UA_TYPES_NODEID]); return retval; } *results_count += 1; } } return UA_STATUSCODE_GOOD; }
static UA_StatusCode copyStandardAttributes(UA_Node *node, const UA_AddNodesItem *item, const UA_NodeAttributes *attr) { UA_StatusCode retval = UA_STATUSCODE_GOOD; retval |= UA_NodeId_copy(&item->requestedNewNodeId.nodeId, &node->nodeId); retval |= UA_QualifiedName_copy(&item->browseName, &node->browseName); retval |= UA_LocalizedText_copy(&attr->displayName, &node->displayName); retval |= UA_LocalizedText_copy(&attr->description, &node->description); node->writeMask = attr->writeMask; node->userWriteMask = attr->userWriteMask; return retval; }
static UA_StatusCode getHierarchyForReferenceTypes(void *nsCtx, const UA_NodeId *leafType, const UA_NodeReferenceKind *references, size_t referencesSize, UA_NodeId **typeHierarchy, size_t *typeHierarchySize) { /* Allocate the results array. Probably too big, but saves mallocs. */ size_t results_size = 20; UA_NodeId *results = (UA_NodeId*)UA_malloc(sizeof(UA_NodeId) * results_size); if(!results) return UA_STATUSCODE_BADOUTOFMEMORY; /* The leaf is the first element */ size_t results_count = 1; UA_StatusCode retval = UA_NodeId_copy(leafType, &results[0]); if(retval != UA_STATUSCODE_GOOD) { UA_free(results); return retval; } /* Loop over the array members .. and add new elements to the end */ for(size_t idx = 0; idx < results_count; ++idx) { /* Get the node */ const UA_Node *node = UA_Nodestore_getNode(nsCtx, &results[idx]); /* Invalid node, remove from the array */ if(!node) { for(size_t i = idx; i < results_count-1; ++i) results[i] = results[i+1]; results_count--; continue; } /* Add references from the current node to the end of the array */ retval = getReferencedNodesWithReferenceType(&results, &results_count, &results_size, node, references, referencesSize); /* Release the node */ UA_Nodestore_releaseNode(nsCtx, node); if(retval != UA_STATUSCODE_GOOD) { UA_Array_delete(results, results_count, &UA_TYPES[UA_TYPES_NODEID]); return retval; } } /* Zero results. The leaf node was not found */ if(results_count == 0) { UA_free(results); results = NULL; } *typeHierarchy = results; *typeHierarchySize = results_count; return UA_STATUSCODE_GOOD; }
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; }
static UA_StatusCode SessionHandshake(UA_Client *client) { UA_CreateSessionRequest request; UA_CreateSessionRequest_init(&request); // todo: is this needed for all requests? UA_NodeId_copy(&client->authenticationToken, &request.requestHeader.authenticationToken); request.requestHeader.timestamp = UA_DateTime_now(); request.requestHeader.timeoutHint = 10000; UA_ByteString_copy(&client->channel.clientNonce, &request.clientNonce); request.requestedSessionTimeout = 1200000; request.maxResponseMessageSize = UA_INT32_MAX; UA_CreateSessionResponse response; UA_CreateSessionResponse_init(&response); __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST], &response, &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE]); UA_NodeId_copy(&response.authenticationToken, &client->authenticationToken); UA_CreateSessionRequest_deleteMembers(&request); UA_CreateSessionResponse_deleteMembers(&response); return response.responseHeader.serviceResult; // not deleted }
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; }
static UA_StatusCode CloseSession(UA_Client *client) { UA_CloseSessionRequest request; UA_CloseSessionRequest_init(&request); request.requestHeader.timestamp = UA_DateTime_now(); request.requestHeader.timeoutHint = 10000; request.deleteSubscriptions = UA_TRUE; UA_NodeId_copy(&client->authenticationToken, &request.requestHeader.authenticationToken); UA_CloseSessionResponse response; __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST], &response, &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE]); UA_CloseSessionRequest_deleteMembers(&request); UA_CloseSessionResponse_deleteMembers(&response); return response.responseHeader.serviceResult; // not deleted }
static UA_StatusCode UA_Node_copy(const UA_Node *src, UA_Node *dst) { UA_StatusCode retval = UA_STATUSCODE_GOOD; UA_Node_init(dst); retval |= UA_NodeId_copy(&src->nodeId, &dst->nodeId); dst->nodeClass = src->nodeClass; retval |= UA_QualifiedName_copy(&src->browseName, &dst->browseName); retval |= UA_LocalizedText_copy(&src->displayName, &dst->displayName); retval |= UA_LocalizedText_copy(&src->description, &dst->description); dst->writeMask = src->writeMask; dst->userWriteMask = src->userWriteMask; dst->referencesSize = src->referencesSize; retval |= UA_Array_copy(src->references, (void**)&dst->references, &UA_TYPES[UA_TYPES_REFERENCENODE], src->referencesSize); if(retval) UA_Node_deleteMembers(dst); return retval; }
static UA_StatusCode writeDataTypeAttribute(UA_Server *server, UA_Session *session, UA_VariableNode *node, const UA_VariableTypeNode *type, const UA_NodeId *dataType) { UA_assert(node != NULL); UA_assert(type != NULL); /* If this is a variabletype, there must be no instances or subtypes of it when we do the change */ if(node->nodeClass == UA_NODECLASS_VARIABLETYPE && UA_Node_hasSubTypeOrInstances((const UA_Node*)node)) return UA_STATUSCODE_BADINTERNALERROR; /* Does the new type match the constraints of the variabletype? */ if(!compatibleDataType(server, dataType, &type->dataType)) return UA_STATUSCODE_BADTYPEMISMATCH; /* Check if the current value would match the new type */ UA_DataValue value; UA_DataValue_init(&value); UA_StatusCode retval = readValueAttribute(server, session, node, &value); if(retval != UA_STATUSCODE_GOOD) return retval; if(value.hasValue) { if(!compatibleValue(server, dataType, node->valueRank, node->arrayDimensionsSize, node->arrayDimensions, &value.value, NULL)) retval = UA_STATUSCODE_BADTYPEMISMATCH; UA_DataValue_deleteMembers(&value); if(retval != UA_STATUSCODE_GOOD) { UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SERVER, "The current value does not match the new data type"); return retval; } } /* Replace the datatype nodeid */ UA_NodeId dtCopy = node->dataType; retval = UA_NodeId_copy(dataType, &node->dataType); if(retval != UA_STATUSCODE_GOOD) { node->dataType = dtCopy; return retval; } UA_NodeId_deleteMembers(&dtCopy); return UA_STATUSCODE_GOOD; }
/* Adds a one-way reference to the local nodestore */ static UA_StatusCode addOneWayReference(UA_Server *server, UA_Session *session, UA_Node *node, const UA_AddReferencesItem *item) { size_t i = node->referencesSize; size_t refssize = (i+1) | 3; // so the realloc is not necessary every time UA_ReferenceNode *new_refs = UA_realloc(node->references, sizeof(UA_ReferenceNode) * refssize); if(!new_refs) return UA_STATUSCODE_BADOUTOFMEMORY; node->references = new_refs; UA_ReferenceNode_init(&new_refs[i]); UA_StatusCode retval = UA_NodeId_copy(&item->referenceTypeId, &new_refs[i].referenceTypeId); retval |= UA_ExpandedNodeId_copy(&item->targetNodeId, &new_refs[i].targetId); new_refs[i].isInverse = !item->isForward; if(retval == UA_STATUSCODE_GOOD) node->referencesSize = i+1; else UA_ReferenceNode_deleteMembers(&new_refs[i]); return retval; }
static void variables_nodeids(void) { UA_NodeId id1 = UA_NODEID_NUMERIC(1, 1234); id1.namespaceIndex = 3; UA_NodeId id2 = UA_NODEID_STRING(1, "testid"); /* the string is static */ UA_Boolean eq = UA_NodeId_equal(&id1, &id2); if(eq) return; UA_NodeId id3; UA_NodeId_copy(&id2, &id3); UA_NodeId_deleteMembers(&id3); UA_NodeId id4 = UA_NODEID_STRING_ALLOC(1, "testid"); /* the string is copied to the heap */ UA_NodeId_deleteMembers(&id4); }
/* finds the NodeId of a StateNumber child of a given node id */ static void findChildId(UA_NodeId stateId, UA_NodeId referenceType, const UA_QualifiedName targetName, UA_NodeId *result) { UA_RelativePathElement rpe; UA_RelativePathElement_init(&rpe); rpe.referenceTypeId = referenceType; rpe.isInverse = false; rpe.includeSubtypes = false; rpe.targetName = targetName; UA_BrowsePath bp; UA_BrowsePath_init(&bp); bp.startingNode = stateId; bp.relativePath.elementsSize = 1; bp.relativePath.elements = &rpe; //clion complains but is ok UA_BrowsePathResult bpr = UA_Server_translateBrowsePathToNodeIds(server, &bp); ck_assert_uint_eq(bpr.statusCode, UA_STATUSCODE_GOOD); UA_NodeId_copy(&bpr.targets[0].targetId.nodeId, result); UA_BrowsePathResult_deleteMembers(&bpr); }
static UA_StatusCode deleteHistory(UA_DateTime start, UA_DateTime end) { UA_DeleteRawModifiedDetails *details = UA_DeleteRawModifiedDetails_new(); details->startTime = start; details->endTime = end; details->isDeleteModified = false; UA_NodeId_copy(&outNodeId, &details->nodeId); UA_HistoryUpdateRequest request; UA_HistoryUpdateRequest_init(&request); request.historyUpdateDetailsSize = 1; request.historyUpdateDetails = UA_ExtensionObject_new(); UA_ExtensionObject_init(request.historyUpdateDetails); request.historyUpdateDetails[0].encoding = UA_EXTENSIONOBJECT_DECODED; request.historyUpdateDetails[0].content.decoded.type = &UA_TYPES[UA_TYPES_DELETERAWMODIFIEDDETAILS]; request.historyUpdateDetails[0].content.decoded.data = details; UA_HistoryUpdateResponse response; UA_HistoryUpdateResponse_init(&response); Service_HistoryUpdate(server, &server->adminSession, &request, &response); UA_HistoryUpdateRequest_deleteMembers(&request); UA_StatusCode ret = UA_STATUSCODE_GOOD; if (response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) ret = response.responseHeader.serviceResult; else if (response.resultsSize != 1) ret = UA_STATUSCODE_BADUNEXPECTEDERROR; else if (response.results[0].statusCode != UA_STATUSCODE_GOOD) ret = response.results[0].statusCode; else if (response.results[0].operationResultsSize != 0) ret = UA_STATUSCODE_BADUNEXPECTEDERROR; UA_HistoryUpdateResponse_deleteMembers(&response); return ret; }
OV_DLLFNCEXPORT UA_StatusCode servicesOPCUAInterface_interface_ovServiceOutputArgumentsNodeToOPCUA( void *handle, const UA_NodeId *nodeId, UA_Node** opcuaNode) { UA_Node *newNode = NULL; UA_StatusCode result = UA_STATUSCODE_GOOD; OV_PATH path; OV_INSTPTR_ov_object pobj = NULL; OV_TICKET *pTicket = NULL; OV_VTBLPTR_ov_object pVtblObj = NULL; OV_ACCESS access; UA_NodeClass nodeClass; OV_ELEMENT element; OV_STRING tmpString = NULL; OV_UINT len = 0; OV_STRING *plist = NULL; copyOPCUAStringToOV(nodeId->identifier.string, &tmpString); plist = ov_string_split(tmpString, "||", &len); ov_string_setvalue(&tmpString, NULL); UA_NodeId tmpNodeId; UA_NodeId_init(&tmpNodeId); tmpNodeId.namespaceIndex = nodeId->namespaceIndex; tmpNodeId.identifierType = nodeId->identifierType; tmpNodeId.identifier.string = UA_String_fromChars(plist[0]); ov_string_freelist(plist); ov_memstack_lock(); result = opcua_nodeStoreFunctions_resolveNodeIdToPath(tmpNodeId, &path); UA_NodeId_deleteMembers(&tmpNodeId); if(result != UA_STATUSCODE_GOOD){ ov_memstack_unlock(); return result; } element = path.elements[path.size-1]; ov_memstack_unlock(); result = opcua_nodeStoreFunctions_getVtblPointerAndCheckAccess(&(element), pTicket, &pobj, &pVtblObj, &access); if(result != UA_STATUSCODE_GOOD){ return result; } nodeClass = UA_NODECLASS_VARIABLE; newNode = (UA_Node*)UA_calloc(1, sizeof(UA_VariableNode)); // Basic Attribute // BrowseName UA_QualifiedName qName; qName.name = UA_String_fromChars("OutputArguments"); qName.namespaceIndex = 0; //pinterface->v_interfacenamespace.index; newNode->browseName = qName; // Description OV_STRING tempString = pVtblObj->m_getcomment(pobj, &element); UA_LocalizedText lText; UA_LocalizedText_init(&lText); lText.locale = UA_String_fromChars("en"); if(tempString){ lText.text = UA_String_fromChars(tempString); } else { lText.text = UA_String_fromChars(""); } UA_LocalizedText_copy(&lText,&newNode->description); UA_LocalizedText_deleteMembers(&lText); // DisplayName UA_LocalizedText displayName; UA_LocalizedText_init(&displayName); displayName.locale = UA_String_fromChars("en"); displayName.text = UA_String_fromChars("OutputArguments"); UA_LocalizedText_copy(&displayName, &newNode->displayName); UA_LocalizedText_deleteMembers(&displayName); // NodeId UA_NodeId_copy(nodeId, &newNode->nodeId); // NodeClass newNode->nodeClass = nodeClass; // WriteMask UA_UInt32 writeMask = 0; if(element.elemtype != OV_ET_VARIABLE){ if(access & OV_AC_WRITE){ writeMask |= (1<<2); // BrowseName writeMask |= (1<<6); // DisplayName } if(access & OV_AC_RENAMEABLE){ writeMask |= (1<<14); // NodeId } } newNode->writeMask = writeMask; // Variable specific attributes // value OV_ELEMENT tmpPart; tmpPart.elemtype = OV_ET_NONE; tmpPart.pobj = NULL; OV_ELEMENT tmpParrent; tmpParrent.pobj = pobj; tmpParrent.elemtype = OV_ET_OBJECT; OV_UINT sizeOutput = 0; do { ov_element_getnextpart(&tmpParrent, &tmpPart, OV_ET_VARIABLE); if (tmpPart.elemtype == OV_ET_NONE) break; if (tmpPart.elemunion.pvar->v_flags == 16384){ // OutputFlag is set sizeOutput++; continue; } } while(TRUE); // arrayDemensions if (sizeOutput > 1){ ((UA_VariableNode*)newNode)->arrayDimensionsSize = 1; UA_UInt32 *pOutputDimension = UA_UInt32_new(); *pOutputDimension = sizeOutput; ((UA_VariableNode*)newNode)->arrayDimensions = pOutputDimension; //UA_Array_new(((UA_VariableNode*)newNode)->arrayDimensionsSize, &UA_TYPES[UA_TYPES_INT32]); /* scalar or one dimension */ // valuerank ((UA_VariableNode*)newNode)->valueRank = 1; /* one dimension */ }else{ ((UA_VariableNode*)newNode)->arrayDimensionsSize = 0; ((UA_VariableNode*)newNode)->arrayDimensions = NULL; //UA_Array_new(((UA_VariableNode*)newNode)->arrayDimensionsSize, &UA_TYPES[UA_TYPES_INT32]); /* scalar or one dimension */ // valuerank ((UA_VariableNode*)newNode)->valueRank = -1; /* one dimension */ } // value ((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->type = &UA_TYPES[UA_TYPES_ARGUMENT]; ((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->arrayLength = sizeOutput; if (sizeOutput > 1){ ((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data = UA_Array_new(sizeOutput, &UA_TYPES[UA_TYPES_ARGUMENT]); }else{ ((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data = UA_Argument_new(); } if (!((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data){ result = UA_STATUSCODE_BADOUTOFMEMORY; return result; } ((UA_VariableNode*)newNode)->value.data.value.hasValue = TRUE; ((UA_VariableNode*)newNode)->valueSource = UA_VALUESOURCE_DATA; tmpPart.elemtype = OV_ET_NONE; tmpPart.pobj = NULL; OV_UINT count = 0; do { ov_element_getnextpart(&tmpParrent, &tmpPart, OV_ET_VARIABLE); if (tmpPart.elemtype == OV_ET_NONE) break; if (tmpPart.elemunion.pvar->v_flags == 16384){ // OutputFlag is set UA_Argument_init(&((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count]); ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].description = UA_LOCALIZEDTEXT_ALLOC("en_US",""); ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].name = UA_STRING_ALLOC(tmpPart.elemunion.pvar->v_identifier); ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].valueRank = -1; switch(tmpPart.elemunion.pvar->v_vartype){ case OV_VT_BOOL: ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].dataType = UA_TYPES[UA_TYPES_BOOLEAN].typeId; ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].valueRank = -1; break; case OV_VT_INT: ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].dataType = UA_TYPES[UA_TYPES_INT32].typeId; ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].valueRank = -1; break; case OV_VT_UINT: ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].dataType = UA_TYPES[UA_TYPES_UINT32].typeId; ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].valueRank = -1; break; case OV_VT_SINGLE: ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].dataType = UA_TYPES[UA_TYPES_FLOAT].typeId; ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].valueRank = -1; break; case OV_VT_DOUBLE: ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].dataType = UA_TYPES[UA_TYPES_DOUBLE].typeId; ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].valueRank = -1; break; case OV_VT_ANY: ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].dataType = UA_TYPES[UA_TYPES_VARIANT].typeId; ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].valueRank = 1; break; case OV_VT_STRING: ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].dataType = UA_TYPES[UA_TYPES_STRING].typeId; ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].valueRank = -1; break; case OV_VT_BOOL_VEC: ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].dataType = UA_TYPES[UA_TYPES_BOOLEAN].typeId; ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].valueRank = 1; break; case OV_VT_INT_VEC: ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].dataType = UA_TYPES[UA_TYPES_INT32].typeId; ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].valueRank = 1; break; case OV_VT_UINT_VEC: ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].dataType = UA_TYPES[UA_TYPES_UINT32].typeId; ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].valueRank = 1; break; case OV_VT_SINGLE_VEC: ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].dataType = UA_TYPES[UA_TYPES_FLOAT].typeId; ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].valueRank = 1; break; case OV_VT_DOUBLE_VEC: ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].dataType = UA_TYPES[UA_TYPES_DOUBLE].typeId; ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].valueRank = 1; break; case OV_VT_STRING_VEC: ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].dataType = UA_TYPES[UA_TYPES_STRING].typeId; ((UA_Argument*)((UA_Variant*)&((UA_VariableNode*)newNode)->value.data.value.value)->data)[count].valueRank = 1; break; default: break; } count++; if (count == sizeOutput){ break; }else{ continue; } } } while(TRUE); ov_string_setvalue(&tmpString, NULL); // accessLevel UA_Byte accessLevel = 0; if(access & OV_AC_READ){ accessLevel |= (1<<0); } if(access & OV_AC_WRITE){ accessLevel |= (1<<1); } ((UA_VariableNode*)newNode)->accessLevel = accessLevel; // minimumSamplingInterval ((UA_VariableNode*)newNode)->minimumSamplingInterval = -1; // historizing ((UA_VariableNode*)newNode)->historizing = UA_FALSE; // dataType ((UA_VariableNode*)newNode)->dataType = UA_NODEID_NUMERIC(0, 0); // References have to do manual because it is an virtual node size_t size_references = 0; size_references = size_references + 2;// For Parent&TypeNode newNode->references = UA_calloc(size_references, sizeof(UA_ReferenceNode)); if (!newNode->references){ result = ov_resultToUaStatusCode(OV_ERR_HEAPOUTOFMEMORY); UA_free(newNode); return result; } newNode->referencesSize = size_references; // ParentNode newNode->references[0].referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY); newNode->references[0].isInverse = UA_TRUE; len = 0; plist = NULL; tmpString = NULL; copyOPCUAStringToOV(nodeId->identifier.string, &tmpString); plist = ov_string_split(tmpString, "||", &len); newNode->references[0].targetId = UA_EXPANDEDNODEID_STRING_ALLOC(pinterface->v_interfacenamespace.index, plist[0]); ov_string_freelist(plist); ov_string_setvalue(&tmpString, NULL); // TypeNode newNode->references[1].referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION); newNode->references[1].isInverse = UA_FALSE; newNode->references[1].targetId = UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE); *opcuaNode = newNode; return UA_STATUSCODE_GOOD; }