139 lines
7.3 KiB
Markdown
139 lines
7.3 KiB
Markdown
# Bento 1 fresh bentonite consumption
|
||
|
||
`config/bento1-material-consumption.yaml` defines
|
||
`bento1-fresh-bentonite-consumption`, an estimate of **fresh bentonite consumption**
|
||
from actual spreader roll speeds. Both needle rolls apply sequentially across the
|
||
full web width. The recycled/recovered third spreader is excluded.
|
||
|
||
The generic `rotational_discharge` source converts one or more rpm signals to the
|
||
existing integrator's kg/h: `sum(rpm) × nominal_width_m × specific_discharge_kg_per_rev_m × 60`.
|
||
Bento config sets the factor to **3.12 kg/(rev·m)** and uses:
|
||
|
||
- Right ACT: `6e5d2d94-98f9-4cc1-8a88-7987c6282525`
|
||
- Left ACT: `cd7385c4-337b-4759-ab32-45d65beaf190`
|
||
|
||
ENLYZE now returns physical rpm directly (scaling factor 1.0); no division by
|
||
1000 is applied. For 3.739 + 3.956 rpm and 5 m width, the rate is 120.042 kg/min
|
||
(7202.52 kg/h), giving 20.007 kg in ten seconds.
|
||
|
||
Transport speed `fef41976-1103-4090-b780-eaeecc02fdfa` is exclusively the
|
||
production gate: speed must be strictly greater than 0.3 m/min. It does not
|
||
multiply the mass rate. The generic rotational mode also supports omitting
|
||
`gate_signal_ref` and `gate_threshold`, in which case all valid intervals are
|
||
active. Bento retains its gate.
|
||
|
||
The two old SET sources `19ea65d2-bd35-4d02-89de-4495583d9026` and
|
||
`d9f47615-69cf-4f97-88df-199585764491` are no longer requested by Bento.
|
||
`direct_mass_rate` remains the default for K7; `area_application` remains
|
||
available for other configurations. There is no Bento branch in the integrator.
|
||
|
||
The previous-value integration, JSON state format and order bootstrap/resume
|
||
remain unchanged. Totals accumulate across disjoint runs, with a new baseline
|
||
at each run boundary, even if the inter-run gap is under 20 seconds. Intervals
|
||
up to 20 seconds use the preceding rate and gate; longer sample gaps and
|
||
unobserved run tails are not integrated. Missing/nonfinite source values reject
|
||
the cycle. Finite negative speeds retain the existing generic signed-rate
|
||
semantics; no clamping is introduced.
|
||
|
||
Width comes from the existing ERP nominal-width parser, with workplace
|
||
`Bento 1` and order format `Bento 1-{production_order}`. Workplace comparisons
|
||
use `strip().casefold()`; order matching remains strict. Missing/mismatched ERP
|
||
context or an unparseable width rejects the cycle without saving state. The
|
||
current ERP context supplies width for all runs of the same order, assuming
|
||
constant article width. Historical orders no longer in the ERP workplace view
|
||
need a historical width source for replay.
|
||
|
||
The configured factor is based on the supplied independent historical checks:
|
||
3.1175 at 5.00 m (article 180305), 3.1193 and 3.1187 at 4.85 m (article 173000),
|
||
and median 3.1208 at 5.00 m (article 180005; p05–p95 3.0703–3.1558).
|
||
Tests use realistic rpm values and synthetic samples, including disjoint-run
|
||
bootstrap and persisted resume. They are not a new replay of recorded ENLYZE data.
|
||
|
||
## Old calculation cleanup: review before execution
|
||
|
||
No production state or database rows were changed during this implementation,
|
||
and no service start was requested. The operator reports Bento stopped;
|
||
sandbox systemd access could not independently confirm that state.
|
||
The deployed `/etc/systemd/system/production-analytics-bento1.service` specifies
|
||
`/opt/git-projects/production-analytics/data/state/material` as its state directory.
|
||
|
||
The existing state file for machine `5f42a4f6-9ca0-4f6f-9786-40d50a35b230`
|
||
and order `Bento 1-12026000857` is exactly:
|
||
|
||
```text
|
||
/opt/git-projects/production-analytics/data/state/material/4d6cc209e35bc58887e5b4a3816835006425429e810e0d957f651971723e8c2f.json
|
||
```
|
||
|
||
This identity was verified using the store's SHA-256 of the JSON machine/order
|
||
pair. The file exists but its contents are not readable by the sandbox user.
|
||
The other state file, `6d11088159b8e4fd21543560a54a31a0f86faf22bbf8f16873b228d1903c23f9.json`,
|
||
has not been attributed here and must be left untouched.
|
||
|
||
Old PostgreSQL snapshots are in `material_consumption_snapshots`, scoped by both
|
||
`calculation_id = 'bento1-fresh-bentonite-consumption'` and
|
||
`machine_id = '5f42a4f6-9ca0-4f6f-9786-40d50a35b230'`.
|
||
The table has no calculation-source/version provenance column. Given the stopped
|
||
service and no rpm deployment yet, existing rows in this scope belong to the old
|
||
calculation. PostgreSQL was unreachable from the sandbox, so exact row counts,
|
||
order/run membership and timestamp bounds remain unverified. Do not mistake
|
||
this predicate for a completed row inventory. Review the following output first.
|
||
|
||
Run these **read-only inventory commands** on the deployment host:
|
||
|
||
```sh
|
||
cd /opt/git-projects/production-analytics
|
||
sudo systemctl is-active production-analytics-bento1.service
|
||
sudo cat data/state/material/4d6cc209e35bc58887e5b4a3816835006425429e810e0d957f651971723e8c2f.json
|
||
sudo docker compose exec -T timescaledb psql -U production_analytics -d production_analytics -v ON_ERROR_STOP=1 <<'SQL'
|
||
BEGIN READ ONLY;
|
||
SELECT production_order, run_id, count(*) AS rows,
|
||
min(timestamp) AS first_snapshot, max(timestamp) AS last_snapshot,
|
||
min(consumption_kg), max(consumption_kg)
|
||
FROM material_consumption_snapshots
|
||
WHERE calculation_id = 'bento1-fresh-bentonite-consumption'
|
||
AND machine_id = '5f42a4f6-9ca0-4f6f-9786-40d50a35b230'
|
||
GROUP BY production_order, run_id ORDER BY first_snapshot;
|
||
SELECT * FROM material_consumption_snapshots
|
||
WHERE calculation_id = 'bento1-fresh-bentonite-consumption'
|
||
AND machine_id = '5f42a4f6-9ca0-4f6f-9786-40d50a35b230'
|
||
ORDER BY production_order, timestamp;
|
||
COMMIT;
|
||
SQL
|
||
```
|
||
|
||
After reviewing the inventory, and **only with cleanup authorization**, keep the
|
||
service stopped and execute this backup-and-delete transaction. The backup table
|
||
intentionally has no `IF NOT EXISTS`: a repeated invocation fails rather than
|
||
reusing an older backup. Only rows with the backed-up primary keys are deleted.
|
||
K7 rows are outside the predicate.
|
||
|
||
```sh
|
||
cd /opt/git-projects/production-analytics
|
||
sudo docker compose exec -T timescaledb psql -U production_analytics -d production_analytics -v ON_ERROR_STOP=1 <<'SQL'
|
||
BEGIN;
|
||
CREATE TABLE bento1_material_snapshots_before_rpm_20260907 AS
|
||
SELECT * FROM material_consumption_snapshots
|
||
WHERE calculation_id = 'bento1-fresh-bentonite-consumption'
|
||
AND machine_id = '5f42a4f6-9ca0-4f6f-9786-40d50a35b230';
|
||
DELETE FROM material_consumption_snapshots AS s
|
||
USING bento1_material_snapshots_before_rpm_20260907 AS old
|
||
WHERE s.calculation_id = old.calculation_id AND s.machine_id = old.machine_id
|
||
AND s.production_order = old.production_order AND s.timestamp = old.timestamp;
|
||
COMMIT;
|
||
SQL
|
||
sudo mv -n -- \
|
||
data/state/material/4d6cc209e35bc58887e5b4a3816835006425429e810e0d957f651971723e8c2f.json \
|
||
data/state/material/4d6cc209e35bc58887e5b4a3816835006425429e810e0d957f651971723e8c2f.json.before-rpm-20260907
|
||
```
|
||
|
||
Verify the original JSON path is absent before restarting; `mv -n` preserves an
|
||
existing backup and will not overwrite it. If inventory reveals other Bento
|
||
orders, derive their paths with `JsonMaterialStateStore._path(machine, order)`
|
||
and review any existing files before moving them too. Do not clear the shared
|
||
directory. Complete both state and snapshot cleanup before starting the new
|
||
code: the state schema deliberately does not detect a changed source model.
|
||
|
||
A later start bootstraps only the currently open order using its current ERP
|
||
width. It does not automatically rebuild snapshots for closed historical
|
||
orders. Reconstructing those requires a separately reviewed historical replay.
|