跳到主要内容

Safe API — 永不抛异常变体

概述

UI 主线程 / 批处理不希望被一条 RPC 失败抛出的 OpcUaException 中断, SDK 为常用调用各提供一个 Safe 版本 — 任何异常折叠为 StatusCode, 调用方用 std::pair / 结构体判读。

对应规范段: Browse Part 4 §5.8, Read §5.10.2, Write §5.10.4, Call §5.11.2, HistoryRead Part 11 §6.5。

API

方法类别读写说明
ua.BrowseSafe(nodeId, filter)浏览返回 BrowseResult { status, references }
ua.ReadSafe(nodeId, attribute)返回 ReadResult { status, value }
ua.WriteSafe(nodeId, value, attribute)返回 StatusCode
ua.CallSafe(objectId, methodId, inputs)方法返回 CallResult { status, outputs }
ua.ReadHistorySafe(nodeId, t0, t1, max)历史返回 HistoryResult { status, values }

代码示例

#include <darra/opcua.h>
using namespace darra::opcua;

DarraOpcUa ua("opc.tcp://localhost:4840");
ua.Connect();

// 1) 浏览 - 节点删除不让全树报错
auto br = ua.BrowseSafe("ns=2;s=Boiler1");
if (br.status != StatusCode::Good) {
std::cout << "Browse 失败 " << br.status << "\n";
} else {
for (auto& r : br.references) std::cout << r.browse_name << "\n";
}

// 2) 批量轮询 - 单点失败不打断
for (auto& nid : node_list) {
auto rr = ua.ReadSafe(nid);
if (rr.status == StatusCode::Good && rr.value) {
std::cout << nid << " = " << rr.value->value << "\n";
} else {
std::cout << nid << " = <" << rr.status << ">\n";
}
}

// 3) 批量下发参数
for (auto& [nid, val] : setpoints) {
auto rc = ua.WriteSafe(nid, Variant(val));
if (rc != StatusCode::Good) std::cout << "写 " << nid << " 失败 " << rc << "\n";
}

// 4) 调用方法
auto cr = ua.CallSafe("ns=2;s=Robot", "ns=2;s=Robot.Home", {});
if (cr.status != StatusCode::Good) std::cerr << "Home 失败: " << cr.status << "\n";

// 5) 历史
auto hr = ua.ReadHistorySafe("ns=2;s=Temp", t0, t1, 5000);

与重试机制的关系

普通 Read/Write/Browse/Call/ReadHistory 内部都包了 RetryOnSessionFault, session 级故障会自动重连一次。Safe 变体也受益于自动重连, 把"重连后仍失败"的异常折叠为 StatusCode。

最佳实践

  • UI 主线程一律用 Safe — C++ 异常逃逸到 Qt event loop 会让进程挂掉
  • 批处理 / 巡检循环用 Safe
  • 业务关键路径仍用普通版本

跨语言对照

C#PythonJavaC++RustC
BrowseSafebrowse_safebrowseSafeBrowseSafebrowse_safeDarraUa_Session_BrowseSafe
ReadSaferead_safereadSafeReadSaferead_safeDarraUa_Session_ReadSafe
WriteSafewrite_safewriteSafeWriteSafewrite_safeDarraUa_Session_WriteSafe
CallSafecall_safecallSafeCallSafecall_safeDarraUa_Session_CallSafe
ReadHistorySaferead_history_safereadHistorySafeReadHistorySaferead_history_safeDarraUa_Session_ReadHistorySafe

下一步