using Opc.Ua; using Opc.Ua.Server; namespace ZB.MOM.WW.OtOpcUa.OpcUaServer.Compatibility.Aggregates; /// Adapts the versioned baseline algorithms to the SDK 2 calculator protocol without a second SDK runtime. internal static class CompatibilityAggregateFactory { internal static IAggregateCalculator Create(NodeId id, DateTimeUtc start, DateTimeUtc end, double interval, bool stepped, AggregateConfiguration configuration, ITelemetryContext telemetry) => new Adapter(Aggregators.CreateStandardCalculator(id, (DateTime)start, (DateTime)end, interval, stepped, configuration, telemetry) ?? throw new ArgumentOutOfRangeException(nameof(id), "Unsupported baseline aggregate.")); /// Replaces exactly the existing standard factories; no aggregate IDs are added or removed. internal static async ValueTask RegisterAsync(AggregateManager manager, CancellationToken ct) { foreach (var id in Aggregators.SupportedIds) await manager.RegisterFactoryAsync(id, Aggregators.GetNameForStandardAggregate(id).Name!, Create, ct).ConfigureAwait(false); } private sealed class Adapter(AggregateCalculator calculator) : IAggregateCalculator { public NodeId AggregateId => calculator.AggregateId; public bool QueueRawValue(Opc.Ua.DataValue value) => calculator.QueueRawValue(LegacyDataValue.FromSdk(value)); public bool HasEndTimePassed(DateTimeUtc currentTime) => calculator.HasEndTimePassed((DateTime)currentTime); public bool TryGetProcessedValue(bool returnPartial, out Opc.Ua.DataValue value) { var processed = calculator.GetProcessedValue(returnPartial); value = processed is null ? default : processed.ToSdk(); return processed is not null; } } }