docs: rotatingMachine trial-ready — submodule bumps, wiki manual, session note
Some checks failed
CI / lint-and-test (push) Has been cancelled

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>
This commit is contained in:
znetsixe
2026-04-13 13:22:10 +02:00
parent 6cf1821161
commit a1aa44f6ca
5 changed files with 385 additions and 3 deletions

View File

@@ -0,0 +1,134 @@
---
title: "Session: rotatingMachine trial-ready — FSM interruptibility, config schema, UX fixes"
created: 2026-04-13
updated: 2026-04-13
status: proven
tags: [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
```bash
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
```