using System.Text.Json; using System.Text.Json.Serialization; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client; /// /// Driver probe for the -shaped driver config. /// The Wonderware Historian client communicates over a Windows named pipe (not a TCP socket), /// so a cheap TCP-connect probe is not applicable for this transport. This probe always /// returns a well-formed "not applicable" result so the AdminUI can display a meaningful /// message instead of a red error. A full named-pipe connect + Hello-frame probe is a /// documented follow-up. /// public sealed class WonderwareHistorianDriverProbe : IDriverProbe { private static readonly JsonSerializerOptions _opts = new() { PropertyNameCaseInsensitive = true, UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip, }; /// public string DriverType => "Historian.Wonderware"; /// public Task ProbeAsync(string configJson, TimeSpan timeout, CancellationToken ct) { // Validate the config JSON can at least be parsed — surface bad JSON immediately. WonderwareHistorianClientOptions? opts; try { opts = JsonSerializer.Deserialize(configJson, _opts); } catch (Exception ex) { return Task.FromResult(new DriverProbeResult(false, $"Config JSON is invalid: {ex.Message}", null)); } if (opts is null) return Task.FromResult(new DriverProbeResult(false, "Config JSON deserialized to null.", null)); // The Wonderware Historian sidecar communicates over a Windows named pipe; there is no // TCP endpoint to connect to. A full pipe connect + Hello-frame probe is a follow-up. return Task.FromResult(new DriverProbeResult( false, "TCP probe not applicable for this transport — the Historian sidecar uses a named pipe. " + "A full named-pipe probe is a documented follow-up.", null)); } }