using ZB.MOM.WW.OtOpcUa.AdminUI.Uns.TagEditors; namespace ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.DeviceForms; /// /// Typed working model for an OPC UA Client Device's connection endpoint. Authors the PascalCase /// EndpointUrl key that OpcUaClientDriverOptions binds. (The driver-level EndpointUrls /// failover list stays on the driver config; a device's EndpointUrl is used only when that list /// is empty.) Preserves unrecognised keys across a load→save. /// public sealed class OpcUaClientDeviceModel { /// The single upstream server endpoint URL (opc.tcp://…). public string EndpointUrl { get; set; } = "opc.tcp://localhost:4840"; private System.Text.Json.Nodes.JsonObject _bag = new(); /// Loads a model from a DeviceConfig JSON string, defaulting absent keys and retaining /// every original key so fields this editor doesn't expose survive a load→save. /// The raw DeviceConfig JSON string, or null for a new/empty device. /// The populated . public static OpcUaClientDeviceModel FromJson(string? json) { var o = TagConfigJson.ParseOrNew(json); return new OpcUaClientDeviceModel { EndpointUrl = TagConfigJson.GetString(o, "EndpointUrl") ?? "opc.tcp://localhost:4840", _bag = o, }; } /// Serializes this model back to a DeviceConfig JSON string, writing the PascalCase /// EndpointUrl key over the preserved key bag. /// The serialised DeviceConfig JSON string. public string ToJson() { TagConfigJson.Set(_bag, "EndpointUrl", EndpointUrl); return TagConfigJson.Serialize(_bag); } /// Validation hook; returns an error message or null when the model is valid. /// An error message describing the validation failure, or null when the model is valid. public string? Validate() { if (string.IsNullOrWhiteSpace(EndpointUrl)) return "Endpoint URL is required."; if (!EndpointUrl.Trim().StartsWith("opc.tcp://", StringComparison.OrdinalIgnoreCase)) return "Endpoint URL must start with opc.tcp://"; return null; } }