feat(commons): IOpcUaNodeWriteGateway + NodeWriteOutcome for write-outcome routing
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
namespace ZB.MOM.WW.OtOpcUa.Commons.OpcUa;
|
||||
|
||||
/// <summary>
|
||||
/// Reverse-path gateway for an inbound OPC UA operator write to a writable equipment-tag node.
|
||||
/// The node manager calls <see cref="WriteAsync"/> fire-and-forget from its OnWriteValue handler
|
||||
/// (which runs under the node-manager Lock, so the call MUST return promptly — it kicks off an
|
||||
/// asynchronous route and the Task completes later) and uses the resolved
|
||||
/// <see cref="NodeWriteOutcome"/> to self-correct the node on failure.
|
||||
/// </summary>
|
||||
public interface IOpcUaNodeWriteGateway
|
||||
{
|
||||
/// <summary>Route a write of <paramref name="value"/> to the driver backing node
|
||||
/// <paramref name="nodeId"/>; the returned task resolves with the device-write outcome.</summary>
|
||||
/// <param name="nodeId">The folder-scoped equipment-variable node id being written.</param>
|
||||
/// <param name="value">The value the client wrote.</param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
/// <returns>A task resolving to the device-write outcome.</returns>
|
||||
Task<NodeWriteOutcome> WriteAsync(string nodeId, object? value, CancellationToken ct);
|
||||
}
|
||||
|
||||
/// <summary>Outcome of routing an inbound node write to the backing driver.</summary>
|
||||
/// <param name="Success">True when the driver accepted the write.</param>
|
||||
/// <param name="Reason">Failure detail when <paramref name="Success"/> is false; null on success.</param>
|
||||
public readonly record struct NodeWriteOutcome(bool Success, string? Reason);
|
||||
|
||||
/// <summary>No-op gateway: every write resolves to "writes unavailable" (matches the legacy
|
||||
/// no-router-wired <c>BadNotWritable</c>). The default before the host wires the real gateway.</summary>
|
||||
public sealed class NullOpcUaNodeWriteGateway : IOpcUaNodeWriteGateway
|
||||
{
|
||||
/// <summary>The shared singleton instance.</summary>
|
||||
public static readonly NullOpcUaNodeWriteGateway Instance = new();
|
||||
private NullOpcUaNodeWriteGateway() { }
|
||||
/// <inheritdoc />
|
||||
public Task<NodeWriteOutcome> WriteAsync(string nodeId, object? value, CancellationToken ct) =>
|
||||
Task.FromResult(new NodeWriteOutcome(false, "writes unavailable"));
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.OtOpcUa.Commons.OpcUa;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Commons.Tests.OpcUa;
|
||||
|
||||
public class NullOpcUaNodeWriteGatewayTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task NullGateway_returns_writes_unavailable()
|
||||
{
|
||||
var outcome = await NullOpcUaNodeWriteGateway.Instance.WriteAsync("ns=2;s=x", 1, TestContext.Current.CancellationToken);
|
||||
outcome.Success.ShouldBeFalse();
|
||||
outcome.Reason.ShouldBe("writes unavailable");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user