Auto: abcip-2.3 — descriptions to OPC UA Description

Threads tag/UDT-member descriptions captured by the L5K (#346) and L5X
(#347) parsers through AbCipTagDefinition + AbCipStructureMember into
DriverAttributeInfo, so the address-space builder sets the OPC UA
Description attribute on each Variable node. L5kMember and L5xParser
also now capture per-member descriptions (via the (Description := "...")
attribute block on L5K and the <Description> child on L5X), and
L5kIngest forwards them. DriverNodeManager surfaces
DriverAttributeInfo.Description as the Variable's Description property.

Description is added as a trailing optional parameter on
DriverAttributeInfo (default null) so every other driver continues
to construct the record unchanged.

Closes #231
This commit is contained in:
Joseph Doherty
2026-04-25 18:23:31 -04:00
parent e5b192fcb3
commit e5299cda5a
8 changed files with 248 additions and 11 deletions

View File

@@ -120,6 +120,10 @@ public sealed record AbCipDeviceOptions(
/// and <c>GetString</c> / <c>SetString</c> truncate at the right boundary. <c>null</c>
/// keeps libplctag's default 82-byte STRING behaviour for back-compat. Ignored for
/// non-<see cref="AbCipDataType.String"/> types.</param>
/// <param name="Description">Tag description carried from the L5K/L5X export (or set explicitly
/// in pre-declared config). Surfaces as the OPC UA <c>Description</c> attribute on the
/// produced Variable node so SCADA / engineering clients see the comment from the source
/// project. <c>null</c> leaves Description unset, matching pre-2.3 behaviour.</param>
public sealed record AbCipTagDefinition(
string Name,
string DeviceHostAddress,
@@ -129,7 +133,8 @@ public sealed record AbCipTagDefinition(
bool WriteIdempotent = false,
IReadOnlyList<AbCipStructureMember>? Members = null,
bool SafetyTag = false,
int? StringLength = null);
int? StringLength = null,
string? Description = null);
/// <summary>
/// One declared member of a UDT tag. Name is the member identifier on the PLC (e.g. <c>Speed</c>,
@@ -137,12 +142,18 @@ public sealed record AbCipTagDefinition(
/// <see cref="AbCipTagDefinition"/>. Declaration-driven — the real CIP Template Object reader
/// (class 0x6C) that would auto-discover member layouts lands as a follow-up PR.
/// </summary>
/// <remarks>
/// <see cref="Description"/> carries the per-member comment from L5K/L5X UDT definitions so
/// the OPC UA Variable nodes produced for individual members surface their descriptions too,
/// not just the top-level tag.
/// </remarks>
public sealed record AbCipStructureMember(
string Name,
AbCipDataType DataType,
bool Writable = true,
bool WriteIdempotent = false,
int? StringLength = null);
int? StringLength = null,
string? Description = null);
/// <summary>
/// One L5K-import entry. Either <see cref="FilePath"/> or <see cref="InlineText"/> must be