using Opc.Ua; using Opc.Ua.Server; using ZB.MOM.WW.OtOpcUa.Commons.OpcUa; namespace ZB.MOM.WW.OtOpcUa.OpcUaServer; /// /// subclass that wires in the v2 . /// Exposes the live node manager after start so callers (, /// the fused Host's DI binding) can wrap it in a and hand /// it to OpcUaPublishActor. /// public sealed class OtOpcUaSdkServer : StandardServer { private OtOpcUaNodeManager? _otOpcUaNodeManager; /// The custom node manager once StartAsync has called /// . Null until the SDK has bootstrapped. public OtOpcUaNodeManager? NodeManager => _otOpcUaNodeManager; /// /// Wire the reverse-path sink for inbound Part 9 alarm method calls onto the created /// . The host calls this after start with a non-blocking /// mediator.Tell that publishes each onto the /// alarm-commands DistributedPubSub topic. No-op (returns false) when the node /// manager has not been created yet, so the caller can detect a too-early call. /// /// The router invoked by the condition handlers once the AlarmAck /// gate passes; may be null to clear it. /// true when the router was set on a live node manager; false when no node /// manager exists yet. public bool SetAlarmCommandRouter(Action? router) { if (_otOpcUaNodeManager is null) return false; _otOpcUaNodeManager.AlarmCommandRouter = router; return true; } /// protected override MasterNodeManager CreateMasterNodeManager( IServerInternal server, ApplicationConfiguration configuration) { _otOpcUaNodeManager = new OtOpcUaNodeManager(server, configuration); return new MasterNodeManager(server, configuration, dynamicNamespaceUri: null, _otOpcUaNodeManager); } }