提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
使用 libopen62541,如节点为mandatory 属性,则创建的mandatory child节点 node ID是使用随机数字生成的,如想node ID的值是固定生成,当前有两种方式供开发者选择:
1.调用UA_Server_addNode_begin接口,手动创建整个子树;
2.使用open62541源码提供的一种用户自定义node ID的回调接口;
一、源码分析
open62541-1.2\src\server\ua_services_nodemanagement.c
判断节点是否为mandatory节点
/* Is the child mandatory? If not, ask callback whether child should be instantiated.
* If not, skip. */
if(!isMandatoryChild(server, session, &rd->nodeId.nodeId)) {
if(!server->config.nodeLifecycle.createOptionalChild)
return UA_STATUSCODE_GOOD;
通过generateChildNodeId挂接回调,自定义mandatory节点的node ID
if (server->config.nodeLifecycle.generateChildNodeId) {
UA_UNLOCK(&server->serviceMutex);
retval = server->config.nodeLifecycle.
generateChildNodeId(server, &session->sessionId, session->sessionHandle,
&rd->nodeId.nodeId, destinationNodeId,
&rd->referenceTypeId, &node->head.nodeId);
UA_LOCK(&server->serviceMutex);
if(retval != UA_STATUSCODE_GOOD) {
UA_NODESTORE_DELETE(server, node);
return retval;
}
}
二、实现方案
- 初始化server config,挂接回调
server = UA_Server_new();
config = UA_Server_getConfig(server);
config->nodeLifecycle.generateChildNodeId = generateChildNodeIdInParentNs;
UA_ServerConfig_setDefault(config);
2.回调接口实现
UA_StatusCode generateChildNodeIdInParentNs(
UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *sourceNodeId, /* ObjectType节点node ID */
const UA_NodeId *targetParentNodeId,
const UA_NodeId *referenceTypeId,
UA_NodeId *targetNodeId)
{
static int tmp = 50000; /* 创建了node ID是50000的mandatory节点 */
targetNodeId->namespaceIndex = targetParentNodeId->namespaceIndex;
targetNodeId->identifierType = UA_NODEIDTYPE_NUMERIC;
targetNodeId->identifier.numeric = tmp++;
return UA_STATUSCODE_GOOD;
}