Bumps: - nodes/generalFunctions 024db55 -> 75d16c6 (FSM abort recovery + schema sync) - nodes/rotatingMachine 07af7ce -> 17b8887 (interruptible sequences, dual-curve tests, rewritten README) Wiki: - wiki/manuals/nodes/rotatingMachine.md — new user manual covering inputs, outputs, state machine, supported curves, and troubleshooting. - wiki/sessions/2026-04-13-rotatingMachine-trial-ready.md — session note with findings, fixes, test additions, and dual-curve E2E results. - wiki/index.md — link both and bump updated date. Status: rotatingMachine is now trial-ready. 91/91 unit tests green, live Docker E2E verifies shutdown/emergency-stop during ramps and prediction behaviour across both shipped pump curves (hidrostal-H05K-S03R, hidrostal-C5-D03R-SHN1). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
8.2 KiB
title, created, updated, status, tags
| title | created | updated | status | tags | |||||
|---|---|---|---|---|---|---|---|---|---|
| Session: rotatingMachine trial-ready — FSM interruptibility, config schema, UX fixes | 2026-04-13 | 2026-04-13 | proven |
|
2026-04-13 — rotatingMachine trial-ready
Scope
Honest review + production-hardening pass on rotatingMachine. Fixes landed on top of the 2026-04-07 hardening and are verified against a Docker-hosted Node-RED stack.
Findings (before fixes)
From a live E2E run captured via the Node-RED debug websocket (/comms):
- Clean startup→operational→shutdown→idle path works to spec: 3 s starting + 2 s warmup + 3 s stopping + 2 s cooldown, matching config exactly.
- Tick cadence: 1000 ms (min 1000, max 1005, avg 1002.5).
- Predictions gate correctly on pressure injection; at 900 mbar Δp the hidrostal-H05K-S03R curve yields a monotonic flow/power response.
- State machine FSM rejects
stopping/coolingdown/idletransitions while the machine is inaccelerating/decelerating, leaving a shutdown command silently dropped. Log symptom:Invalid transition from accelerating to stopping. Transition not executed. - Sequence
emergencyStopnot defined warn appears when a parent orchestrator with the capital-S casing (e.g.machineGroupControlconfig) forwards the sequence name. - Config validator strips
functionality.distanceand top-leveloutputthatbuildConfigadds; every deploy prints removal warnings. - Cosmetic: typo "acurate" in single-side pressure warn; editor lacks unit hints for
speed/startup/ etc.
Fixes
1. Interruptible movement (generalFunctions/src/state/state.js)
moveTo's catch block now detects Movement aborted / Transition aborted errors and transitions the FSM back to operational, unblocking subsequent sequence transitions. A new movementAborted event is emitted for observability.
2. Auto-abort on shutdown/emergency-stop (rotatingMachine/src/specificClass.js)
executeSequence now:
- Normalizes the sequence name to lowercase (defensive against parent callers using mixed case).
- When
shutdownoremergencystopis requested fromaccelerating/decelerating, callsstate.abortCurrentMovement(...)and waits up to 2 s for the FSM to return tooperationalvia the new_waitForOperational(timeoutMs)helper that listens on the state emitter.
3. Config schema sync (generalFunctions/src/configs/rotatingMachine.json)
Added to the schema:
functionality.distance,.distanceUnit,.distanceDescription(produced by the HTML editor).- Top-level
output.process/output.dbase(produced bybuildConfig).
Also reverted an overly broad buildConfig addition to only emit distance (not distanceUnit/distanceDescription) so other nodes aren't forced to add these to their schemas.
4. UX polish
- Fixed typo "acurate" → "accurate" in the single-side pressure warning, plus made the message actionable.
- Added unit hints to Reaction Speed / Startup / Warmup / Shutdown / Cooldown fields in the editor.
- Expanded the Node-RED help panel with a topic reference, state diagram, prediction rules, and port documentation.
Tests added
test/integration/interruptible-movement.integration.test.js — three regression tests for the FSM fix:
shutdown during accelerating aborts the move and reaches idleemergency stop during accelerating reaches offexecuteSequence accepts mixed-case sequence names
test/integration/curve-prediction.integration.test.js — 12 parametrized tests across both shipped pump curves (hidrostal-H05K-S03R and hidrostal-C5-D03R-SHN1):
- Curve loader returns nq + np with matching pressure slices.
- Predicted flow and power at mid-pressure / mid-ctrl are finite and inside the curve envelope.
- Flow is monotonically non-decreasing across a ctrl sweep at fixed pressure.
- Flow decreases (or stays level) when pressure rises at fixed ctrl — centrifugal-pump physics.
- CoG / NCog are computed, finite, and inside [0, 100] controller units.
- Reverse predictor (flow → ctrl via reversed nq) round-trips within 10 % of the known controller position.
test/e2e/curve-prediction-benchmark.py + test/e2e/README.md — live Dockerized Node-RED benchmark that deploys one rotatingMachine per curve and records a (pressure × ctrl) sweep.
Full unit suite: 91/91 passing (was 76/76 on the morning review).
E2E verification (Dockerized Node-RED)
Via /tmp/rm_e2e_verify.py — deploys the example flow to docker compose-hosted Node-RED, drives it via POST /inject/:id, captures port-output via ws://localhost:1880/comms.
| Scenario | Observed state sequence | Pass? |
|---|---|---|
Shutdown fired while accelerating |
starting → warmingup → operational → accelerating → decelerating → stopping → coolingdown → idle | ✅ |
Emergency stop fired while accelerating |
starting → warmingup → operational → accelerating → off | ✅ |
| Clean startup → shutdown (regression) | starting → warmingup → operational → stopping → coolingdown → idle | ✅ |
Container log scan over a 3-minute window:
Unknown keywarns: 0 (was 6+ per deploy)acuratetypo: 0 (was 2)Invalid transition from accelerating/decelerating to ...errors: 0 (was 3+)Sequence '...' not defined: 0 (was 1)
Dual-curve prediction sweep
Via nodes/rotatingMachine/test/e2e/curve-prediction-benchmark.py. Deploys two live rotatingMachines, one per pump curve, and runs a (pressure × ctrl) sweep per pump. Each pump is tested only inside its own curve envelope.
| Pump | Pressures swept (mbar) | Ctrl setpoints (%) | Samples in envelope | Flow monotonic | Flow observed (m³/h) | Power observed (kW) |
|---|---|---|---|---|---|---|
| hidrostal-H05K-S03R | 700 / 2300 / 3900 | 20 / 40 / 60 / 80 | 12/12 ✅ | ✅ | 10.3 – 208.3 | 12.3 – 50.3 |
| hidrostal-C5-D03R-SHN1 | 400 / 1700 / 2900 | 20 / 40 / 60 / 80 | 12/12 ✅ | ✅ | 8.7 – 45.6 | 0.7 – 13.0 |
Inverse-pressure monotonicity (centrifugal-pump physics) also verified: for both pumps, flow at the highest pressure slice is strictly lower than flow at the lowest pressure slice for the same ctrl.
Known limitation captured in the memory file: extrapolating pressure below the curve's minimum slice produces nonsensical flow values (e.g. H05K at 400 mbar ctrl=20% predicts ~30 000 m³/h vs envelope max 227 m³/h). Upstream measurement nodes are expected to clamp sensors to realistic ranges; rotatingMachine itself does not.
Separately, the C5 curve still exhibits the previously-documented power non-monotonicity at p=1700 mbar (sparse-data spline artefact noted in the 2026-04-07 session); this is compensated by the group-optimization marginal-cost refinement loop.
Files changed
nodes/generalFunctions/src/state/state.js # abort recovery
nodes/generalFunctions/src/configs/index.js # buildConfig trim
nodes/generalFunctions/src/configs/rotatingMachine.json # schema sync
nodes/rotatingMachine/src/specificClass.js # exec + typo
nodes/rotatingMachine/rotatingMachine.html # UX hints + help
nodes/rotatingMachine/test/integration/interruptible-movement.integration.test.js # +3 tests (FSM)
nodes/rotatingMachine/test/integration/curve-prediction.integration.test.js # +12 tests (dual curve)
nodes/rotatingMachine/test/e2e/curve-prediction-benchmark.py # new E2E benchmark
nodes/rotatingMachine/test/e2e/README.md # benchmark docs
nodes/rotatingMachine/README.md # rewrite
Production readiness
Status: trial-ready. The caveats flagged in the 2026-04-13 memory file (node_rotatingMachine.md) are resolved. Remaining items are in the wishlist (interruptible curve validation feedback, domain review of ctrl≈0% + backpressure flow prediction, opt-in full-snapshot port-0 mode, per-machine /health endpoint).
Verification command
cd /mnt/d/gitea/EVOLV
docker compose up -d nodered influxdb
cd nodes/rotatingMachine && npm test
python3 /tmp/rm_e2e_verify.py # end-to-end smoke