Auto: focas-f5a — cycle time per part / last cycle delta

Closes #272
This commit is contained in:
Joseph Doherty
2026-04-26 09:11:21 -04:00
parent 45770e8d90
commit e3d7c65f61
7 changed files with 711 additions and 9 deletions

View File

@@ -8,6 +8,47 @@ Power Mate i families. Talks to the controller via the licensed
For range-validation and per-series capability surface see
[`docs/v2/focas-version-matrix.md`](../v2/focas-version-matrix.md).
## Fixed-tree `Production/` projection — issue #258 (F1-b) + issue #272 (F5-a)
Per-device read-only nodes refreshed from the same `cnc_rdparam` /
cycle-timer poll the probe loop already runs. No additional wire calls
are issued for any of these — they are all cache-or-derive reads.
| Node | DataType | Source | Notes |
| --- | --- | --- | --- |
| `Production/PartsProduced` | `Int32` | `cnc_rdparam(6711)` | Active parts-count counter. Wraps to 0 on operator reset. |
| `Production/PartsRequired` | `Int32` | `cnc_rdparam(6712)` | Operator-set target. |
| `Production/PartsTotal` | `Int32` | `cnc_rdparam(6713)` | Lifetime parts counter. |
| `Production/CycleTimeSeconds` | `Int32` | `cnc_rdtimer` (channel 0) | Live cycle-time accumulator. Resets to 0 on next cycle start (CNC-side behaviour). |
| **`Production/LastCycleSeconds`** | **`Float64`** | **derived** | **Plan PR F5-a — seconds for the most recently completed cycle, computed as `CycleTimeSeconds(now) - CycleTimeSeconds(at previous parts-count increment)`. `null` until the second observed parts-count increment establishes a delta. Pure derivation, no new wire calls. See edge-case rules below.** |
| **`Production/LastCycleStartUtc`** | **`DateTime`** *(UTC)* | **derived** | **Plan PR F5-a — UTC wall-clock of the most-recent cycle's start, computed as `nowUtc - LastCycleSeconds`. `null` alongside `LastCycleSeconds` until the second observed increment.** |
### F5-a derivation edge-case rules
- **First observation** establishes the baseline; `LastCycleSeconds` /
`LastCycleStartUtc` stay `null` until the second observed parts-count
increment produces the first delta.
- **Parts-count counter reset** (current value goes backwards, e.g.
shift-change zero) **preserves the last published values** so an
operator reading the tag mid-shift-change sees the last known cycle
duration rather than `null` / Bad. The next positive transition
produces a fresh delta from the new baseline.
- **Cycle-timer rollover** (delta would be negative — e.g. CNC zeroes
the cycle timer at part completion) **leaves the previously-published
values unchanged for one tick** and re-baselines so the next
increment produces a clean delta. The driver does NOT publish a
negative `LastCycleSeconds`.
- **Parts-count jumps `> 1`** (backfill — e.g. counter increments by
3 at once) publish the **timer delta over the window** as
`LastCycleSeconds`. The plan's "delta over the window between
successive parts-count increments" definition does not divide by the
count delta; the value reflects the actual elapsed timer between the
two observations.
- **Reconnect / reinit** clears the derivation state — the prior CNC
session's cycle-timer + parts-count snapshots may be invalidated by
the FWLIB session boundary, so the next post-reconnect probe tick
re-establishes the baseline before the next delta publishes.
## Alarm history (`cnc_rdalmhistry`) — issue #267, plan PR F3-a
`FocasAlarmProjection` exposes two modes via `FocasDriverOptions.AlarmProjection`: