using Microsoft.Extensions.Logging; using ZB.MOM.WW.OtOpcUa.Configuration.Entities; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; 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; namespace ZB.MOM.WW.OtOpcUa.Server.Phase7; /// /// Phase 7 follow-up (task #243) — maps the generation's / /// / rows into the runtime /// definitions + /// expect, builds the engine instances, and returns the /// sources plus an for the DriverNodeManager /// wiring added by task #239. /// /// /// /// Empty Phase 7 config (no virtual tags + no scripted alarms) is a valid state: /// returns a with null /// sources so Program.cs can pass them through to OpcUaApplicationHost /// unchanged — deployments without scripts behave exactly as they did before /// Phase 7. /// /// /// The caller owns the returned /// and must dispose them on shutdown. Engine cascades + timer ticks run off /// background threads until then. /// /// public static class Phase7EngineComposer { public static Phase7ComposedSources Compose( IReadOnlyList