Events and alarms
- Subscribe to the events of the Server object (
i=2253). - Activate the simulator’s alarm and receive the alarm event.
- Acknowledge and confirm the alarm, then get the current state again with ConditionRefresh.
What you need
Section titled “What you need”- The
appspackage and theOPCUA_APPSvariable from the lab setup. - One terminal. The subscriptions tutorial introduces the headless simulator.
1. Start the simulator and connect
Section titled “1. Start the simulator and connect”"$OPCUA_APPS/bin/pdcomm-opcua-headless"Start the server and connect:
{"action":"server_start"}{"action":"connect"}2. Subscribe to events
Section titled “2. Subscribe to events”{"action":"event_subscribe"}{"ok":true,"result":{"good":true,"handle":1,"monitored_item":1,"node":"i=2253","status":"Good (0x00000000)","subscription":1}}Without a notifier, event_subscribe watches the Server object. If no subscription exists, it creates one with a 250 ms publishing interval. Its EventFilter selects EventId, EventType, SourceNode, SourceName, Time, Message, Severity, ConditionId, Retain, ActiveState/Id, AckedState/Id and ConfirmedState/Id.
3. Activate the alarm
Section titled “3. Activate the alarm”Set the alarm source variable Simulator.AlarmSource to true:
{"action":"alarm_set","active":true}{"ok":true,"result":{"good":true,"node":"ns=2;s=Simulator.AlarmSource","status":"Good (0x00000000)"}}Receive the event with 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}}It’s an OffNormalAlarmType (i=10637) event: the alarm is active (ActiveState true) and not yet acknowledged (AckedState false), with severity 700. Copy the EventId value for the next step; it differs on every run.
4. Acknowledge the alarm
Section titled “4. Acknowledge the alarm”Call Acknowledge with the EventId you copied, replacing the one below:
{"action":"condition","method":"acknowledge","event_id":"43da01187d15378575644e4988945eed","comment":"Checked the pump"}{"ok":true,"result":{"good":true,"input_results":[],"outputs":[],"status":"Good (0x00000000)"}}The state changed, so a new event follows:
{"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 is now true and ConfirmedState false, and the event has a new EventId. Acknowledging again with this EventId fails, because the state is already acknowledged:
{"action":"condition","method":"acknowledge","event_id":"d6a70225556c1a1c53804ec777c6c35f","comment":"Again"}{"ok":true,"result":{"good":false,"input_results":[],"outputs":[],"status":"BadConditionBranchAlreadyAcked (0x80CF0000)"}}5. Confirm the alarm
Section titled “5. Confirm the alarm”Call Confirm with the latest EventId:
{"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}}The alarm is still active, so Retain stays true.
6. Refresh the conditions
Section titled “6. Refresh the conditions”ConditionRefresh makes the server send the current condition states to the subscription again:
{"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}}A RefreshStartEvent (i=2787), the current alarm state and a RefreshEndEvent (i=2788) arrive in that order. The refresh events aren’t conditions, so their condition fields are null.
7. Clear the alarm
Section titled “7. Clear the alarm”{"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}}The alarm is inactive, acknowledged and confirmed, so Retain is false; a client can now remove the condition from its list.
8. Clean up
Section titled “8. Clean up”{"action":"shutdown"}{"ok":true,"result":{"client_closed":true,"pubsub_stopped":false,"server_stopped":true}}Common errors
Section titled “Common errors”status or error in the reply |
Cause and fix |
|---|---|
BadEventIdUnknown (0x809A0000) |
The EventId is unknown. Copy the EventId of a received event exactly. |
BadConditionBranchAlreadyAcked (0x80CF0000) |
You acknowledged a state that’s already acknowledged. |
BadConditionBranchAlreadyConfirmed (0x80D00000) |
You confirmed a state that’s already confirmed. |
No subscription exists |
You ran condition_refresh or publish before event_subscribe. |
The method of condition accepts acknowledge, confirm, add_comment, enable and disable. In the GUI, Acknowledge last and Confirm last on the Events & Conditions tab use the EventId of the last condition event for you.