Files
EVOLV/wiki/sessions/2026-04-13-rotatingMachine-trial-ready.md
znetsixe a1aa44f6ca
Some checks failed
CI / lint-and-test (push) Has been cancelled
docs: rotatingMachine trial-ready — submodule bumps, wiki manual, session note
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>
2026-04-13 13:22:10 +02:00

8.2 KiB
Raw Blame History

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
session
rotatingMachine
state-machine
docker
e2e

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/idle transitions while the machine is in accelerating/decelerating, leaving a shutdown command silently dropped. Log symptom: Invalid transition from accelerating to stopping. Transition not executed.
  • Sequence emergencyStop not defined warn appears when a parent orchestrator with the capital-S casing (e.g. machineGroupControl config) forwards the sequence name.
  • Config validator strips functionality.distance and top-level output that buildConfig adds; 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 shutdown or emergencystop is requested from accelerating/decelerating, calls state.abortCurrentMovement(...) and waits up to 2 s for the FSM to return to operational via 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 by buildConfig).

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 idle
  • emergency stop during accelerating reaches off
  • executeSequence 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 key warns: 0 (was 6+ per deploy)
  • acurate typo: 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