feat(dcl): OPC UA Alarms & Conditions adapter (event subscription + ConditionRefresh)

Adds IAlarmSubscribableConnection to OpcUaDataConnection, IOpcUaClient alarm
subscription methods, and RealOpcUaClient A&C event monitored-item +
EventFilter + ConditionRefresh snapshot, mapping fields via OpcUaAlarmMapper.
Behavior verified against a live A&C server in Task 28; mapper unit-tested.
This commit is contained in:
Joseph Doherty
2026-05-29 16:42:27 -04:00
parent 1fbb814daa
commit 0d30b7dec0
3 changed files with 240 additions and 1 deletions
@@ -1,4 +1,5 @@
using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Protocol;
using ZB.MOM.WW.ScadaBridge.Commons.Types.Alarms;
namespace ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Adapters;
@@ -81,6 +82,22 @@ public interface IOpcUaClient : IAsyncDisposable
/// <returns>A task representing the asynchronous operation.</returns>
Task RemoveSubscriptionAsync(string subscriptionHandle, CancellationToken cancellationToken = default);
/// <summary>
/// Subscribes to OPC UA Alarms &amp; Conditions events under
/// <paramref name="sourceNodeId"/> (or the Server object when null). On
/// (re)subscribe the adapter issues a ConditionRefresh and replays the
/// active conditions as Snapshot…SnapshotComplete transitions. Returns a
/// handle for <see cref="RemoveAlarmSubscriptionAsync"/>.
/// </summary>
Task<string> CreateAlarmSubscriptionAsync(
string? sourceNodeId,
string? conditionFilter,
Action<NativeAlarmTransition> onTransition,
CancellationToken cancellationToken = default);
/// <summary>Removes an alarm-event subscription by handle.</summary>
Task RemoveAlarmSubscriptionAsync(string subscriptionHandle, CancellationToken cancellationToken = default);
/// <summary>
/// Reads the current value of a node.
/// </summary>
@@ -182,6 +199,19 @@ internal class StubOpcUaClient : IOpcUaClient
return Task.CompletedTask;
}
/// <inheritdoc />
public Task<string> CreateAlarmSubscriptionAsync(
string? sourceNodeId, string? conditionFilter,
Action<NativeAlarmTransition> onTransition, CancellationToken cancellationToken = default)
{
// Stub: no events. Real A&C subscription lives in RealOpcUaClient.
return Task.FromResult(Guid.NewGuid().ToString());
}
/// <inheritdoc />
public Task RemoveAlarmSubscriptionAsync(string subscriptionHandle, CancellationToken cancellationToken = default)
=> Task.CompletedTask;
/// <inheritdoc />
public Task<(object? Value, DateTime SourceTimestamp, uint StatusCode)> ReadValueAsync(
string nodeId, CancellationToken cancellationToken = default)