事件订阅
OPC UA 事件 (Alarms & Conditions) 通过 subscribe_events 订阅. 这是 OPC UA 协议事件, 与 SDK 内部 ua.events.* 不是一回事.
区别
ua.subscribe_events(...)— OPC UA 协议事件 (报警 / 条件, 服务端推送, 本节)ua.events.*— SDK 内部事件 (会话 / 订阅生命周期, 与协议无关)
签名
def subscribe_events(self,
node_id: Optional[str] = None,
existing_subscription: Optional[Subscription] = None
) -> EventSubscription: ...
| 参数 | 默认 | 说明 |
|---|---|---|
node_id | None (Server, i=2253) | 事件源节点 |
existing_subscription | None | 复用已存在的 Subscription, None 则内部新建 |
EventSubscription
| 成员 | 说明 |
|---|---|
event_arrived | List[Callable[[EventArrivedEventArgs], None]] 事件到达回调列表 |
dispose() / close() | 移除该 Event MI; 如果是内部新建容器还会销毁容器 |
支持 with context manager.
EventArrivedEventArgs
@dataclass
class EventArrivedEventArgs:
severity: int = 0
message: Optional[str] = None
source_name: Optional[str] = None
time: Optional[datetime] = None
event_type: Optional[str] = None
| 字段 | 类型 | 说明 |
|---|---|---|
severity | int | 严重度 1-1000 |
message | Optional[str] | 事件文本 |
source_name | Optional[str] | 事件源名 |
time | Optional[datetime] | 事件发生时间 (UTC) |
event_type | Optional[str] | 事件类型 NodeId |
用法
默认订阅 Server 节点
import time
with ua.subscribe_events() as ev:
def on_event(e):
print(f"[{e.severity}] {e.source_name}: {e.message}")
print(f" EventType={e.event_type} Time={e.time}")
ev.event_arrived.append(on_event)
time.sleep(300) # 5 分钟
订阅指定节点的事件
with ua.subscribe_events("ns=2;s=Line1") as ev: # Line1 必须是 EventNotifier
ev.event_arrived.append(lambda e: print(e.message))
time.sleep(60)
复用已有 Subscription 容器
with ua.create_subscription(500) as sub:
sub.add_node("ns=2;s=Counter") # 数据订阅
# 把 Event MI 挂到同一个容器
with ua.subscribe_events("ns=2;s=Line1", existing_subscription=sub) as ev:
ev.event_arrived.append(lambda e: print(e.message))
time.sleep(60)
# ev.dispose 只移除 Event MI, 不销毁 sub
EventNotifier
只有 EventNotifier Attribute (12) 非 0 的节点才能产生事件. 默认 Server (i=2253) 是 EventNotifier. 自定义节点是否有事件源能力, 看服务端实现.
EventFilter (高级)
OPC UA EventFilter 可以过滤 EventType / Severity / SourceNode, 当前 SDK 默认订阅 BaseEventType (全部事件), 复杂过滤待后续版本暴露.
报警操作 (Acknowledge / Confirm)
收到 AlarmConditionType 事件后, 操作员通常要 Acknowledge (确认). 通过 call 调用报警节点的 Acknowledge Method:
from darra_opcua import OpcUaVariant
ua.call(
object_node_id=condition_id,
method_node_id=f"{condition_id}.Acknowledge",
inputs=[
OpcUaVariant().set_string(event_id), # bytes(EventId) 视服务端实现
OpcUaVariant().set_string("Operator confirmed"), # LocalizedText 简化为 string
])