open62541 (http://open62541.org)是用C99和c++ 98语言的公共子集编写的OPC UA (OPC统一架构)的开源和免费实现。该库可用于所有主要编译器,并提供必要的工具来实现专用的OPC UA客户端和服务器,或将基于OPC UA的通信集成到现有应用程序中。open62541库是平台独立的。所有特定于平台的功能都是通过可交换的插件实现的。主要的操作系统都提供了插件实现。
使用以下命令去下载源码:
git clone -b 1.0 https://github.com/open62541/open62541.git
open62541还有一些子模块,当enable一些特殊功能时就需要他们了,例如自定义namespace等,这个需要使用以下命令去下载(在上面下载源码后的源码根目录下操作):
git submodule update –init
cd到源码根目录下,创建build目录,然后cd到build目录下,输入以下命令去调用cmake:(生成open62541.h和open62541.c文件)
cmake .. -DUA_ENABLE_AMALGAMATION=ON
执行结果:
注意:如果出现下面错误:请先安装g++,g++安装命令:
sudo apt-get install g++
接着再运行make
命令,生成以下文件:
这里解释下cmake的命令行中的UA_ENABLE_AMALGAMATION选项,这是open62541的CMakeLists.txt提供的选项,专门用于生成single distribution版本的open62541,即open62541.c 和 open62541.h文件,方便用于集成到其它程序里。在bin目录下生成的是open62541的静态库,可以用于和别的程序进行链接。
也就是说open62541的CMakeLists.txt提供了2种调用方式:
这样我们就可以很方便的把open62541集成到自己代码里来了,这2种方式下面都会讲下。
我们在别的地方建立一个目录runDemoOpen62541,然后把libopen62541.a 和open62541.h拷贝进来,然后在这个目录下创建bin和build目录,创建server.c,client.c和CMakeLists.txt,整体结构如下:
server.c,client.c和CMakeLists.txt内容分别如下:
// server.c
/* 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"
#include
#include
UA_Boolean running = true;
static void stopHandler(int sign) {
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c");
running = false;
}
int main(void)
{
signal(SIGINT, stopHandler);
signal(SIGTERM, stopHandler);
UA_Server *server = UA_Server_new();
UA_ServerConfig_setDefault(UA_Server_getConfig(server));
UA_StatusCode retval = UA_Server_run(server, &running);
UA_Server_delete(server);
return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}
Client.c:
// client.c,功能主要是从server那里获取时间
#include
#include "open62541.h"
int main(void)
{
UA_Client *client = UA_Client_new();
UA_ClientConfig_setDefault(UA_Client_getConfig(client));
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; /* Variants can hold scalar values and arrays of any type */
UA_Variant_init(&value);
/* NodeId of the variable holding the current time */
const UA_NodeId nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
retval = UA_Client_readValueAttribute(client, nodeId, &value);
if(retval == UA_STATUSCODE_GOOD && UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DATETIME]))
{
UA_DateTime raw_date = *(UA_DateTime *) value.data;
UA_DateTimeStruct dts = UA_DateTime_toStruct(raw_date);
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "date is: %u-%u-%u %u:%u:%u.%03u\n",
dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec);
}
/* Clean up */
UA_Variant_clear(&value);
UA_Client_delete(client); /* Disconnects the client internally */
return EXIT_SUCCESS;
}
CMakeLists.txt内容如下:
cmake_minimum_required(VERSION 3.5)
project(demoOpen62541)
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flto")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")
SET(CMAKE_AR "gcc-ar")
SET(CMAKE_C_ARCHIVE_CREATE " qcs " )
SET(CMAKE_C_ARCHIVE_FINISH true)
add_definitions(-std=c99)
include_directories(${PROJECT_SOURCE_DIR}/open62541)
link_directories(${PROJECT_SOURCE_DIR}/open62541/bin)
add_executable(server ${PROJECT_SOURCE_DIR}/src/server.c)
target_link_libraries(server libopen62541.a)
add_executable(client ${PROJECT_SOURCE_DIR}/src/client.c)
target_link_libraries(client libopen62541.a)
然后cd到build目录下,运行cmake .. && mak
e,就会在bin目录下生成server和client这2个执行文件。
client的功能是从server那里获取时间,下面就先运行server,./server
然后运行client,./client
,可以看到打印出来的server时间,
这样server和client之间就通信成功了!
我们在别的地方建立一个目录runDemoOpen62541,然后把open62541.c 和open62541.h拷贝进来,然后在这个目录下创建bin和build目录,创建server.c,client.c和CMakeLists.txt,整体结构如下,
server.c和client.c的代码和上面讲第1种方法的内容一样,CMakeLists.txt不一样,内容如下:
cmake_minimum_required(VERSION 3.5)
project(demoOpen62541)
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
add_definitions(-std=c99)
include_directories(${PROJECT_SOURCE_DIR}/open62541)
add_executable(server ${PROJECT_SOURCE_DIR}/src/server.c ${PROJECT_SOURCE_DIR}/open62541/open62541.c)
add_executable(client ${PROJECT_SOURCE_DIR}/src/client.c ${PROJECT_SOURCE_DIR}/open62541/open62541.c)
然后cd到build目录下,运行cmake .. && make
,就会在bin目录下生成server和client这2个执行文件。
client的功能是从server那里获取时间,下面就先运行server,./server
然后运行client,./client
,可以看到打印出来的server时间,
这样server和client之间就通信成功了!
如果不使用CMake,直接将生成的open62541.h和open62541.c文件放到你写的.c代码路径下,然后使用以下命令直接编译:
open62541.h、open62541.c、client.c、server.c、同一个目录下。
gcc -std=c99 open62541.c client.c -o client
gcc -std=c99 open62541.c server.c -o server
./server
重新打开一个终端
./client
即可通信成功.
参考前辈链接:https://blog.csdn.net/whahu1989/article/details/99189801