跳到主要内容

MethodBuilder

概述

OPC UA Call 服务要求把入参打包成 std::vector<Variant>, 顺序与服务端 InputArguments 对应。MethodBuilder 提供链式 API。

对应规范段: Part 4 §5.11.2 / Part 5 §6.4。

API

方法类别读写说明
MethodBuilder(ua, object_id, method_id)构造绑定到方法
.LoadInputArgs()链式读 InputArguments 描述
.Arg(std::string name, T value)链式按名设值 (模板)
.Arg(int index, T value)链式按索引设值
.Invoke()终端返回 CallResult { status, outputs }
.InputArgs()属性LoadInputArgs 后清单

支持 C++ 类型: bool / int8/16/32/64_t / uint8/16/32/64_t / float / double / std::string / system_clock::time_point / std::vector<uint8_t>

代码示例

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

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

// 1) 流式调用 - 按名
auto r = MethodBuilder(ua, "ns=2;s=Robot", "ns=2;s=Robot.MoveTo")
.LoadInputArgs()
.Arg("x", 100.0)
.Arg("y", 200.0)
.Arg("speed", 50)
.Invoke();

if (r.status != StatusCode::Good)
std::cerr << "MoveTo 失败: " << r.status << "\n";

// 2) 按索引
auto r2 = MethodBuilder(ua, "ns=2;s=Calc", "ns=2;s=Calc.Add")
.Arg(0, 3.14).Arg(1, 2.71).Invoke();
std::cout << "Add → " << r2.outputs[0].AsDouble() << "\n";

// 3) 复用 builder
auto b = MethodBuilder(ua, "ns=2;s=Pump", "ns=2;s=Pump.SetSpeed").LoadInputArgs();
for (int rpm : {100, 500, 1000, 1500}) {
auto r3 = b.Arg("rpm", rpm).Invoke();
if (r3.status != StatusCode::Good) break;
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}

与 Call 的对比

// 旧写法
std::vector<Variant> inputs = {
Variant(100.0), Variant(200.0), Variant(50) // 类型?
};
auto outs = ua.Call("ns=2;s=Robot", "ns=2;s=Robot.MoveTo", inputs);

// 新写法
auto r = MethodBuilder(ua, "ns=2;s=Robot", "ns=2;s=Robot.MoveTo")
.LoadInputArgs()
.Arg("x", 100.0).Arg("y", 200.0).Arg("speed", 50)
.Invoke();

实现限制

  • LoadInputArgs 依赖 ExtensionObject 解码
  • 不支持复杂结构入参
  • Invoke 走 Call, 失败抛 OpcUaException; Safe 自己包 try/catch

跨语言对照

C#PythonJavaC++RustC
MethodBuilderMethodBuilderMethodBuilderMethodBuilderMethodBuilderDarraUa_MethodBuilder_*

下一步