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
@@ -70,6 +70,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="port">The FOCAS/2 TCP port (typically 8193).</param>
/// <param name="timeoutSeconds">Connection timeout in seconds; zero or negative disables the timeout.</param>
/// <param name="cancellationToken">Cancellation token for the connect operation.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
public Task ConnectAsync(
string host,
int port,
@@ -90,6 +91,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="port">The FOCAS/2 TCP port (typically 8193).</param>
/// <param name="timeout">Connection timeout duration; <see cref="TimeSpan.Zero"/> disables the timeout.</param>
/// <param name="cancellationToken">Cancellation token for the connect operation.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
public Task ConnectAsync(
string host,
int port,
@@ -183,6 +185,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Async dispose — sends the close PDU when connected and tears down both sockets.
/// Idempotent.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
public async ValueTask DisposeAsync()
{
await _lifetimeGate.WaitAsync(CancellationToken.None).ConfigureAwait(false);
@@ -218,6 +221,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The CNC identity/sysinfo, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public async Task<FocasResult<WireSysInfo>> ReadSysInfoAsync(
CancellationToken cancellationToken = default,
TimeSpan? timeout = null,
@@ -233,6 +237,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The aggregated CNC status bits, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public async Task<FocasResult<WireStatus>> ReadStatusAsync(
CancellationToken cancellationToken = default,
TimeSpan? timeout = null,
@@ -272,6 +277,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The configured axis name records, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public async Task<FocasResult<IReadOnlyList<WireAxisRecord>>> ReadAxisNamesAsync(
short maxCount = 32,
CancellationToken cancellationToken = default,
@@ -288,6 +294,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The configured spindle name records, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public async Task<FocasResult<IReadOnlyList<WireSpindleRecord>>> ReadSpindleNamesAsync(
short maxCount = 8,
CancellationToken cancellationToken = default,
@@ -308,6 +315,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The fast-poll dynamic snapshot for the axis, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public async Task<FocasResult<WireDynamic>> ReadDynamic2Async(
short axis = 1,
CancellationToken cancellationToken = default,
@@ -353,6 +361,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The servo-meter load percentages, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public async Task<FocasResult<IReadOnlyList<WireServoMeter>>> ReadServoMeterAsync(
short maxCount = 32,
CancellationToken cancellationToken = default,
@@ -387,6 +396,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The per-axis position decimal-place figures, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public async Task<FocasResult<IReadOnlyList<int>>> ReadPositionFiguresAsync(
CancellationToken cancellationToken = default,
TimeSpan? timeout = null,
@@ -413,6 +423,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The per-spindle load percentages, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public Task<FocasResult<IReadOnlyList<WireSpindleMetric>>> ReadSpindleLoadAsync(
short spindleSelector = -1,
CancellationToken cancellationToken = default,
@@ -425,6 +436,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The per-spindle maximum RPMs, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public Task<FocasResult<IReadOnlyList<WireSpindleMetric>>> ReadSpindleMaxRpmAsync(
short spindleSelector = -1,
CancellationToken cancellationToken = default,
@@ -442,6 +454,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The raw parameter payload bytes, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public async Task<FocasResult<byte[]>> ReadParameterBytesAsync(
short dataNumber,
short axis = 0,
@@ -461,6 +474,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The typed parameter value, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public async Task<FocasResult<WireParameter>> ReadParameterAsync(
short dataNumber,
short type = 0,
@@ -481,6 +495,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The typed 8-bit parameter value, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public async Task<FocasResult<byte>> ReadParameterByteAsync(short dataNumber, short axis = 0, CancellationToken cancellationToken = default, TimeSpan? timeout = null, ushort? pathId = null)
{
var result = await ReadParameterBytesAsync(dataNumber, axis, cancellationToken, timeout, pathId).ConfigureAwait(false);
@@ -495,6 +510,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The typed 16-bit parameter value, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public async Task<FocasResult<short>> ReadParameterInt16Async(short dataNumber, short axis = 0, CancellationToken cancellationToken = default, TimeSpan? timeout = null, ushort? pathId = null)
{
var result = await ReadParameterBytesAsync(dataNumber, axis, cancellationToken, timeout, pathId).ConfigureAwait(false);
@@ -509,6 +525,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The typed 32-bit parameter value, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public async Task<FocasResult<int>> ReadParameterInt32Async(short dataNumber, short axis = 0, CancellationToken cancellationToken = default, TimeSpan? timeout = null, ushort? pathId = null)
{
var result = await ReadParameterBytesAsync(dataNumber, axis, cancellationToken, timeout, pathId).ConfigureAwait(false);
@@ -523,6 +540,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The typed single-precision parameter value, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public async Task<FocasResult<float>> ReadParameterFloat32Async(short dataNumber, short axis = 0, CancellationToken cancellationToken = default, TimeSpan? timeout = null, ushort? pathId = null)
{
var result = await ReadParameterBytesAsync(dataNumber, axis, cancellationToken, timeout, pathId).ConfigureAwait(false);
@@ -537,6 +555,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The typed double-precision parameter value, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public async Task<FocasResult<double>> ReadParameterFloat64Async(short dataNumber, short axis = 0, CancellationToken cancellationToken = default, TimeSpan? timeout = null, ushort? pathId = null)
{
var result = await ReadParameterBytesAsync(dataNumber, axis, cancellationToken, timeout, pathId).ConfigureAwait(false);
@@ -550,6 +569,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The macro variable value, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public Task<FocasResult<WireMacro>> ReadMacroAsync(
short number,
CancellationToken cancellationToken = default,
@@ -573,6 +593,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The decoded PMC range values, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public async Task<FocasResult<WirePmcRange>> ReadPmcRangeAsync(
short area,
short dataType,
@@ -601,6 +622,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The decoded PMC range values, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public Task<FocasResult<WirePmcRange>> ReadPmcRangeAsync(
FocasPmcArea area,
FocasPmcDataType dataType,
@@ -621,6 +643,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The active alarm list, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public async Task<FocasResult<IReadOnlyList<WireAlarm>>> ReadAlarmsAsync(
short type = -1,
short count = 32,
@@ -640,6 +663,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The current operation mode, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public Task<FocasResult<FocasOperationMode>> ReadOperationModeAsync(
CancellationToken cancellationToken = default,
TimeSpan? timeout = null,
@@ -657,6 +681,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The raw operation mode code, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public Task<FocasResult<short>> ReadOperationModeCodeAsync(
CancellationToken cancellationToken = default,
TimeSpan? timeout = null,
@@ -670,6 +695,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The executing program name and O-number, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public Task<FocasResult<WireProgramName>> ReadExecutingProgramNameAsync(
CancellationToken cancellationToken = default,
TimeSpan? timeout = null,
@@ -680,6 +706,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The executed block count, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public Task<FocasResult<int>> ReadBlockCountAsync(
CancellationToken cancellationToken = default,
TimeSpan? timeout = null,
@@ -697,6 +724,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <param name="cancellationToken">Cancellation token for the read operation.</param>
/// <param name="timeout">Optional per-call timeout override.</param>
/// <param name="pathId">Optional path ID override; defaults to <see cref="PathId"/>.</param>
/// <returns>The cumulative timer value, wrapped in a <see cref="FocasResult{T}"/>.</returns>
public Task<FocasResult<WireTimer>> ReadTimerAsync(
short type,
CancellationToken cancellationToken = default,
@@ -895,6 +923,9 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// cutting-time payload <c>ac f2 10 00 90 a3 00 00</c> → minute=1110188, msec=41872. See
/// <c>docs/plans/2026-06-25-focas-pdu-v3-30i-b-support.md</c>.
/// </summary>
/// <param name="type">Timer type selector, carried through into the returned <see cref="WireTimer"/>.</param>
/// <param name="payload">The raw 8-byte <c>cnc_rdtimer</c> response payload.</param>
/// <returns>The decoded minute/msec timer value.</returns>
internal static WireTimer ParseTimer(short type, byte[] payload) => new(
type,
payload.Length >= 4 ? BinaryPrimitives.ReadInt32LittleEndian(payload.AsSpan(0, 4)) : 0,
@@ -914,6 +945,10 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// machine's servo-meter screen — confirm magnitude at commissioning. The alignment + name
/// fix here is what removes the gross misaligned garbage.</para>
/// </summary>
/// <param name="svPayload">The raw <c>cnc_rdsvmeter</c> response payload.</param>
/// <param name="axisNamePayload">The raw <c>cnc_rdaxisname</c> response payload used to correlate axis names by index.</param>
/// <param name="maxCount">Maximum number of servo meter records to return.</param>
/// <returns>The decoded servo-meter records.</returns>
internal static IReadOnlyList<WireServoMeter> ParseServoMeters(byte[] svPayload, byte[] axisNamePayload, int maxCount)
{
var result = new List<WireServoMeter>();
@@ -935,6 +970,8 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
}
/// <summary>Byte width of one PMC slot for a FOCAS data-type code: Byte=1, Word=2, Long/Real=4, Double=8.</summary>
/// <param name="dataType">The PMC data width code.</param>
/// <returns>The byte width of one slot for the given data-type code.</returns>
internal static int PmcByteWidth(short dataType) => dataType switch
{
1 => 2,
@@ -950,6 +987,12 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// <c>WireFocasClient.ReadPmcAsync</c>) or a trailing partial slot is dropped — which on the
/// 31i-B surfaced as a spurious <c>BadOutOfRange</c> for a single Word read. 2026-06-25.
/// </summary>
/// <param name="area">The PMC address-letter code numeric value.</param>
/// <param name="dataType">The PMC data width code numeric value.</param>
/// <param name="start">The starting address.</param>
/// <param name="end">The ending address.</param>
/// <param name="payload">The raw <c>pmc_rdpmcrng</c> response payload.</param>
/// <returns>The decoded PMC range values.</returns>
internal static WirePmcRange ParsePmcRange(short area, short dataType, ushort start, ushort end, byte[] payload)
{
var width = PmcByteWidth(dataType);