fix(opcua): condition Severity is carried verbatim, not re-bucketed to 5 points

OtOpcUaNodeManager.MapSeverity re-bucketed every projected severity onto the
SDK's five EventSeverity values (<800 -> 700, else 900), defeating #626's exact
OpcUaSeverity: an MTConnect Fault (800) read and evented as 900; a scripted
alarm graded 1000 published 900 while /alerts said 1000; a native Low (200)
published 300. EventSeverity merely names points on the 1..1000 scale, so the
node now carries the value clamped to 1..1000 (ToPart9Severity), at
materialise, projection and in the delta gate.

MTConnect wire test now asserts Fault ActiveState=true/Severity=800 and the
Normal clear ActiveState=false/Retain=false/Severity=800.

Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
Joseph Doherty
2026-10-08 16:19:27 -04:00
parent 49a470a080
commit aba3aa7a8d
4 changed files with 45 additions and 40 deletions
+10 -17
View File
@@ -274,9 +274,10 @@ overwrites an already-authored alarm section.
#### Severity mapping
The authored `severity` (1–1000) seeds the OPC UA condition node at materialisation
time. Every native transition maps the driver's `AlarmSeverity` to one of four fixed
buckets via `NativeAlarmProjector.MapSeverity`, overriding the authored `severity` seed
from the first transition onward:
time. Every native transition replaces it from the first transition onward. A source with a
finer scale supplies the exact Part 9 severity (`AlarmEventArgs.OpcUaSeverity`, e.g. MTConnect
Fault = 800, #626); otherwise `NativeAlarmProjector.MapSeverity` maps the driver's
`AlarmSeverity` to one of four fixed values:
| `AlarmSeverity` enum | Projected value |
|---|---|
@@ -286,20 +287,12 @@ from the first transition onward:
| `Critical` | 900 |
| *(default/unspecified)* | 500 |
That projected integer is then mapped to the OPC UA SDK `EventSeverity` enum
by `OtOpcUaNodeManager.MapSeverity` on each `AlarmStateUpdate` write:
| Projected value range | `EventSeverity` |
|---|---|
| < 200 | `Low` |
| 200 – 399 | `MediumLow` |
| 400 – 599 | `Medium` |
| 600 – 799 | `MediumHigh` |
| ≥ 800 | `High` |
Consequently the four authored buckets land as: Low→`MediumLow`, Medium→`Medium`,
High→`MediumHigh`, Critical→`High`. The authored `severity` field is overridden by
live driver events on every transition.
The condition node carries that projected integer **verbatim** (clamped to 1–1000), on a direct
Read and on every event. It used to be re-bucketed onto the SDK's five `EventSeverity` points
(< 200 → 100, < 400 → 300, < 600 → 500, < 800 → 700, else 900) by the node manager — so an
MTConnect Fault read and evented as 900, a `Low` native alarm as 300, and a scripted alarm the
engine graded 1000 published 900 while its `/alerts` row said 1000. That re-bucketing is gone
(the `EventSeverity` enum merely names points on the 1–1000 scale; any value is valid).
### Runtime flow