diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client.Contracts/WonderwareHistorianClientOptions.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client.Contracts/WonderwareHistorianClientOptions.cs index 77488ed9..57e190eb 100644 --- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client.Contracts/WonderwareHistorianClientOptions.cs +++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client.Contracts/WonderwareHistorianClientOptions.cs @@ -40,4 +40,20 @@ public sealed record WonderwareHistorianClientOptions( [Display(Name = "Probe timeout (seconds)", Description = "Connection test timeout. Default 15s.", GroupName = "Diagnostics")] [Range(1, 60)] public int ProbeTimeoutSeconds { get; init; } = 15; + + /// Sidecar TCP host (DNS name or IP). Required for the TCP transport. + public string? Host { get; init; } + + /// Sidecar TCP port (matches the sidecar's OTOPCUA_HISTORIAN_TCP_PORT). + public int Port { get; init; } + + /// When true, the client wraps the TCP stream in TLS before the Hello handshake. + public bool UseTls { get; init; } + + /// + /// Optional SHA-1 thumbprint (hex, no spaces) the client pins the sidecar's TLS server + /// cert against. When null/empty and is true, the client validates + /// the cert chain normally (CA-issued cert). + /// + public string? ServerCertThumbprint { get; init; } } diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client.Tests/WonderwareHistorianClientOptionsTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client.Tests/WonderwareHistorianClientOptionsTests.cs new file mode 100644 index 00000000..6f56032c --- /dev/null +++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client.Tests/WonderwareHistorianClientOptionsTests.cs @@ -0,0 +1,38 @@ +using Shouldly; +using Xunit; + +namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client.Tests; + +/// +/// Unit tests for TCP/TLS fields. +/// +public sealed class WonderwareHistorianClientOptionsTests +{ + [Fact] + public void TcpTlsFields_AreStoredCorrectly_WhenExplicitlySet() + { + var opts = new WonderwareHistorianClientOptions("pipe", "secret") + { + Host = "h", + Port = 32569, + UseTls = true, + ServerCertThumbprint = "AB" + }; + + opts.Host.ShouldBe("h"); + opts.Port.ShouldBe(32569); + opts.UseTls.ShouldBeTrue(); + opts.ServerCertThumbprint.ShouldBe("AB"); + } + + [Fact] + public void TcpTlsFields_HaveCorrectDefaults_WhenNotSet() + { + var opts = new WonderwareHistorianClientOptions("pipe", "secret"); + + opts.Host.ShouldBeNull(); + opts.Port.ShouldBe(0); + opts.UseTls.ShouldBeFalse(); + opts.ServerCertThumbprint.ShouldBeNull(); + } +}