feat(adminui): Transport dropdown on AbCip/AbLegacy driver forms (live-verified on docker-dev)

- AbCip/AbLegacy driver forms gain a Transport InputSelect; FromOptions/ToOptions now carry
  Transport, so saving any other field no longer silently reverts Native to libplctag.
- Both drivers log the constructed transport once per init.
- AbCip factory now takes the host ILoggerFactory (it ran on NullLogger in production, hiding
  every AbCip log line); DriverFactoryBootstrap passes it.
- Gate results: AdminUI /run (T19) native, inverted (dead port) and libplctag legs.
This commit is contained in:
Joseph Doherty
2026-10-07 19:05:50 -04:00
parent c8b35663e5
commit b8ebafc642
11 changed files with 359 additions and 11 deletions
@@ -187,7 +187,76 @@ see the same split on the press.
## AdminUI /run (T19)
_(pending)_
Run 2026-10-07 on the local docker-dev rig (OrbStack), against the ab_server `controllogix` fixture
on `10.100.0.35:44818`. Every container ran the same freshly built image
(`otopcua-host:dev` `sha256:91bffbb0…`, checked per container because `:9200` round-robins). The
modal was driven with the Chrome tools against `http://localhost:9200/raw`.
**Authoring (UI).**
- Created the AbCip driver `t19-abcip` (`DRV-8ea0f0a8cfde`) in the MAIN cluster.
- Configure → Transport = "Native (managed)" → Save. `DriverInstance.DriverConfig` then held
`"transport":"Native"`, a string.
- Reopened Configure. The dropdown showed "Native (managed)". Changed only Timeout from 2 to 3 and
saved. The row then held `"transport":"Native"` and `"timeout":"00:00:03"`, so the save-reverts-transport
defect is fixed live, not only in unit tests.
- Created device `Device1plc1` with host `ab://10.100.0.35:44818/1,0` (ControlLogix). Test Connect
returned `OK · 62 ms`.
- Added the raw tag `TestDINT` (Int32, read-only, tag path `TestDINT`, DInt).
- Seeded `TestDINT = 4242` on the simulator so a non-zero value proves the read path.
- Raw namespace: `ns=2`, the shared `s=OtOpcUa` root plus RawPath ids. UNS uses `ns=3`.
- RawPath: `t19-abcip/Device1plc1/TestDINT`.
**Leg 1: Native.** The deploy sealed with `acks=6`. Both central nodes logged:
```
AbCip driver DRV-8ea0f0a8cfde initializing: transport=Native tagFactory=NativeAbCipTagFactory
```
CLI read on central-1 (`:4840`) and central-2 (`:4841`):
```
Node: ns=2;s=t19-abcip/Device1plc1/TestDINT
Value: 4242
Status: 0x00000000
```
The simulator value was then changed to 5150 through the libplctag CLI. The native-served node
followed it (`Value: 5150`, `Status: 0x00000000`, source time `23:02:09.60Z`).
**Leg 2: inverted gate (Native, dead port).**
- Device host changed to `ab://10.100.0.35:44819/1,0`. Nothing listens on 44819
(`ss -ltn` count 0).
- The node went `BadNoCommunication` (value retained). A CLI read failed with
`ServiceResultException: [80050000]` (BadCommunicationError). The CLI `read` throws on a Bad
status rather than printing it.
- The central-1 log showed the native error text, raised from `NativeAbCipTagRuntime.ReadAsync`:
```
ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport.AbTransportException: TCP connect to 10.100.0.35:44819 failed: ConnectionRefused
---> System.Net.Sockets.SocketException (111): Connection refused
```
- For contrast, the same dead port under libplctag logged different wording:
```
ZB.MOM.WW.OtOpcUa.Driver.Ab.Transport.AbTransportException: ErrorTimeout
---> libplctag.LibPlcTagException: ErrorTimeout
```
So the switch changes behaviour and is not inert.
**Leg 3: back to libplctag.**
- Device restored to port 44818. Configure → Transport = "libplctag (default)" → Save. The row held
`"transport":"Libplctag"`.
- The redeploy sealed with `acks=6`. Both centrals logged
`initializing: transport=Libplctag tagFactory=LibplctagTagFactory`.
- CLI reads on `:4840` and `:4841`: `Value: 5150`, `Status: 0x00000000`.
**Fix found by the gate.** The first deploy logged no transport line. `AbCipDriverFactoryExtensions.Register`
took no `ILoggerFactory`, and `DriverFactoryBootstrap` registered AbCip without one, so every production
AbCip driver ran on `NullLogger`. That hid the new line and every existing AbCip warning or error. AbCip
now takes the host logger factory the same way AbLegacy and Modbus do. `AbCipTransportInitLogTests` is
falsified by reverting that wiring: 2/2 tests fail.
**Cleanup.**
- The `t19-abcip` driver, device and tag rows were deleted and the change redeployed (sealed,
`acks=6`). Both centrals logged `stopped driver child DRV-8ea0f0a8cfde`.
- The rig has no test driver pointing at the fixture.
- The fixture was brought down (`docker compose --profile controllogix down`).
- The simulator's `TestDINT` was left at 5150 until teardown. The container is gone, so the value
does not persist.
## Real press (T21)