Merge #608/#602/#596: stale WaveC TODOs resolved, FOCAS/TwinCAT factory logging, Modbus health asymmetry documented, AbCip browsePageDelayMs field, Device1 by-design

Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
Joseph Doherty
2026-10-08 06:53:59 -04:00
17 changed files with 192 additions and 50 deletions
+6
View File
@@ -48,6 +48,12 @@ settings; the device's `DeviceConfig` holds host/port/endpoint. At deploy/probe
connect (inside the **Device** modal) probes that merged config. Driver forms no longer
serialize the endpoint keys, so `DeviceConfig` is the single source of truth.
**Creating a driver auto-creates an empty `Device1` (by design, #596).** Every driver needs at least one
device to hang browse and tags off, and for a single-device driver the merger treats that device's
`DeviceConfig` as the endpoint, so an empty, renamable, deletable `Device1` is the lowest-friction start
(`RawTreeService.CreateDriverAsync`; pinned by `RawTreeServiceWaveBTests`). It is not a placeholder to be
removed later.
## Authoring tags
**Add tags ▸** on a Device or TagGroup offers:
+1 -2
View File
@@ -247,8 +247,7 @@ The driver has two interchangeable wire transports, selected by one `DriverConfi
bench controller exists.
- Native browse (#572, resolved in code): listing paging no longer assumes ascending instance order, pages
are paced, and a browse's template reads share one lease. One residual: whether a real controller ever
lists a page out of order is unobserved — the reader is now correct either way. `browsePageDelayMs` has no AdminUI form field; author it in
the driver-config JSON (the form preserves keys it does not model, #576).
lists a page out of order is unobserved — the reader is now correct either way. `browsePageDelayMs` is an AdminUI driver-form field ("Browse page delay (ms)", #596); keys the form does not model are preserved on save (#576).
- Micro800, routed and `logixpccc` paths are covered by `ab_server` only. The Micro800 profile passes
natively. The AbLegacy default excludes `logixpccc` (and PLC-5).
- Follow-up issues for this workstream: #564 to #577.
+1
View File
@@ -149,3 +149,4 @@ and the UI authoring flow.
- **`WriteOnChangeOnly` + write-only tags** — the suppression cache is only invalidated by a read that returns a divergent value. A tag that is never subscribed/polled never refreshes its cache entry, so a re-asserted value can be suppressed indefinitely. Subscribe every tag that needs deterministic re-writes, or leave the option off.
- **Auto-prohibited ranges** are visible via `GetAutoProhibitedRanges` and logged on first occurrence / on clear — use them to find protected register holes in a device's map.
- **Int64 / UInt64 OPC UA node DataType** — tags declared with `DataType: Int64` or `DataType: UInt64` advertise the correct OPC UA scalar type (`Int64` / `UInt64`) on their node. Values outside the 32-bit range are preserved end-to-end; the wire codec (4-register read/write) was already correct before this fix.
- **Health is per-tag, last-writer-wins — a deliberate asymmetry (#602).** Unlike the S7 read/write passes, which accumulate one worst-state-wins outcome per batch, `ModbusDriver` stamps `ReadHealth`/`WriteHealth` (Volatile) per tag as the loop runs. This is intentional: the comms-loss watchdog keys on `LastSuccessfulRead`, which any success advances and `Degraded`/`Faulted` writes preserve, so a late healthy tag cannot mask a dead device, and a per-pass accumulator would add risk to the `Degraded` latch semantics (CLAUDE.md "Comms-loss detection") for no observable gain. Revisit only if a test shows a defect.