Client端有个api叫UA_Client_Service_browse,可以遍历Server里指定node下所有的直接子node,其原型如下,
static UA_INLINE UA_BrowseResponse
UA_Client_Service_browse(UA_Client *client, const UA_BrowseRequest request);
一 例子
先准备个Server代码,如下,
#include "open62541.h"
#include <signal.h>
#include <stdlib.h>
UA_Boolean running = true;
static void stopHandler(int sign) {
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c");
running = false;
}
int main(void)
{
signal(SIGINT, stopHandler);
signal(SIGTERM, stopHandler);
UA_Server *server = UA_Server_new();
UA_ServerConfig_setDefault(UA_Server_getConfig(server));
UA_StatusCode retval = UA_Server_run(server, &running);
UA_Server_delete(server);
return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}
下面是client代码,程序遍历Objects目录,
#include <stdlib.h>
#include "open62541.h"
int main(void)
{
UA_Client *client = UA_Client_new();
UA_ClientConfig_setDefault(UA_Client_getConfig(client));
UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840");
if(retval != UA_STATUSCODE_GOOD) {
UA_Client_delete(client);
return (int)retval;
}
printf("Browsing nodes in objects folder:\n");
UA_BrowseRequest bReq;
UA_BrowseRequest_init(&bReq);
bReq.requestedMaxReferencesPerNode = 0;
bReq.nodesToBrowse = UA_BrowseDescription_new();
bReq.nodesToBrowseSize = 1;
bReq.nodesToBrowse[0].nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL;
UA_BrowseResponse bResp = UA_Client_Service_browse(client, bReq);
if (bResp.responseHeader.serviceResult)
{
printf("%-9s %-16s %-16s %-16s\n", "NAMESPACE", "NODEID", "BROWSE NAME", "DISPLAY NAME");
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]);
if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC) {
printf("%-9d %-16d %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex,
ref->nodeId.nodeId.identifier.numeric, (int)ref->browseName.name.length,
ref->browseName.name.data, (int)ref->displayName.text.length,
ref->displayName.text.data);
} else if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_STRING) {
printf("%-9d %-16.*s %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex,
(int)ref->nodeId.nodeId.identifier.string.length,
ref->nodeId.nodeId.identifier.string.data,
(int)ref->browseName.name.length, ref->browseName.name.data,
(int)ref->displayName.text.length, ref->displayName.text.data);
}
}
}
}
UA_BrowseRequest_clear(&bReq);
UA_BrowseResponse_clear(&bResp);
UA_Client_delete(client);
return EXIT_SUCCESS;
}
最终打印如下, 可以看出只能遍历Objects目录下的所有直接子node,那么如何遍历间接的node呢?就是再遍历读取到的直接node,好像有点傻…
二 相关结构体
结构体UA_BrowseRequest的定义如下,用来发送遍历请求,可以同时遍历多个节点
typedef struct {
UA_RequestHeader requestHeader;
UA_ViewDescription view;
UA_UInt32 requestedMaxReferencesPerNode;
size_t nodesToBrowseSize;
UA_BrowseDescription *nodesToBrowse;
} UA_BrowseRequest;
|