Darra OPC UA Client — C++ SDK
Darra OPC UA Client C++ 绑定. header-only, C++17, RAII, 命名空间 darra::opcua. API 命名 / 行为与 C# 完全对齐, 学一种全语言可用.
章节导航
- 入门 → Session 会话 (构造 / Connect / Read / Write / KeepAlive)
- 浏览 → Nodes 节点 (Browse / 路径解析 / RegisterNodes)
- 实时 → Subscription 订阅 (CreateSubscription / MonitoredItem / on_data_change)
- 历史 → History 历史 (Raw / Modified / AtTime / Processed / Events / Update / Delete)
- 调用 → Method 方法 (Call)
- 发现 → Discovery 发现 (GetEndpoints / FindServers)
- 数据 → Data Types (Variant / DataValue / WellKnownNodes)
- 安全 → Security (证书 / 加密)
安装
C++ SDK 是 header-only, 不需要单独编译 .cpp. 把 Darra_OPCUA_ClassLibrary/CPP/include/ 加到工程 include 路径, 并 link 底层 C 实现 darra_opcua 即可.
- CMake (推荐)
- 手动 (Makefile / MSBuild)
- vcpkg (后续版本)
add_executable(my_app main.cpp)
target_include_directories(my_app PRIVATE
${CMAKE_SOURCE_DIR}/third_party/Darra_OPCUA_ClassLibrary/CPP/include
${CMAKE_SOURCE_DIR}/third_party/Darra_OPCUA_ClassLibrary/C/include)
target_link_libraries(my_app PRIVATE darra_opcua)
target_compile_features(my_app PRIVATE cxx_std_17)
g++ -std=c++17 main.cpp \
-I third_party/Darra_OPCUA_ClassLibrary/CPP/include \
-I third_party/Darra_OPCUA_ClassLibrary/C/include \
-L third_party/Darra_OPCUA_ClassLibrary/C/lib \
-ldarra_opcua -o my_app
# 后续版本提供 vcpkg port, 当前请用 CMake 直接 include
vcpkg install darra-opcua
系统要求
| 项 | 要求 |
|---|---|
| 编译器 | C++17 (MSVC 2019+, GCC 8+, Clang 10+) |
| OS | Windows 10/11, Windows Server 2019+, Linux (Ubuntu 20.04+) |
| 平台 | x64 |
| 协议 | OPC UA TCP (opc.tcp://) |
命名空间
#include <darra/opcua/client.hpp> // Session / Variant / DataValue / Subscription
#include <darra/opcua/discovery.hpp> // Discovery::GetEndpoints / FindServers
#include <darra/opcua/history.hpp> // HistoryAggregate / HistoryUpdateType
#include <darra/opcua/well_known_nodes.hpp> // 标准节点常量
using namespace darra::opcua;
主要类型:
| C++ 类型 | C# 对应 | 用途 |
|---|---|---|
darra::opcua::Session | DarraOpcUa | Client 主类 (一个 Session) |
darra::opcua::Subscription | OpcUaSubscription | 数据订阅容器 |
darra::opcua::EventSubscription | OpcUaEventSubscription | 事件订阅 (Alarms & Conditions) |
darra::opcua::NodeCollection / Node | NodeCollection / OpcUaNode | Lazy Load 节点访问 |
darra::opcua::Variant / DataValue | 同名 | 数据封装 |
darra::opcua::Discovery (静态) | 同名 | GetEndpoints / FindServers |
darra::opcua::WellKnownNodes (静态) | 同名 | OPC Foundation 标准节点常量 |
darra::opcua::Exception | OpcUaException | 携带 StatusCode 的异常 |
一分钟快速开始
#include <darra/opcua/client.hpp>
#include <iostream>
using namespace darra::opcua;
int main() {
Stack::Init(); // 全局初始化
Session s("opc.tcp://localhost:4840"); // RAII, 栈对象
s.Connect();
// 读
auto dv = s.Read("ns=2;s=Temperature");
std::cout << "Temperature = " << dv.Value().AsString() << " degC\n";
// 写
Variant v; v.SetDouble(42.0);
s.Write("ns=2;s=Setpoint", v);
// 订阅
auto sub = s.CreateSubscription(500.0);
sub.AddNode("ns=2;s=Counter", [](DataValue const& dv) {
std::cout << "Counter = " << dv.Value().AsString() << "\n";
});
Stack::Shutdown();
return 0;
}
高级 API 概览
| 功能 | 入口 API | 说明 |
|---|---|---|
| 连接 / 加密 | Session(...) + s.Connect() | None / Sign / SignAndEncrypt + Username / Anonymous / Certificate |
| 单点读写 | s.Read / s.Write | 单节点单 Attribute |
| 批量读 | s.ReadMany(node_ids[, attr]) | 一次 RPC, N 节点 |
| 浏览树 | s.Browse / BrowseMany / BrowseWithPaging / BrowseNext | 完整分页支持 |
| 路径解析 | s.Resolve / TranslateBrowsePaths | 浏览路径 → NodeId |
| 注册节点 | s.RegisterNodes / UnregisterNodes | 高频访问加速 30-50% |
| 数据订阅 | s.CreateSubscription + sub.AddNode / AddMany | publishing / sampling 双层 |
| 事件订阅 | s.SubscribeEvents | 报警 & 条件 |
| 调方法 | s.Call(obj_id, mtd_id, inputs) | OPC UA Method 节点 |
| 历史读 | s.ReadHistory / ReadHistoryModified / AtTime / Processed / Events | 5 模式 |
| 历史写 | s.UpdateHistory / DeleteHistoryRange | Insert / Replace / Update / Delete |
| 心跳 | s.SetKeepAliveInterval(ms) | 后台周期探测 |
| 自动重连 | (内置, 由 ConnectionConfig.auto_reconnect 控制) | 检测断线 → Republish 订阅 |
| 统一事件 | s.Events().on_* | 会话 / 订阅 / 数据 / 通讯异常 |
| 服务发现 | Discovery::GetEndpoints / FindServers | 不需要 Session |
RAII 与异常
C++ SDK 全部资源都是 RAII, 栈对象自动管理生命周期, 不要 new, 析构自动释放. 错误统一抛 darra::opcua::Exception, 含 status_code() / status() 方法:
try {
Session s("opc.tcp://localhost:4840");
s.Connect();
auto dv = s.Read("ns=2;s=NotExist");
} catch (Exception const& ex) {
std::cerr << "OPC UA error: " << ex.what()
<< " status=0x" << std::hex << ex.status_code() << std::dec << "\n";
if (ex.status() == Status::BadNodeIdUnknown) { /* 处理 */ }
}
Move-only 语义
Session / Subscription / EventSubscription / Variant / DataValue 都不可拷贝, 但可 move (像 std::unique_ptr):
Session s1("opc.tcp://localhost:4840");
// Session s2 = s1; // 编译错误: copy ctor deleted
Session s2 = std::move(s1); // OK, s1 此后失效
防止重复释放 native handle.
FileTime 时间约定
历史 API 时间一律用 FileTime (UTC 100ns since 1601-01-01), 与 Windows DateTime.ToFileTimeUtc() 一致:
constexpr int64_t WIN_EPOCH_OFFSET = 116444736000000000LL; // 1601 → 1970 间隔
auto now_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
int64_t now_ft = WIN_EPOCH_OFFSET + now_ns / 100;
跨语言对齐
C# SDK 是参考实现, C++ 命名 / 参数 / 行为完全对齐. C# ua.Read(...) ↔ C++ s.Read(...) ↔ Python ua.read(...). 选 C++ 后切其他语言时只需查 跨语言映射.
按左侧侧边栏顺序读完即可掌握全部 SDK API.