Merge b647-twincat: ADS sum-read (opt-in) + TwinCAT diagnostics on /hosts (#645 #310/#314, #612 docs)
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
+48
-1
@@ -185,9 +185,56 @@ notifications; `DInt` over a `STRING(80)` → `BadTypeMismatch` in both paths wi
|
||||
the rest of the subscription Good. No PLC value held a genuine non-ASCII string
|
||||
to exercise Windows-1252 live — that rule is unit-tested only.
|
||||
|
||||
## Sum-read and diagnostics (Gitea #645)
|
||||
|
||||
Two items ported from the stranded `auto/driver-gaps` branch (#310, #314), re-implemented against the
|
||||
current raw-byte read path rather than cherry-picked (the branch predates the type guard, the string codec
|
||||
and the array codec). Unit-tested against the fake client only; the live gate is read-only and pending a
|
||||
route (see `docs/v3/twincat-backlog.md`).
|
||||
|
||||
### Sum-read (opt-in)
|
||||
|
||||
`useSumRead: true` (default **off**) batches a poll's reads for one device into ADS sum-read commands
|
||||
(`IndexGroup 0xF080`) of at most `sumReadMaxItems` symbols (default 200, ceiling 500) and at most 32 KiB of
|
||||
payload (read lengths + 4 bytes each) instead of one round-trip per tag. TC2 CE 2.11 support for the sum
|
||||
command is unverified, hence opt-in.
|
||||
|
||||
- **Eligibility is strict.** The sum path reads raw bytes at the symbol's index group / offset and decodes them
|
||||
as the DECLARED type (the notification rules), so a scalar rides the batch only when it passes
|
||||
`TwinCATTypeGuard.CheckNotification` — same width, same float/integer kind. A tag the lenient single read
|
||||
accepts by value conversion (`DInt` over a PLC `INT`, `Real` over `LREAL` or `DINT`) is read **individually**
|
||||
inside the call, keeping the Beckhoff conversion; the batch never publishes reinterpreted bytes at Good.
|
||||
Arrays use the same raw-bytes rule as on the single path. A type-mismatched item gets `BadTypeMismatch`
|
||||
without joining the batch; a bit-indexed BOOL and a handle-addressed symbol (`0xF005`) are read singly.
|
||||
- Per-item ADS error codes map to that tag only (`MapAdsError`); a response shorter than asked is a size error
|
||||
for that item, not a failed chunk. The overall code is the command's.
|
||||
- **Latch vs read-singly.** Only overall ADS **1793 / 1794** (service / index group not supported) throws
|
||||
`TwinCATSumReadRefusedException`; the driver logs once, marks the device `SumReadUnsupported` and reads
|
||||
singly until re-initialise. **Any other non-comms overall code** (1792 general error, 1795 offset, 1797 size, 1798 data, ...) means
|
||||
*this request* was rejected — typically too big — so that chunk is read singly for this poll, nothing is
|
||||
latched, and a Warning is logged once per device so the live gate can see sum-read is not working there. A
|
||||
comms-level failure (router / port / timeout) is neither: that chunk goes `BadCommunicationError` and the next poll tries again.
|
||||
- A one-item chunk is just a single read. Sum-**write** is not implemented (writes stay per-tag).
|
||||
|
||||
### `/hosts` diagnostics (`IDriverDiagnostics`, opt-in)
|
||||
|
||||
Behind `diagnosticsEnabled` (default **off** — not yet live-gated). The driver implements the optional
|
||||
`IDriverDiagnostics` bag (the S7 `NegotiatedPduSize` precedent, #640), deliberately not synthetic raw tags.
|
||||
When enabled, after each healthy probe tick **and after the host-state transition** it reads up to four
|
||||
`TwinCAT_SystemInfoVarList` symbols per device — `_AppInfo.AppName`, `_AppInfo.OnlineChangeCnt`,
|
||||
`_TaskInfo[1].CycleTime`, `_TaskInfo[1].LastExecTime` (100 ns ticks) — so up to **4 extra read requests per
|
||||
device per probe interval** (default 5 s). The ADS state is the one `ProbeAsync` already read; no second
|
||||
ReadState. One device: flat keys `TwinCAT.AdsState`, `.AppName`, `.OnlineChangeCnt`, `.CycleTimeMs`,
|
||||
`.LastExecTimeMs`, `.HeadroomMs` (cycle − last exec; negative = the task overran; this is spare time, not
|
||||
jitter). Several devices: one line per device, `TwinCAT.<DeviceName or host>` =
|
||||
`Run; Plc30 App; online-changes 7; cycle 10.0 ms; exec 2.5 ms; headroom 7.5 ms`, so the host's 16-entry cap
|
||||
covers 16 devices. Times round to 0.1 ms (the bag's digest is in the publish fingerprint). Each symbol is
|
||||
best-effort: a runtime that does not export one (older TC2) keeps the others, and a symbol answering "not
|
||||
found" is not re-asked until a new client is installed (reconnect).
|
||||
|
||||
## Capability surface
|
||||
|
||||
`TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery, ISubscribable, IHostConnectivityProbe, IPerCallHostResolver, IRediscoverable`
|
||||
`TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery, ISubscribable, IHostConnectivityProbe, IPerCallHostResolver, IRediscoverable, ISkippedTagReporter, IDriverDiagnostics`
|
||||
(`src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATDriver.cs`).
|
||||
|
||||
| Capability | Path | Notes |
|
||||
|
||||
Reference in New Issue
Block a user