跳到主要内容

事件订阅

OPC UA 事件 (Alarms & Conditions) 通过 subscribeEvents 订阅. 这是 OPC UA 协议事件, 与 SDK 内部 ua.events.* 不是一回事.

区别
  • ua.subscribeEvents(...)OPC UA 协议事件 (报警 / 条件, 服务端推送, 本节)
  • ua.events.*SDK 内部事件 (会话 / 订阅生命周期, 与协议无关)

签名

public OpcUaEventSubscription subscribeEvents();
public OpcUaEventSubscription subscribeEvents(String nodeId);
public OpcUaEventSubscription subscribeEvents(String nodeId,
OpcUaSubscription existingSubscription);
参数默认说明
nodeIdnull (Server, i=2253)事件源节点
existingSubscriptionnull复用已存在的 Subscription, null 则内部新建 (1000ms 间隔)

OpcUaEventSubscription

成员说明
onEventArrivedList<Consumer<EventArrivedEventArgs>> 事件到达回调
close()移除该 Event MI; 如果是内部新建容器还会销毁容器

实现 AutoCloseable, 必须在 try-with-resources 内使用.

EventArrivedEventArgs

字段类型说明
severityint严重度 1-1000
messageString事件文本
sourceNameString事件源名
timeFtlong事件发生时间 (FileTime, 0 = null)
eventTypeString事件类型 NodeId
arrivedAtUtcInstantJava 端记录的到达时间

用法

默认订阅 Server 节点

try (OpcUaEventSubscription evSub = ua.subscribeEvents()) {
evSub.onEventArrived.add(e -> {
System.out.printf("[%d] %s: %s%n", e.severity, e.sourceName, e.message);
long ft = e.timeFt;
Instant t = (ft > 0)
? Instant.ofEpochMilli((ft - 116444736000000000L) / 10000L)
: Instant.now();
System.out.println(" EventType=" + e.eventType + " Time=" + t);
});

Thread.sleep(java.time.Duration.ofMinutes(5).toMillis());
}

订阅指定节点的事件

try (OpcUaEventSubscription evSub = ua.subscribeEvents("ns=2;s=Line1")) {
// Line1 必须是 EventNotifier
evSub.onEventArrived.add(e -> /* ... */);
Thread.sleep(60_000);
}

复用已有 Subscription 容器

try (OpcUaSubscription sub = ua.createSubscription(500.0)) {
sub.add("ns=2;s=Counter", null); // 数据订阅

// 把 Event MI 挂到同一个容器
try (OpcUaEventSubscription evSub = ua.subscribeEvents("ns=2;s=Line1", sub)) {
// evSub.close 只移除 Event MI, 不销毁 sub
evSub.onEventArrived.add(e -> /* ... */);
Thread.sleep(60_000);
}
}

EventNotifier

只有 EventNotifier Attribute (12) 非 0 的节点才能产生事件. 默认 Server (i=2253) 是 EventNotifier. 自定义节点是否有事件源能力, 看服务端实现.

EventFilter (高级)

OPC UA EventFilter 可以过滤 EventType / Severity / SourceNode, 当前 SDK 默认订阅 BaseEventType 并选 4 个标准字段 (Severity / Message / SourceName / Time), 复杂过滤待后续版本暴露.


报警操作 (Acknowledge / Confirm)

收到 AlarmConditionType 事件后, 操作员通常要 Acknowledge (确认). 通过 call 调用报警节点的 Acknowledge Method:

try (OpcUaVariant evtId = new OpcUaVariant().setString("event-id-bytes-as-string");
OpcUaVariant cmnt = new OpcUaVariant().setString("Operator confirmed")) {
ua.call(conditionId, conditionId + ".Acknowledge", evtId, cmnt);
}
JNA Callback 保活

事件订阅内部为每个 EventSubscription 创建一个 JNA trampoline callback, 由 OpcUaEventSubscription.keepAlive 持有强引用防 GC. 用户不要手动销毁 callback, 只要不释放 OpcUaEventSubscription 就安全.

下一步