[focas] FOCAS — Multi-path/multi-channel CNC #355

Merged
dohertj2 merged 1 commits from auto/focas/F2-b into auto/driver-gaps 2026-04-25 19:45:29 -04:00
Owner

Summary

Multi-path / multi-channel CNC support for FOCAS — addresses can target a specific path via @N suffix.

  • FocasAddress — new PathId field (default 1) as a 5th positional record field. Parser accepts @N between the address body and any trailing bit/axis marker:
    • R100@3.0 (PMC bit on path 3)
    • PARAM:1815@2/0
    • MACRO:500@2
    • DIAG:280@2/1
    • Validates PathId in [1, 10]. Canonical round-trips the suffix.
  • IFocasClient — two new default-method members: GetPathCountAsync (returns 1) and SetPathAsync (no-op). Transports that haven't extended their wire surface (IPC variant, stubs) keep behaving as single-path.
  • FwlibNative + FwlibFocasClient — P/Invoke for cnc_rdpathnum and cnc_setpath + ODBPATH struct. Single-path controller failures fall back to PathCount=1 rather than throwing.
  • FocasDriverDeviceState gains PathCount and LastSetPath. EnsureConnectedAsync queries GetPathCountAsync after successful connect; resets LastSetPath=0. ReadAsync/WriteAsync check PathId > PathCount (returning BadOutOfRange) and call SetPathAsync only when PathId != 1 AND differs from LastSetPath.

Default PathId=1 preserves all existing behavior — no extra wire calls.

Test plan

  • dotnet build src/ZB.MOM.WW.OtOpcUa.Driver.FOCAS + Shared + Host — clean (0 / 0)
  • dotnet test tests/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Tests309 / 309 passed (18 new in FocasMultiPathTests: parser positive/negative for all 4 area kinds, canonical round-trip, driver dispatch — default path skips SetPath, non-default triggers it, repeat-on-same-path stays at one call, out-of-range returns BadOutOfRange, DIAG threading through both SetPath and ReadDiagnosticAsync)
  • FOCAS Shared.Tests — 24 / 24
  • FOCAS Host.Tests — 13 / 13
  • Integration tests — skipped (live CNC required)

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

Closes #264

## Summary Multi-path / multi-channel CNC support for FOCAS — addresses can target a specific path via `@N` suffix. - **`FocasAddress`** — new `PathId` field (default 1) as a 5th positional record field. Parser accepts `@N` between the address body and any trailing bit/axis marker: - `R100@3.0` (PMC bit on path 3) - `PARAM:1815@2/0` - `MACRO:500@2` - `DIAG:280@2/1` - Validates `PathId in [1, 10]`. Canonical round-trips the suffix. - **`IFocasClient`** — two new default-method members: `GetPathCountAsync` (returns 1) and `SetPathAsync` (no-op). Transports that haven't extended their wire surface (IPC variant, stubs) keep behaving as single-path. - **`FwlibNative` + `FwlibFocasClient`** — P/Invoke for `cnc_rdpathnum` and `cnc_setpath` + `ODBPATH` struct. Single-path controller failures fall back to `PathCount=1` rather than throwing. - **`FocasDriver`** — `DeviceState` gains `PathCount` and `LastSetPath`. `EnsureConnectedAsync` queries `GetPathCountAsync` after successful connect; resets `LastSetPath=0`. `ReadAsync`/`WriteAsync` check `PathId > PathCount` (returning `BadOutOfRange`) and call `SetPathAsync` only when `PathId != 1` AND differs from `LastSetPath`. **Default `PathId=1` preserves all existing behavior — no extra wire calls.** ## Test plan - [x] `dotnet build src/ZB.MOM.WW.OtOpcUa.Driver.FOCAS` + Shared + Host — clean (0 / 0) - [x] `dotnet test tests/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Tests` — **309 / 309 passed** (18 new in `FocasMultiPathTests`: parser positive/negative for all 4 area kinds, canonical round-trip, driver dispatch — default path skips SetPath, non-default triggers it, repeat-on-same-path stays at one call, out-of-range returns BadOutOfRange, DIAG threading through both SetPath and ReadDiagnosticAsync) - [x] FOCAS Shared.Tests — 24 / 24 - [x] FOCAS Host.Tests — 13 / 13 - [ ] Integration tests — skipped (live CNC required) 🤖 Auto-generated by the Mode-B execution loop. Closes #264. Closes #264
dohertj2 added 1 commit 2026-04-25 19:45:25 -04:00
Adds optional `@N` path suffix to FocasAddress (PARAM:1815@2, R100@3.0,
MACRO:500@2, DIAG:280@2/1) with PathId defaulting to 1 for back-compat.
Per-device PathCount is discovered via cnc_rdpathnum at first connect and
cached on DeviceState; reads with PathId>PathCount return BadOutOfRange.
The driver issues cnc_setpath before each non-default-path read and
tracks LastSetPath so repeat reads on the same path skip the wire call.

Closes #264
dohertj2 merged commit 7042b11f34 into auto/driver-gaps 2026-04-25 19:45:29 -04:00
dohertj2 deleted branch auto/focas/F2-b 2026-04-25 19:45:30 -04:00
Sign in to join this conversation.