feat(alarms): scripted condition Quality from worst-of-input tag quality (#478) #480
Reference in New Issue
Block a user
Delete Branch "feat/scripted-alarm-quality-478"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Layer 3 of #477 — a scripted OPC UA alarm condition's
Qualitynow reflects the worst quality across its input tags, mirroring the native OT semantic ("can I trust this condition's state?"). PreviouslyScriptedAlarmHostActor.ToSnapshothardcodedGood.Closes #478.
Two blockers found on the live path (both silently discarded quality)
DependencyMuxActorbuiltDependencyValueChangedwithout theAttributeValuePublished.Qualityit already carried.ScriptedAlarmHostActor.OnDependencyChangedpushed each mux value into the engine with a hardcoded0u(Good) StatusCode.So even a
Baddriver value reached the engine as Good — Layer 3 plumbs quality first.Design
DependencyValueChangedgainsQuality(defaultedGood, VT engine unchanged); the mux forwards it;OnDependencyChangedmaps it to a StatusCode on the pushed snapshot.ScriptedAlarmEvent.WorstInputStatusCode. A real transition carries it →ToSnapshotprojects it (no clobber-back-to-Good when a transition fires while an input isUncertain).AreInputsReadyholds state — no transition), exactly like a comms-lost native driver. A quality-bucket change with no transition emits the newEmissionKind.QualityChanged, routed to the existing #477-L2AlarmQualityUpdate → WriteAlarmQualitynode path (quality only, one Part 9 event per bucket change, no/alertsrow, no historian write). No new sink surface.ScriptedAlarmSourceskipsQualityChangedso it never fabricates a phantomIAlarmSourceevent (which would materialize/historize a condition).Good(theAreInputsReadyguard already holds the condition), so scripted conditions don't flashBadat deploy; the first actually-Badpublished value flips the bucket and annotates.Tests (TDD, RED-first)
Uncertain;Badinput with no transition emitsQualityChanged(Bad); restore emitsQualityChanged(Good); unchanged bucket emits nothing.ScriptedAlarmSource:QualityChangedraises noOnAlarmEvent.DependencyValueChangedcarries the published quality.Baddependency →AlarmQualityUpdate(Bad)+ no/alerts; transition snapshot carries the worst quality.All green: Core.ScriptedAlarms 76/76, Runtime 386/386; full solution builds clean. Docs:
AlarmTracking.mdLayer-3 section + design doc.