diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs index f069a77f..c317a8aa 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs +++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs @@ -58,6 +58,9 @@ public sealed class OpcUaPublishActor : ReceiveActor, IWithTimers public sealed record RebuildAddressSpace(CorrelationId Correlation, DeploymentId? DeploymentId = null); /// Inject driver-discovered nodes (FixedTree) under an equipment at runtime (post-connect). + /// The OPC UA NodeId of the equipment root folder to inject the + /// discovered nodes under (e.g. "EQ-3686c0272279"); also the node the NodeAdded model-change is + /// announced under. public sealed record MaterialiseDiscoveredNodes( string EquipmentRootNodeId, IReadOnlyList Folders, @@ -399,10 +402,17 @@ public sealed class OpcUaPublishActor : ReceiveActor, IWithTimers } /// Forwards driver-discovered (FixedTree) nodes to the applier so they are injected under - /// the equipment at runtime. No-op when no applier is wired (dev/Mac/legacy seam), matching the + /// the equipment at runtime. No-op (logged) when no applier is wired (dev/Mac/legacy seam), matching the /// optional-applier tolerance of . private void HandleMaterialiseDiscovered(MaterialiseDiscoveredNodes msg) - => _applier?.MaterialiseDiscoveredNodes(msg.EquipmentRootNodeId, msg.Folders, msg.Variables); + { + if (_applier is null) + { + _log.Debug("OpcUaPublish: no applier wired — discarding MaterialiseDiscoveredNodes for {Equipment}", msg.EquipmentRootNodeId); + return; + } + _applier.MaterialiseDiscoveredNodes(msg.EquipmentRootNodeId, msg.Folders, msg.Variables); + } private void HandleServiceLevelChanged(ServiceLevelChanged msg) {