从 open62541Client 读取节点的 UA_Arguments

Posted

技术标签:

【中文标题】从 open62541Client 读取节点的 UA_Arguments【英文标题】:Reading UA_Arguments of a Node from open62541Client 【发布时间】:2020-09-01 14:22:08 【问题描述】:

我有兴趣从客户端读取 Method 节点的 InputArguments 和 OutputArgument 节点。假设我有 2 个 InputArgument 并且我正在尝试读取第一个 InputArgument。

    UA_Variant v;
    UA_NodeId n = UA_NODEID_NUMERIC(0, node_id_inp_arg);
    UA_Client_readValueAttribute(client, n, &v);
    UA_Argument* a = (UA_Argument*)v.data;
    std::cout<<(char*)a[0].name.data<<"\n";    // Prints junk
    std::cout<<a[0].arrayDimensionsSize<<"\n"; // Works
    //Need to access other attributes as well

我正在做上面的事情,但不幸的是没有成功。任何可以提供帮助的人都将不胜感激。我也想为 OutputArguments 做同样的事情。 谢谢。

【问题讨论】:

【参考方案1】:

方法在地址空间中没有输入和输出参数,因此您无法“读取”它们。输入和输出参数传入/传出 CallMethod 服务。 (地址空间中可能有输入和输出参数的描述,但我认为这不是你想要的)。

open62541中有UA_Client_CallServerMethod调用UA方法。

【讨论】:

我不想读取输入参数值,而是读取 IputArgument 的签名。比如有多少输入参数和类型?据我所知, InputArgument 和 OutputArgumets 属于 PropertyType 并且是方法节点的 HasProperty 引用。那么,为什么我们不能使用 UA_Client_readValueAttribute 来读取属性节点呢?【参考方案2】:

我想出了一个解决方案,但这不是很直接

UA_ReadRequest request;
UA_ReadValueId id;
UA_ReadRequest_init(&request);
UA_ReadValueId_init(&id);
id.attributeId          = UA_ATTRIBUTEID_VALUE;
id.nodeId               = node; /* NodeId of the Input or Output Argument*/
request.nodesToRead     = &id;
request.nodesToReadSize = 1;
size_t argLen           = argument_length; /* Cardinatlity of argument */

UA_ReadResponse response = UA_Client_Service_read(m_client, request);

UA_StatusCode retval = UA_STATUSCODE_GOOD;
if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
    retval = response.responseHeader.serviceResult;
 else if(response.resultsSize != 1 || !response.results[0].hasValue)
    retval = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
else if(response.results[0].value.type != &UA_TYPES[UA_TYPES_EXTENSIONOBJECT])
    retval = UA_STATUSCODE_BADTYPEMISMATCH;
if(retval != UA_STATUSCODE_GOOD) 
    UA_ReadResponse_deleteMembers(&response);
    return retval;

retval = UA_STATUSCODE_BADNOTFOUND;

UA_ExtensionObject *value = reinterpret_cast<UA_ExtensionObject*>(response.results[0].value.data);

for(size_t l(0); l < argLen; l++)
    UA_Argument* arg = reinterpret_cast<UA_Argument*>(value[l].content.decoded.data);
    /* Do my stuff*/

【讨论】:

以上是关于从 open62541Client 读取节点的 UA_Arguments的主要内容,如果未能解决你的问题,请参考以下文章

open62541 windows VS client/server 实例

OPC UA open62541历史数据读取客户端未编译

open62541 浏览节点和使用它的方法

客户端和服务器之间的双工通信 open62541(OPC-UA)

从节点属性读取数据类型

如何使用 open62541 一次使用 OPC-UA 编写多个节点?