namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip;
///
/// AB CIP / EtherNet-IP driver configuration, bound from the driver's DriverConfig
/// JSON at DriverHost.RegisterAsync. One instance supports N devices (PLCs) behind
/// the same driver; per-device routing is keyed on
/// via IPerCallHostResolver.
///
///
/// Per v2 plan decisions #11 (libplctag), #41 (AbCip vs AbLegacy split), #143–144 (per-call
/// host resolver + resilience keys), #144 (bulkhead keyed on (DriverInstanceId, HostName)).
///
public sealed class AbCipDriverOptions
{
///
/// PLCs this driver instance talks to. Each device contributes its own
/// string as the hostName key used by resilience pipelines and the Admin UI.
///
public IReadOnlyList Devices { get; init; } = [];
/// Pre-declared tag map across all devices — AB discovery lands in PR 5.
public IReadOnlyList Tags { get; init; } = [];
/// Per-device probe settings. Falls back to defaults when omitted.
public AbCipProbeOptions Probe { get; init; } = new();
///
/// Default libplctag call timeout applied to reads/writes/discovery when the caller does
/// not pass a more specific value. Matches the Modbus driver's 2-second default.
///
public TimeSpan Timeout { get; init; } = TimeSpan.FromSeconds(2);
}
///
/// One PLC endpoint. must parse via
/// ; misconfigured devices fail driver
/// initialization rather than silently connecting to nothing.
///
/// Canonical ab://gateway[:port]/cip-path string.
/// Which per-family profile to apply. Determines ConnectionSize,
/// request-packing support, unconnected-only hint, and other quirks.
/// Optional display label for Admin UI. Falls back to .
public sealed record AbCipDeviceOptions(
string HostAddress,
AbCipPlcFamily PlcFamily = AbCipPlcFamily.ControlLogix,
string? DeviceName = null);
///
/// One AB-backed OPC UA variable. Mirrors the ModbusTagDefinition shape.
///
/// Tag name; becomes the OPC UA browse name and full reference.
/// Which device () this tag lives on.
/// Logix symbolic path (controller or program scope).
/// Logix atomic type, or for UDT-typed tags.
/// When true and the tag's ExternalAccess permits writes, IWritable routes writes here.
/// Per plan decisions #44–#45, #143 — safe to replay on write timeout. Default false.
/// For -typed tags, the declared UDT
/// member layout. When supplied, discovery fans out the UDT into a folder + one Variable per
/// member (member TagPath = {tag.TagPath}.{member.Name}). When null on a Structure
/// tag, the driver treats it as a black-box and relies on downstream configuration to address
/// members individually via dotted syntax. Ignored for atomic types.
/// GuardLogix safety-partition tag hint. When true, the driver
/// forces SecurityClassification.ViewOnly on discovery regardless of
/// — safety tags can only be written from the safety task of a
/// GuardLogix controller; non-safety writes violate the safety-partition isolation and are
/// rejected by the PLC anyway. Surfaces the intent explicitly instead of relying on the
/// write attempt failing at runtime.
public sealed record AbCipTagDefinition(
string Name,
string DeviceHostAddress,
string TagPath,
AbCipDataType DataType,
bool Writable = true,
bool WriteIdempotent = false,
IReadOnlyList? Members = null,
bool SafetyTag = false);
///
/// One declared member of a UDT tag. Name is the member identifier on the PLC (e.g. Speed,
/// Status), DataType is the atomic Logix type, Writable/WriteIdempotent mirror
/// . Declaration-driven — the real CIP Template Object reader
/// (class 0x6C) that would auto-discover member layouts lands as a follow-up PR.
///
public sealed record AbCipStructureMember(
string Name,
AbCipDataType DataType,
bool Writable = true,
bool WriteIdempotent = false);
/// Which AB PLC family the device is — selects the profile applied to connection params.
public enum AbCipPlcFamily
{
ControlLogix,
CompactLogix,
Micro800,
GuardLogix,
}
///
/// Background connectivity-probe settings. Enabled by default; the probe reads a cheap tag
/// on the PLC at the configured interval to drive
/// state transitions + Admin UI health status.
///
public sealed class AbCipProbeOptions
{
public bool Enabled { get; init; } = true;
public TimeSpan Interval { get; init; } = TimeSpan.FromSeconds(5);
public TimeSpan Timeout { get; init; } = TimeSpan.FromSeconds(2);
///
/// Tag path used for the probe. If null, the driver attempts to read a default
/// system tag (PR 8 wires this up — the choice is family-dependent, e.g.
/// @raw_cpu_type on ControlLogix or a user-configured probe tag on Micro800).
///
public string? ProbeTagPath { get; init; }
}