跳到主要内容

事件订阅

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

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

签名

EventSubscription SubscribeEvents(
std::string const& node_id = "",
Subscription* existing = nullptr);
参数默认说明
node_id"" (Server, i=2253)事件源节点
existingnullptr复用已存在的 Subscription, nullptr 则内部新建一个 1000ms 容器

EventSubscription

EventSubscription 是 Move-only 栈对象, 析构时:

  • 如果是内部新建容器: 销毁容器 (Subscription_Delete)
  • 如果是借用外部容器: 仅移除该 Event MI
成员说明
SetOnEvent(cb)设置事件回调
on_event() = cb同 SetOnEvent 的语法糖

EventArrivedEventArgs

struct EventArrivedEventArgs {
uint16_t severity = 0; // 1-1000
std::string message;
std::string source_name;
int64_t time = 0; // FileTime (UTC 100ns since 1601)
std::string event_type; // 事件类型 NodeId
};

用法

默认订阅 Server 节点

auto ev_sub = s.SubscribeEvents();
ev_sub.SetOnEvent([](EventArrivedEventArgs const& e) {
std::cout << "[" << e.severity << "] " << e.source_name << ": " << e.message
<< " ft=" << e.time << " type=" << e.event_type << "\n";
});

std::this_thread::sleep_for(std::chrono::minutes(5));
// ev_sub 离开作用域: 自动移除 Event MI + 销毁内部容器

订阅指定节点的事件

auto ev_sub = s.SubscribeEvents("ns=2;s=Line1");
// Line1 必须是 EventNotifier

复用已有 Subscription 容器

auto sub = s.CreateSubscription(500.0);
sub.AddNode("ns=2;s=Counter", [](DataValue const& dv) { /* 数据订阅 */ });

// 把 Event MI 挂到同一个容器 (借用)
auto ev_sub = s.SubscribeEvents("ns=2;s=Line1", &sub);
ev_sub.SetOnEvent([](EventArrivedEventArgs const& e) { /* ... */ });

// ev_sub 析构: 只移除 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:

std::vector<Variant> args;
{ Variant a; a.SetByteString(event_id.data(), event_id.size()); args.push_back(std::move(a)); }
{ Variant b; b.SetString("Operator confirmed"); args.push_back(std::move(b)); }

s.Call(condition_id, condition_id + ".Acknowledge", args);

下一步