feat(twincat): 1-D array symbol read via ADS + IsArray discovery

This commit is contained in:
Joseph Doherty
2026-06-16 21:59:17 -04:00
parent 950069392c
commit 3e74239532
7 changed files with 341 additions and 14 deletions
@@ -27,6 +27,10 @@ internal class FakeTwinCATClient : ITwinCATClient
public Dictionary<string, uint> ReadStatuses { get; } = new(StringComparer.OrdinalIgnoreCase);
/// <summary>Gets the write statuses by symbol path.</summary>
public Dictionary<string, uint> WriteStatuses { get; } = new(StringComparer.OrdinalIgnoreCase);
/// <summary>Records the <c>arrayCount</c> argument of the most recent <see cref="ReadValueAsync"/>
/// call (null = scalar read) so Phase 4c array-read tests can assert the driver requested
/// the array with the authored length.</summary>
public int? LastReadArrayCount { get; private set; }
/// <summary>Gets the log of all write operations.</summary>
public List<(string symbol, TwinCATDataType type, int? bit, object? value)> WriteLog { get; } = new();
/// <summary>Gets or sets the result returned by ProbeAsync.</summary>
@@ -55,12 +59,14 @@ internal class FakeTwinCATClient : ITwinCATClient
/// <param name="symbolPath">The path to the symbol to read.</param>
/// <param name="type">The data type of the symbol.</param>
/// <param name="bitIndex">The optional bit index for bit-level reads.</param>
/// <param name="arrayCount">The optional 1-D array element count (null = scalar read).</param>
/// <param name="ct">The cancellation token.</param>
/// <returns>A task that returns the simulated value and status.</returns>
public virtual Task<(object? value, uint status)> ReadValueAsync(
string symbolPath, TwinCATDataType type, int? bitIndex, CancellationToken ct)
string symbolPath, TwinCATDataType type, int? bitIndex, int? arrayCount, CancellationToken ct)
{
if (ThrowOnRead) throw Exception ?? new InvalidOperationException();
LastReadArrayCount = arrayCount;
var status = ReadStatuses.TryGetValue(symbolPath, out var s) ? s : TwinCATStatusMapper.Good;
var value = Values.TryGetValue(symbolPath, out var v) ? v : null;
return Task.FromResult((value, status));