diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Server/Phase7/Phase7Composer.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Server/Phase7/Phase7Composer.cs index c834a37..7a54343 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.Server/Phase7/Phase7Composer.cs +++ b/src/Server/ZB.MOM.WW.OtOpcUa.Server/Phase7/Phase7Composer.cs @@ -7,6 +7,7 @@ using ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian; using ZB.MOM.WW.OtOpcUa.Core.Hosting; using ZB.MOM.WW.OtOpcUa.Core.OpcUa; using ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms; +using ZB.MOM.WW.OtOpcUa.Server.History; using ZB.MOM.WW.OtOpcUa.Server.OpcUa; namespace ZB.MOM.WW.OtOpcUa.Server.Phase7; @@ -42,6 +43,7 @@ public sealed class Phase7Composer : IAsyncDisposable private readonly DriverEquipmentContentRegistry _equipmentRegistry; private readonly IAlarmHistorianSink _historianSink; private readonly IAlarmHistorianWriter? _injectedWriter; + private readonly IHistoryRouter? _historyRouter; private readonly ILoggerFactory _loggerFactory; private readonly Serilog.ILogger _scriptLogger; private readonly ILogger _logger; @@ -61,13 +63,15 @@ public sealed class Phase7Composer : IAsyncDisposable ILoggerFactory loggerFactory, Serilog.ILogger scriptLogger, ILogger logger, - IAlarmHistorianWriter? injectedWriter = null) + IAlarmHistorianWriter? injectedWriter = null, + IHistoryRouter? historyRouter = null) { _scopeFactory = scopeFactory ?? throw new ArgumentNullException(nameof(scopeFactory)); _driverHost = driverHost ?? throw new ArgumentNullException(nameof(driverHost)); _equipmentRegistry = equipmentRegistry ?? throw new ArgumentNullException(nameof(equipmentRegistry)); _historianSink = historianSink ?? throw new ArgumentNullException(nameof(historianSink)); _injectedWriter = injectedWriter; + _historyRouter = historyRouter; _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); _scriptLogger = scriptLogger ?? throw new ArgumentNullException(nameof(scriptLogger)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); @@ -117,7 +121,8 @@ public sealed class Phase7Composer : IAsyncDisposable alarmStateStore: new InMemoryAlarmStateStore(), historianSink: historianSink, rootScriptLogger: _scriptLogger, - loggerFactory: _loggerFactory); + loggerFactory: _loggerFactory, + historyRouter: _historyRouter); _logger.LogInformation( "Phase 7: composed engines from generation {Gen} — {Vt} virtual tag(s), {Al} scripted alarm(s), {Sc} script(s)", diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Server/Phase7/Phase7EngineComposer.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Server/Phase7/Phase7EngineComposer.cs index 1414331..8f1583c 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.Server/Phase7/Phase7EngineComposer.cs +++ b/src/Server/ZB.MOM.WW.OtOpcUa.Server/Phase7/Phase7EngineComposer.cs @@ -5,6 +5,7 @@ using ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian; using ZB.MOM.WW.OtOpcUa.Core.Scripting; using ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms; using ZB.MOM.WW.OtOpcUa.Core.VirtualTags; +using ZB.MOM.WW.OtOpcUa.Server.History; namespace ZB.MOM.WW.OtOpcUa.Server.Phase7; @@ -32,6 +33,14 @@ namespace ZB.MOM.WW.OtOpcUa.Server.Phase7; /// public static class Phase7EngineComposer { + /// + /// Prefix used when registering the virtual-tag ring-buffer history source in + /// . All virtual-tag UNS paths are prefixed with this + /// string so the router resolves reads to the + /// rather than a driver-owned historian. + /// + public const string VirtualTagHistoryPrefix = "virtual:"; + public static Phase7ComposedSources Compose( IReadOnlyList