fix(abcip): thread CIP template-instance-id so discovered-UDT expansion works in production (review)
This commit is contained in:
Binary file not shown.
@@ -78,12 +78,19 @@ public static class CipSymbolObjectDecoder
|
||||
var (programScope, simpleName) = SplitProgramScope(name);
|
||||
var dataType = isStruct ? AbCipDataType.Structure : MapTypeCode((byte)typeCode);
|
||||
|
||||
// For a struct symbol the lower 12 bits (typeCode) are NOT a primitive CIP type code —
|
||||
// they are the CIP template instance id (per the bit-15 struct-flag remarks above). Surface
|
||||
// it so the driver can fetch the UDT's Template Object during discovery. Atomic symbols
|
||||
// carry no template id.
|
||||
var templateInstanceId = isStruct ? (uint?)typeCode : null;
|
||||
|
||||
yield return new AbCipDiscoveredTag(
|
||||
Name: simpleName,
|
||||
ProgramScope: programScope,
|
||||
DataType: dataType ?? AbCipDataType.Structure, // unknown type code → treat as opaque
|
||||
ReadOnly: false, // Symbol Object doesn't carry write-protection bits; lift via AccessControl Object later
|
||||
IsSystemTag: isSystem);
|
||||
IsSystemTag: isSystem,
|
||||
TemplateInstanceId: templateInstanceId);
|
||||
|
||||
_ = instanceId; // retained in the wire format for diagnostics; not surfaced to the driver today
|
||||
}
|
||||
|
||||
@@ -45,6 +45,9 @@ public interface IAbCipTagEnumeratorFactory
|
||||
/// reported a 1-D array (even of length 1). Surfaces the tag as an OPC UA array node at
|
||||
/// discovery; <see cref="ElementCount"/> alone can't distinguish a scalar from a 1-element
|
||||
/// array.</param>
|
||||
/// <param name="TemplateInstanceId">The CIP template instance id for a discovered Structure tag
|
||||
/// (<c>null</c> for non-structs / when unknown). Used to fetch the UDT's Template Object shape
|
||||
/// during discovery so the struct can be fanned out into addressable member variables.</param>
|
||||
public sealed record AbCipDiscoveredTag(
|
||||
string Name,
|
||||
string? ProgramScope,
|
||||
@@ -52,7 +55,8 @@ public sealed record AbCipDiscoveredTag(
|
||||
bool ReadOnly,
|
||||
bool IsSystemTag = false,
|
||||
int ElementCount = 1,
|
||||
bool IsArray = false);
|
||||
bool IsArray = false,
|
||||
uint? TemplateInstanceId = null);
|
||||
|
||||
/// <summary>
|
||||
/// No-op enumerator returning an empty sequence. Useful for tests + strict-config
|
||||
|
||||
@@ -45,6 +45,9 @@ internal sealed class LibplctagTagEnumerator : IAbCipTagEnumerator
|
||||
await _tag.ReadAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var buffer = _tag.GetBuffer();
|
||||
// The decoder already surfaces each struct tag's CIP template instance id on
|
||||
// AbCipDiscoveredTag.TemplateInstanceId (from the lower 12 bits of the symbol type), so
|
||||
// re-yielding the decoded records as-is carries it through to DiscoverAsync's UDT fan-out.
|
||||
foreach (var tag in CipSymbolObjectDecoder.Decode(buffer))
|
||||
yield return tag;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user