OPC-UA使用入门-linux搭建简单的服务器与客户端

使用OPCUA的目标是:将linux端的共享内存的一些信息实时反馈集成到window端去,并从window给到linux的共享内存赋值。最后是成功的,可以看我专栏。

这里使用的是一个免费的开源项目https://github.com/open62541/open62541。

仔细查看,上面有足够详细的文档与例子,感觉已经是一个成熟的协议,开始学习吧。

OPC-UA使用入门-linux搭建简单的服务器与客户端_第1张图片

首先在https://open62541.org/下载一份linux32的包,我这里使用的是链接:https://pan.baidu.com/s/16nUPH7drmoNDKSCz51YQPg 
提取码:y3b6

Git-Revision: v0.3-rc4,当时是最新的。

,这里的包是把github的源码处理成.a加接口文件open62541.c与open62541.h。在bin文件夹中有已经编好了的.a静态库,如下(不详细截图了。):

OPC-UA使用入门-linux搭建简单的服务器与客户端_第2张图片

Server

最简单的案例:在linux中搭建服务器与客户端,传输一个int值。服务器myServer.c文件内容如下:

  - 创建结束ctrl-c的处理函数

  - 定义一个int变量的节点,并添加到信息模型

  - 运行并等待ctrl-c 

#include 
#include 
#include "open62541.h"

UA_Boolean runing = true;
static void stopHandler(int sig)
{
    UA_LOG_INFO(UA_Log_Stdout,UA_LOGCATEGORY_USERLAND,"received ctrl c");
    runing = false;
}

static void addVariable(UA_Server *server)
{
    /*Define the attribute of the myInteger variable node*/
    UA_VariableAttributes attr = UA_VariableAttributes_default;
    UA_Int32 myInteger = 43;
    UA_Variant_setScalar(&attr.value,&myInteger,&UA_TYPES[UA_TYPES_INT32]);
    attr.description = UA_LOCALIZEDTEXT("en-US","the answer");
    attr.displayName = UA_LOCALIZEDTEXT("en-US","the answer");
    attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
    attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;

    /*Add the variable node to the information model*/
    UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1,"the.answer");
    UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1,"the answer");
    UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0,UA_NS0ID_OBJECTSFOLDER);
    UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0,UA_NS0ID_ORGANIZES);
    UA_Server_addVariableNode(server,myIntegerNodeId,parentNodeId,\
                              parentReferenceNodeId,myIntegerName,\
                              UA_NODEID_NUMERIC(0,UA_NS0ID_BASEDATAVARIABLETYPE),\
                              attr,NULL,NULL);

}


int main(void)
{
    signal(SIGINT,stopHandler);
    signal(SIGTERM,stopHandler);
    UA_ServerConfig *config = UA_ServerConfig_new_default();
    UA_Server *server = UA_Server_new(config);

    addVariable(server);


    UA_StatusCode retval = UA_Server_run(server,&runing);
    UA_Server_delete(server);
    UA_ServerConfig_delete(config);
    return (int)retval;
}

Client

然后就是客户端的读取了。

  - 连接到默认的端口

  - 根据UA_NodeId将server中的值读取

  - 打印输出,结束

#include 
#include "open62541.h"

int main(void)
{
    UA_Client *client = UA_Client_new(UA_ClientConfig_default);
    UA_StatusCode retval = UA_Client_connect(client,"opc.tcp://localhost:4840");
    if(retval != UA_STATUSCODE_GOOD)
    {
        UA_Client_delete(client);
        return (int)retval;
    }
    /*read the value attribute of the node.UA_Client_readValueAttribute is a wrapper for the
    raw read service available as UA_Client_Service_read.*/
    UA_Variant value;
    UA_Variant_init(&value);

    UA_NodeId testvar = UA_NODEID_STRING(1,"the.answer");
    retval = UA_Client_readValueAttribute(client, testvar, &value);

    if(retval == UA_STATUSCODE_GOOD) {
        UA_Int32 *p = (UA_Int32 *)value.data;
        printf("Var = %d \n",*p);
    }

    /*Clean up */
    UA_Variant_deleteMembers(&value);
    UA_Client_delete(client);
    return UA_STATUSCODE_GOOD;
}

编译:

gcc -std=c99 open62541.c myClient.c -o myClient
gcc -std=c99 open62541.c myServer.c -o myServer

运行:

./myServer
打开一个终端
./myClient

反馈正确,Var = 43 .over

 

拓展

若是想在Arm上使用该例子,则需要下载其中的raspiberry树莓派的版本的发布包,里面是一个动态库。使用时有可能会出以下错误:

undefined reference to `clock_gettime'

请使用在最后添加 -lrt库:

gcc -std=c99 open62541.c myClient.c -o myClient -lrt
gcc -std=c99 open62541.c myServer.c -o myServer -lrt

拷贝到arm板子上执行即可!

 

这里提供一个简单的客户端,是从别人那下来的:

链接:https://pan.baidu.com/s/1KqcguYOpXKNB42CWdOJUDA 密码:1t0r

可以从linux连接网线到window,使用opc.tcp://192.168.XXX.XXX:4840连接:

如下,43也是打印出来的:

OPC-UA使用入门-linux搭建简单的服务器与客户端_第3张图片

 

你可能感兴趣的:(OPC,UA,OPCUA-62541使用总结)