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
@@ -88,7 +88,7 @@ public sealed class WriteCommand : S7CommandBase
internal static object ParseValue(string raw, S7DataType type)
{
if (type == S7DataType.Bool) return ParseBool(raw);
if (type == S7DataType.String) return raw;
if (type is S7DataType.String or S7DataType.WString or S7DataType.Char or S7DataType.WChar) return raw;
try
{
return type switch
@@ -102,7 +102,11 @@ public sealed class WriteCommand : S7CommandBase
S7DataType.UInt64 => (object)ulong.Parse(raw, CultureInfo.InvariantCulture),
S7DataType.Float32 => (object)float.Parse(raw, CultureInfo.InvariantCulture),
S7DataType.Float64 => (object)double.Parse(raw, CultureInfo.InvariantCulture),
S7DataType.DateTime => (object)DateTime.Parse(raw, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind),
S7DataType.DateTime or S7DataType.Dtl or S7DataType.Date
=> (object)DateTime.Parse(raw, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind),
// TOD / TIME / S5TIME are Int32 milliseconds on the OPC UA side.
S7DataType.Tod or S7DataType.Time or S7DataType.S5Time
=> (object)long.Parse(raw, CultureInfo.InvariantCulture),
_ => throw new CliFx.Exceptions.CommandException($"Unsupported DataType '{type}' for write."),
};
}