docs(xmldoc): fill missing XML docs + strip tracking-ID comments across src
v2-ci / build (push) Failing after 41s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped

Adds <summary>/<param>/<returns>/<inheritdoc> where missing and removes
project bookkeeping IDs (task/tracking refs) from shipped code comments,
so the docs read cleanly and CommentChecker is quiet except for known
false positives (PLC/protocol terms, event/IEqualityComparer inheritdoc).
Doc/comment-only; no logic changed; solution builds clean.
This commit is contained in:
Joseph Doherty
2026-07-07 12:38:39 -04:00
parent 384dbd7d36
commit 9cad9ed0fc
375 changed files with 1899 additions and 2493 deletions
@@ -84,36 +84,35 @@ public sealed class ModbusDriverOptions
/// <b>Reserved / no-op</b> kill-switch for FC23 (Read/Write Multiple Registers). The
/// driver does not currently emit FC23 — toggling this option has no observable effect
/// today. The slot exists so a future block-read-coalescing enhancement that opts into
/// FC23 can be disabled per-deployment without a code change. Track Driver.Modbus-007
/// for the wiring follow-up. Default <c>false</c>.
/// FC23 can be disabled per-deployment without a code change. Default <c>false</c>.
/// </summary>
public bool DisableFC23 { get; init; } = false;
/// <summary>
/// #151 — interval for the background re-probe loop that retries auto-prohibited
/// coalesced ranges (#148). When non-null, every <c>AutoProhibitReprobeInterval</c>
/// Interval for the background re-probe loop that retries auto-prohibited
/// coalesced ranges. When non-null, every <c>AutoProhibitReprobeInterval</c>
/// the driver attempts each prohibition's coalesced read once. If the re-probe
/// succeeds, the prohibition clears and the planner resumes coalescing across the
/// range on the next scan. Default <c>null</c> = re-probe disabled (prohibitions
/// persist until <c>ReinitializeAsync</c>; preserves pre-#151 behaviour).
/// persist until <c>ReinitializeAsync</c>; preserves the previous behaviour).
/// </summary>
public TimeSpan? AutoProhibitReprobeInterval { get; init; } = null;
/// <summary>
/// Block-read coalescing budget (#143). When non-zero, the read planner combines tags
/// Block-read coalescing budget. When non-zero, the read planner combines tags
/// in the same (UnitId, Region) group whose addresses are at most this many registers
/// apart into a single FC03/FC04/FC01/FC02 read. The sliced response is then dispatched
/// back to per-tag values. Default <c>0</c> = no coalescing — every tag gets its own
/// PDU (preserves pre-#143 behaviour). Typical opt-in values are 5..32 — large enough
/// PDU (preserves the previous behaviour). Typical opt-in values are 5..32 — large enough
/// to bridge a few unused registers, small enough to avoid trampling protected holes.
/// </summary>
public ushort MaxReadGap { get; init; } = 0;
/// <summary>
/// PLC family hint that drives the parser's family-native branch (#144). When set to a
/// PLC family hint that drives the parser's family-native branch. When set to a
/// non-Generic value, address strings using that family's native syntax (DL205 V2000 /
/// MELSEC D100) parse to the right region + offset directly. Defaults to
/// <see cref="ModbusFamily.Generic"/> = Modicon-only behaviour preserved from #137.
/// <see cref="ModbusFamily.Generic"/> = Modicon-only behaviour preserved by default.
/// </summary>
public ModbusFamily Family { get; init; } = ModbusFamily.Generic;
@@ -134,7 +133,7 @@ public sealed class ModbusDriverOptions
/// </summary>
/// <remarks>
/// <para>
/// <b>Driver.Modbus-010 — write-only-tag caveat:</b> the suppression cache is only
/// <b>Write-only-tag caveat:</b> the suppression cache is only
/// invalidated by a <i>read</i> that returns a divergent value. A tag that is never
/// subscribed or polled (write-only setpoints, command registers) never sees its
/// cache entry refreshed — so a value the operator believes was re-asserted is
@@ -176,7 +175,7 @@ public sealed class ModbusDriverOptions
/// <summary>
/// Reconnect backoff settings used by the auto-reconnect path. Default is no backoff
/// (immediate retry — preserves the historical pre-#139 behaviour). Set to a non-zero
/// (immediate retry — preserves the historical behaviour). Set to a non-zero
/// <see cref="ModbusReconnectOptions.InitialDelay"/> to sleep before the first reconnect
/// attempt; <see cref="ModbusReconnectOptions.MaxDelay"/> caps the geometric growth.
/// </summary>
@@ -253,8 +252,8 @@ public sealed class ModbusProbeOptions
/// character in the low byte instead — see <c>docs/v2/dl205.md</c> §strings.
/// </param>
/// <param name="WriteIdempotent">
/// Per <c>docs/v2/plan.md</c> decisions #44, #45, #143 — flag a tag as safe to replay on
/// write timeout / failure. Default <c>false</c>; writes do not auto-retry. Safe candidates:
/// Flags a tag as safe to replay on write timeout / failure. Default <c>false</c>; writes
/// do not auto-retry. Safe candidates:
/// holding-register set-points for analog values and configuration registers where the same
/// value can be written again without side-effects. Unsafe: coils that drive edge-triggered
/// actions (pulse outputs), counter-increment addresses on PLCs that treat writes as deltas,
@@ -273,14 +272,14 @@ public sealed class ModbusProbeOptions
/// array tags. Default null = no deadband (every change publishes).
/// </param>
/// <param name="UnitId">
/// Per-tag UnitId override for multi-slave gateway topology (#142). When non-null this
/// Per-tag UnitId override for multi-slave gateway topology. When non-null this
/// UnitId is used in the MBAP header instead of the driver-level <c>ModbusDriverOptions.UnitId</c>.
/// Defaults to null = use the driver-level value (preserves single-slave deployments).
/// Tags with different UnitIds belong to different physical slaves and the read planner
/// must NOT coalesce them across slaves — even at the same address.
/// </param>
/// <param name="CoalesceProhibited">
/// Escape hatch for #143 block-read coalescing. When <c>true</c>, the planner reads this
/// Escape hatch for block-read coalescing. When <c>true</c>, the planner reads this
/// tag in isolation regardless of <c>ModbusDriverOptions.MaxReadGap</c>. Use when the
/// surrounding registers are write-only or fault on read (some Schneider Premium / Siemens
/// PNs have protected holes). Default <c>false</c>.
@@ -36,13 +36,12 @@ public static class ModbusEquipmentTagParser
var stringLength = (ushort)ReadInt(root, "stringLength");
// Guard: String tags require StringLength >= 1. RegisterCount = (StringLength+1)/2,
// so StringLength=0 → 0 registers → spec-illegal FC03/FC04 with quantity=0 → PLC
// returns exception 03. Reject here (analogous to Driver.Modbus-009 / ValidateStringLength
// returns exception 03. Reject here (analogous to ValidateStringLength
// in the pre-declared tag path) so the driver surfaces BadNodeIdUnknown rather than a
// misleading BadCommunicationError. (Driver.Modbus.Contracts-002)
// misleading BadCommunicationError.
if (dataType == ModbusDataType.String && stringLength < 1) return false;
// Guard: BitInRegister tags require BitIndex 015. Shift by ≥ 16 on an int overflows
// a ushort mask silently — reads always return false, writes have no effect.
// (Driver.Modbus.Contracts-001)
if (dataType == ModbusDataType.BitInRegister && bitIndex > 15) return false;
// isArray / arrayLength — optional keys authored by the typed Modbus tag editor.
// Canonical rule: a tag is an array iff isArray:true AND arrayLength >= 1.