docs(alarms): native driver-alarm TagConfig schema (Phase B)

This commit is contained in:
Joseph Doherty
2026-06-14 03:28:55 -04:00
parent 422e5b7db2
commit b0e83902b8
+65
View File
@@ -111,6 +111,71 @@ Two mapping notes specific to this adapter:
- `SubscribeAlarmsAsync` accepts a list of source-node-id filters, interpreted as Equipment-path prefixes. Empty list matches every alarm. Each emission is matched against every live subscription — the adapter keeps no per-subscription cursor.
- `IAlarmSource.AcknowledgeAsync` does not carry a user identity. The adapter defaults the audit user to `"opcua-client"` so callers using the base interface still produce an audit entry. The server's Part 9 method handlers call the engine's richer `AcknowledgeAsync` / `ConfirmAsync` / `OneShotShelveAsync` / `TimedShelveAsync` / `UnshelveAsync` / `AddCommentAsync` directly with the authenticated principal instead.
## Native driver alarms (equipment-tag path)
> Design reference: [docs/plans/2026-06-14-galaxy-phase-b-native-alarms-design.md](plans/2026-06-14-galaxy-phase-b-native-alarms-design.md)
A native driver alarm is an authored equipment `Tag` bound to an `IAlarmSource`
driver (today: Galaxy `GalaxyMxGateway`) whose `TagConfig` carries an `"alarm"`
object alongside the usual `"FullName"`:
```json
{ "FullName": "TestMachine_002.HiAlarm", "alarm": { "alarmType": "OffNormalAlarm", "severity": 700 } }
```
`"alarm"` **absent** → the tag materialises as an ordinary value variable
(unchanged behaviour). `"alarm"` **present** → the tag materialises as a Part 9
`AlarmConditionState` under its equipment folder **instead of** a value variable.
No EF/schema change is required; the intent rides in the schemaless `TagConfig`
blob and is parsed byte-parity in both the compose (`Phase7Composer`) and deploy
(`DeploymentArtifact`) paths.
### TagConfig alarm fields
| Field | Values | Default |
|---|---|---|
| `alarmType` | `"AlarmCondition"`, `"OffNormalAlarm"`, `"DiscreteAlarm"`, `"LimitAlarm"` | `"AlarmCondition"` |
| `severity` | OPC UA 11000 scale | `500` |
An unknown `alarmType` string falls back to the base `AlarmCondition` OPC UA
ObjectType. `severity` seeds the condition's initial severity at materialisation;
the driver's live alarm events may carry a different severity that overrides it at
runtime.
### Runtime flow
The driver's live `IAlarmSource.OnAlarmEvent` is the sole input. Transition kinds
(`Raise`, `Clear`, `Acknowledge`, `Retrigger`) drive the condition's Active /
Acknowledged / Severity / Message fields via `NativeAlarmProjector`, a pure
per-condition state projector. The projected `AlarmConditionSnapshot` is forwarded
through `DriverHostActor``OpcUaPublishActor.AlarmStateUpdate`
`OtOpcUaNodeManager.WriteAlarmCondition` — the same delta-gated Part 9
condition-event path that scripted alarms use, reused verbatim.
The same `AlarmTransitionEvent` that scripted alarms publish is emitted to the
cluster `alerts` topic, so the AdminUI `/alerts` page and the Historian sink see
native alarm transitions identically. Publication to the `alerts` topic is
**Primary-gated** (only the redundancy Primary publishes cluster-wide transitions);
the OPC UA condition-node write is ungated on all nodes so a Secondary stays warm
for failover.
The alarm is authored on the `Tags` tab of the equipment page (`/uns/equipment/{id}`)
by editing the tag's raw `TagConfig` JSON to include the `"alarm"` object. No
other configuration is required.
### Deferred follow-ups
Two items are explicitly out of scope for Phase B:
1. **Inbound device-ack**: an OPC UA client `Acknowledge` currently updates the
local `AlarmConditionState` but does **not** yet propagate back to the device
via `IAlarmSource.AcknowledgeAsync` (→ AVEVA). Device-ack round-trip is a
deferred follow-up.
2. **AdminUI Galaxy address-picker pre-fill**: the `alarm` object must be authored
by editing the tag's raw `TagConfig` JSON today; a future picker enhancement
could pre-fill `alarmType` / `severity` from driver discovery
(`DriverAttributeInfo.IsAlarm`).
## Inbound operator ack/shelve
Operators interact with active scripted alarms through two surfaces — both converge on the same `alarm-commands` DPS topic consumed by `ScriptedAlarmHostActor`.