664ff75ee2
Read-only live gate on Elma presses Z35474 (TC3 3.1.4024) and Z34834 (TC2 2.11): - Sum-read: every chunk came back BadCommunicationError. Beckhoff's SumRead(IList<IgIoSumReadEntity>) ctor casts to IList<SumDataEntity>, which throws InvalidCastException for a List<> (only an array survives via covariance). The fake-client tests never built a real SumRead. New AdsTwinCATClient.CreateSumRead passes an array; TwinCATSumReadConstructionTests pins it (red on the List form) plus a falsifiability control on the library. After the fix: 59 tags, status identical everywhere, values identical on every non-moving tag, ~0.35-0.66 s vs ~2.7 s per poll; TC2 CE 2.11 answers sum reads. - An unexpected sum chunk failure now logs one Warning per device (it was invisible: the health message was overwritten by the next good read). - Diagnostics: TC2 has no TwinCAT_SystemInfoVarList; fall back to .SYSTEMINFO / .SYSTEMTASKINFOARR[1] once the TC3 name answers not-found (live: all six keys). - #612 browse: Flat verified on TC3 (10,770 leaves; VirtualTree 1,459 strict subset) — comment and docs updated, no load-mode option needed. Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
73 lines
4.9 KiB
Markdown
73 lines
4.9 KiB
Markdown
# TwinCAT driver — v3 backlog
|
||
|
||
The v2 TwinCAT driver is considered solid: 28 integration tests (14 `[TwinCATFact]` +
|
||
16-case `[TwinCATTheory]`) running live against the TCBSD fixture, 110 unit tests,
|
||
three latent driver bugs shaken out (notification cycle units, `STRING(N)` mapper,
|
||
bit-indexed BOOL path). Further work is deferred.
|
||
|
||
Archived from `docs/drivers/TwinCAT-Test-Fixture.md` § Follow-up candidates. Refreshed 2026-10-08
|
||
(Gitea #612 / #645); live-validation results live in `docs/drivers/TwinCAT.md` § "Live validation".
|
||
|
||
## Hardware available (as of 2026-10-08)
|
||
|
||
The Elma cleaner fleet (25 presses, 23 live) is the only real TwinCAT hardware in reach, and it is
|
||
**production — strictly read-only**:
|
||
|
||
| Press | Runtime | AMS | Notes |
|
||
|---|---|---|---|
|
||
| 22 presses (e.g. Z33856 `10.201.45.236.1.1`, Z33733 `5.25.53.46.1.1`) | **TC2 2.11 on WinCE 6.0** | port **801** | read-validated 2026-10-07 |
|
||
| **Z35474** (`5.118.56.93.1.1`, 10.201.23.227) | **TC3 3.1.4024** (Win NT 10) | port **851** | the **only TC3 press**; "Plc30 App" |
|
||
| TCBSD fixture `10.100.0.128` (`41.169.163.43.1.1:851`) | TC3 | 851 | not a press; unreachable from the Mac |
|
||
|
||
Access facts: ADS is TCP 48898. The driver sends no AddRoute (routes are provisioned out of band) and has
|
||
no IP field, so a host needs a local AMS router — TwinCAT XAR, or `Beckhoff.TwinCAT.Ads.TcpRouter` hosted
|
||
in-process (the driver csproj does not reference TcpRouter; the 2026-10-07 run used a scratch harness).
|
||
The Mac reaches the presses directly over the VPN. **Routes (2026-10-08, hw2 live gate):** with the
|
||
user's approval, an `oee-tagdump-mac` route for the Mac's current VPN IP (`10.181.201.108.1.1`) was added
|
||
to **Z35474** (TC3) and **Z34834** (TC2, `5.69.178.220.1.1`, 10.201.45.197) by UDP-48899 AddRoute with the
|
||
factory login. ⚠️ A same-name AddRoute does **not** replace on either runtime: both presses now carry TWO
|
||
`oee-tagdump-mac` entries — the stale `10.181.198.189.1.1` and the new one (route table read back over ADS,
|
||
port 10000 / IG 803). Removing the stale one needs an ADS write and was not done. Every other press still
|
||
has only the stale route, so it refuses the Mac; the VPN IP changes again ⇒ the routes go stale again.
|
||
|
||
## Status of the original items
|
||
|
||
1. **TC2 coverage — DONE (read side).** No longer "blocked on hardware": the 2026-10-07 Elma run
|
||
(TwinCAT 2.11) verified browse, scalar/array/string reads and native notifications on TC2. What is
|
||
still unverified there: sum-read support (see item 6) and anything that writes.
|
||
|
||
2. **Notification coalescing under load** — run the subscribe test while the PLC cycle is saturated.
|
||
Needs the TCBSD fixture (loading a production press is out of the question) and the `GVL_Perf` /
|
||
`FB_PerfChurn` fixture project from the stranded `auto/driver-gaps` branch. Fixture-gated.
|
||
|
||
3. **Multi-hop AMS route** — a test behind an IPC gateway with a chained route entry. No hardware.
|
||
|
||
4. **License-rotation automation** — XAR's 7-day trial expires on schedule. Ops item, not code.
|
||
|
||
5. **Lab rig** — cheapest IPC on a dedicated network; the only route that covers real EtherCAT I/O
|
||
timing and cycle jitter under CPU load. Blocked on hardware + budget.
|
||
|
||
## Added by #612 / #645
|
||
|
||
6. **ADS sum-read (#310) — DONE, live-gated 2026-10-08** on Z35474 (TC3) and Z34834 (TC2 2.11): 59 real
|
||
symbols (BOOL/INT/UINT/DINT/UDINT/USINT/REAL/LREAL/STRING/TIME + 7 value-converted pairs), sum vs single
|
||
bracketed by two single passes, `sumReadMaxItems` 8 (≥ 7 chunks) and 200: identical status on every tag,
|
||
identical value on every tag that did not move between passes; poll 59 tags in ~0.35–0.66 s vs ~2.7 s.
|
||
**TC2 CE 2.11 answers the sum command** (no refusal, no fallback). The gate found the shipped path broken —
|
||
every chunk `BadCommunicationError` because Beckhoff's `SumRead` constructor throws `InvalidCastException` for
|
||
a `List<IgIoSumReadEntity>` (see `AdsTwinCATClient.CreateSumRead`); fixed and pinned by
|
||
`TwinCATSumReadConstructionTests`.
|
||
|
||
7. **Driver diagnostics (#314) — DONE, live-gated 2026-10-08** (opt-in `diagnosticsEnabled`). TC3 Z35474: all six
|
||
keys from `TwinCAT_SystemInfoVarList` (`AppName=Port_851`, cycle 5.0 ms, exec 0.1 ms). TC2 Z34834 has **no**
|
||
`TwinCAT_SystemInfoVarList`; the driver now falls back to `.SYSTEMINFO.PROJECTNAME` / `.ONLINECHANGECOUNT`
|
||
and `.SYSTEMTASKINFOARR[1].CYCLETIME` / `.LASTEXECTIME` (all six keys live: cycle 20.0 ms, exec 0.6 ms).
|
||
|
||
8. **Flat vs VirtualTree browse on TC3 (#612) — DONE, keep Flat.** Z35474: Flat 3,384 roots → 10,770 leaves,
|
||
every struct root carried SubSymbols (0 without); VirtualTree 1,027 roots → 1,459 leaves, a strict subset
|
||
(it loses array-of-struct element members such as `.L_Axis[10].IN._AT.*`). The driver's `DiscoverAsync`
|
||
returned 10,628 variables. No `SymbolsLoadMode` option is needed.
|
||
|
||
9. **Discovered struct/FB member writes (#612)** — deferred: writes, never on a press; fixture-only.
|
||
Likewise **sum-write** was deliberately NOT ported from the stranded branch.
|