test+docs(mtconnect): wire test for the Unavailable blip + ack survival; docs for the review rulings (#626)
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
+25
-12
@@ -413,14 +413,17 @@ CONDITION String tag into a condition node on upgrade.
|
||||
| `Normal` | inactive (return to normal) | — | Good |
|
||||
| `Warning` | active, unacknowledged | 500 | Good |
|
||||
| `Fault` | active, unacknowledged | 800 | Good |
|
||||
| `Unavailable` | inactive | — | `BadNoCommunication` |
|
||||
| `Unavailable` | **unchanged** (an active condition stays active and acknowledged) | — | `BadNoCommunication` |
|
||||
|
||||
`Unavailable` has no precedent among native sources (none reports an "unknown" condition per alarm),
|
||||
so it follows the #477 comms-loss annotation: inactive, with the condition's `Quality` Bad. An active
|
||||
condition going Unavailable is a **Clear** carrying the Bad quality; Normal ⇄ Unavailable while inactive
|
||||
is a **quality-only annotation** (no `/alerts` row). Severity is the exact Part 9 value
|
||||
(`AlarmEventArgs.OpcUaSeverity`, #626), not one of the four buckets. A clear keeps the severity of the
|
||||
alarm it clears.
|
||||
**`Unavailable` is comms loss one hop further out, not a return to normal.** A cppagent marks every
|
||||
DataItem of an adapter UNAVAILABLE when the adapter socket drops, so it is treated exactly like the
|
||||
host's own transport loss (#477/#481): the condition keeps its Active/Acked state and only its `Quality`
|
||||
goes `BadNoCommunication`, as a **quality-only annotation** (no `/alerts` row, written through the host's
|
||||
Quality-only node path — it can never rewrite message/severity or acknowledge anything). When data
|
||||
returns: the **same** statement ⇒ quality-only Good (an ack survives an adapter blip); `Normal` ⇒ Clear;
|
||||
a **different** active statement ⇒ Retrigger. An inactive condition going Unavailable is likewise a
|
||||
quality-only Bad. Severity is the exact Part 9 value (`AlarmEventArgs.OpcUaSeverity`, #626), not one of
|
||||
the four buckets. A clear keeps the severity of the alarm it clears.
|
||||
|
||||
**Message** = the condition's text content; without text, `"{type} {level}"` (e.g. `SYSTEM Fault`).
|
||||
Whichever of `nativeCode` / `nativeSeverity` / `qualifier` the Agent supplied is appended —
|
||||
@@ -428,13 +431,18 @@ Whichever of `nativeCode` / `nativeSeverity` / `qualifier` the Agent supplied is
|
||||
event model has no slot for them. `AlarmType` is the condition's `type`; `SourceNodeId` the DataItem id.
|
||||
|
||||
**Several simultaneous conditions.** MTConnect can hold several active conditions on one DataItem
|
||||
(distinct `nativeCode`s). The OPC UA condition shows **the most severe active one** (newest on a tie).
|
||||
(distinct `nativeCode`s). The OPC UA condition shows **the most severe active one**; equal levels tie-break deterministically
|
||||
(ordinal `nativeCode`, then `type`), never by Agent document order, so a re-baseline that lists them
|
||||
differently cannot re-raise.
|
||||
The driver tracks them with MTConnect's own rules (`MTConnectConditionTracker`): `Warning`/`Fault`
|
||||
activates its `nativeCode`; `Normal` with a `nativeCode` clears only that code, `Normal` without one
|
||||
clears all; `Unavailable` clears all; a `/current` re-baseline replaces the DataItem's set. So a
|
||||
`/sample` chunk clearing code A while code B is active is **not** a return to normal. An escalation
|
||||
(Warning → Fault), a different winning code, or a changed message is a **Retrigger** — active and
|
||||
unacknowledged again with the new severity/message. (The String value surface still reconciles per
|
||||
(Warning → Fault) or a different winning code is a **Retrigger** — active and unacknowledged again with
|
||||
the new severity/message. By design that includes **clearing the worst of several codes**: the next one
|
||||
down is re-raised un-acked, because it is a statement the operator has not seen. A **text-only change**
|
||||
on the same level + `nativeCode` (an adapter embedding a live value in the text) updates nothing — no
|
||||
retrigger, no un-ack — and the message shown stays the statement's first text. (The String value surface still reconciles per
|
||||
document, so on a delta it shows the state word of that chunk; the alarm is the authoritative view.)
|
||||
|
||||
**Acknowledge.** MTConnect has no acknowledgement upstream. Native conditions support Acknowledge and
|
||||
@@ -443,8 +451,8 @@ AddComment only; the ack is applied server-side and the driver's `AcknowledgeAsy
|
||||
native source.
|
||||
|
||||
**Restart / reconnect / comms loss.** The driver diffs each condition against what the server was last
|
||||
**told** — dedup on level + `nativeCode` + `nativeSeverity` + `qualifier` + text, never on the value — and
|
||||
records a state only when an alarm handler was attached to receive it. Consequences:
|
||||
**told** — dedup on level + `nativeCode` + `nativeSeverity` + `qualifier` (not text, never the value) —
|
||||
and records a state only when an alarm handler was attached to receive it. Consequences:
|
||||
|
||||
- A replayed `/current` (reconnect, re-initialize, Agent restart, ring-buffer re-baseline) re-raises
|
||||
nothing that is unchanged — re-raising would un-acknowledge an operator's ack.
|
||||
@@ -454,6 +462,11 @@ records a state only when an alarm handler was attached to receive it. Consequen
|
||||
condition the driver owns `BadNoCommunication` on the connectivity edge (#477) and keeps its Active
|
||||
state; the reconnect edge re-annotates Good, after which the driver re-asserts any still-`Unavailable`
|
||||
condition's Bad quality on its re-subscribe.
|
||||
- A re-subscribe with a **changed** alarm set clears the whole told record: only an alarm-bearing raw-tag
|
||||
delta changes the set, the server applies that as a full rebuild, and a rebuild recreates every
|
||||
condition node inactive — so every active condition is re-asserted onto its new node. The **same** set
|
||||
(a reconnect) keeps the record. (A rebuild that leaves this driver's alarm set unchanged triggers no
|
||||
re-subscribe; that is a host-wide gap shared with every native source.)
|
||||
- An alarm-only driver (no value tags) still runs the `/sample` pump.
|
||||
|
||||
**EVENT controlled vocabularies as OPC UA enumerations — won't fix.** EVENT values (`Execution`,
|
||||
|
||||
Reference in New Issue
Block a user