Auto: twincat-1.3 — bit-indexed BOOL writes (RMW)
Replace the NotSupportedException at AdsTwinCATClient.WriteValueAsync for bit-indexed BOOL writes with a read-modify-write path: 1. Strip the trailing .N selector from the symbol path. 2. Read the parent as UDINT. 3. Set or clear bit N via the standard mask. 4. Write the parent back. Concurrent bit writers against the same parent serialise through a per-parent SemaphoreSlim cached in a ConcurrentDictionary (never removed — bounded by writable-bit-tag cardinality). Mirrors the AbCip / Modbus / FOCAS bit-RMW pattern shipped in #181 pass 1. The path-stripping (TryGetParentSymbolPath) and mask helper (ApplyBit) are exposed as internal statics so tests can pin the pure logic without needing a real ADS target. The FakeTwinCATClient mirrors the same RMW semantics so driver-level round-trip tests assert the parent-word state. Closes #307
This commit is contained in:
@@ -41,7 +41,25 @@ internal class FakeTwinCATClient : ITwinCATClient
|
||||
{
|
||||
if (ThrowOnWrite) throw Exception ?? new InvalidOperationException();
|
||||
WriteLog.Add((symbolPath, type, bitIndex, value));
|
||||
Values[symbolPath] = value;
|
||||
|
||||
// Model the parent-word RMW path the production AdsTwinCATClient performs for
|
||||
// bit-indexed BOOL writes so driver-level tests can assert the resulting parent state.
|
||||
if (bitIndex is int bit && type == TwinCATDataType.Bool)
|
||||
{
|
||||
var parentPath = AdsTwinCATClient.TryGetParentSymbolPath(symbolPath);
|
||||
if (parentPath is not null)
|
||||
{
|
||||
var current = Values.TryGetValue(parentPath, out var p) && p is not null
|
||||
? Convert.ToUInt32(p) : 0u;
|
||||
Values[parentPath] = AdsTwinCATClient.ApplyBit(
|
||||
current, bit, Convert.ToBoolean(value));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Values[symbolPath] = value;
|
||||
}
|
||||
|
||||
var status = WriteStatuses.TryGetValue(symbolPath, out var s) ? s : TwinCATStatusMapper.Good;
|
||||
return Task.FromResult(status);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user