open62541 client读取server下方法参数信息

概述

本文主要讲述如何去获取服务器中方法节点中的输入输出参数的个数和类型。

服务端

这里我们使用uaexpert软件中自带的示例服务器UaCPPServer,我们将其运行起来如下所示。
在这里插入图片描述
我们使用uaexpert去连接它找到定义的方法节点那里,
在这里插入图片描述
这里我们以Multiply这个方法节点为例。

读取节点信息

这里代码相对简单,如下

/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */

#include "open62541.h"

UA_StatusCode printMethodParameter(UA_Client *client, UA_NodeId nodeId)
{
    UA_StatusCode statuscode = UA_STATUSCODE_GOOD;

    UA_NodeClass nodeClass;
    statuscode = UA_Client_readNodeClassAttribute(client, nodeId, &nodeClass);
    if (statuscode != UA_STATUSCODE_GOOD)
        return statuscode;
    if (nodeClass != UA_NODECLASS_METHOD){ // 不是方法节点
        printf("Not method node\n");
        return UA_STATUSCODE_BAD;
    }

    UA_NodeId inputNode, outputNode;

    // 浏览输入的节点下的节点
    printf("Browsing nodes in objects folder:\n");
    UA_BrowseRequest bReq;
    UA_BrowseRequest_init(&bReq);
    bReq.requestedMaxReferencesPerNode = 0;//限制查到的最大节点数,0 不限制
    bReq.nodesToBrowse = UA_BrowseDescription_new();
    bReq.nodesToBrowseSize = 1;
    bReq.nodesToBrowse[0].browseDirection = UA_BROWSEDIRECTION_FORWARD;
    bReq.nodesToBrowse[0].includeSubtypes = UA_TRUE;//是否包含subtypes
    bReq.nodesToBrowse[0].nodeId = nodeId;//设置起始浏览节点
    bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; 
    UA_BrowseResponse bResp = UA_Client_Service_browse(client, bReq);

    // 浏览方法节点下的输入输出node
    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]);
           
            UA_QualifiedName nodeName;
            UA_Client_readBrowseNameAttribute(client, ref->nodeId.nodeId, &nodeName);
            if (!strncmp("InputArguments", (char*)nodeName.name.data, nodeName.name.length)) { // 输入参数node
                inputNode = ref->nodeId.nodeId;
            }
            else { // 输出参数node
                outputNode = ref->nodeId.nodeId;
            }

            /* TODO: distinguish further types */
        }
    }
    UA_BrowseRequest_clear(&bReq);
    UA_BrowseResponse_clear(&bResp);

    UA_Variant variant;
    UA_Variant_init(&variant);

    // 获取输入参数类型
    printf("InputArguments : ");
    statuscode = UA_Client_readValueAttribute(client, inputNode, &variant);
    if (statuscode == UA_STATUSCODE_GOOD)
    {
        if (UA_Variant_hasArrayType(&variant, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]))
        {
            UA_ExtensionObject* object = (UA_ExtensionObject*)variant.data;
            for (size_t ii = 0; ii < variant.arrayLength; ii++) 
            {
                UA_Argument* argument = (UA_Argument * )object[ii].content.decoded.data;
                UA_NodeId intNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_INT32);
                UA_NodeId doubleNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_DOUBLE);
                if (UA_NodeId_equal(&argument->dataType, &intNodeId))
                {
                    printf(" %d:Int32", ii);
                }
                else if(UA_NodeId_equal(&argument->dataType, &doubleNodeId))
                {
                    printf(" %d:Double", ii);
                }
                // .....其他类型判断
            }
        }
    }
    else {
        return statuscode;
    }
    printf("\n");

    // 获取输出参数类型
    printf("OutputArguments : ");
    statuscode = UA_Client_readValueAttribute(client, outputNode, &variant);
    if (statuscode == UA_STATUSCODE_GOOD)
    {
        if (UA_Variant_hasArrayType(&variant, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]))
        {
            UA_ExtensionObject* object = (UA_ExtensionObject*)variant.data;
            for (size_t ii = 0; ii < variant.arrayLength; ii++)
            {
                UA_Argument* argument = (UA_Argument*)object[ii].content.decoded.data;
                UA_NodeId intNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_INT32);
                UA_NodeId doubleNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_DOUBLE);
                if (UA_NodeId_equal(&argument->dataType, &intNodeId))
                {
                    printf(" %d:Int32", ii);
                }
                else if (UA_NodeId_equal(&argument->dataType, &doubleNodeId))
                {
                    printf(" %d:double", ii);
                }
                // .....其他类型判断
            }
        }
    }
    else {
        return statuscode;
    }
    printf("\n");
}

int main(int argc, char *argv[]) {
    UA_Client *client = UA_Client_new();
    UA_ClientConfig_setDefault(UA_Client_getConfig(client));

	UA_StatusCode retval;
    /* Connect to a server */
	retval = UA_Client_connect(client, "opc.tcp://localhost:48010");
    if(retval != UA_STATUSCODE_GOOD) {
        UA_Client_delete(client);
        return EXIT_FAILURE;
    }

    printMethodParameter(client, UA_NODEID_STRING_ALLOC(2, "Demo.Method.Multiply"));

    UA_Client_disconnect(client);
    UA_Client_delete(client);
	system("pause");
    return EXIT_SUCCESS;
}

主要是通过浏览方法节点下的InputArguments和OuputArguments节点去获取对应的输入输出参数信息。运行改代码结果如下
在这里插入图片描述
这样我们就可以通过这些输入输出参数去调用server端方法了。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: open62541是一种开源的OPC UA(开放式连接性架构-统一架构)服务端框架。OPC UA是一种独立于硬件和操作系统的通信协议,用于在工业自动化领域中连接和通信不同类型的设备和系统。 open62541服务端框架提供了一套强大的工具和函数,用于开发和实现OPC UA服务端。它可以帮助开发人员轻松地创建自定义的OPC UA服务,以实现数据交换和通信。 open62541具有以下特点和功能: 1. 开源:open62541是一个完全开源的项目,任何人都可以访问和使用它的代码。这使得开发人员可以根据自己的需求进行修改和适应。 2. 跨平台:open62541可在不同的操作系统上运行,例如Windows、Linux和嵌入式系统等。 3. 易于使用:open62541提供了一套清晰的API,使开发人员能够轻松地创建和管理OPC UA服务。它还提供了示例代码和文档,以帮助开发人员快速入门和理解。 4. 功能丰富:open62541支持OPC UA的核心规范,并提供了包括节点浏览、读取、写入、订阅和发布等在内的一系列功能。开发人员可以根据自己的需求扩展和定制这些功能。 5. 可扩展性:open62541支持自定义的信息模型和节点类型,开发人员可以根据自己的应用需求进行扩展和修改。 总之,open62541服务端框架是一个强大而灵活的工具,可帮助开发人员快速构建和实现OPC UA服务,并实现工业自动化系统之间的数据交换和通信。 ### 回答2: open62541是一个开源的OPC UA(OPC Unified Architecture)(工业自动化通信协议)库,可用于构建OPC UA服务端。OPC UA是一种用于在工业领域中实现跨平台、跨网络的通信和数据交换的标准化协议。 open62541库提供了一套API,使用户能够轻松地将OPC UA服务端集成到自己的应用程序中。用户可以使用这个库来创建OPC UA通信的服务器,以便与其他OPC UA客户端进行数据交换。open62541支持多线程操作和异步通信,可以处理大量并发连接,并提供了一些内置功能来验证和保护通信的安全性。 使用open62541服务端,可以实现对工业设备、传感器和其他系统的监控和控制。用户可以定义自己的OPC UA对象模型,将设备的数据、状态和功能以一致的方式表示出来。这样,各种不同类型的客户端都可以通过OPC UA协议与设备进行通信,无论客户端所在的系统和平台是什么。 open62541还支持诸如安全认证、加密通信、权限管理等功能,以保护服务器和客户端之间的通信和数据的安全性。此外,open62541库还提供了工具和示例代码,可以帮助用户更好地理解和使用该库。 总而言之,open62541服务端是一个功能强大且易于使用的库,适用于构建OPC UA服务端应用程序,可实现工业自动化系统之间的数据交换和控制,并提供了一系列的安全性功能。 ### 回答3: open62541是一个开源的OPC UA(OPC Unified Architecture)实现软件库,可以用于构建OPC UA服务端。 open62541提供了一组功能强大的API,可以轻松地创建和管理OPC UA实例以及与客户端进行通信。使用open62541,我们可以创建自定义的OPC UA节点、对象和方法,并将其暴露给客户端。同时,open62541还支持OPC UA的各种特性,例如安全性、传输协议和服务。 在open62541中,我们可以通过以下几个步骤来创建一个OPC UA服务端: 1. 初始化服务器:首先,我们需要初始化一个服务器实例,并设置服务器的基本信息,如名称和描述。 2. 创建命名空间:命名空间用于组织OPC UA节点的层次结构,我们可以创建多个命名空间,每个命名空间下可以有不同的节点。 3. 创建节点:在命名空间下,我们可以创建各种类型的节点,如变量节点、对象节点方法节点节点是OPC UA通信的基本单位,它们可以包含数据、状态和方法。通过open62541的API,我们可以设置节点的属性和订阅变量的变化。 4. 注册方法:如果我们需要在服务端执行某些操作,我们可以创建方法节点,并注册对应的方法处理函数。当客户端调用方法时,服务器将执行处理函数,并返回执行结果。 5. 启动服务器:在所有节点方法都创建完毕后,我们可以启动服务器,并监听来自客户端的连接请求。一旦建立连接,服务器将与客户端进行通信,并处理客户端的请求。 通过open62541,我们可以轻松地编写和管理OPC UA服务端,提供可靠和安全的数据传输和通信。它是一个功能丰富且易于使用的库,被广泛应用于工业自动化和物联网领域。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

复杂的世界311

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值