using ZB.MOM.WW.OtOpcUa.AdminUI.Uns.TagEditors;
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.DeviceForms;
///
/// Typed working model for an S7 Device's connection endpoint (the v3 endpoint→DeviceConfig
/// split). Authors the PascalCase Host/Port/Rack/Slot keys that
/// S7DriverOptions binds — the exact casing the seed and runtime probe
/// (PropertyNameCaseInsensitive) expect. Preserves unrecognised keys across a load→save.
///
public sealed class S7DeviceModel
{
/// PLC host / IP address.
public string Host { get; set; } = "127.0.0.1";
/// ISO-on-TCP port (usually 102).
public int Port { get; set; } = 102;
/// PLC rack number (almost always 0).
public int Rack { get; set; } = 0;
/// PLC slot number (S7-300/400 = 2; S7-1200/1500 = 0).
public int Slot { get; set; } = 0;
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 S7DeviceModel FromJson(string? json)
{
var o = TagConfigJson.ParseOrNew(json);
return new S7DeviceModel
{
Host = TagConfigJson.GetString(o, "Host") ?? "127.0.0.1",
Port = TagConfigJson.GetInt(o, "Port", 102),
Rack = TagConfigJson.GetInt(o, "Rack", 0),
Slot = TagConfigJson.GetInt(o, "Slot", 0),
_bag = o,
};
}
/// Serializes this model back to a DeviceConfig JSON string, writing the PascalCase endpoint
/// keys over the preserved key bag.
/// The serialised DeviceConfig JSON string.
public string ToJson()
{
TagConfigJson.Set(_bag, "Host", Host);
TagConfigJson.Set(_bag, "Port", Port);
TagConfigJson.Set(_bag, "Rack", Rack);
TagConfigJson.Set(_bag, "Slot", Slot);
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()
=> string.IsNullOrWhiteSpace(Host) ? "Host is required." : null;
}