OPC UA的好处就不说了,既然你找到了这篇文章,说明你对其已经有了一定的了解。
open62541是在Mozilla Public License v2.0下授权的一个开源的、可跨平台的OPC UA库,采用C(C99)实现。
open62541的官网地址:https://open62541.org/ github地址:https://github.com/open62541/open62541
在open62541的官网有详细的帮助文档,推荐直接查看该文档,作者也是根据其文档的帮助实现的基本功能。
在下方可根据需要自行下载相关文件
当然,你也可以去github下载最新文件,自行编译获得open62541的.c和.h文件,这是我编译的详细过程【零】基于open62541项目编译单独的open62541源文件和头文件
环境:Windows 10 home、visual studio 2017 community
所需lib包:WS2_32.Lib
- 建立服务器
首先打开VS2017新建一个空项目,然后将open62541.c、open62541.h和WS2_32.Lib分别添加到项目中去,然后新建一个.c或者.cpp文件,主要用于编写服务器相关的代码,刚开始可以直接复制open62541提供的参考代码server,文后附有我所用的server代码
完成后就可以直接编译运行了,如下是结果
2. 建立客户端
在打开VS2017新建一个空项目,然后将open62541.c、open62541.h和WS2_32.Lib分别添加到项目中去,然后新建一个.c或者.cpp文件,主要用于编写客户端相关的代码,刚开始可以直接复制open62541提供的参考代码client,完成后如下所示,文后附有我所用的client代码
直接编译运行之后会发现终端一闪而过,我们查看服务器的连接信息可以看到如下消息
这意味着我们用代码建立的客户端是连接到了服务器的,所以我们在原有的客户端代码如下位置加一句话,然后运行就能看到客户端的信息啦
与服务器代码进行比较可以发现其值是一样的
如想较为直观的感受到建立的服务器,可以下载UaExpert进行查看,官网的需要登录才能下载,可以直接下我提供的1,2.(安装软件>10M,无法一次上传,分两次传的)
安装完成之后运行软件,界面如下所示
点击途中红圈添加需要连接的服务器
点击红框进行服务器url的配置
1:添加服务器url地址,由ip(或者localhost)+port组成,可以在服务器代码中查看——必填
2:选择服务器所用的安全策略——选填
3:填写与第2步对应的验证账户、密码或者密匙、证书——根据第2步填写
4:填写与服务器建立会话的session名称——选填
5:之所以放在第5步,是因为如果之前添加过其他的服务时,会沿用上一个的名字,所以可以添加了url之后在修改
如图是我添加完了之后的界面
之后选中要连接的服务器,连接可以点红色方框的快捷键也可以在服务上右键连接
连接成功之后可以在UaExpert左边会显示服务器的数据结构组成;连接成功的同时,在服务器的终端也会打印出连接的通道和会话建立的工程和信息
现在,把ua-expert左边的the-answer拖到中间区域查看详细信息,可以看到其值与服务器代码里写的值和代码客户端读出来的值是一样的。
以上就是在Windows 10下通过visual studio 2017基于open62541建立OPC UA服务器和客户端的全部过程,如有不懂的可以留言,我看到并且我会的话会回复的。
这是根据2019年7月7日【零】基于open62541项目编译单独的open62541源文件和头文件的.c和.h建立的工程文件
server代码
#include#include "open62541.h" UA_Boolean running = true; void signalHandler(int sig) { running = false; } int main(int argc, char** argv) { signal(SIGINT, signalHandler); /* catch ctrl-c */ /* Create a server listening on port 4840 */ UA_ServerConfig *config = UA_ServerConfig_new_default(); UA_Server *server = UA_Server_new(config); /* Add a variable node */ /* 1) Define the node attributes */ UA_VariableAttributes attr = UA_VariableAttributes_default; attr.displayName = UA_LOCALIZEDTEXT("en-US", "the answer"); UA_Int32 myInteger = 42; UA_Variant_setScalar(&attr.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]); /* 2) Define where the node shall be added with which browsename */ UA_NodeId newNodeId = UA_NODEID_STRING(1, "the.answer"); UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES); UA_NodeId variableType = UA_NODEID_NULL; /* take the default variable type */ UA_QualifiedName browseName = UA_QUALIFIEDNAME(1, "the answer"); /* 3) Add the node */ UA_Server_addVariableNode(server, newNodeId, parentNodeId, parentReferenceNodeId, browseName, variableType, attr, NULL, NULL); /* Run the server loop */ UA_StatusCode status = UA_Server_run(server, &running); UA_Server_delete(server); UA_ServerConfig_delete(config); return status; }
client代码
#include#include "open62541.h" int main(int argc, char *argv[]) { /* Create a client and connect */ UA_Client *client = UA_Client_new(UA_ClientConfig_default); UA_StatusCode status = UA_Client_connect(client, "opc.tcp://localhost:4840"); if (status != UA_STATUSCODE_GOOD) { UA_Client_delete(client); return status; } /* 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; /* Variants can hold scalar values and arrays of any type */ UA_Variant_init(&value); status = UA_Client_readValueAttribute(client, UA_NODEID_STRING(1, "the.answer"), &value); if (status == UA_STATUSCODE_GOOD && UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_INT32])) { printf("the value is: %i\n", *(UA_Int32*)value.data); } /* Clean up */ UA_Variant_deleteMembers(&value); UA_Client_delete(client); /* Disconnects the client internally */ system("pause"); return status; }