feat(ablegacy): PCCC multi-element file array read + IsArray discovery
This commit is contained in:
@@ -267,7 +267,17 @@ public sealed class AbLegacyDriver : IDriver, IReadable, IWritable, ITagDiscover
|
||||
await runtime.ReadAsync(cancellationToken).ConfigureAwait(false);
|
||||
status = runtime.GetStatus();
|
||||
var parsed = AbLegacyAddress.TryParse(def.Address);
|
||||
value = status == 0 ? runtime.DecodeValue(def.DataType, parsed?.BitIndex) : null;
|
||||
// Phase 4c #137 — when the tag addresses a multi-element span (ArrayLength > 1)
|
||||
// decode the whole contiguous read into a typed CLR array; otherwise decode a
|
||||
// single scalar value as before. The runtime was created with a matching
|
||||
// ElementCount in EnsureTagRuntimeAsync so its buffer holds all the elements.
|
||||
var arrayLen = EffectiveArrayLength(def);
|
||||
if (status != 0)
|
||||
value = null;
|
||||
else if (arrayLen > 1)
|
||||
value = runtime.DecodeArray(def.DataType, arrayLen);
|
||||
else
|
||||
value = runtime.DecodeValue(def.DataType, parsed?.BitIndex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -428,19 +438,20 @@ public sealed class AbLegacyDriver : IDriver, IReadable, IWritable, ITagDiscover
|
||||
string.Equals(t.DeviceHostAddress, device.HostAddress, StringComparison.OrdinalIgnoreCase));
|
||||
foreach (var tag in tagsForDevice)
|
||||
{
|
||||
// Driver.AbLegacy-013 (tracked follow-up) — PCCC files are inherently arrays of
|
||||
// elements (a single N7 file is up to 256 words), but the current tag-definition
|
||||
// surface only addresses one element. IsArray/ArrayDim are hard-wired false/null
|
||||
// until multi-element addressing lands; tags that genuinely span a range have to
|
||||
// be enumerated one element at a time today. This is consistent with the
|
||||
// PR-staged scope documented in docs/v2/driver-specs.md (AbLegacy ships with thin
|
||||
// array coverage); when array support is added, ArrayCount on the tag definition
|
||||
// will flow through here as it already does on the Modbus driver.
|
||||
// Phase 4c #137 — PCCC data files are inherently arrays of elements (a single N7
|
||||
// file is up to 256 words). A tag whose ArrayLength addresses a multi-element span
|
||||
// now materialises a 1-D array OPC UA node. ArrayDim is clamped to the PCCC file
|
||||
// maximum (AbLegacyArray.MaxElements = 256) so the declared dimension can never
|
||||
// exceed what a single data file holds; an ArrayLength of 1 (or null) stays scalar.
|
||||
var isArray = tag.ArrayLength is int len && len > 1;
|
||||
var arrayDim = isArray
|
||||
? (uint)Math.Min(tag.ArrayLength!.Value, AbLegacyArray.MaxElements)
|
||||
: (uint?)null;
|
||||
deviceFolder.Variable(tag.Name, tag.Name, new DriverAttributeInfo(
|
||||
FullName: tag.Name,
|
||||
DriverDataType: tag.DataType.ToDriverDataType(),
|
||||
IsArray: false,
|
||||
ArrayDim: null,
|
||||
IsArray: isArray,
|
||||
ArrayDim: arrayDim,
|
||||
SecurityClass: tag.Writable
|
||||
? SecurityClassification.Operate
|
||||
: SecurityClassification.ViewOnly,
|
||||
@@ -674,6 +685,16 @@ public sealed class AbLegacyDriver : IDriver, IReadable, IWritable, ITagDiscover
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Phase 4c #137 — the effective libplctag element count for a tag definition: the tag's
|
||||
/// <see cref="AbLegacyTagDefinition.ArrayLength"/> clamped to the PCCC file maximum
|
||||
/// (<see cref="AbLegacyArray.MaxElements"/> = 256), or <c>1</c> when the tag is scalar
|
||||
/// (null or non-positive ArrayLength). Used both to size the runtime at create time and to
|
||||
/// decide whether the read path decodes a scalar or an array.
|
||||
/// </summary>
|
||||
private static int EffectiveArrayLength(AbLegacyTagDefinition def) =>
|
||||
def.ArrayLength is int len && len > 1 ? Math.Min(len, AbLegacyArray.MaxElements) : 1;
|
||||
|
||||
private async Task<IAbLegacyTagRuntime> EnsureTagRuntimeAsync(
|
||||
DeviceState device, AbLegacyTagDefinition def, CancellationToken ct)
|
||||
{
|
||||
@@ -698,7 +719,11 @@ public sealed class AbLegacyDriver : IDriver, IReadable, IWritable, ITagDiscover
|
||||
CipPath: device.EffectiveCipPath,
|
||||
LibplctagPlcAttribute: device.Profile.LibplctagPlcAttribute,
|
||||
TagName: parsed.ToLibplctagName(),
|
||||
Timeout: _options.Timeout));
|
||||
Timeout: _options.Timeout,
|
||||
// Phase 4c #137 — multi-element PCCC file read. A multi-element span (ArrayLength
|
||||
// > 1) creates the libplctag tag with that element count so a single read fetches
|
||||
// the whole array from the base address; scalar tags pass 1 and read unchanged.
|
||||
ElementCount: EffectiveArrayLength(def)));
|
||||
try
|
||||
{
|
||||
await runtime.InitializeAsync(ct).ConfigureAwait(false);
|
||||
|
||||
Reference in New Issue
Block a user