跳到主要内容

MethodBuilder

概述

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

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

API

方法类别读写说明
MethodBuilder::new(ua, object_id, method_id)构造绑定到方法
.load_input_args()链式读 InputArguments 描述
.arg(name_or_index, value)链式设值 (impl 多类型)
.invoke()终端返回 Result<(StatusCode, Vec<Variant>)>
.input_args()方法LoadInputArgs 后清单

支持 Rust 类型: bool / i8/16/32/64 / u8/16/32/64 / f32 / f64 / String / DateTime<Utc> / Vec<u8>

代码示例

use opcua::{DarraOpcUa, MethodBuilder, StatusCode};

let ua = DarraOpcUa::new("opc.tcp://localhost:4840")?;
ua.connect()?;

// 1) 流式调用 - 按名
let (st, _outs) = MethodBuilder::new(&ua, "ns=2;s=Robot", "ns=2;s=Robot.MoveTo")
.load_input_args()?
.arg("x", 100.0_f64)
.arg("y", 200.0_f64)
.arg("speed", 50_i32)
.invoke()?;

if st != StatusCode::Good { eprintln!("MoveTo 失败: {:?}", st); }

// 2) 按索引
let (st2, outs2) = MethodBuilder::new(&ua, "ns=2;s=Calc", "ns=2;s=Calc.Add")
.arg(0, 3.14_f64).arg(1, 2.71_f64)
.invoke()?;
println!("Add → {}", outs2[0].as_double()?);

// 3) 复用 builder
let mut b = MethodBuilder::new(&ua, "ns=2;s=Pump", "ns=2;s=Pump.SetSpeed")
.load_input_args()?;
for rpm in [100, 500, 1000, 1500] {
let (s, _) = b.arg("rpm", rpm).invoke()?;
if s != StatusCode::Good { break; }
std::thread::sleep(std::time::Duration::from_millis(500));
}

与 call 的对比

// 旧写法
let inputs = vec![
Variant::from(100.0_f64),
Variant::from(200.0_f64),
Variant::from(50_i32), // 类型?
];
let outs = ua.call("ns=2;s=Robot", "ns=2;s=Robot.MoveTo", &inputs)?;

// 新写法
let (st, outs) = MethodBuilder::new(&ua, "ns=2;s=Robot", "ns=2;s=Robot.MoveTo")
.load_input_args()?
.arg("x", 100.0_f64).arg("y", 200.0_f64).arg("speed", 50_i32)
.invoke()?;

实现限制

  • load_input_args 依赖 ExtensionObject 解码
  • 不支持复杂结构入参
  • invoke 走 call 内部, Err 返回; 想 Safe 转 safe_invoke()

跨语言对照

C#PythonJavaC++RustC
MethodBuilderMethodBuilderMethodBuilderMethodBuilderMethodBuilderDarraUa_MethodBuilder_*

下一步