Phase 7 follow-up #245 — ScriptedAlarmReadable adapter over engine state #191

Merged
dohertj2 merged 1 commits from phase-7-fu-245-alarm-readable into v2 2026-04-20 21:32:59 -04:00
Owner

Exposes each scripted alarm's current ActiveState as IReadable so OPC UA variable reads on Source=ScriptedAlarm nodes return the live predicate truth instead of BadNotFound.

ScriptedAlarmReadable

Wraps ScriptedAlarmEngine + implements IReadable:

  • Known alarm + Active → DataValueSnapshot(true, Good)
  • Known alarm + Inactive → DataValueSnapshot(false, Good)
  • Unknown alarm id → DataValueSnapshot(null, BadNodeIdUnknown) — surfaces misconfiguration rather than silently reading false
  • Batch reads preserve request order

Phase7EngineComposer.Compose now returns this as ScriptedAlarmReadable when ScriptedAlarm rows are present. ScriptedAlarmSource (the IAlarmSource for the event stream) stays in place — the IReadable is a separate adapter over the same engine.

Tests — 6 new + 1 updated composer test = 19 Phase 7 tests

ScriptedAlarmReadableTests covers: inactive + active predicate → bool snapshot, unknown alarm id → BadNodeIdUnknown, batch order preservation, null-engine + null-fullReferences guards. The active-predicate test uses ctx.GetTag on a seeded upstream value to drive a real cascade through the engine.

Updated Phase7EngineComposerTests to assert ScriptedAlarmReadable is non-null when alarms compose, null when only virtual tags.

Remaining Phase 7 production wiring

  • #244 — driver-bridge feed populating CachedTagUpstreamSource from live driver subscriptions
  • #246Program.cs Compose call + SqliteStoreAndForwardSink lifecycle + Galaxy.Host IPC writer

Task #240 (live E2E smoke) unblocks once both land.

Exposes each scripted alarm's current `ActiveState` as `IReadable` so OPC UA variable reads on `Source=ScriptedAlarm` nodes return the live predicate truth instead of `BadNotFound`. ## `ScriptedAlarmReadable` Wraps `ScriptedAlarmEngine` + implements `IReadable`: - Known alarm + Active → `DataValueSnapshot(true, Good)` - Known alarm + Inactive → `DataValueSnapshot(false, Good)` - Unknown alarm id → `DataValueSnapshot(null, BadNodeIdUnknown)` — surfaces misconfiguration rather than silently reading false - Batch reads preserve request order `Phase7EngineComposer.Compose` now returns this as `ScriptedAlarmReadable` when `ScriptedAlarm` rows are present. `ScriptedAlarmSource` (the `IAlarmSource` for the event stream) stays in place — the `IReadable` is a separate adapter over the same engine. ## Tests — 6 new + 1 updated composer test = **19 Phase 7 tests** `ScriptedAlarmReadableTests` covers: inactive + active predicate → bool snapshot, unknown alarm id → `BadNodeIdUnknown`, batch order preservation, null-engine + null-fullReferences guards. The active-predicate test uses `ctx.GetTag` on a seeded upstream value to drive a real cascade through the engine. Updated `Phase7EngineComposerTests` to assert `ScriptedAlarmReadable` is non-null when alarms compose, null when only virtual tags. ## Remaining Phase 7 production wiring - **#244** — driver-bridge feed populating `CachedTagUpstreamSource` from live driver subscriptions - **#246** — `Program.cs` Compose call + `SqliteStoreAndForwardSink` lifecycle + Galaxy.Host IPC writer Task #240 (live E2E smoke) unblocks once both land.
dohertj2 added 1 commit 2026-04-20 21:32:49 -04:00
Task #245 — exposes each scripted alarm's current ActiveState as IReadable so
OPC UA variable reads on Source=ScriptedAlarm nodes return the live predicate
truth instead of BadNotFound.

## ScriptedAlarmReadable

Wraps ScriptedAlarmEngine + implements IReadable:
- Known alarm + Active → DataValueSnapshot(true, Good)
- Known alarm + Inactive → DataValueSnapshot(false, Good)
- Unknown alarm id → DataValueSnapshot(null, BadNodeIdUnknown) — surfaces
  misconfiguration rather than silently reading false
- Batch reads preserve request order

Phase7EngineComposer.Compose now returns this as ScriptedAlarmReadable when
ScriptedAlarm rows are present. ScriptedAlarmSource (IAlarmSource for the event
stream) stays in place — the IReadable is a separate adapter over the same engine.

## Tests — 6 new + 1 updated composer test = 19 total Phase 7 tests

ScriptedAlarmReadableTests covers: inactive + active predicate → bool snapshot,
unknown alarm id → BadNodeIdUnknown, batch order preservation, null-engine +
null-fullReferences guards. The active-predicate test uses ctx.GetTag on a seeded
upstream value to drive a real cascade through the engine.

Updated Phase7EngineComposerTests to assert ScriptedAlarmReadable is non-null
when alarms compose, null when only virtual tags.

## Follow-ups remaining
- #244 — driver-bridge feed populating CachedTagUpstreamSource
- #246 — Program.cs Compose call + SqliteStoreAndForwardSink lifecycle
dohertj2 merged commit a5bd60768d into v2 2026-04-20 21:32:59 -04:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#191