Auto: opcuaclient-10 — auto re-import on ModelChangeEvent

Closes #282
This commit is contained in:
Joseph Doherty
2026-04-26 00:24:24 -04:00
parent eed5857aa9
commit ab3ed6b6a3
8 changed files with 796 additions and 0 deletions

View File

@@ -88,6 +88,41 @@ public sealed class OpcPlcFixture : IAsyncDisposable
}
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
/// <summary>
/// Trigger a model-change event on the upstream simulator by calling its HTTP control
/// surface. Microsoft's <c>opc-plc</c> exposes <c>/AddSlowNode</c> + <c>/AddFastNode</c>
/// methods on the OPC UA <c>OpcPlc</c> object node — the call also fires a
/// <c>GeneralModelChangeEventType</c> notification on the Server node which the driver's
/// model-change watch picks up.
/// </summary>
/// <remarks>
/// <para>
/// <b>TODO</b>: opc-plc's documented HTTP control surface (image v2.x) currently
/// only exposes the <c>--showpnjson</c> publishedNodes endpoint, not a
/// model-change trigger. The OPC UA-method route (<c>OpcPlc/Methods/AddSlowNode</c>)
/// is the supported way to mutate the address space at runtime — and that's exactly
/// what the model-change watch needs to observe. Tests that need an immediate
/// topology change should call this method via <c>IMethodInvoker</c> on the driver
/// under test, OR use a separate raw OPC UA session to invoke the method (avoids
/// coupling the assertion path to the driver-under-test).
/// </para>
/// <para>
/// When opc-plc adds a dedicated HTTP <c>/addtag</c> endpoint, swap the
/// implementation here. Until then this method returns a stub Task so callers can
/// wire the trigger optimistically; the real driving happens through the OPC UA
/// method call in the integration test itself.
/// </para>
/// </remarks>
public Task TriggerModelChangeAsync(string newNodeName, CancellationToken ct)
{
// Stub — see remarks. The integration test that needs a topology change drives
// it via the OPC UA Method-call path instead, since opc-plc's REST surface
// doesn't currently expose a "fire ModelChangeEvent" knob.
_ = newNodeName;
_ = ct;
return Task.CompletedTask;
}
}
[Xunit.CollectionDefinition(Name)]