[3]Ubuntu下安裝open62541並建立服務器和客戶端通信的詳細步驟

Ubuntu下安裝open62541並建立服務器和客戶端通信的詳細步驟


理論看多了,也該動手實踐了。

open62541簡介

open62541 (http://open62541.org)是用C99和c++ 98語言的公共子集編寫的OPC UA (OPC統一架構)的開源和免費實現。該庫可用於所有主要編譯器,並提供必要的工具來實現專用的OPC UA客戶端和服務器,或將基於OPC UA的通信集成到現有應用程序中。open62541庫是平臺獨立的。所有特定於平臺的功能都是通過可交換的插件實現的。主要的操作系統都提供了插件實現。

1 下載源碼

使用以下命令去下載源碼:

git clone -b 1.0  https://github.com/open62541/open62541.git

open62541還有一些子模塊,當enable一些特殊功能時就需要他們了,例如自定義namespace等,這個需要使用以下命令去下載(在上面下載源碼後的源碼根目錄下操作):

git submodule update –init

2 編譯

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種調用方式:

  1. open62541.h + libopen62541.a
  2. open62541.h + open62541.c

這樣我們就可以很方便的把open62541集成到自己代碼裏來了,這2種方式下面都會講下。

3 運行demo(第一種方法):

我們在別的地方建立一個目錄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 <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;
}

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 "<CMAKE_AR> qcs <TARGET> <LINK_FLAGS> <OBJECTS>")
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 .. && make,就會在bin目錄下生成server和client這2個執行文件。
在這裏插入圖片描述
client的功能是從server那裏獲取時間,下面就先運行server,./server
在這裏插入圖片描述
然後運行client,./client,可以看到打印出來的server時間,
在這裏插入圖片描述
這樣server和client之間就通信成功了!

4 運行demo(第二種方法):

我們在別的地方建立一個目錄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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章