Files
lmxopcua/docs/v2/implementation/exit-gate-phase-3.md
Joseph Doherty 69e0d02c72 task-galaxy-e2e branch — non-FOCAS work-in-progress snapshot
Catch-all commit for pending work on the task-galaxy-e2e branch that
wasn't part of the FOCAS migration. Grouping by topic so future per-topic
commits can be cherry-picked if needed.

TwinCAT
- src/.../Driver.TwinCAT/AdsTwinCATClient.cs + TwinCATDriverFactoryExtensions.cs:
  factory-registration extensions + ADS client refinements.
- src/.../Driver.TwinCAT.Cli/Commands/BrowseCommand.cs: new browse command
  for the TwinCAT test-client CLI.
- tests/.../Driver.TwinCAT.IntegrationTests/TwinCAT3SmokeTests.cs + TwinCatProject/:
  fixture scaffold with a minimal POU + README pointing at the TCBSD/ESXi
  VM for e2e.
- docs/Driver.TwinCAT.Cli.md + docs/drivers/TwinCAT-Test-Fixture.md:
  documentation for the above.
- docs/v3/twincat-backlog.md: forward-looking backlog seed.

Admin UI + fleet status
- src/.../Admin/Components/Pages/Clusters/DriversTab.razor + Hosts.razor:
  UI refresh for fleet-status rendering.
- src/.../Admin/Hubs/FleetStatusHub.cs + FleetStatusPoller.cs +
  Admin/Program.cs: SignalR hub + poller plumbing for live fleet data.
- tests/.../Admin.Tests/FleetStatusPollerTests.cs: poller coverage.

Server + redundancy runtime (Phase 6.3 follow-ups)
- src/.../Server/Hosting/RedundancyPublisherHostedService.cs: HostedService
  that owns the RedundancyStatePublisher lifecycle + wires peer reachability.
- src/.../Server/Redundancy/ServerRedundancyNodeWriter.cs: OPC UA
  variable-node writer binding ServiceLevel + ServerUriArray to the
  publisher's events.
- src/.../Server/Program.cs + Server.csproj: hosted-service registration.
- tests/.../Server.Tests/ServerRedundancyNodeWriterTests.cs +
  Server.Tests.csproj: coverage for the above.

Configuration
- src/.../Configuration/Validation/DraftValidator.cs +
  tests/.../Configuration.Tests/DraftValidatorTests.cs: draft-validation
  refinements.

E2E scripts (shared infrastructure)
- scripts/e2e/README.md + _common.ps1 + test-all.ps1: shared helpers + the
  all-drivers test-all runner.
- scripts/e2e/test-opcuaclient.ps1: OPC UA Client e2e runner.

Docs
- docs/v2/implementation/phase-6-{1,2,3,4}*.md + exit-gate-phase-{3,7}.md:
  phase-gate + implementation doc updates.
- docs/v2/plan.md: top-level plan refresh.
- docs/v2/redundancy-interop-playbook.md: client interop playbook for the
  Phase 6.3 redundancy-runtime work.

Two orphan FOCAS docs remain on disk but deliberately unstaged —
docs/v2/focas-deployment.md and docs/v2/implementation/focas-simulator-plan.md
describe the now-retired Tier-C topology and should either be rewritten
or deleted in a follow-up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 14:12:19 -04:00

10 KiB
Raw Blame History

Phase 3 Exit Gate — Driver Fleet (reconstructed retroactively)

Status: CLOSED (reconstructed 2026-04-23). The original plan split the driver work across Phases 3 / 4 / 5 (Modbus alone → four PLC drivers → two specialty drivers). In execution, all seven non-Galaxy drivers shipped under one umbrella against Core.Abstractions + Core's generic driver-hosting machinery. This doc captures the closure retroactively; no forward work remains under these three original phase numbers.

Plan doc: none — phases 3/4/5 were intentionally not split out into separate plan docs once it was clear the capability-interface contract introduced in Phase 1 (Core.Abstractions — plan decision #4) was stable enough that each driver could land as its own stream rather than as a gated mini-phase. See docs/v2/plan.md §6 for the now-consolidated migration strategy.

Scope

All seven drivers in the v2 target list (Decision #5) minus Galaxy (closed separately under Phase 2). The Galaxy Proxy+Host+Shared split exited under exit-gate-phase-2-final.md; this gate does not re-cover it.

What shipped

Drivers

Driver Project Capability surface Test projects
Modbus TCP Driver.Modbus + Driver.Modbus.Cli IDriver + ITagDiscovery + IReadable + IWritable + ISubscribable + IHostConnectivityProbe Tests, IntegrationTests, Cli.Tests
AB CIP Driver.AbCip + Driver.AbCip.Cli all of the above + IPerCallHostResolver + IAlarmSource Tests, IntegrationTests, Cli.Tests
AB Legacy (PCCC / DF1) Driver.AbLegacy + Driver.AbLegacy.Cli IDriver + IReadable + IWritable + ITagDiscovery + ISubscribable + IHostConnectivityProbe + IPerCallHostResolver Tests, IntegrationTests, Cli.Tests
Siemens S7 Driver.S7 + Driver.S7.Cli IDriver + ITagDiscovery + IReadable + IWritable + ISubscribable + IHostConnectivityProbe Tests, IntegrationTests, Cli.Tests
Beckhoff TwinCAT (ADS) Driver.TwinCAT + Driver.TwinCAT.Cli IDriver + IReadable + IWritable + ITagDiscovery + ISubscribable + IHostConnectivityProbe + IPerCallHostResolver Tests, IntegrationTests, Cli.Tests
FANUC FOCAS Driver.FOCAS + Driver.FOCAS.Host + Driver.FOCAS.Shared + Driver.FOCAS.Cli IDriver + IReadable + IWritable + ITagDiscovery + ISubscribable + IHostConnectivityProbe + IPerCallHostResolver; Tier-C out-of-process backend mirrors the Galaxy Proxy/Host split. Fwlib64FocasBackend shipped 2026-04-23 as the production backend (P/Invoke against Fwlib64.dll); Host retargeted from net48 x86 to net10.0-windows x64 at the same time. Tests, Host.Tests, Shared.Tests, Cli.Tests
OPC UA Client (gateway) Driver.OpcUaClient IDriver + ITagDiscovery + IReadable + IWritable + ISubscribable + IHostConnectivityProbe + IAlarmSource + IHistoryProvider (richest surface in the fleet — it's bridging another UA server) Tests, IntegrationTests

Supporting infrastructure

PR / Task Summary
#248 DriverFactoryRegistry + DriverInstanceBootstrapper — central DB DriverInstance rows materialise into live IDriver instances at server startup.
#210 Modbus server-side factory + seed SQL (closed first child of umbrella #209).
#211 #212 #213 AB CIP / S7 / AB Legacy server-side factories + seed SQL.
#220 (FOCAS) FOCAS factory wired into the bootstrap pipeline; Tier-C split (Driver.FOCAS.Host process launcher, named-pipe IPC, NSSM install scripts, post-mortem MMF) shipped across the five-PR series.
(this session) TwinCAT factory wired in + Server project reference added; all seven driver factories now register uniformly in Server/Program.cs.
#249 #250 #251 Per-driver test-client CLI suite (otopcua-<driver>-cli) — shared lib + one CLI per driver for direct-to-PLC smoke testing independent of the server.
#253 + follow-ups E2E CLI test scripts (scripts/e2e/test-<driver>.ps1) — five-stage bidirectional bridge + subscribe-sees-change assertions per driver, plus test-all.ps1 matrix runner.
(this session) OPC UA Client e2e script shipped (test-opcuaclient.ps1, 8 stages) — the only driver that was missing an e2e script.

Docs

Per-driver test-fixture documentation:

  • docs/drivers/Modbus-Test-Fixture.md
  • docs/drivers/AbServer-Test-Fixture.md (covers AB CIP fixture)
  • docs/drivers/AbLegacy-Test-Fixture.md
  • docs/drivers/S7-Test-Fixture.md
  • docs/drivers/TwinCAT-Test-Fixture.md
  • docs/drivers/FOCAS-Test-Fixture.md
  • docs/drivers/OpcUaClient-Test-Fixture.md

Driver-level ops docs:

  • docs/Driver.Modbus.Cli.md, docs/Driver.AbCip.Cli.md, docs/Driver.AbLegacy.Cli.md, docs/Driver.S7.Cli.md, docs/Driver.TwinCAT.Cli.md, docs/Driver.FOCAS.Cli.md
  • docs/v2/driver-specs.md — unified capability-matrix spec for all eight drivers (Galaxy + seven).

Compliance evidence

No dedicated phase-3-compliance.ps1 exists — scope was too broad to fit the single-script pattern that worked for Phases 6.x and 7. Verification instead takes the form of the per-driver test suites + e2e scripts:

  • Unit tests — every driver has a Tests project with capability-interface contract tests; dotnet test tests/ZB.MOM.WW.OtOpcUa.Driver.*.Tests is green.
  • Integration testsDriver.*.IntegrationTests stands up Docker-hosted simulators (pymodbus, ab_server, python-snap7, opc-plc) at collection init and exercises real wire-level read/write/subscribe/probe per driver.
  • CLI testsDriver.*.Cli.Tests covers the per-driver test-client CLIs (#249#251).
  • E2E scriptsscripts/e2e/test-<driver>.ps1 covers the driver-CLI → PLC → OtOpcUa server → OPC UA client round-trip for all seven drivers + Galaxy; test-all.ps1 aggregates; README status section (rewritten this session) summarises live-boot evidence.
  • Factory registration — all seven factories plus Galaxy register in src/ZB.MOM.WW.OtOpcUa.Server/Program.cs inside the DriverFactoryRegistry composition; the DriverInstanceBootstrapper can materialise any configured row.
  • Seed SQL — #210#213 provide per-driver Config DB seed scripts so a fresh Config DB is populatable without Admin UI interaction.

Live-boot verification

Recorded across the session-level tracking tasks:

Driver Fixture Stages Tracking
Modbus pymodbus (dl205 profile) 5/5 #209 exit gate; bidirectional + subscribe-sees-change added in #253 follow-ups
AB CIP ab_server ControlLogix 5/5 #220
S7 python-snap7 5/5 #220
AB Legacy ab_server SLC500 / MicroLogix / PLC-5 (requires /1,0 cip-path for Docker fixture) 5/5 #222 partial
OPC UA Client opc-plc Docker fixture 5/8 (probe, remote read, forward bridge, subscribe, browse) (this session)
TwinCAT TCBSD VM @ 10.100.0.128 (AmsNetId 41.169.163.43.1.1) — real TwinCAT runtime under FreeBSD on ESXi; bypasses the Hyper-V/RTIME conflict that blocks XAR on this dev box features validated fixture is the TCBSD VM; TWINCAT_TRUST_WIRE=1 still gates the e2e script by default so unintentional runs against cold fixtures don't false-pass
FOCAS Lab-rig CNC + Fwlib64.dll deferredFwlib64FocasBackend shipped 2026-04-23; wire-level live-boot gated FOCAS_TRUST_WIRE=1, lab rig tracked under #222 follow-up
Galaxy Live Galaxy + OtOpcUaGalaxyHost (this dev box) 7/7 (read / write / subscribe / alarms / history) closed under Phase 2

Deferred to post-gate follow-ups

Items intentionally not blocking closure of this umbrella — each is hardware- dependent and tracked separately:

  • FOCAS wire-level live-boottest-focas.ps1 against a real CNC once Fwlib64.dll is on PATH and FOCAS_TRUST_WIRE=1 (#222 follow-up). The Fwlib64FocasBackend shipped 2026-04-23 — code exists, unit-tests green; only the live-CNC smoke test remains.
  • FOCAS Fwlib64FocasBackendCLOSED 2026-04-23. The production backend in src/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Host/Backend/Fwlib64FocasBackend.cs wraps FwlibFocasClient to fulfil IFocasBackend against the licensed Fwlib64.dll. Host project retargeted to net10.0-windows x64. Default when OTOPCUA_FOCAS_BACKEND is unset. 6 new backend tests green. Only wire-level live-boot against real hardware remains — see item above.
  • OPC UA Client stages 5/7/8 — reverse-bridge, alarm, history stages are opt-in via sidecar NodeId params because opc-plc's default image has no writable nodes and doesn't historize. Against a richer upstream (Prosys, UA Expert sample server) all eight stages can run.

Completion checklist

  • Modbus driver shipped + unit + integration + CLI tests green
  • AB CIP driver shipped + tests green + live-boot 5/5
  • AB Legacy driver shipped + tests green + live-boot 5/5
  • S7 driver shipped + tests green + live-boot 5/5
  • TwinCAT driver shipped + tests green + features validated against the TCBSD VM virtual-PLC fixture
  • FOCAS driver shipped (Tier-C split) + tests green (wire-live deferred)
  • OPC UA Client driver shipped + tests green + live-boot 5/8
  • DriverFactoryRegistry + DriverInstanceBootstrapper shipped
  • All seven factories registered in Server/Program.cs
  • Per-driver test-client CLI suite shipped
  • E2E test scripts shipped + test-all.ps1 aggregator green
  • Per-driver test-fixture docs present
  • docs/v2/driver-specs.md unified capability spec present
  • scripts/e2e/README.md status section reflects current live-boot matrix
  • Exit gate doc checked in (this file)
  • TwinCAT validated against the TCBSD VM virtual-PLC fixture — TWINCAT_TRUST_WIRE=1 + e2e script still gated by default to prevent false-pass against cold fixtures
  • FOCAS lab-rig follow-up filed + tracked (#222)

Why no compliance script

The Phases 6.1/6.2/6.3/6.4/7 pattern of a single phase-N-compliance.ps1 worked because each of those phases touched a narrow slice of server-side runtime. A "phase-3-compliance.ps1" would have had to boot seven simulators, configure seven DriverInstance rows, and run seven e2e scripts — which is exactly what scripts/e2e/test-all.ps1 already does. The aggregate runner

  • its README is the compliance artefact for this umbrella.