fix: shutdown clears delayedMove so abort+autoPickup can't re-engage pump

When PS commanded turnOffAllMachines, executeSequence's interruptible
abort path triggered transitionToState('operational'), which auto-picked
up the queued delayedMove and re-started the pump. Pump bounced
accelerating ↔ decelerating forever and never reached idle.

Clear state.delayedMove at the top of shutdown/emergencystop sequences
so a user-commanded stop cancels any pending move.

Observed live: in pumpingstation-complete-example the basin drained
past stopLevel and equilibrated at ~0.3 m with one pump stuck at min
flow. With this fix pumps shut down cleanly at stopLevel.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rene De Ren
2026-05-09 18:17:45 +02:00
parent 5a8113a9d1
commit 8f9150e160
2 changed files with 84 additions and 1 deletions

View File

@@ -885,13 +885,22 @@ _callMeasurementHandler(measurementType, value, position, context) {
return;
}
// A shutdown/emergency-stop must cancel any pending move. Without this,
// the abort path below (returnToOperational=true) lets state.transitionToState
// auto-pick up state.delayedMove as soon as it lands in 'operational',
// which re-engages the pump on every shutdown attempt — pump bounces
// forever between accelerating and decelerating and never reaches idle.
const interruptible = new Set(["shutdown", "emergencystop"]);
if (interruptible.has(sequenceName)) {
this.state.delayedMove = null;
}
// Interruptible movement: if a shutdown or emergency-stop is requested
// while a setpoint move is mid-flight (accelerating/decelerating), abort
// the move first and wait briefly for the FSM to return to 'operational'.
// Without this, transitions like accelerating->stopping are rejected by
// stateManager.isValidTransition, leaving the machine running.
const currentState = this.state.getCurrentState();
const interruptible = new Set(["shutdown", "emergencystop"]);
if (interruptible.has(sequenceName) &&
(currentState === "accelerating" || currentState === "decelerating")) {
this.logger.warn(`Sequence '${sequenceName}' requested during '${currentState}'. Aborting active movement.`);