跳到主要内容

EventFilter — 自定义事件字段与过滤

概述

OPC UA Part 4 §7.18 EventFilter 由两部分组成:

  • SelectClauses — 抓哪些字段 (按顺序对应到 EventFieldList)
  • WhereClause — 过滤条件 (ContentFilter 表达式树, V1 暂未实现)

每个 SelectClause 是一个 SimpleAttributeOperand (Part 4 §7.4.4.5):

字段说明
TypeDefinitionId事件类型 NodeId (如 i=2041 BaseEventType)
BrowsePath字段路径 (如 ["Severity"] / ["EnabledState", "Id"])
AttributeId属性 Id, 默认 Value
IndexRange数组下标范围 (一般 null)

不传 EventFilter 时, SDK 默认订阅 5 个字段: EventId / EventType / SourceName / Time / Message

API

类 / 字段类别读写说明
EventFilter过滤器容器
.SelectClauses属性读写SimpleAttributeOperand[]
.WhereClause属性读写string (V1 占位)
SimpleAttributeOperand单个字段定义
eventSub.Subscribe(nodeId, filter)方法带 filter 的事件订阅重载

代码示例

using DarraOpcUa_Client;

using var ua = new DarraOpcUa("opc.tcp://localhost:4840");
ua.Connect();

using var sub = ua.CreateSubscription(500);

// 1) 自定义抓 8 字段 (默认 5 + 报警特有 3)
var filter = new EventFilter
{
SelectClauses = new[]
{
// 默认 5 字段
new SimpleAttributeOperand { TypeDefinitionId = "i=2041", BrowsePath = new[] { "EventId" } },
new SimpleAttributeOperand { TypeDefinitionId = "i=2041", BrowsePath = new[] { "EventType" } },
new SimpleAttributeOperand { TypeDefinitionId = "i=2041", BrowsePath = new[] { "SourceName" } },
new SimpleAttributeOperand { TypeDefinitionId = "i=2041", BrowsePath = new[] { "Time" } },
new SimpleAttributeOperand { TypeDefinitionId = "i=2041", BrowsePath = new[] { "Message" } },
// 报警特有
new SimpleAttributeOperand { TypeDefinitionId = "i=2041", BrowsePath = new[] { "Severity" } },
new SimpleAttributeOperand { TypeDefinitionId = "i=2782", BrowsePath = new[] { "ConditionId" } },
new SimpleAttributeOperand { TypeDefinitionId = "i=2915", BrowsePath = new[] { "ActiveState", "Id" } },
}
};

using var ev = sub.SubscribeEvents("i=2253", filter);

ev.EventArrived += (s, e) =>
{
// EventFieldList 顺序与 SelectClauses 一致
var eid = e.Fields[0].AsByteString;
var etype = e.Fields[1].AsString;
var src = e.Fields[2].AsString;
var time = e.Fields[3].AsDateTime;
var msg = e.Fields[4].AsString;
var sev = e.Fields[5].AsUInt16;
var condId = e.Fields[6].AsString;
var active = e.Fields[7].AsBoolean;

Console.WriteLine($"[{time:HH:mm:ss}] sev={sev} {src}: {msg} active={active}");
};

实现说明

  • Stack 不支持自定义 SelectClauses 时, SDK graceful 降级:
    • 回退默认 5 字段
    • 推一条 Diagnostic 类别 Info 事件
  • WhereClause 当前只是占位字符串, V2 接通后会支持完整 ContentFilter (ElementOperand 树)

字段速查 (常用 EventType + BrowsePath)

EventTypeBrowsePath含义
BaseEventType (i=2041)["EventId"]事件唯一 ID (ByteString)
BaseEventType["EventType"]事件类型 NodeId
BaseEventType["SourceName"]触发源名
BaseEventType["Time"]事件时间 (UTC)
BaseEventType["Message"]文本消息
BaseEventType["Severity"]严重度 1-1000
ConditionType (i=2782)["ConditionId"]条件 NodeId
ConditionType["ConditionName"]条件名
ConditionType["EnabledState", "Id"]Bool 是否启用
AcknowledgeableConditionType (i=2881)["AckedState", "Id"]Bool 是否已 Ack
AlarmConditionType (i=2915)["ActiveState", "Id"]Bool 是否激活
AlarmConditionType["ShelvingState", "CurrentState"]LocalizedText 屏蔽态

最佳实践

  • 明确列字段 — 不要靠"默认 5 字段", 显式声明易调试
  • 顺序与读出顺序对齐e.Fields[i] 顺序就是 SelectClauses 顺序
  • 报警面板必抓 ConditionId — 后续 Acknowledge / Confirm 都需要它
  • ActiveState 用嵌套 BrowsePath["ActiveState", "Id"] 拿 Bool, ["ActiveState"] 拿 LocalizedText

跨语言对照

C#PythonJavaC++RustC
EventFilterEventFilterEventFilterEventFilterEventFilterDarraUa_EventFilter
SimpleAttributeOperandSimpleAttributeOperandSimpleAttributeOperandSimpleAttributeOperandSimpleAttributeOperandDarraUa_SimpleAttributeOperand

下一步