← 전체 글
OPC UA/약 10분 읽기/ 조회

OPC UA Alarm & Condition 시운전: Retain, Acknowledge, Reconnect 제대로 잡기

SCADA에서 OPC UA Alarm & Condition subscription을 시운전할 때 event filter, Retain flag, ConditionRefresh method, acknowledge 경로, timestamp, 그리고 reconnect 뒤에야 드러나는 문제를 짚는다.

OPC UA알람SCADA문제 해결프로젝트 노트

Analog faceplate가 다 잘 갱신되길래 OPC UA 연결을 통과시키고 넘어간다. 그런데 limit이 트립됐는데 alarm summary가 비어 있거나, 더 나쁘게는 알람이 떴다가 2초 만에 clear되면서 operator가 row를 보기도 전에 사라진다. Value subscription이 깨끗하다고 해서 알람이 실제로 들어오고, 목록에 남고, acknowledge까지 되는지는 전혀 알 수 없다.

Alarm & Condition(OPC UA Part 9)은 data access(Part 4/8)와 다른 메커니즘이기 때문이다. Data access는 node의 value change를 구독한다. A&C는 event-notifier object의 event를 client에 구독시키고, condition 상태 변화를 전달하며, client가 method를 호출하기를 기대한다 — Acknowledge, Confirm, Enable, Disable, Shelve, Unshelve. Alarm 태그를 analog 태그처럼 import하면 아무도 신뢰하지 않는 alarm summary가 나온다. A&C는 별도 시험 항목으로 잡는다.

서버가 event를 실제로 내보내는지 확인한다

EventNotifier attribute를 읽을 수 있는 UA client로 browse한다(UaExpert의 attribute view면 된다). Object는 EventNotifier의 bit 0(SubscribeToEvents)이 켜져 있어야만 event를 내보낸다. SCADA runtime이 실제로 구독할 바로 그 node — Server object, area folder, equipment object — 를 겨냥하고, "비슷해 보이는" 상위 node로 넘어가지 않는다.

더 진행하기 전에 다섯 가지를 기록한다.

항목확인 내용
Event sourceEventNotifier에 SubscribeToEvents가 켜진 node — Server object, area, equipment, vendor folder 중 어디인지
Condition typeAlarmConditionType, LimitAlarmType, OffNormalAlarmType, 또는 vendor subtype
MethodAcknowledge, Confirm, Shelve, Unshelve, Enable, Disable 중 실제로 필요한 것
ConditionRefreshServer object가 ConditionRefresh를 노출하는지 (reconnect마다 필요하다 — 아래 참조)
SecurityEngineering 로그인이 아니라 runtime 계정이 event 수신과 alarm method 실행 권한을 갖는지

실제 SCADA runtime이 쓸 network segment와 계정으로 browse한다. Vendor 화면은 아무것도 증명하지 않는다. Engineering laptop에서는 A&C browse가 잘 되는데 runtime 계정에서는 role에 event 권한이 없어 event가 하나도 안 나오는 경우를 직접 봤다.

Event filter는 의도적으로 만든다

Event filter(SelectClause 목록)는 client가 받을 필드를 정한다. 너무 좁으면 alarm row에 message만 뜨고 source, active state, severity가 없다. 너무 넓으면 operator alarm이 아니던 event까지 밀려와 summary가 지저분해진다.

내가 항상 select하는 필드다.

  • EventId, EventType, SourceNode, SourceName, Time
  • Message, Severity, ConditionName, ConditionClassId, ConditionClassName
  • ActiveState, AckedState, ConfirmedState, EnabledState, Retain
  • Server가 채워 준다면 QualityLastSeverity
  • Alarm branch를 쓰는 서버라면 BranchId

ActiveState, AckedState 등은 TwoStateVariableType이다. boolean인 Id sub-field를 명시적으로 select해야 한다. 안 그러면 filter 걸 수 없는 "Active/Inactive" 문자열만 목록에 남는다.

Production alarm summary에 붙이기 전에 임시 event view로 먼저 본다. 빠진 필드는 operator가 쓰기 전이면 5분이면 고치지만, 쓰기 시작한 뒤에는 change-control 골칫거리가 된다.

알람 목록 기준은 ActiveState가 아니라 Retain이다

대부분의 alarm summary가 여기서 틀어진다. Retain은 이 condition이 operator에게 아직 의미가 있는지를 알려 준다. Condition은 acknowledge가 안 됐다는 이유만으로 inactive여도 계속 retained일 수 있다.

전형적인 버그: ActiveState가 false가 되는 순간 row를 지우는 것. 그러면 operator가 보기 전에 clear된 알람 — 가장 놓치기 쉬운 순간 알람 — 이 전부 사라진다. 반대 버그는 모든 event를 영원히 남겨 alarm summary를 event journal로 만드는 것이다.

ActiveState가 아니라 Retain을 "이 row 보여 줘" flag로 쓰고, 다섯 전이를 모두 시험한다.

  1. Active, unacknowledged.
  2. 아무도 acknowledge하기 전에 clear (inactive, Retain=true 유지).
  3. Active 상태에서 acknowledge.
  4. Clear된 뒤 acknowledge (이때 Retain이 false로 떨어져야 한다).
  5. Acknowledge 뒤 Confirm까지 필요한 경우.

Row 유지 규칙은 현장 alarm philosophy가 정하되, 모든 client가 같은 규칙을 적용해야 한다.

Acknowledge 경로를 끝까지 검증한다

Acknowledge는 write가 아니라 method call이다. Client는 condition의 현재 EventId와 선택적 operator comment를 보내고, server의 return status를 처리해야 한다. HMI에서 직접 확인하는 것들이다.

  • Operator role이 담당 area만 acknowledge할 수 있는지.
  • 거부된 acknowledge가 조용히 삼켜지지 않고 눈에 보이게 실패하는지.
  • Comment가 server audit trail이나 SCADA event journal에 남는지.
  • Client 재시작 없이 row가 갱신되는지.
  • 다른 client의 acknowledge가 여기에도 반영되는지.

EventId를 빨리 재활용하는 서버를 조심한다. Client가 쥐고 있던 EventId가 더 이상 resolve되지 않아 오래된 row를 acknowledge하지 못할 수 있다. 오래 지속되는 알람과 깜빡이는 알람을 둘 다 시험한다.

Timestamp를 대충 통과시키지 않는다

Alarm event time은 장애 분석에 바로 쓰이므로 "그럴듯해 보이는" 화면으로는 부족하다. 한 event에 대해 네 시계를 맞춰 본다: UA Time 필드, SCADA receive time, historian event time, operator workstation 표시. 흔한 범인들:

  • Zone 표시 없이 나오는 local time.
  • 장시간 운전 중 DST offset 전환.
  • PLC, OPC UA server, SCADA server, domain time source 사이의 clock drift (수백 ms만 어긋나도 빠른 sequence의 순서가 뒤집힌다).
  • Event time이 아니라 receive time으로 정렬되는 목록.
  • SQL로 들어가며 잘리는 millisecond.

시운전 기록에는 raw UA timestamp와 HMI 표시가 나란히 보이는 알람 하나는 남겨 둔다.

Reconnect를 기다렸다 터지는 문제들

A&C는 부하가 걸리거나 link가 끊겼다 붙기 전까지는 대체로 얌전하다. 매번 사람들을 잡는 것 하나: reconnect 뒤 client는 ConditionRefresh를 호출해야 한다. 안 하면 현재 retained된 condition을 다시 받지 못해 alarm list가 조용히 stale해진다. Server는 RefreshStartMOEvent로 답하고 retained condition을 재전송한 뒤 RefreshEndMOEvent로 닫는다. Client가 reconnect 시 이걸 안 하면, 실제 알람이 서 있는데도 summary는 평온해 보인다.

내가 겪은 다른 것들:

  • Event 없는 node를 구독 — 알람 0개, error도 없음.
  • Filter에 Retain이나 AckedState가 빠져 row 관리가 안 됨.
  • Severity mapping이 뒤집히거나 뭉개짐 — OPC UA severity는 1–1000이다(1이 최저, 1000이 최고). 세 priority로 압축해서 순서를 잃지 말 것.
  • Client가 standard condition type만 처리하고 알람이 실제로 쓰는 vendor subtype을 무시함.
  • Shelving 상태가 한 client에는 보이고 다른 client에는 안 보임.
  • Engineering 계정에서는 되던 method call이 runtime service account에서 실패함.

그래서 cable 분리나 OPC UA server restart를 시험 계획에 넣는다. Reconnect 뒤 retained alarm이 돌아오는 것까지 봐야 A&C 시운전이 끝난 것이다.

Project file 옆에 남길 증거

알람 누락이 PLC인지 server인지 client인지 따질 때 처음부터 값을 하는 작은 증거 묶음이다.

  • Event subscription source의 export 또는 screenshot (EventNotifier 값 포함).
  • Event filter field 목록.
  • Active, cleared-unacknowledged, acknowledged, shelved 상태의 alarm list 화면.
  • Acknowledge와 shelve 시험에 쓴 user role.
  • EventId, SourceName, Time, Message, Severity, Retain, ActiveState, AckedState가 보이는 raw event sample 하나.
  • Reconnect 시험 결과와 retained alarm 복구에 걸린 시간.