1 下载源码
git clone https://github.com/open62541/open62541.git
安装依赖的软件包
# enable additional features
sudo apt-get install cmake-curses-gui # for the ccmake graphical interface
sudo apt-get install libmbedtls-dev # for encryption support
sudo apt-get install check libsubunit-dev # for unit tests
sudo apt-get install python-sphinx graphviz # for documentation generation
sudo apt-get install python-sphinx-rtd-theme # documentation style
2 创建build目录
在源码根目录下新建build目录,并进入build目录
3 设置环境变量
export CC=arm-linux-gnueabihf-gcc
export CXX=arm-linux-gnueabihf-g++
4 编译
cd build
# cmake ..
# cmake .. -DBUILD_SHARED_LIBS=ON # 编译成动态库
cmake .. -DUA_ENABLE_AMALGAMATION=ON
make
这里解释下cmake的命令行中的UA_ENABLE_AMALGAMATION选项,这是open62541的CMakeLists.txt提供的选项,专门用于生成single distribution版本的open62541,即open62541.c 和 open62541.h文件,方便用于集成到其它程序里。在bin目录下生成的是open62541的静态库,可以用于和别的程序进行链接。
5 编译成功
[ 86%] Building C object CMakeFiles/open62541-plugins.dir/plugins/crypto/ua_pki_none.c.o
[ 88%] Building C object CMakeFiles/open62541-plugins.dir/plugins/crypto/ua_securitypolicy_none.c.o
[ 88%] Building C object CMakeFiles/open62541-plugins.dir/plugins/ua_log_syslog.c.o
[ 90%] Building C object CMakeFiles/open62541-plugins.dir/arch/posix/ua_clock.c.o
[ 92%] Building C object CMakeFiles/open62541-plugins.dir/arch/posix/ua_architecture_functions.c.o
[ 94%] Building C object CMakeFiles/open62541-plugins.dir/arch/network_tcp.c.o
[ 98%] Built target open62541-plugins
Scanning dependencies of target open62541
[100%] Linking C static library bin/libopen62541.a
[100%] Built target open62541
编译后的库在build/bin/下面
$ ls bin/
libopen62541.a
并且在build目录下有:open62541.c open62541.h
6 测试
serv.c
// 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 <signal.h>
#include <stdlib.h>
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 <stdlib.h>
#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;
}
把上面编译的open62541.c open62541.h和这两个测试代码放在一个目录下
$ ls
client.c open62541.c open62541.h server.c
编译:
$ arm-linux-gnueabihf-gcc -std=c99 open62541.c client.c -o client
$ arm-linux-gnueabihf-gcc -std=c99 open62541.c server.c.c -o server
运行:
把serv和client放到目标机器上:
# ./server
[2020-10-22 15:08:54.667 (UTC+0800)] warn/server AccessControl: Unconfigured AccessControl. Users have all permissions.
[2020-10-22 15:08:54.668 (UTC+0800)] info/server AccessControl: Anonymous login is enabled
[2020-10-22 15:08:54.669 (UTC+0800)] warn/server Username/Password configured, but no encrypting SecurityPolicy. This can leak credentials on the network.
[2020-10-22 15:08:54.670 (UTC+0800)] warn/userland AcceptAll Certificate Verification. Any remote certificate will be accepted.
[2020-10-22 15:08:54.672 (UTC+0800)] info/network TCP network layer listening on opc.tcp://imx6ull14x14evk:4840/
[2020-10-22 15:09:07.601 (UTC+0800)] info/network Connection 5 | New connection over TCP from ::1
[2020-10-22 15:09:07.603 (UTC+0800)] info/channel Connection 5 | SecureChannel 1 | SecureChannel opened with SecurityPolicy http://opcfoundation.org/UA/SecurityPolicy#None and a revised lifetime of 600.00s
[2020-10-22 15:09:07.609 (UTC+0800)] info/channel Connection 5 | SecureChannel 1 | Session 5f208920-4bab-1eeb-c8ec-1e0143c4fc3f created
[2020-10-22 15:09:07.618 (UTC+0800)] info/channel Connection 5 | SecureChannel 1 | CloseSecureChannel
[2020-10-22 15:09:07.618 (UTC+0800)] info/network Connection 5 | Closed
# ./client
[2020-10-22 15:09:07.586 (UTC+0800)] warn/userland AcceptAll Certificate Verification. Any remote certificate will be accepted.
[2020-10-22 15:09:07.604 (UTC+0800)] info/channel Connection 3 | SecureChannel 1 | SecureChannel opened with SecurityPolicy http://opcfoundation.org/UA/SecurityPolicy#None and a revised lifetime of 600.00s
[2020-10-22 15:09:07.605 (UTC+0800)] info/client Client Status: ChannelState: Open, SessionState: Closed, ConnectStatus: Good
[2020-10-22 15:09:07.607 (UTC+0800)] info/client Selected Endpoint opc.tcp://localhost:4840 with SecurityMode None and SecurityPolicy http://opcfoundation.org/UA/SecurityPolicy#None
[2020-10-22 15:09:07.608 (UTC+0800)] info/client Selected UserTokenPolicy open62541-anonymous-policy with UserTokenType Anonymous and SecurityPolicy http://opcfoundation.org/UA/SecurityPolicy#None
[2020-10-22 15:09:07.610 (UTC+0800)] info/client Client Status: ChannelState: Open, SessionState: Created, ConnectStatus: Good
[2020-10-22 15:09:07.612 (UTC+0800)] info/client Client Status: ChannelState: Open, SessionState: Activated, ConnectStatus: Good
[2020-10-22 15:09:07.613 (UTC+0800)] info/userland date is: 22-10-2020 7:9:7.613
[2020-10-22 15:09:07.620 (UTC+0800)] info/client Client Status: ChannelState: Closed, SessionState: Closed, ConnectStatus: Good
root@imx6ull14x14evk:/data/vpnclient#
可以 看到client已经获取到了时间
出现的问题
- cmake时报错:
The C compiler
"/home/sundh/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/arm-linux-gnueabihf-gcc"
is not able to compile a simple test program.
...略...
arm-linux-gnueabihf-gcc: error: unrecognized command line option ‘-m32’
...略...
解决办法:修改代码根目录下的CMakeLists.txt 把"-m32"部分的代码屏蔽掉
# if(UA_FORCE_32BIT)
# string(FIND "${CMAKE_C_FLAGS}" "-m32" m32_already_set)
# if(m32_already_set EQUAL -1)
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
# endif()
# unset(flag_supported CACHE)
# endif()
参考说明:
https://github.com/open62541/open62541/blob/master/doc/building.rst