bug(alarms): condition Quality is hardcoded Good regardless of the source tag's quality #477
Reference in New Issue
Block a user
Delete Branch "%!s()"
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
Found while fixing #475 (PR #476). Lower priority than #473 / #475, and a genuinely different bug class — worth being precise about why.
MaterialiseAlarmConditionnever assignsAlarmConditionState.Quality, and neither does theWriteAlarmConditiontransition path. Grep confirms no assignment anywhere insrc/(the.Qualityhits are unrelated: GalaxyEventPump, historian sample mapping, the historization outbox).Why this is NOT the same class as #473/#475
Those two shipped null on the wire and broke conformant clients.
Qualitydoes not:StatusCodes.Goodis0x00000000, sodefault(StatusCode)isGood. The field is accidentally valid — clients parse it fine. There is no null defect here, which is why it was deliberately left out of #475.The actual defect
Every condition reports
Goodunconditionally, regardless of the backing tag's real quality. A native alarm condition is materialised at a raw tag; if that tag goes Bad (device offline / comms lost) or Uncertain, the condition still reportsQuality = Good.Part 9 defines
ConditionType.Qualityas the quality of the Condition's source data, so this is a wrong value rather than a missing one — arguably worse to detect, since nothing looks broken.OT impact: an operator (or an HMI bucketing on Quality) cannot distinguish "this alarm is genuinely not active" from "we have lost contact with the device and have no idea whether it is active". Both read as a healthy, inactive, Good condition. That is a meaningful distinction in a plant context.
Why it is not a 2-line fix
Unlike #473/#475 — static values known at the materialise seam —
Qualityis dynamic: it must track the source tag's live status code, which means plumbing the driver's quality through to the condition and updating it on quality transitions (not just alarm-state transitions).The raw tag's quality already reaches the node manager via the value path (
WriteValuecarriesOpcUaQuality), but an alarm-bearing raw tag materialises only a condition and no sibling value variable, so the quality currently has nowhere to land. Design questions to settle:Qualityfollow the source tag's status code directly, or map through a policy (e.g. Bad -> Uncertain)?Retain/ suppress transitions, or only annotateQuality?Suggested test
Extend
NativeAlarmEventIdentityFieldDeliveryTests(the wire-level guard from #474/#476) with a case that drives the source tag Bad and asserts the condition event reports non-GoodQuality.References