Auto: s7-c1 — surface negotiated PDU size via DriverHealth.Diagnostics

Closes #294
This commit is contained in:
Joseph Doherty
2026-04-26 00:35:49 -04:00
parent f469cf7e0d
commit 6540bbe1ef
6 changed files with 165 additions and 1 deletions

View File

@@ -98,6 +98,21 @@ public sealed class S7Driver(S7DriverOptions options, string driverInstanceId)
private long _totalMultiVarBatches; // Plc.ReadMultipleVarsAsync calls issued
private long _totalSingleReads; // per-tag ReadOneAsync fallbacks
/// <summary>
/// Negotiated PDU size from the most recent <see cref="Plc.OpenAsync"/>. Snapshotted
/// once into a field so the diagnostics dictionary keeps a stable reading even after
/// the underlying <c>Plc</c> instance is closed (e.g. mid-reinit). Resets to 0 on
/// <see cref="ShutdownAsync"/> so a stale post-disconnect reading never confuses an
/// operator inspecting the driver-diagnostics panel.
/// </summary>
private int _negotiatedPduSize;
/// <summary>
/// Test-only entry point for the negotiated PDU size that's surfaced via
/// <see cref="DriverHealth.Diagnostics"/> as <c>S7.NegotiatedPduSize</c>.
/// </summary>
internal int NegotiatedPduSize => _negotiatedPduSize;
/// <summary>
/// Total <c>Plc.ReadBytesAsync</c> calls the coalesced byte-range path issued.
/// Test-only entry point for the integration assertion that 50 contiguous DBWs
@@ -160,8 +175,13 @@ public sealed class S7Driver(S7DriverOptions options, string driverInstanceId)
await plc.OpenAsync(cts.Token).ConfigureAwait(false);
Plc = plc;
// S7netplus exposes the PDU size negotiated during the COTP/S7comm handshake on
// Plc.MaxPDUSize. Snapshot once so the diagnostics surface (S7.NegotiatedPduSize)
// doesn't have to dereference Plc on every BuildDiagnostics() call. Default S7-1500
// CPUs negotiate 240 bytes; CPUs running the extended PDU advertise 480 or 960.
_negotiatedPduSize = plc.MaxPDUSize;
_health = new DriverHealth(DriverState.Healthy, DateTime.UtcNow, null);
_health = new DriverHealth(DriverState.Healthy, DateTime.UtcNow, null, BuildDiagnostics());
// Kick off the probe loop once the connection is up. Initial HostState stays
// Unknown until the first probe tick succeeds — avoids broadcasting a premature
@@ -204,6 +224,9 @@ public sealed class S7Driver(S7DriverOptions options, string driverInstanceId)
try { Plc?.Close(); } catch { /* best-effort — tearing down anyway */ }
Plc = null;
// Reset the snapshot so a post-shutdown diagnostics read doesn't display a stale
// PDU size from the previous connection. Reinit will repopulate after OpenAsync.
_negotiatedPduSize = 0;
_health = new DriverHealth(DriverState.Unknown, _health.LastSuccessfulRead, null);
return Task.CompletedTask;
}
@@ -422,6 +445,10 @@ public sealed class S7Driver(S7DriverOptions options, string driverInstanceId)
["S7.TotalBlockReads"] = Interlocked.Read(ref _totalBlockReads),
["S7.TotalMultiVarBatches"] = Interlocked.Read(ref _totalMultiVarBatches),
["S7.TotalSingleReads"] = Interlocked.Read(ref _totalSingleReads),
// Negotiated PDU size from the COTP/S7comm handshake — 240 bytes on a default
// S7-1500 CPU, 480 or 960 on CPUs running the extended PDU. 0 before connect /
// after shutdown so an operator can tell the driver isn't currently online.
["S7.NegotiatedPduSize"] = _negotiatedPduSize,
};
/// <summary>