diff --git a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/IMxGatewayClient.cs b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/IMxGatewayClient.cs new file mode 100644 index 00000000..db9eefca --- /dev/null +++ b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/IMxGatewayClient.cs @@ -0,0 +1,79 @@ +using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Protocol; + +namespace ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Adapters; + +/// Connection parameters resolved from the flat config dict. +public record MxGatewayConnectionOptions( + string Endpoint, string ApiKey, string ClientName, int WriteUserId, + bool UseTls, string? CaFile, string? ServerName, int ReadTimeoutMs); + +/// One advised-tag value change pushed from the gateway event stream. +public record MxValueUpdate(string TagPath, object? Value, QualityCode Quality, DateTimeOffset Timestamp); + +/// Per-tag read outcome. +public record MxReadOutcome(string TagPath, bool Success, object? Value, QualityCode Quality, DateTimeOffset Timestamp, string? Error); + +/// Per-tag write outcome. +public record MxWriteOutcome(string TagPath, bool Success, string? Error); + +/// One node in a Galaxy browse level. +public record MxBrowseChild(string NodeId, string DisplayName, BrowseNodeClass NodeClass, bool HasChildren); + +/// +/// Seam over the MxAccess Gateway .NET client + Galaxy repository client. Decouples +/// from the generated gRPC/protobuf types so the +/// adapter is unit-testable with a fake. The real implementation lives in +/// RealMxGatewayClient. +/// +public interface IMxGatewayClient : IAsyncDisposable +{ + /// Opens the gateway session and registers the client (Register → serverHandle held internally). + /// Resolved connection parameters. + /// Cancellation token. + Task ConnectAsync(MxGatewayConnectionOptions options, CancellationToken ct = default); + + /// Closes the session. + /// Cancellation token. + Task DisconnectAsync(CancellationToken ct = default); + + /// AddItem + Advise; returns the gateway item handle (as a string subscription id). + /// Tag address to subscribe to. + /// Cancellation token. + Task SubscribeAsync(string tagPath, CancellationToken ct = default); + + /// UnAdvise + RemoveItem for a previously returned subscription id. + /// Subscription id returned by . + /// Cancellation token. + Task UnsubscribeAsync(string subscriptionId, CancellationToken ct = default); + + /// Snapshot read of one or more tags (ReadBulk). + /// Tag addresses to read. + /// Cancellation token. + Task> ReadAsync(IReadOnlyList tagPaths, CancellationToken ct = default); + + /// Write one or more tag/value pairs (WriteBulk with the configured WriteUserId). + /// Tag/value pairs to write. + /// Cancellation token. + Task> WriteAsync(IReadOnlyList<(string TagPath, object? Value)> writes, CancellationToken ct = default); + + /// One Galaxy browse level (BrowseChildren). null → root. + /// Parent node id (Galaxy contained path), or null for root. + /// Cancellation token. + Task<(IReadOnlyList Children, bool Truncated)> BrowseChildrenAsync(string? parentNodeId, CancellationToken ct = default); + + /// + /// Long-running event consumer. Invokes for each advised-tag + /// data change. Resumes from the last delivered worker sequence on reconnect. Completes + /// (or throws) when the stream ends — the adapter treats that as a disconnect. + /// + /// Callback invoked per advised-tag value change. + /// Cancellation token; ends the loop when cancelled. + Task RunEventLoopAsync(Action onUpdate, CancellationToken ct = default); +} + +/// Builds instances. +public interface IMxGatewayClientFactory +{ + /// Creates a new, unconnected client instance. + IMxGatewayClient Create(); +} diff --git a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/MxGatewayGlobalOptions.cs b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/MxGatewayGlobalOptions.cs new file mode 100644 index 00000000..190f1017 --- /dev/null +++ b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/MxGatewayGlobalOptions.cs @@ -0,0 +1,11 @@ +namespace ZB.MOM.WW.ScadaBridge.DataConnectionLayer; + +/// +/// Deployment-wide MxGateway defaults, bound from the "MxGateway" section of +/// appsettings.json. Per-endpoint behavior lives on MxGatewayEndpointConfig. +/// +public class MxGatewayGlobalOptions +{ + /// Prefix used to derive a per-connection client registration name when the connection's ClientName is blank. + public string ClientNamePrefix { get; set; } = "scadabridge"; +}