OPC UA/DA协议库open62541的源码编译及案例测试

目录

一、下载源码

二、编译源码

三、案例编译

        3.1 工程目录

        3.2 server端

        3.3 client端

       3.4 程序运行

四、补充open62541库的linux编译

        4.1 cmake版本升级

        4.2 python3支持

扫描二维码关注公众号,回复: 15633439 查看本文章

        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端类似

猜你喜欢

转载自blog.csdn.net/py8105/article/details/130524539
opc