Some checks failed
v2-ci / build (push) Failing after 38s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (push) Has been skipped
OtOpcUaNodeManager + SdkAddressSpaceSink: the v2 IOpcUaAddressSpaceSink
seam now has a production adapter against a real Opc.Ua.Server
CustomNodeManager2. Writes through OpcUaPublishActor's sink materialise
as real OPC UA Variable updates that subscribed clients see via the
standard ClearChangeMasks notification path.
OtOpcUaNodeManager (CustomNodeManager2):
- Owns a ConcurrentDictionary<string, BaseDataVariableState> under a
single namespace (https://zb.com/otopcua/ns) hung off Objects/.
- WriteValue lazy-creates the variable on first write, sets Value +
StatusCode (mapped from OpcUaQuality severity bits) + SourceTimestamp,
then ClearChangeMasks to notify subscribers.
- WriteAlarmState surfaces a [active, acknowledged] pair on a
dedicated node id — full AlarmConditionState/event firing comes
with #85 F14b (EquipmentNodeWalker SDK integration).
- RebuildAddressSpace tears down every registered variable + clears
the dictionary so the next write-pass starts fresh.
- Address-space root folder is materialised in CreateAddressSpace.
SdkAddressSpaceSink: thin IOpcUaAddressSpaceSink → OtOpcUaNodeManager
bridge. Production DI binding (#108) constructs this once the host's
StandardServer has booted.
OtOpcUaSdkServer (StandardServer subclass): overrides
CreateMasterNodeManager to inject OtOpcUaNodeManager via the
MasterNodeManager additionalManagers ctor. NodeManager property
exposes the live instance so OpcUaApplicationHost callers can wrap
it in a sink.
Tests: OpcUaServer 20 -> 24 (+4):
- WriteValue creates + updates variables in the manager
- WriteAlarmState creates a node distinct from value writes
- RebuildAddressSpace clears everything; subsequent writes start fresh
- NullOpcUaAddressSpaceSink no-op sanity
Each test boots a real OpcUaApplicationHost on a free port with the
SDK certificate auto-create flow (F13a) intact — full integration
slice on macOS.
All 6 v2 test suites green: 167 tests passing.
F10 status updated to reflect SDK binding shipped. Residuals:
- #109 OpcUaPublishActor.RebuildAddressSpace → Phase7Applier wiring
- #108 Host DI default to SdkAddressSpaceSink when hasDriver
- #85 F14b EquipmentNodeWalker integration (proper AlarmConditionState
+ folder hierarchy)
- IServiceLevelPublisher SDK binding (writes Server.ServiceLevel node)
28 lines
1.1 KiB
C#
28 lines
1.1 KiB
C#
using Opc.Ua;
|
|
using Opc.Ua.Server;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.OpcUaServer;
|
|
|
|
/// <summary>
|
|
/// <see cref="StandardServer"/> subclass that wires in the v2 <see cref="OtOpcUaNodeManager"/>.
|
|
/// Exposes the live node manager after start so callers (<see cref="OpcUaApplicationHost"/>,
|
|
/// the fused Host's DI binding) can wrap it in a <see cref="SdkAddressSpaceSink"/> and hand
|
|
/// it to <c>OpcUaPublishActor</c>.
|
|
/// </summary>
|
|
public sealed class OtOpcUaSdkServer : StandardServer
|
|
{
|
|
private OtOpcUaNodeManager? _otOpcUaNodeManager;
|
|
|
|
/// <summary>The custom node manager once <c>StartAsync</c> has called
|
|
/// <see cref="CreateMasterNodeManager"/>. Null until the SDK has bootstrapped.</summary>
|
|
public OtOpcUaNodeManager? NodeManager => _otOpcUaNodeManager;
|
|
|
|
/// <inheritdoc />
|
|
protected override MasterNodeManager CreateMasterNodeManager(
|
|
IServerInternal server, ApplicationConfiguration configuration)
|
|
{
|
|
_otOpcUaNodeManager = new OtOpcUaNodeManager(server, configuration);
|
|
return new MasterNodeManager(server, configuration, dynamicNamespaceUri: null, _otOpcUaNodeManager);
|
|
}
|
|
}
|