报警与条件
概述
OPC UA Part 9 在 ConditionType / AlarmConditionType 上定义了固定 NodeId 的标准 Method。SDK 封装为形参清晰的 C API。
| Method | NodeId | 入参 |
|---|---|---|
| Acknowledge | i=9111 | (event_id: uint8_t*, n: size_t, comment: char*) |
| Confirm | i=9113 | (event_id, n, comment) |
| AddComment | i=9029 | (event_id, n, comment) |
| Enable | i=2803 | — |
| Disable | i=2805 | — |
| ConditionRefresh | i=3875 | (sub_id: uint32_t) |
| ConditionRefresh2 | i=12912 | (sub_id, mi_id) |
| OneShotShelve | i=9211 | — |
| TimedShelve | i=9213 | (shelving_time_ms: double) |
| Unshelve | i=9215 | — |
API
| 函数 | 类别 | 读写 | 说明 |
|---|---|---|---|
| DarraUa_Condition_Acknowledge(ua, cond_id, eid, n, comment) | 报警 | 写 | 用户已知 |
| DarraUa_Condition_Confirm(ua, cond_id, eid, n, comment) | 报警 | 写 | 现场已处理 |
| DarraUa_Condition_AddComment(ua, cond_id, eid, n, comment) | 报警 | 写 | 加备注 |
| DarraUa_Condition_Enable(ua, cond_id) | 报警 | 写 | 启用 |
| DarraUa_Condition_Disable(ua, cond_id) | 报警 | 写 | 禁用 |
| DarraUa_Condition_Refresh(ua, sub_id) | 报警 | 写 | 补发激活报警 |
| DarraUa_Condition_Refresh2(ua, sub_id, mi_id) | 报警 | 写 | 仅指定 MI |
| DarraUa_Condition_OneShotShelve(ua, shelving_state_id) | 报警 | 写 | 一次性屏蔽 |
| DarraUa_Condition_TimedShelve(ua, shelving_state_id, ms) | 报警 | 写 | 限时屏蔽 |
| DarraUa_Condition_Unshelve(ua, shelving_state_id) | 报警 | 写 | 取消屏蔽 |
返回 DarraUa_StatusCode。
代码示例
#include <opcua.h>
void on_event(const DarraUa_EventArgs* e, void* ctx) {
DarraUa_Session* ua = (DarraUa_Session*)ctx;
uint8_t* event_id = NULL;
size_t eid_n = 0;
DarraUa_EventArgs_GetByteString(e, "EventId", &event_id, &eid_n);
char* condition_id = NULL;
DarraUa_EventArgs_GetString(e, "ConditionId", &condition_id);
// a. 让服务端补发当前激活报警 (sub_id 从 ctx 携带)
uint32_t sub_id = /* from ctx */;
DarraUa_Condition_Refresh(ua, sub_id);
// b. 用户点 "确认"
DarraUa_StatusCode rc = DarraUa_Condition_Acknowledge(ua,
condition_id, event_id, eid_n, "操作员已知");
if (rc != UA_GOOD) fprintf(stderr, "Acknowledge 失败 0x%08X\n", rc);
// c. 现场处理
DarraUa_Condition_Confirm(ua, condition_id, event_id, eid_n, "现场已处理");
// d. 临时屏蔽 30 秒
char shelving_id[256];
snprintf(shelving_id, sizeof(shelving_id), "%s.ShelvingState", condition_id);
DarraUa_Condition_TimedShelve(ua, shelving_id, 30000.0);
DarraUa_FreeBytes(event_id);
DarraUa_FreeString(condition_id);
}
int main() {
DarraUa_Session* ua;
DarraUa_Session_New("opc.tcp://server:4840", &ua);
DarraUa_Session_Connect(ua);
DarraUa_Subscription* sub;
DarraUa_Session_CreateSubscription(ua, 500.0, &sub);
DarraUa_EventSubscription* ev;
DarraUa_Subscription_SubscribeEvents(sub, "i=2253", NULL, &ev);
DarraUa_EventSubscription_RegisterArrived(ev, on_event, ua);
/* run loop ... */
DarraUa_Session_Free(ua);
return 0;
}
错误处理
| StatusCode | 含义 |
|---|---|
| Good (0x0) | 成功 |
| BadEventIdUnknown | EventId 不匹配 |
| BadConditionAlreadyEnabled | 已启用 |
| BadConditionAlreadyShelved | 已屏蔽 |
最佳实践
- 首次订阅后必调
DarraUa_Condition_Refresh - Acknowledge 后再 Confirm, 两步
- TimedShelve 单位 ms, 不是秒
- 不要在事件回调里同步 ack, 推队列后台处理
- 释放: event_id / condition_id 都要 Free
跨语言对照
| C# | Python | Java | C++ | Rust | C |
|---|---|---|---|---|---|
| Acknowledge | acknowledge | acknowledge | Acknowledge | acknowledge | DarraUa_Condition_Acknowledge |
| Confirm | confirm | confirm | Confirm | confirm | DarraUa_Condition_Confirm |
| ConditionRefresh | condition_refresh | conditionRefresh | ConditionRefresh | condition_refresh | DarraUa_Condition_Refresh |