feat(scripted-alarms): materialise real Part 9 AlarmConditionState nodes (T14)

This commit is contained in:
Joseph Doherty
2026-06-10 19:19:10 -04:00
parent 4217b213b0
commit 60d48a2a0a
14 changed files with 443 additions and 12 deletions
@@ -38,6 +38,15 @@ public sealed class DeferredAddressSpaceSink : IOpcUaAddressSpaceSink
public void WriteAlarmState(string alarmNodeId, bool active, bool acknowledged, DateTime sourceTimestampUtc)
=> _inner.WriteAlarmState(alarmNodeId, active, acknowledged, sourceTimestampUtc);
/// <summary>Materialises a real Part 9 alarm-condition node through the inner sink.</summary>
/// <param name="alarmNodeId">The alarm node ID (== ScriptedAlarmId).</param>
/// <param name="equipmentNodeId">The equipment folder node ID the condition parents under.</param>
/// <param name="displayName">The human-readable condition name.</param>
/// <param name="alarmType">The domain alarm type.</param>
/// <param name="severity">The domain severity.</param>
public void MaterialiseAlarmCondition(string alarmNodeId, string equipmentNodeId, string displayName, string alarmType, int severity)
=> _inner.MaterialiseAlarmCondition(alarmNodeId, equipmentNodeId, displayName, alarmType, severity);
/// <summary>Ensures a folder exists in the address space through the inner sink.</summary>
/// <param name="folderNodeId">The node ID of the folder.</param>
/// <param name="parentNodeId">The node ID of the parent folder, or null for root.</param>
@@ -15,13 +15,29 @@ public interface IOpcUaAddressSpaceSink
/// <param name="sourceTimestampUtc">The source timestamp in UTC.</param>
void WriteValue(string nodeId, object? value, OpcUaQuality quality, DateTime sourceTimestampUtc);
/// <summary>Write an alarm-condition Variable's active/acknowledged state.</summary>
/// <param name="alarmNodeId">The OPC UA node ID of the alarm.</param>
/// <summary>Write an alarm-condition's active/acknowledged state. When a real Part 9 condition
/// node has been materialised for <paramref name="alarmNodeId"/> via
/// <see cref="MaterialiseAlarmCondition"/>, this projects onto its ActiveState/AckedState/Retain;
/// otherwise it falls back to the legacy two-element placeholder variable.</summary>
/// <param name="alarmNodeId">The OPC UA node ID of the alarm (== ScriptedAlarmId for materialised conditions).</param>
/// <param name="active">Whether the alarm is active.</param>
/// <param name="acknowledged">Whether the alarm has been acknowledged.</param>
/// <param name="sourceTimestampUtc">The source timestamp in UTC.</param>
void WriteAlarmState(string alarmNodeId, bool active, bool acknowledged, DateTime sourceTimestampUtc);
/// <summary>
/// Materialise a real OPC UA Part 9 alarm-condition node under its equipment folder so clients
/// can browse it as a proper condition (with basic Active/Ack state). The node id equals the
/// alarm node id (the ScriptedAlarmId) so subsequent <see cref="WriteAlarmState"/> calls update
/// it. Used by <c>Phase7Applier.MaterialiseScriptedAlarms</c>. Idempotent.
/// </summary>
/// <param name="alarmNodeId">The alarm node ID (== ScriptedAlarmId); becomes the condition's NodeId.</param>
/// <param name="equipmentNodeId">The equipment folder node ID the condition parents under.</param>
/// <param name="displayName">Human-readable condition name (BrowseName / DisplayName / Message).</param>
/// <param name="alarmType">Domain alarm type — mapped to the SDK condition subtype by the sink.</param>
/// <param name="severity">Domain severity (OPC UA 1..1000 scale); mapped to the SDK severity buckets.</param>
void MaterialiseAlarmCondition(string alarmNodeId, string equipmentNodeId, string displayName, string alarmType, int severity);
/// <summary>
/// Ensure a folder node exists under the given parent. Used by <c>Phase7Applier</c> to
/// materialise the UNS Area/Line/Equipment hierarchy in the address space. When
@@ -70,6 +86,9 @@ public sealed class NullOpcUaAddressSpaceSink : IOpcUaAddressSpaceSink
/// <inheritdoc />
public void WriteAlarmState(string alarmNodeId, bool active, bool acknowledged, DateTime sourceTimestampUtc) { }
/// <inheritdoc />
public void MaterialiseAlarmCondition(string alarmNodeId, string equipmentNodeId, string displayName, string alarmType, int severity) { }
/// <inheritdoc />
public void EnsureFolder(string folderNodeId, string? parentNodeId, string displayName) { }