跳到主要内容

Call

前置 / 配套
  • 数据类型 OpcUaVariant 是入参 / 出参的容器.
  • 找方法 NodeId 用 Browsefilter=NodeClass.Method.

签名

public List<OpcUaVariant> call(
String objectNodeId,
String methodNodeId,
OpcUaVariant... inputs);
参数说明
objectNodeId方法所在 Object 节点
methodNodeId方法本身 NodeId
inputs入参 OpcUaVariant 数组 (可空)

返回 List<OpcUaVariant> 输出参数列表.


内存所有权 (重要)

返回列表里每个 OpcUaVariant 都持有 native handle, 必须 close, 否则泄漏 native Variant 内存.

入参 OpcUaVariant 也是用户构造, 也要 close. 推荐 try-with-resources 把入参与 close 包一起:

try (OpcUaVariant a = new OpcUaVariant().setInt32(3);
OpcUaVariant b = new OpcUaVariant().setInt32(4)) {
List<OpcUaVariant> outputs = ua.call(objId, mtdId, a, b);
try {
for (OpcUaVariant v : outputs) {
// 用 v.asXxx() ...
}
} finally {
for (OpcUaVariant v : outputs) v.close();
}
}

例子

// 调 Calculator.Add(3, 4)
try (OpcUaVariant a = new OpcUaVariant().setInt32(3);
OpcUaVariant b = new OpcUaVariant().setInt32(4)) {
List<OpcUaVariant> outputs = ua.call(
"ns=2;s=Calculator",
"ns=2;s=Calculator.Add",
a, b);
try {
for (OpcUaVariant v : outputs) {
System.out.println("sum = " + v.asInt32());
}
} finally {
for (OpcUaVariant v : outputs) v.close();
}
}

异常

异常含义
OpcUaException(BadNodeIdInvalid)NodeId 解析失败
OpcUaException(BadCommunicationError)Transport 错
OpcUaException 业务码服务端返回的方法 status (statusCode 字段是业务码)

业务级失败 (方法返回非 Good) 也抛异常 OpcUaException, ex.statusCode 即业务码.


找方法的 NodeId

// 1. Browse Object 子节点过滤 Method
List<Reference> methods = ua.browse("ns=2;s=Calculator", Enums.NodeClass.Method);
for (Reference m : methods) {
System.out.println(" " + m.getBrowseName() + " -> " + m.getNodeId());
}

// 2. 看入参 / 出参签名 (Browse 该方法节点的 Property)
List<Reference> props = ua.browse(methods.get(0).getNodeId());
// 找 BrowseName == "InputArguments" / "OutputArguments" 的 Property, read 它即可看到 Argument[] 描述

输入参数构造

按方法签名构造 OpcUaVariant:

// Add(Int32, Int32) -> Int32
new OpcUaVariant().setInt32(3), new OpcUaVariant().setInt32(4)

// SetTemperature(string deviceId, double value)
new OpcUaVariant().setString("Boiler1"), new OpcUaVariant().setDouble(85.5)

// 复杂结构 (ExtensionObject) — 高级用法, 后续版本完善

异步 (后续版本)

当前 call 是同步阻塞 (内部走 RPC + 等响应). 异步版本 (callAsync) 在后续版本提供.

如果想异步, 用 CompletableFuture.supplyAsync:

import java.util.concurrent.CompletableFuture;

CompletableFuture<List<OpcUaVariant>> f = CompletableFuture.supplyAsync(() -> {
try (OpcUaVariant a = new OpcUaVariant().setInt32(3);
OpcUaVariant b = new OpcUaVariant().setInt32(4)) {
return ua.call(objId, mtdId, a, b);
}
});

List<OpcUaVariant> outputs = f.join();
try { /* 用 outputs */ }
finally { for (OpcUaVariant v : outputs) v.close(); }

下一步