feat(s7): STRING/WSTRING/CHAR/WCHAR and DTL/DATE/TOD/TIME/S5TIME codecs, TSAP/connection-type override, negotiated PDU surfaced (#632 #288 #289 #294 #295)

New S7DataType members WString/Char/WChar/Dtl/Date/Tod/Time/S5Time mapped onto existing
DriverDataType (String / DateTime / Int32 ms); writes refuse out-of-range with BadOutOfRange.
Optional localTsap/remoteTsap/connectionType through options, factory JSON, probe and AdminUI form.
NegotiatedPduSize snapshotted at connect and exposed via GetDiagnostics (DriverHealth has no bag).

Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
Joseph Doherty
2026-10-08 14:31:44 -04:00
parent d898262c4a
commit 34c52defb3
18 changed files with 1430 additions and 31 deletions
@@ -51,6 +51,27 @@ public sealed class S7DriverOptions
/// </summary>
public short Slot { get; init; } = 0;
/// <summary>
/// Optional override of the LOCAL ISO-TSAP, as two hex bytes <c>"01.00"</c> (also accepted:
/// <c>"0100"</c>, <c>"0x0100"</c>). Null/blank keeps S7.Net's per-CPU default (<c>01.00</c>).
/// Needed for CPUs / gateways that reserve connection resources by TSAP (S7-400H, CP343, LOGO!).
/// </summary>
public string? LocalTsap { get; init; }
/// <summary>
/// Optional override of the REMOTE ISO-TSAP, same text form as <see cref="LocalTsap"/>
/// (e.g. <c>"03.01"</c> = S7-basic resource, rack 0 slot 1). Null/blank keeps the slot-derived default.
/// Mutually exclusive with <see cref="ConnectionType"/>.
/// </summary>
public string? RemoteTsap { get; init; }
/// <summary>
/// Optional connection resource (PG / OP / S7Basic) written into the first byte of the slot-derived
/// remote TSAP, keeping <c>rack × 0x20 + slot</c> as the second byte. Null keeps the default.
/// Mutually exclusive with <see cref="RemoteTsap"/>.
/// </summary>
public S7ConnectionType? ConnectionType { get; init; }
/// <summary>Connect + per-operation timeout.</summary>
public TimeSpan Timeout { get; init; } = TimeSpan.FromSeconds(5);
@@ -197,5 +218,22 @@ public enum S7DataType
Float32,
Float64,
String,
/// <summary>S7 DATE_AND_TIME (DT, 8-byte BCD) → DateTime. The other date/time members below were appended after it.</summary>
DateTime,
/// <summary>S7 WSTRING (UTF-16BE, 4-byte header) → String. <c>StringLength</c> is the declared max in characters (≤ 16382).</summary>
WString,
/// <summary>S7 CHAR (1 byte, Latin-1) → one-character String.</summary>
Char,
/// <summary>S7 WCHAR (UTF-16BE code unit) → one-character String.</summary>
WChar,
/// <summary>S7 DTL (12 bytes, ns resolution) → DateTime.</summary>
Dtl,
/// <summary>S7 DATE (UInt16 days since 1990-01-01) → DateTime.</summary>
Date,
/// <summary>S7 TIME_OF_DAY (UInt32 ms since midnight) → Int32 milliseconds.</summary>
Tod,
/// <summary>S7 TIME (Int32 ms, signed duration) → Int32 milliseconds.</summary>
Time,
/// <summary>S7 S5TIME (BCD + time base) → Int32 milliseconds.</summary>
S5Time,
}