Events — ua.events.*
OpcUaSession.events 是 SDK 内部事件统一通道, 把会话生命周期 / 订阅生命周期 / 数据变化 / 通讯异常都汇集到一个对象上, 方便上层 UI 做日志 / 状态栏 / 调试.
Java 没有原生 event 关键字, 用 List<Consumer<...>> (CopyOnWriteArrayList) 替代 — 用户直接 add(consumer) / remove(consumer).
ua.events.*— SDK 内部事件 (本节, 与协议无关)ua.subscribeEvents(...)— OPC UA 协议事件 (Alarms & Conditions), 见 事件订阅
完整事件清单
会话生命周期
| 字段 | EventArgs 类型 | 触发时机 |
|---|---|---|
events.onConnected | ConnectionEventArgs | 首次连接成功 |
events.onDisconnected | ConnectionEventArgs | 主动 / 被动断开 |
events.onReconnecting | ConnectionEventArgs | 检测到断线, 启动自动重连 |
events.onReconnected | ConnectionEventArgs | 自动重连成功 |
events.onKeepAlive | KeepAliveEventArgs | KeepAlive 心跳成功 |
events.onStateChanged | SessionStateChangedEventArgs | 任何 SessionState 变化 |
异常
| 字段 | EventArgs 类型 | 触发时机 |
|---|---|---|
events.onCommunicationError | CommunicationErrorEventArgs | 通讯失败 (KeepAlive 失败 / Read 异常等) |
events.onSubscriptionLost | SubscriptionLostEventArgs | 订阅被服务端清理 |
统一通道
| 字段 | EventArgs 类型 | 触发时机 |
|---|---|---|
events.onAny | OpcUaEventEntry | 所有事件汇集 (Connected / Disconnected / DataChange / Read / Write / Browse / Call / HistoryRead / Alarm / ...) |
OpcUaEventEntry 字段: category (Enums.OpcUaEventCategory) + severity (Enums.OpcUaEventSeverity) + source + message + statusCode + timestampUtc + original.
OpcUaEventCategory 枚举
OpcUaEventEntry.category 字段, 完整清单:
Unknown,
Connected, Disconnected, Reconnecting, Reconnected, KeepAlive, StateChanged,
SubscriptionCreated, SubscriptionLost, SubscriptionRestored,
MonitoredItemAdded, MonitoredItemRemoved, SubscriptionCleared,
DataChange, ServerEvent, Alarm,
Read, Write, Browse, Call, HistoryRead,
CommunicationError, SecurityError, ProtocolError,
Info, Diagnostic
OpcUaEventSeverity 枚举
Trace, Debug, Info, Warn, Error, Fatal
用法示例
通用日志钩子 (一行打印 SDK 内所有事件)
ua.events.onAny.add(e ->
System.out.printf("[%s] [%s] %s: %s (%s)%n",
e.severity, e.category, e.source, e.message, e.statusCode));
调试期非常省事 — 不订阅具体事件, 一行 hook 看全部.
状态栏绑定 (Swing)
import javax.swing.SwingUtilities;
ua.events.onStateChanged.add(e -> {
SwingUtilities.invokeLater(() -> {
statusLabel.setText(e.newState.toString());
statusLabel.setForeground(e.newState == Enums.SessionState.Connected
? Color.GREEN : Color.RED);
});
});
错误统计
java.util.concurrent.atomic.AtomicInteger errorCount = new java.util.concurrent.atomic.AtomicInteger();
ua.events.onCommunicationError.add(e -> errorCount.incrementAndGet());
与订阅 onDataChanged 的关系
订阅 sub.onDataChanged 仅收到该订阅的事件; ua.events.onAny (Category=DataChange) 收到 SDK 下所有订阅的事件 (统一通道). 两者并存, 上层按场景选用:
- 单订阅业务逻辑 →
sub.onDataChanged.add(...) - 全局日志 / 录波 / 调试 →
ua.events.onAny.add(...)
线程模型
事件回调在 C 层 Publish 线程上调用, 不在调用方线程. UI 操作必须 SwingUtilities.invokeLater (Swing) / Platform.runLater (JavaFX) 切回 UI 线程, 否则跨线程 UI 操作会崩.
不要在事件里执行长操作 (>100 ms), 否则会阻塞 Publish 队列.
回调里抛异常会被 SDK 吞掉 (try-catch ignored), 不会传播到 native, 不会让 Stack 闪退.