open62541 (http://open62541.org) 是用 C 語言編寫的 OPC UA(OPC 統一架構/IEC 62541)的開源實作。該程式庫可與所有主要編譯器一起使用,並提供必要的工具來實現專用 OPC UA 用戶端和伺服器,或將基於 OPC UA 的通訊整合到現有應用程式中。 open62541 函式庫是獨立於平台的:所有特定於平台的功能都是透過可交換插件實現的,以便輕鬆移植到不同(嵌入式)目標。
open62541 根據 Mozilla 公共授權 v2.0 (MPLv2) 獲得許可。這使得 open62541 庫可以與任何專有軟體組合和分發。在複製和分發時,只有對 open62541 庫本身的變更需要根據 MPLv2 獲得許可。插件以及伺服器和用戶端範例均屬於公共領域(CC0 許可證)。它們可以在任何許可下重複使用,並且不必發布更改。
該庫以標準原始碼和二進制形式提供。此外,單一文件原始碼分發將整個庫合併為單一 .c 和 .h 文件,可輕鬆新增至現有專案中。範例伺服器和客戶端實作可以在 /examples 目錄或本頁的下方找到。
open62541 實作了 OPC UA SDK,支援伺服器、用戶端和 PubSub(發布-訂閱)通訊。有關完整詳細信息,請參閱功能概述。
open62541 根據 MPLv2 獲得許可。也就是說,對 MPLv2 下的文件進行的更改屬於同一開源許可證。但是,即使產生靜態二進位文件,該程式庫也可以與來自單獨文件的私人開發相結合,而許可證不會影響私人檔案。有關詳細信息,請參閱完整的許可文件。
Fraunhofer IOSB僱用了多名 open62541 開發人員並提供商業支援。 open62541.org 上列出了 open62541 生態系統中的其他服務提供者。
使用open62541 v1.0 建置的範例伺服器(server_ctt) 符合OPC 基金會的「微型嵌入式裝置伺服器」設定文件,支援OPC UA 用戶端/伺服器通訊、訂閱、方法呼叫和安全性(加密),安全性策略為“Basic128Rsa15” '、'Basic256' 和 'Basic256Sha256' 以及方面“方法伺服器”和“節點管理”。有關更多詳細信息,請參閱 https://open62541.org/certified-sdk。
PubSub (UADP) 在 open62541 中實作。但由於缺乏官方測試案例和測試工具,目前無法獲得認證(2019 年 9 月)。
在開發過程中,定期應用OPC基金會的一致性測試工具(CTT)。 CTT 配置和結果可在 https://github.com/open62541/open62541-ctt 上追蹤。目前在 CTT 中定期測試的 OPC UA 設定檔有:
請參閱 open62541 功能頁面,深入了解對構成 OPC UA 設定檔的一致性單元的支援。
有關 OPC UA 的一般介紹和 open62541 文檔,請造訪 http://open62541.org。該庫的過去版本可以在 https://github.com/open62541/open62541/releases 下載。
整個 open62541 社群處理 Github 和郵件清單上的公開支援請求。如需個人討論與支持,請使用以下管道:
我們希望建立一個開放、熱情的社區。請考慮我們的行為準則。
open62541的建置環境是透過CMake產生的。有關詳細信息,請參閱建置文件。為了簡化與現有軟體專案的集成,可以將 open62541 原始碼壓縮(合併)為單一檔案分發,即一對open62541.c/.h
檔案。單一檔案發行版中包含的功能取決於目前的 CMake 配置。
原始碼結構如下:
/include
):公共 API 向使用 open62541 的應用程式公開。插件實現的標頭位於/plugins/include
中。/src
):除了 C99 標準頭之外,核心庫沒有任何相依性。/arch
):架構支援是透過EventLoop
插件實現的。這將特定於體系結構的程式碼(例如使用 POSIX API)保留在核心庫之外。提供了不同(嵌入式)架構的連接埠。/plugins
):插件介面允許與不同的後端系統和函式庫整合。例如關於加密原語、資訊模型的儲存等等。提供了預設實現。/deps
):一些附加程式庫透過 git 子模組使用或已內化到deps/
資料夾中。有關第三方庫及其各自許可證的更多資訊可以在 deps/README.md 中找到在大多數系統上,一個簡單的 open62541 只需要 C 標準函式庫。根據建置配置,open62541 依賴其他函式庫,例如用於加密的 mbedTLS 或 OpenSSL。
作為一個開源項目,我們鼓勵新的貢獻者幫助改進 open62541。文件 CONTRIBUTING.md 匯總了我們期望的程式碼貢獻的良好實踐。以下是新貢獻者的良好起點:
對於最終將成為 open62541 庫一部分的客製化開發,請讓核心維護者之一了解情況。
我們強調程式碼品質。以下品質指標經過持續檢查,並確保在正式發布之前保持有效:
該專案建立了處理漏洞的流程。有關詳細資訊以及如何負責任地向維護人員揭露調查結果,請參閱 SECURITY.md。
程式碼範例可以在 /examples 目錄中找到。要建置範例,我們建議安裝上一節中提到的 open62541。使用 GCC 編譯器,只需執行gcc -std=c99 <server.c> -lopen62541 -o server
(在 Windows 下,您可能需要新增針對ws2_32
套接字庫的額外連結)。
#include <open62541/server.h>
int main ( int argc , char * * argv )
{
/* Create a server listening on port 4840 (default) */
UA_Server * server = UA_Server_new ();
/* Add a variable node to the server */
/* 1) Define the variable 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_NS0ID ( OBJECTSFOLDER );
UA_NodeId parentReferenceNodeId = 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 (until ctrl-c interrupt) */
UA_StatusCode status = UA_Server_runUntilInterrupt ( server );
/* Clean up */
UA_Server_delete ( server );
return status == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE ;
}
#include <stdio.h>
#include <open62541/client.h>
#include <open62541/client_highlevel.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: %in" , * ( UA_Int32 * ) value . data );
}
/* Clean up */
UA_Variant_clear ( & value );
UA_Client_delete ( client ); /* Disconnects the client internally */
return status == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE ;
}