Add incremental material consumption integrator

This commit is contained in:
2026-09-05 04:27:27 +02:00
parent 231e18082c
commit b308b4f545
5 changed files with 342 additions and 0 deletions
+34
View File
@@ -62,6 +62,40 @@ The current Compose file has no application service, so it deliberately does
not pass ENLYZE credentials to TimescaleDB. A future application service should
use `env_file: ./secrets/enlyze.env` rather than copying secrets into Compose.
## Material-consumption integration
`MaterialConsumptionIntegrator` in `calculations` accepts `MaterialSample`
values (timezone-aware timestamp, material rate in kg/h, numeric gate value).
Configure a strict `gate_value > gate_threshold` condition and an explicit,
positive `max_sample_gap_seconds`. Each interval uses the preceding sample's
rate and gate, converting elapsed seconds to hours to accumulate kg. A longer
gap contributes neither consumption nor running time and resets the baseline
to the newer sample. No time before the first or after the last sample is inferred.
Call `process(sample)` or `process_many(samples)` on the same instance for live
input, replay, or successive chunks. Both use the same calculation. The immutable
`state` snapshot exposes cumulative kg, integrated running seconds, last timestamp
(UTC), last rate, last gate, and whether the latest gate is active. State restoration
and persistence are not implemented yet. Naive timestamps and non-finite values
are rejected; backwards timestamps raise without changing state. Duplicate
timestamps add no consumption but replace the baseline in arrival order.
Finite negative material rates are currently accepted and decrease cumulative
consumption during affected integrated intervals. This is intentional generic
behavior for now; machine-specific validation or clamping may be added later
at the input/adapter layer if required by process semantics.
Run `python scripts/validate_k7_material_consumption.py` from the repository root
with the ignored `k7-00842-throughput.raw.json` and `k7-00842-speed.raw.json`
captures in `data/raw/enlyze/`. The utility joins common non-null timestamps
without filling values and rejects unordered or duplicate capture records.
K7-specific signal UUIDs are confined to the utility: `Stundenleistung Anlage`
is gated by `Geschwindigkeit Gesamtanlage > 0.5 m/min`. With the explicit
20-second validation gap limit (`--max-sample-gap-seconds` to override),
2,672 common samples yield **5.205555556 h** and **5,180.127150811 kg** for run
00842, matching the previous manual calculation's rounded results. Synthetic
tests verify equivalence to manual interval integration without local captures
or live ENLYZE access. Production polling, Grafana, and Bento 1 are not implemented.
## Peak-cycle detection
`PeakCycleDetector` is a pure calculation-domain component for roll length,