review(Driver.S7): reject writable array tags at init instead of silent write failure
Re-review at 7286d320. S7-015 (Medium): a Writable array tag had no WriteArrayAsync path
and silently returned BadCommunicationError on write; now rejected at init with a clear
NotSupportedException (read-only arrays still accepted) + TDD. S7-016 (factory JSON can't
produce array tags; needs AdminUI DTO) deferred.
This commit is contained in:
@@ -378,6 +378,21 @@ public sealed class S7Driver
|
||||
$"S7 tag '{t.Name}' is a Timer/Counter ('{t.Address}') declared Writable — " +
|
||||
"Timer/Counter are read-only this phase; set Writable=false.");
|
||||
}
|
||||
|
||||
// (e) Array tag declared Writable — WriteOneAsync has no WriteArrayAsync path yet
|
||||
// (Driver.S7-015). Without this guard a writable array node is discovered and
|
||||
// accepted, then every write returns BadCommunicationError (InvalidCastException from
|
||||
// BoxValueForWrite receiving a typed array) instead of the informative BadNotSupported
|
||||
// the caller could act on. Wide-type arrays are already rejected above (guard-a); this
|
||||
// targets non-wide types (Int16[], Byte[], Float32[], etc.) that ARE supported for
|
||||
// reading but not yet for writing.
|
||||
if (t.ArrayCount is >= 1 && t.Writable)
|
||||
{
|
||||
throw new NotSupportedException(
|
||||
$"S7 tag '{t.Name}' is a {t.DataType} array (ArrayCount={t.ArrayCount}) declared Writable — " +
|
||||
"array writes are not yet supported by the S7 driver. Set Writable=false for read-only array tags, " +
|
||||
"or split into individual scalar tags until array-write support lands.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1013,6 +1028,15 @@ public sealed class S7Driver
|
||||
|
||||
private async Task WriteOneAsync(Plc plc, S7TagDefinition tag, object? value, CancellationToken ct)
|
||||
{
|
||||
// Defence-in-depth guard for Driver.S7-015: authored array tags are rejected at init
|
||||
// (RejectUnsupportedTagConfigs guard-e), but a transient equipment-tag ref resolved by
|
||||
// _resolver bypasses that path. Both should fail with NotSupportedException → BadNotSupported,
|
||||
// not InvalidCastException → BadCommunicationError from BoxValueForWrite receiving an array.
|
||||
if (tag.ArrayCount is >= 1)
|
||||
throw new NotSupportedException(
|
||||
$"S7 array writes are not yet supported (tag '{tag.Name}'). " +
|
||||
"Use individual scalar tags or set Writable=false for read-only arrays.");
|
||||
|
||||
// Parse the address the same way ReadOneAsync does: authored tags pre-parse at init
|
||||
// (_parsedByName); an equipment-tag ref (resolved transiently) parses on demand. Needed
|
||||
// here so the wide-type write can byte-address the block (the narrow path below addresses
|
||||
|
||||
Reference in New Issue
Block a user