open62541/open62541
GitHub: open62541/open62541
OPC UA 协议的开源 C 语言实现,提供跨平台的客户端/服务器开发框架,用于构建工业自动化通信应用。
Stars: 3044 | Forks: 1396
open62541 (
) 是用 C 语言编写的 OPC UA (OPC Unified Architecture / IEC 62541) 开源实现。该库兼容所有主流编译器,并提供了必要的工具来实现专用的 OPC UA 客户端和服务器,或将基于 OPC UA 的通信集成到现有应用程序中。有关完整详细信息,请参阅 [功能概述](FEATURES.md)。
open62541 库是平台无关的:所有平台特定的功能都通过可交换的插件实现,以便轻松移植到不同的(嵌入式)目标平台。
open62541 采用 Mozilla Public License v2.0 (MPLv2) 授权。这允许将 open62541 库与任何专有软件组合并分发。只有在复制和分发时对 open62541 库本身的更改才需要根据 MPLv2 授权。部分插件和示例属于公共领域(CC0 许可),部分采用 MPLv2 授权。采用 CC0 许可的部分可以在任何许可下重用,且更改无需公开。
该库提供标准的源码和二进制形式。此外,单文件源码分发版将整个库合并为一个 .c 和一个 .h 文件,可轻松添加到现有项目中。示例服务器和客户端实现可在 [/examples](examples/) 目录或本页下方找到。
[](https://www.openhub.net/p/open62541/)
[](https://ci.appveyor.com/project/open62541/open62541/branch/master)
[](https://github.com/open62541/open62541/actions/workflows/codeql.yml)
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:open62541)
[](https://codecov.io/gh/open62541/open62541)
## 文档与支持
关于 OPC UA 的一般性介绍以及 open62541 文档可在 http://open62541.org 找到。
该库的历史版本可在 https://github.com/open62541/open62541/releases 下载。
open62541 社区整体在 Github 和邮件列表上处理公开的支持请求。
如需个人讨论和支持,请使用以下渠道:
- [邮件列表](https://groups.google.com/d/forum/open62541)
- [问题追踪器](https://github.com/open62541/open62541/issues)
- [Pull Requests](https://github.com/open62541/open62541/pulls)
[o6 Automation GmbH](https://www.o6-automation.com/) 雇佣了 open62541 的核心贡献者,并提供 **[商业支持](https://www.o6-automation.com/services)**。
然而,该项目接受外部贡献,并且 **贡献者保留其个人版权**。这防止了未来在不同许可条件下重新授权。
我们希望培养一个开放和友好的社区。请遵守我们的 [行为准则](CODE_OF_CONDUCT.md)。
## 商业用途
open62541 采用 MPLv2 授权。也就是说,对 MPLv2 下文件的更改需遵循相同的开源许可。
但是,该库可以与来自独立文件的私有开发代码组合,即使是生成静态二进制文件,许可也不会影响私有文件。
详情请参阅完整的 [许可文档](LICENSE)。
## 官方认证
使用 open62541 v1.4 构建的示例服务器已通过 OPC Foundation 的“Standard Server 2017 Profile”认证。
更多详情请参阅 https://open62541.org/certification。
## 构建系统、代码结构和依赖项
open62541 的构建环境通过 CMake 生成。详情请参阅 [构建文档](https://www.open62541.org/doc/master/building.html)。
为了简化与现有软件项目的集成,open62541 源码可以压缩(合并)为单文件分发版,即一对 `open62541.c/.h` 文件。
单文件分发版中包含的功能取决于当前的 CMake 配置。
源代码结构如下:
- 公共 API (`/include`):公共 API 暴露给使用 open62541 的应用程序。插件实现的头文件位于 `/plugins/include`。
- 核心库 (`/src`):除了 C99 标准头文件外,核心库没有其他依赖项。
- 架构支持 (`/arch`):架构支持通过 `EventLoop` 插件实现。这将特定于架构的代码(例如使用 POSIX API 的代码)排除在核心库之外。提供了针对不同(嵌入式)架构的移植。
- 默认插件实现 (`/plugins`):插件接口允许与不同的后端系统和库集成。例如,涉及加密原语、信息模型的存储等。提供了默认实现。
- 依赖项 (`/deps`):一些额外的库通过 git submodules 使用,或者已经被内化到 `deps/` 文件夹中。有关第三方库及其各自许可的更多信息,请参见 [deps/README.md](deps/README.md)
- 构建和代码生成:部分代码是从 OPC UA 标准中的 XML 定义自动生成的。代码生成脚本在构建过程中使用 Python。
在大多数系统上,基本的 open62541 仅需要 C 标准库。
根据构建配置,open62541 可能依赖于额外的库,例如用于加密的 mbedTLS 或 OpenSSL。
## 开发
作为一个开源项目,我们鼓励新贡献者帮助改进 open62541。
文件 [CONTRIBUTING.md](CONTRIBUTING.md) 汇总了我们期望的代码贡献最佳实践。
以下是新贡献者的良好起点:
- [报告 Bug](https://github.com/open62541/open62541/issues)
- 改进 [文档](http://open62541.org/doc/current)
- 处理标记为“[good first issue](https://github.com/open62541/open62541/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)”的问题
对于最终旨在成为 open62541 库一部分的定制开发,请让一位核心维护者知情。
### 代码质量
我们强调代码质量。以下质量指标会持续检查,并确保在发布正式版本前得到满足:
- OPC Foundation 的 Compliance Testing Tool (CTT) 对支持的功能指示零错误
- GCC/Clang/MSVC 在非常严格的编译标志下零编译器警告
- 单元测试指示零问题(我们的目标是超过 80% 的代码覆盖率)
- clang-analyzer、clang-tidy、cpp-check 和 Codacy 静态代码分析工具指示零问题
- 在 Google 的 oss-fuzz 基础设施中对库进行 Fuzzing 测试零未解决问题
- Valgrind (Linux)、DrMemory (Windows) 和 Clang AddressSanitizer / MemorySanitizer 对 CTT 测试、单元测试和 Fuzzing 测试指示零问题
### 安全与漏洞处理
该项目已建立漏洞处理流程。
详情及如何负责任地向维护者披露发现,请参阅 [SECURITY.md](SECURITY.md)。
## 安装与示例
在 Debian/Ubuntu 系统上,只需执行 `apt install libopen62541-1.4-dev` 即可安装该库和开发头文件。
使用 GCC 编译器时,只需运行 `gcc -std=c99 -lopen62541 -o server`。
有关如何安装 open62541 SDK 的更详细说明,请参阅我们的 [文档](https://www.open62541.org/doc/master/building.html#building-the-library)。
基本上,克隆仓库并使用 `git submodule update --init --recursive` 初始化所有子模块。然后使用 CMake 配置您的构建。
完整的示例列表可以在 [examples 目录](https://github.com/open62541/open62541/tree/master/examples) 中找到。
### 示例服务器实现
```
#include
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
#include
#include
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 == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}
```
标签:Bash脚本, IEC 62541, impacket, MPLv2许可证, OPC UA, OPC统一架构, PKINIT, PLC通信, SCADA, 中间件, 协议栈, 哈希传递, 安全测试工具, 客户端加密, 客户端/服务器, 嵌入式系统, 工业4.0, 工业互联网, 工业自动化, 工控安全, 开源库, 搜索引擎爬虫, 智能制造, 物联网, 逆向工具