目录
一、下载源码
二、编译源码
三、案例编译
3.1 工程目录
3.2 server端
3.3 client端
3.4 程序运行
四、补充open62541库的linux编译
4.1 cmake版本升级
4.2 python3支持
4.3 open62541源码编译
一、下载源码
win10系统下,安装git工具,下载open62541库源码,该源码是MPLv2的License
git clone --recursive https://github.com/open62541/open62541.git
#gitee
git clone --recursive https://gitee.com/qihuanweidu007/open62541.git
#如果某些模块无法加载,重新调整网络后,继续加载确保无fail输出
cd open62541
git submodule update --remote --recursive
系统安装了cmake、MinGW、VC和python3工具,将工作路径加入环境变量path中。
二、编译源码
进入open62541目录
#本文的源码路径是D:\\workForOrgCode\\open62541
#创建编译目录
mkdir build_mingw
#或cmd指令md指令创建目录
cd build_mingw
cmake -G "MinGW Makefiles" .. -DUA_ENABLE_AMALGAMATION=ON
#如果提示无法查找到python3包,直接显式指定
cmake -G "MinGW Makefiles" .. -DUA_ENABLE_AMALGAMATION=ON -DPython3_EXECUTABLE="D:\\workForSoftware\\python36\\python.exe"
#编译
mingw32-make -j4 #或cmake --build . --config release
#vc编译
md build_vc
cd build_vc
#本文采用vs2013版本
cmake -G "Visual Studio 12 2013" .. -DUA_ENABLE_AMALGAMATION=ON -DPython3_EXECUTABLE="D:\\workForSoftware\\python36\\python.exe"
cmake --build . --config release
可能会出现 error C2220: 警告被视为错误 - 没有生成“object”文件,
可以通过文本编辑工具将生成的open62541.c文件改为ANSI格式,然后再次编译
在编译过程中,会显示生成open62541.h和open62541.c文件,然后再编译成库文件,按官方说法,直接引入open62541.h和open62541.c来源码及生成库文件来开发,
如果不想引入那么大的open62541.h头文件,也可以按需引入各个头文件,这些文件的存放路径例如:
#"D:\\workForOrgCode\\open62541\\include"
#"D:\\workForOrgCode\\open62541\\build_mingw\\src_generated"
#"D:\\workForOrgCode\\open62541\\arch"
#"D:\\workForOrgCode\\open62541\\deps"
#"D:\\workForOrgCode\\open62541\\plugins\\include"
库文件生成输出在build_mingw\bin目录下。
三、案例编译
3.1 工程目录
#D:\workForOrgCode\open62541目录下
demo
server_test
bin
build_mingw
build_vc
src
main.c
CMakeLists.txt
client_test
bin
build_mingw
build_vc
src
main.c
CMakeLists.txt
3.2 server端
main.c,这里采用的是直接引入编译生成的open62541.h头文件,也可直接引用仅涉及的头文件,如注释的那样:
#include <signal.h>
//#include <open62541/server.h>
//#include <open62541/server_config_default.h>
#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_Server *server = UA_Server_new();
UA_ServerConfig_setDefault(UA_Server_getConfig(server));
/* 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);
return status;
}
CMakeLists.txt,如果采用了单独引入各个头文件的方式,主要把各个头文件及关联头文件的所在路径添加进来,如这些目录(include_directories)如本文所注释掉的那些:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (opc_server_test)
#
if(WIN32)
message(STATUS "windows compiling...")
add_definitions(-D_PLATFORM_IS_WINDOWS_)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
set(WIN_OS true)
else(WIN32)
message(STATUS "linux compiling...")
add_definitions( -D_PLATFORM_IS_LINUX_)
add_definitions("-Wno-invalid-source-encoding")
# add_definitions("-O2")
set(UNIX_OS true)
set(_DEBUG true)
endif(WIN32)
set(UA_IPV6 0)
set(org_dir ${PROJECT_SOURCE_DIR}/../..) #即D:\\workForOrgCode\\open62541
set(build_dir ${PROJECT_SOURCE_DIR}/../../build_mingw)
#set(build_dir ${PROJECT_SOURCE_DIR}/../../build_vc)
#set(build_dir ${PROJECT_SOURCE_DIR}/../../build_linux)
#
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
# 指定源文件的目录,并将名称保存到变量
SET(source_h
#
#${build_dir}/open62541.h #由于添加了其所在目录,不用直接添加
)
SET(source_cpp
#
${PROJECT_SOURCE_DIR}/src/main.c
${build_dir}/open62541.c
)
#头文件目录
include_directories(
${build_dir} #引入open62541.h所在目录
#${org_dir}/include
#${build_dir}/src_generated
#${org_dir}/arch
#${org_dir}/deps
#${org_dir}/plugins/include
)
if (${UNIX_OS})
add_definitions(
"-DUA_ARCHITECTURE_POSIX"
)
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0")
link_directories()
# 指定生成目标
add_executable(opc_server_test ${source_h} ${source_cpp} )
#link
target_link_libraries(opc_server_test
-lpthread
${build_dir}/bin/libopen62541.a
)
endif(${UNIX_OS})
if (${WIN_OS})
add_definitions(
"-DUA_ARCHITECTURE_WIN32"
)
link_directories(
"${build_dir}/bin"
)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/bin)
# 指定生成目标
add_executable(opc_server_testd ${source_h} ${source_cpp} )
#link
target_link_libraries(opc_server_testd
ws2_32.lib wsock32.lib Iphlpapi.lib #win下依赖的基础库
${build_dir}/bin/libopen62541.a #mingw
#${build_dir}/bin/Debug/open62541d.lib #vc
)
else(CMAKE_BUILD_TYPE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/bin)
# 指定生成目标
add_executable(opc_server_test ${source_h} ${source_cpp})
#link
target_link_libraries(opc_server_test
ws2_32.lib wsock32.lib Iphlpapi.lib
${build_dir}/bin/libopen62541.a #mingw
#${build_dir}/bin/Release/open62541.lib #vc
#D:\\workForOrgCode\\open62541\\build_vc\\bin\\Release\\open62541.lib #vc
)
endif (CMAKE_BUILD_TYPE)
endif(${WIN_OS})
编译 ,注意mingw和vc编译时,需要在CMakeLists.txt中调整一下配置路径
#D:\workForOrgCode\open62541\demo\server_test
#工程配置在CMakeLists.txt
set(build_dir ${PROJECT_SOURCE_DIR}/../../build_mingw)
#set(build_dir ${PROJECT_SOURCE_DIR}/../../build_vc)
#link
${build_dir}/bin/libopen62541.a #mingw
#${build_dir}/bin/Release/open62541.lib #vc
编译
cd build_mingw
cmake -G "MinGW Makefiles" ..
mingw32-make -j4
#或cmake --build . --config release
#D:\workForOrgCode\open62541\demo\server_test
#工程配置在CMakeLists.txt
#set(build_dir ${PROJECT_SOURCE_DIR}/../../build_mingw)
set(build_dir ${PROJECT_SOURCE_DIR}/../../build_vc)
#link
#${build_dir}/bin/libopen62541.a #mingw
${build_dir}/bin/Release/open62541.lib #vc
编译
cd build_vc
cmake -G "Visual Studio 12 2013" ..
cmake --build . --config release
3.3 client端
main.c,如果不想直接引用open62541.h,可独立引用关联文件,注意在CMakeLists.txt中配置这头文件所在的目录
#include <stdio.h>
//#include <open62541/client.h>
//#include <open62541/client_config_default.h>
//#include <open62541/client_highlevel.h>
#include "open62541.h"
int main(int argc, char *argv[])
{
/* Create a client and connect */
UA_Client *client = UA_Client_new();
UA_ClientConfig_setDefault(UA_Client_getConfig(client));
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_clear(&value);
UA_Client_delete(client); /* Disconnects the client internally */
return status;
}
CMakeLists.txt
#在D:\workForOrgCode\open62541\demo\client_test目录下
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (opc_client_test)
#
if(WIN32)
message(STATUS "windows compiling...")
add_definitions(-D_PLATFORM_IS_WINDOWS_)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
set(WIN_OS true)
else(WIN32)
message(STATUS "linux compiling...")
add_definitions( -D_PLATFORM_IS_LINUX_)
add_definitions("-Wno-invalid-source-encoding")
# add_definitions("-O2")
set(UNIX_OS true)
set(_DEBUG true)
endif(WIN32)
set(UA_IPV6 0)
set(org_dir ${PROJECT_SOURCE_DIR}/../..)
set(build_dir ${PROJECT_SOURCE_DIR}/../../build_mingw)
#set(build_dir ${PROJECT_SOURCE_DIR}/../../build_vc)
#set(build_dir ${PROJECT_SOURCE_DIR}/../../build_linux)
#
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
# 指定源文件的目录,并将名称保存到变量
SET(source_h
#
#${build_dir}/open62541.h
)
SET(source_cpp
#
${PROJECT_SOURCE_DIR}/src/main.c
${build_dir}/open62541.c
)
#头文件目录
include_directories(
${build_dir}
#${org_dir}/include #独立引用关联头文件需要配置各文件目录
#${build_dir}/src_generated
#${org_dir}/arch
#${org_dir}/deps
#${org_dir}/plugins/include
)
if (${UNIX_OS})
add_definitions(
"-DUA_ARCHITECTURE_POSIX"
)
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0")
link_directories()
# 指定生成目标
add_executable(opc_client_test${source_h} ${source_cpp} )
#link
target_link_libraries(opc_client_test
-lpthread
${build_dir}/bin/libopen62541.a
)
endif(${UNIX_OS})
if (${WIN_OS})
add_definitions(
"-DUA_ARCHITECTURE_WIN32"
)
link_directories(
"${build_dir}/bin"
)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/bin)
# 指定生成目标
add_executable(opc_client_testd ${source_h} ${source_cpp} )
#link
target_link_libraries(opc_client_testd
ws2_32.lib wsock32.lib Iphlpapi.lib
${build_dir}/bin/libopen62541.a #mingw
#${build_dir}/bin/Debug/open62541d.lib #vc
)
else(CMAKE_BUILD_TYPE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/bin)
# 指定生成目标
add_executable(opc_client_test ${source_h} ${source_cpp})
#link
target_link_libraries(opc_client_test
ws2_32.lib wsock32.lib Iphlpapi.lib
${build_dir}/bin/libopen62541.a #mingw
#${build_dir}/bin/Release/open62541.lib #vc
#D:\\workForOrgCode\\open62541\\build_vc\\bin\\Release\\open62541.lib #vc
)
endif (CMAKE_BUILD_TYPE)
endif(${WIN_OS})
编译类似服务端。
3.4 程序运行
程序运行测试,先开启服务端,然后开启客户端,如下,客户端连接上服务端,取回一个数值并打印出来“the value is 42”,如果没有连接上,请检查端口是否被其他程序占用或防火墙隔离:
四、补充open62541库的linux编译
4.1 cmake版本升级
本文ubuntu16-64bit环境,先升级cmake工具(原来是3.5.2版本的)
#D:\workForOrgCode\open62541
mkdir cmake_new_version
cd cmake_new_version
#cmake 源码ftp网站https://cmake.org/files/ 下载需要的版本
wget https://cmake.org/files/v3.24/cmake-3.24.2.tar.gz
tar -zxvf cmake-3.24.2.tar.gz
cd cmake-3.24.2
#apt-get install libssl-dev #OPENSSL依赖 或./configure -DCMAKE_USE_OPENSSL=OFF
./configure
make -j4
#root 用户下
make install
update-alternatives --install /usr/bin/cmake cmake /usr/local/bin/cmake 1 --force
cmake --version
4.2 python3支持
再安装python3支持
#root 用户下
apt-get install python python3 python-pip python3-pip
whereis python3
#例如/usr/bin/python3
4.3 open62541源码编译
编译过程大致如下:
#确保cmake > 3.15版本,确保安装了python3支持,确保安装了gcc
#进入open62541目录
mkdir build_linux
cd build_linux
cmake .. -DUA_ENABLE_AMALGAMATION=ON -DUA_MULTITHREADING=100 -DPython3_EXECUTABLE="/usr/bin/python3"
make -j4
#open62541.c:68808:43: error: comparison is always false due to limited range of data type [-Werror=type-limits] if(i < T##_MIN || (i > 0 && (t)i >= T##_MAX))
#修改为:if(i < T##_MIN || (i > 0 && (t)i >= T##_MAX)) ,再次编译
make -j4
编译结果输出如下:
案例编译与win类似。
#先调整CMakeLists.txt
#set(build_dir ${PROJECT_SOURCE_DIR}/../../build_mingw)
#set(build_dir ${PROJECT_SOURCE_DIR}/../../build_vc)
set(build_dir ${PROJECT_SOURCE_DIR}/../../build_linux)
#进入open62541目录
cd demo/server_test
mkdir build_linux
cd build_linux
cmake .. -DUA_ENABLE_AMALGAMATION=ON
make -j4
#client端类似