[focas] FOCAS — Bulk PMC range read coalescing #357

Merged
dohertj2 merged 1 commits from auto/focas/F2-d into auto/driver-gaps 2026-04-25 20:04:39 -04:00
Owner

Summary

Bulk PMC range read coalescing for FOCAS — eliminates one TCP RTT per PMC byte at scale.

  • Wire/FocasPmcCoalescer.cs (new) — Plan(IEnumerable<PmcAddressRequest>) groups same-letter / same-path requests into contiguous byte ranges. Cap 256 bytes per group with a 16-byte bridge gap (mirrors the Modbus pattern).
  • IFocasClient.ReadPmcRangeAsync(letter, pathId, startByte, byteCount, ct) — new method with a default per-byte fallback so existing transports keep working.
  • FwlibFocasClient — real implementation that chunks 32-byte FWLIB calls under one logical range.
  • FocasDriver.ReadAsync — new PrefetchPmcRangesAsync pre-pass: build requests → plan groups → issue one ReadPmcRangeAsync per group → slice buffer back to per-tag results via DecodePmcSlice (handles Bit/Byte/Int16/Int32/Float32/Float64 + bit-extract for R100.3-style addresses).
  • Bit-addressed tags coalesce on their parent byte. Single-tag PMC reads bypass the range path.
  • FakeFocasClient updated with RangeReadLog and a PmcByteRanges byte store.

Test plan

  • dotnet build src/ZB.MOM.WW.OtOpcUa.Driver.FOCAS — clean (0 / 0)
  • dotnet test tests/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Tests328 / 328 passed (18 new: contiguous 100B → 1 wire call, range cap split 300B → 2 groups, gap bridging vs splitting, different letters/paths splitting, wider-type contiguity, overlapping requests, bit-addressed shared-byte coalescing, mixed PMC+Parameter+Macro batches, ByteWidth helpers)
  • Integration tests — skipped (live CNC required)

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

Closes #266

## Summary Bulk PMC range read coalescing for FOCAS — eliminates one TCP RTT per PMC byte at scale. - **`Wire/FocasPmcCoalescer.cs`** (new) — `Plan(IEnumerable<PmcAddressRequest>)` groups same-letter / same-path requests into contiguous byte ranges. **Cap 256 bytes** per group with a **16-byte bridge gap** (mirrors the Modbus pattern). - **`IFocasClient.ReadPmcRangeAsync(letter, pathId, startByte, byteCount, ct)`** — new method with a default per-byte fallback so existing transports keep working. - **`FwlibFocasClient`** — real implementation that chunks 32-byte FWLIB calls under one logical range. - **`FocasDriver.ReadAsync`** — new `PrefetchPmcRangesAsync` pre-pass: build requests → plan groups → issue one `ReadPmcRangeAsync` per group → slice buffer back to per-tag results via `DecodePmcSlice` (handles Bit/Byte/Int16/Int32/Float32/Float64 + bit-extract for `R100.3`-style addresses). - Bit-addressed tags coalesce on their parent byte. Single-tag PMC reads bypass the range path. - `FakeFocasClient` updated with `RangeReadLog` and a `PmcByteRanges` byte store. ## Test plan - [x] `dotnet build src/ZB.MOM.WW.OtOpcUa.Driver.FOCAS` — clean (0 / 0) - [x] `dotnet test tests/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Tests` — **328 / 328 passed** (18 new: contiguous 100B → 1 wire call, range cap split 300B → 2 groups, gap bridging vs splitting, different letters/paths splitting, wider-type contiguity, overlapping requests, bit-addressed shared-byte coalescing, mixed PMC+Parameter+Macro batches, ByteWidth helpers) - [ ] Integration tests — skipped (live CNC required) 🤖 Auto-generated by the Mode-B execution loop. Closes #266. Closes #266
dohertj2 added 1 commit 2026-04-25 20:04:34 -04:00
dohertj2 merged commit e879b3ae90 into auto/driver-gaps 2026-04-25 20:04:39 -04:00
dohertj2 deleted branch auto/focas/F2-d 2026-04-25 20:04:39 -04:00
Sign in to join this conversation.