이벤트와 알람
- Server 객체(
i=2253)의 이벤트를 구독합니다. - 시뮬레이터 알람을 활성화하고 알람 이벤트를 받습니다.
- 알람을 인지(Acknowledge)하고 확인(Confirm)한 뒤 조건 새로 고침(ConditionRefresh)으로 현재 상태를 다시 받습니다.
준비물
섹션 제목: “준비물”1. 시뮬레이터 실행과 연결
섹션 제목: “1. 시뮬레이터 실행과 연결”"$OPCUA_APPS/bin/pdcomm-opcua-headless"서버를 시작하고 연결합니다.
{"action":"server_start"}{"action":"connect"}2. 이벤트 구독
섹션 제목: “2. 이벤트 구독”{"action":"event_subscribe"}{"ok":true,"result":{"good":true,"handle":1,"monitored_item":1,"node":"i=2253","status":"Good (0x00000000)","subscription":1}}event_subscribe는 notifier를 지정하지 않으면 Server 객체를 감시합니다. 구독이 없으면 게시 주기 250 ms로 새로 만들고, EventFilter로 EventId, EventType, SourceNode, SourceName, Time, Message, Severity, ConditionId, Retain, ActiveState/Id, AckedState/Id, ConfirmedState/Id를 선택합니다.
3. 알람 활성화
섹션 제목: “3. 알람 활성화”알람 원천 변수 Simulator.AlarmSource를 true로 바꿉니다.
{"action":"alarm_set","active":true}{"ok":true,"result":{"good":true,"node":"ns=2;s=Simulator.AlarmSource","status":"Good (0x00000000)"}}Publish로 이벤트를 받습니다.
{"action":"publish","count":2}{"ok":true,"result":{"dropped":0,"notifications":[{"fields":{"AckedState/Id":false,"ActiveState/Id":true,"ConditionId":"ns=2;s=Simulator.Alarm","ConfirmedState/Id":true,"EventId":"43da01187d15378575644e4988945eed","EventType":"i=10637","Message":"Simulator.Alarm","Retain":true,"Severity":700,"SourceName":"PDComm","SourceNode":"ns=2;s=Simulator.AlarmSource","Time":1791997610261},"handle":1,"kind":"event","sequence":1}],"queued":1}}OffNormalAlarmType(i=10637) 이벤트입니다. 알람이 활성화되었고(ActiveState true), 아직 인지되지 않았습니다(AckedState false). 심각도는 700입니다. 다음 단계에서 쓰도록 EventId 값을 복사해 둡니다. 값은 실행할 때마다 다릅니다.
4. 알람 인지
섹션 제목: “4. 알람 인지”복사한 EventId로 Acknowledge를 호출합니다. 아래의 EventId를 자신의 값으로 바꿉니다.
{"action":"condition","method":"acknowledge","event_id":"43da01187d15378575644e4988945eed","comment":"Checked the pump"}{"ok":true,"result":{"good":true,"input_results":[],"outputs":[],"status":"Good (0x00000000)"}}상태가 바뀌었으므로 새 이벤트가 나옵니다.
{"action":"publish"}{"ok":true,"result":{"dropped":0,"notifications":[{"fields":{"AckedState/Id":true,"ActiveState/Id":true,"ConditionId":"ns=2;s=Simulator.Alarm","ConfirmedState/Id":false,"EventId":"d6a70225556c1a1c53804ec777c6c35f","EventType":"i=10637","Message":"Simulator.Alarm","Retain":true,"Severity":700,"SourceName":"PDComm","SourceNode":"ns=2;s=Simulator.AlarmSource","Time":1791997611262},"handle":1,"kind":"event","sequence":2}],"queued":2}}AckedState는 true, ConfirmedState는 false가 되었습니다. EventId도 새로 만들어졌습니다. 이 EventId로 다시 Acknowledge를 호출하면 이미 인지한 상태이므로 실패합니다.
{"action":"condition","method":"acknowledge","event_id":"d6a70225556c1a1c53804ec777c6c35f","comment":"Again"}{"ok":true,"result":{"good":false,"input_results":[],"outputs":[],"status":"BadConditionBranchAlreadyAcked (0x80CF0000)"}}5. 알람 확인
섹션 제목: “5. 알람 확인”최신 EventId로 Confirm을 호출합니다.
{"action":"condition","method":"confirm","event_id":"d6a70225556c1a1c53804ec777c6c35f","comment":"Pump replaced"}{"ok":true,"result":{"good":true,"input_results":[],"outputs":[],"status":"Good (0x00000000)"}}{"action":"publish"}{"ok":true,"result":{"dropped":0,"notifications":[{"fields":{"AckedState/Id":true,"ActiveState/Id":true,"ConditionId":"ns=2;s=Simulator.Alarm","ConfirmedState/Id":true,"EventId":"20f3ef4b7cc43ae65e2983fcfc83561d","EventType":"i=10637","Message":"Simulator.Alarm","Retain":true,"Severity":700,"SourceName":"PDComm","SourceNode":"ns=2;s=Simulator.AlarmSource","Time":1791997611518},"handle":1,"kind":"event","sequence":3}],"queued":3}}알람은 아직 활성 상태이므로 Retain이 true입니다.
6. 조건 새로 고침
섹션 제목: “6. 조건 새로 고침”ConditionRefresh는 구독에 현재 조건 상태를 다시 보내게 합니다.
{"action":"condition_refresh"}{"ok":true,"result":{"good":true,"input_results":[],"outputs":[],"status":"Good (0x00000000)"}}{"action":"publish","count":2}{"ok":true,"result":{"dropped":0,"notifications":[{"fields":{"AckedState/Id":null,"ActiveState/Id":null,"ConditionId":null,"ConfirmedState/Id":null,"EventId":"64c6c97bba83b75a5edab0f3ae218f4a","EventType":"i=2787","Message":"Condition refresh started","Retain":null,"Severity":1,"SourceName":"PDComm","SourceNode":"i=2253","Time":1791997611769},"handle":1,"kind":"event","sequence":4},{"fields":{"AckedState/Id":true,"ActiveState/Id":true,"ConditionId":"ns=2;s=Simulator.Alarm","ConfirmedState/Id":true,"EventId":"20f3ef4b7cc43ae65e2983fcfc83561d","EventType":"i=10637","Message":"Simulator.Alarm","Retain":true,"Severity":700,"SourceName":"PDComm","SourceNode":"ns=2;s=Simulator.AlarmSource","Time":1791997611518},"handle":1,"kind":"event","sequence":4},{"fields":{"AckedState/Id":null,"ActiveState/Id":null,"ConditionId":null,"ConfirmedState/Id":null,"EventId":"8e832138bca60fa765e705103240d018","EventType":"i=2788","Message":"Condition refresh ended","Retain":null,"Severity":1,"SourceName":"PDComm","SourceNode":"i=2253","Time":1791997611771},"handle":1,"kind":"event","sequence":4}],"queued":6}}RefreshStartEvent(i=2787), 현재 알람 상태, RefreshEndEvent(i=2788)가 차례로 왔습니다. 새로 고침 이벤트는 조건이 아니므로 조건 필드가 null입니다.
7. 알람 해제
섹션 제목: “7. 알람 해제”{"action":"alarm_set","active":false}{"action":"publish"}{"ok":true,"result":{"dropped":0,"notifications":[{"fields":{"AckedState/Id":true,"ActiveState/Id":false,"ConditionId":"ns=2;s=Simulator.Alarm","ConfirmedState/Id":true,"EventId":"609b0e9f70ba2c7229a74725049dc94b","EventType":"i=10637","Message":"Simulator.Alarm","Retain":false,"Severity":100,"SourceName":"PDComm","SourceNode":"ns=2;s=Simulator.AlarmSource","Time":1791997612766},"handle":1,"kind":"event","sequence":5}],"queued":7}}알람이 비활성이고 인지·확인도 끝났으므로 Retain이 false가 됩니다. 클라이언트는 이 조건을 목록에서 지워도 됩니다.
8. 정리
섹션 제목: “8. 정리”{"action":"shutdown"}{"ok":true,"result":{"client_closed":true,"pubsub_stopped":false,"server_stopped":true}}자주 생기는 오류
섹션 제목: “자주 생기는 오류”응답의 status 또는 error |
원인과 조치 |
|---|---|
BadEventIdUnknown (0x809A0000) |
알 수 없는 EventId입니다. 받은 이벤트의 EventId를 그대로 복사합니다. |
BadConditionBranchAlreadyAcked (0x80CF0000) |
이미 인지한 상태를 다시 인지했습니다. |
BadConditionBranchAlreadyConfirmed (0x80D00000) |
이미 확인한 상태를 다시 확인했습니다. |
No subscription exists |
condition_refresh나 publish 전에 event_subscribe를 실행하지 않았습니다. |
condition의 method에는 acknowledge, confirm, add_comment, enable, disable을 쓸 수 있습니다. GUI에서는 Events & Conditions 탭의 Acknowledge last와 Confirm last가 마지막 조건 이벤트의 EventId를 자동으로 씁니다.