OPC UA SCADA Alarm Refresh: Remove Stale Conditions Only After Refresh Completes
A SCADA client can reconnect successfully yet retain an alarm that no
longer needs attention, or miss one that was already active before it
subscribed. Restoring communication does not reconstruct the current
alarm display. OPC UA ConditionRefresh provides a synchronization
sequence that the display must finish before removing entries left over
from its earlier state.
The reference is OPC UA Part 9, Alarms & Conditions, version
1.05.06. This article concerns retained condition state in a SCADA
display. It does not establish complete historical-event recovery or any
plant safety function. The example sequence is hypothetical and was not
executed against a server.

Treat
subscription startup as a different operation
Part 9’s condition-state
synchronization section explains that event subscriptions report
transitions from their starting point. An already existing condition
need not generate a new transition simply because this client connected.
Refresh supplies retained states rather than a general event-history
replay.
For a SCADA implementation, keep the visible-state cache separate
from the event journal. A refresh can repair the list of conditions
still requiring attention without filling every interval in that
journal. Presenting those as the same recovery result would hide missing
history.
Reconcile a bounded
refresh generation
The specified display procedure marks existing retained entries as
suspect when RefreshStartEventType arrives. Entries returned during the
refresh are reconciled, and newly received events are not marked
suspect. At RefreshEndEventType, entries still suspect can be
removed.
Consider a hypothetical display containing conditions A and B before
a disconnect. The refresh returns A and introduces C, but does not
return B. B remains a suspect entry while the sequence is in progress.
Only the corresponding completion boundary establishes the basis for
removing it from the refreshed display.
If communication fails before that completion, do not silently
interpret the incomplete set as the server’s full retained set. Keep the
synchronization state visible and restart through the supported client
recovery path. A local elapsed-time limit may stop waiting, but it is
not a substitute for a completed refresh.
Preserve condition
branches and live updates
The ConditionRefresh
method contract includes retained previous branches as well as
current conditions. It also allows new notifications to be interspersed
with refresh traffic. A display keyed only by an equipment label can
collapse separate states that still require operator attention.
Use the server and subscription context together with condition and
branch identity in the display model. Keep the reported EventId with
each state. The contract preserves the original EventId for a refreshed
notification, but permits some regenerated properties to differ. Do not
treat an EventId as an ordered counter or assume repeated identity means
every property is byte-for-byte identical.
The client must avoid replacing newer live state with an older
refreshed state for the same branch. Qualify the SDK’s event ordering
and refresh handling explicitly. A rule that blindly overwrites the
cache with the last callback is not an adequate demonstration of that
requirement.
Match completion to the
monitored scope
ConditionRefresh addresses a subscription owned by the calling
session. When that subscription includes several notifier monitored
items, the server sends start and end markers into each applicable
stream. Track completion for the scope being reconciled; the first end
marker from one stream should not certify every other stream.
The special refresh start, end and required events bypass ordinary
event content filtering. Dispatch them before the SCADA application’s
normal alarm-type rejection logic, so the very markers needed for
reconciliation are not discarded as irrelevant events.
Test removal,
interruption and interleaving
A focused simulated campaign should start with stale entries, return
a retained branch, insert a live update during refresh and interrupt
another refresh before its end marker. Add two notifier streams with
different completion times. Inspect both the displayed entries and the
synchronization state after every step.
The acceptance result is a current-state view whose additions,
replacements and removals have an explained refresh boundary. Historical
gaps remain a separate outcome, and an unfinished refresh remains
unfinished rather than being reported as an empty or fully synchronized
alarm list.