open62541 浏览节点并使用其方法

open62541 browsing nodes an using its methods

我想浏览我的 OPC UA 服务器上的特定节点并使用它的方法。 我使用 open62541 堆栈,我想使用自制客户端。我的客户端连接到服务器,然后我使用给定的示例 to browse some Objects。它向我展示了根文件夹之后的第一层节点- 我怎样才能找到一个特定的节点?或者我必须浏览到这一点吗? open62541 项目中是否有一个我看不到的示例文件会让我大开眼界?

我也找到了方法 "Service_TranslateBrowsePathsToNodeIds",但我不太确定如何正确使用它以及我对哪一部分感兴趣。

举个例子: 我想浏览节点 "FileSystem",比根文件夹更深一层,并想使用它的方法 createFile。

要调用方法,需要两个节点id:

  • 包含方法的对象节点id
  • 方法节点id

如果您已经有了这些节点ID,您可以立即调用该方法。如果不, OPC UA 通常支持两种获取这些节点 ID 的选项:

经过反复试验,我发现 'magic' 位可以使其与服务器名称空间中的节点一起工作,例如真实设备的数量,而不是 pre-defined UA 节点,如所有示例中所示的时间戳或服务器状态。下面的代码源自 Open62541 的 corpus_generator.c 和 check_services_view.c 文件,有两个主要区别:

  • 您不必指定 referenceTypeId。
  • 创建字符串时,将它们放在 server 命名空间中,而不是 UA 命名空间(参见下面的 UA_QUALIFIEDNAME_ALLOC)。

下面的函数将采用指向 UA_Client 的指针和形成节点路径的浏览名称矢量,从 OPC-UA 中的对象文件夹开始。

Node::Node (UA_Client *client, const std::vector<std::string> &browse_path)
  : m_client (client)
{
  m_id = UA_NODEID_NULL;
  // Search for ID in client
  UA_BrowsePath browsePath;
  UA_BrowsePath_init (&browsePath);

  browsePath.startingNode = UA_NODEID_NUMERIC (0, UA_NS0ID_OBJECTSFOLDER);
  browsePath.relativePath.elements = (UA_RelativePathElement *)UA_Array_new (browse_path.size (), &UA_TYPES[UA_TYPES_RELATIVEPATHELEMENT]);
  browsePath.relativePath.elementsSize = browse_path.size ();

  for (int i = 0; i < browse_path.size (); i++)
  {
    UA_RelativePathElement *elem = &browsePath.relativePath.elements[i];
    elem->targetName = UA_QUALIFIEDNAME_ALLOC (1, browse_path.at (i).c_str ()); // Create in server namespace (1), not UA namespace (0)!
  }

  UA_TranslateBrowsePathsToNodeIdsRequest request;
  UA_TranslateBrowsePathsToNodeIdsRequest_init (&request);
  request.browsePaths = &browsePath;
  request.browsePathsSize = 1;

  UA_TranslateBrowsePathsToNodeIdsResponse response;
  response = UA_Client_Service_translateBrowsePathsToNodeIds (m_client, request);
  if (UA_STATUSCODE_GOOD == response.responseHeader.serviceResult && response.resultsSize > 0)
  {
    UA_BrowsePathResult *first = response.results;
    if (first->targetsSize >= 1)
    {
      m_id = first->targets[0].targetId.nodeId;
      std::cout << "Found ID";
    }
    else
    {
      std::cout << "OK response but no results";
    }
  }
  else
  {
    std::cout << "Error in translate browsename";
  }

  UA_BrowsePath_deleteMembers (&browsePath); // Marked as deprecated, but UA_BrowsePath_delete() expects a heap-allocated pointer.
  UA_TranslateBrowsePathsToNodeIdsResponse_deleteMembers (&response); // Idem
}