[s7] S7 — STRING/WSTRING/CHAR/WCHAR #337

Merged
dohertj2 merged 1 commits from auto/s7/PR-S7-A2 into auto/driver-gaps 2026-04-25 16:28:24 -04:00
Owner

Summary

S7 STRING / WSTRING / CHAR / WCHAR codecs for issue #288.

  • New S7StringCodec static class with encode/decode for each wire format:
    • STRING: 2 + maxLen bytes (header: declared-max byte + actual-len byte) + ASCII payload
    • WSTRING: 4 + 2 × maxLen bytes (two UInt16-BE header words) + UTF-16BE payload
    • CHAR: one ASCII byte
    • WCHAR: two UTF-16BE bytes
  • Firmware-bug handling: header actualLen > maxLen is clamped on read and rejected on write.
  • S7DataType enum gains WString, Char, WChar members alongside existing String. All four map to DriverDataType.String.
  • S7Driver.ReadOneAsync / WriteOneAsync route via Plc.ReadBytesAsync / WriteBytesAsync keyed off the parsed address. Honours S7TagDefinition.StringLength (default 254).

Test plan

  • dotnet build src/ZB.MOM.WW.OtOpcUa.Driver.S7 — clean (0 / 0)
  • dotnet test tests/ZB.MOM.WW.OtOpcUa.Driver.S7.Tests85 / 85 passed (21 new: golden-byte vectors, round-trip per type, header-clamp behavior, length-cap rejection)
  • Integration tests — Snap7-server fixture supports it; not exercised in this PR

🤖 Auto-generated by the Mode-B execution loop. Closes #288.

Closes #288

## Summary S7 STRING / WSTRING / CHAR / WCHAR codecs for issue #288. - New `S7StringCodec` static class with encode/decode for each wire format: - **STRING**: `2 + maxLen` bytes (header: declared-max byte + actual-len byte) + ASCII payload - **WSTRING**: `4 + 2 × maxLen` bytes (two UInt16-BE header words) + UTF-16BE payload - **CHAR**: one ASCII byte - **WCHAR**: two UTF-16BE bytes - **Firmware-bug handling**: header `actualLen > maxLen` is **clamped** on read and **rejected** on write. - `S7DataType` enum gains `WString`, `Char`, `WChar` members alongside existing `String`. All four map to `DriverDataType.String`. - `S7Driver.ReadOneAsync` / `WriteOneAsync` route via `Plc.ReadBytesAsync` / `WriteBytesAsync` keyed off the parsed address. Honours `S7TagDefinition.StringLength` (default 254). ## Test plan - [x] `dotnet build src/ZB.MOM.WW.OtOpcUa.Driver.S7` — clean (0 / 0) - [x] `dotnet test tests/ZB.MOM.WW.OtOpcUa.Driver.S7.Tests` — **85 / 85 passed** (21 new: golden-byte vectors, round-trip per type, header-clamp behavior, length-cap rejection) - [ ] Integration tests — Snap7-server fixture supports it; not exercised in this PR 🤖 Auto-generated by the Mode-B execution loop. Closes #288. Closes #288
dohertj2 added 1 commit 2026-04-25 16:28:20 -04:00
Closes the NotSupportedException cliff for S7 string-shaped types.

- S7DataType gains WString, Char, WChar members alongside the existing
  String entry.
- New S7StringCodec encodes/decodes the four wire formats:
    STRING  : 2-byte header (max-len + actual-len bytes) + N ASCII bytes
              -> total 2 + max_len.
    WSTRING : 4-byte header (max-len + actual-len UInt16 BE) + N×2
              UTF-16BE bytes -> total 4 + 2 × max_len.
    CHAR    : 1 ASCII byte (rejects non-ASCII on encode).
    WCHAR   : 2 UTF-16BE bytes.
  Header-bug clamp: actualLen > maxLen is silently clamped on read so
  firmware quirks don't walk past the wire buffer; rejected on write
  to avoid silent truncation.
- S7Driver.ReadOneAsync / WriteOneAsync issue ReadBytesAsync /
  WriteBytesAsync against the parsed Area / DbNumber / ByteOffset and
  honour S7TagDefinition.StringLength (default 254 = S7 STRING max).
- MapDataType returns DriverDataType.String for the three new enum
  members so OPC UA discovery surfaces them as scalar strings.

Tests: 21 new cases on S7StringCodec covering golden-byte vectors,
encode/decode round-trips, the firmware-bug header-clamp, ASCII-only
guard on CHAR, and the StringLength default. 85/85 passing.

Closes #288
dohertj2 merged commit b751c1c096 into auto/driver-gaps 2026-04-25 16:28:24 -04:00
dohertj2 deleted branch auto/s7/PR-S7-A2 2026-04-25 16:28:25 -04:00
Sign in to join this conversation.