[s7] S7 — DTL/DT/S5TIME/TIME/TOD/DATE codecs #338

Merged
dohertj2 merged 1 commits from auto/s7/PR-S7-A3 into auto/driver-gaps 2026-04-25 16:40:04 -04:00

1 Commits

Author SHA1 Message Date
Joseph Doherty
2b66cec582 Auto: s7-a3 — DTL/DT/S5TIME/TIME/TOD/DATE codecs
Adds S7DateTimeCodec static class implementing the six Siemens S7 date/time
wire formats:

  - DTL (12 bytes): UInt16 BE year + month/day/dow/h/m/s + UInt32 BE nanos
  - DATE_AND_TIME (8 bytes BCD): yy/mm/dd/hh/mm/ss + 3-digit BCD ms + dow
  - S5TIME (16 bits): 2-bit timebase + 3-digit BCD count → TimeSpan
  - TIME (Int32 ms BE, signed) → TimeSpan, allows negative durations
  - TOD (UInt32 ms BE, 0..86399999) → TimeSpan since midnight
  - DATE (UInt16 BE days since 1990-01-01) → DateTime

Mirrors the S7StringCodec pattern from PR-S7-A2 — codecs operate on raw byte
spans so each format can be locked with golden-byte unit tests without a
live PLC. New S7DataType members (Dtl, DateAndTime, S5Time, Time, TimeOfDay,
Date) are wired into S7Driver.ReadOneAsync/WriteOneAsync via byte-level
ReadBytesAsync/WriteBytesAsync calls — S7.Net's string-keyed Read/Write
overloads have no syntax for these widths.

Uninitialized PLC buffers (all-zero year+month for DTL/DT) reject as
InvalidDataException → BadOutOfRange to operators, rather than decoding as
year-0001 garbage.

S5TIME / TIME / TOD surface as Int32 ms (DriverDataType has no Duration);
DTL / DT / DATE surface as DriverDataType.DateTime.

Test coverage: 30 new golden-vector + round-trip + rejection tests,
including the all-zero buffer rejection paths and BCD-nibble validation.
Build clean, 115/115 S7 tests pass.

Closes #289

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 16:37:39 -04:00