fix: serialize per-pump shutdown + cancel deferred dispatch in turnOffAllMachines
PS calls turnOffAllMachines on every tick once level < stopLevel. Two ways the pump could re-engage after we shut it down: 1. _delayedCall: a 1% dead-zone keep-alive parked in MGC's deferred dispatch fires from the in-flight handleInput's finally block AFTER the shutdown completes, dispatching flow + startup to a fresh pump. Clear _delayedCall at the top of turnOff. 2. Concurrent shutdown calls on the same pump interrupt each other before the sequence can transition past stopping. Track shutdown- in-flight per pump and skip if one is already underway. Together with the rotatingMachine delayedMove-clearing fix, this lets the level-based hysteresis cycle complete: pumps shut off cleanly at stopLevel, basin reverses direction, refills to startLevel, repeat. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1421,8 +1421,28 @@ class MachineGroup {
|
||||
}
|
||||
|
||||
async turnOffAllMachines(){
|
||||
// Cancel any deferred dispatch — turnOff is the latest user intent,
|
||||
// a stale 1% keep-alive must not re-engage a pump after we shut down.
|
||||
this._delayedCall = null;
|
||||
// Per-pump shutdown serialization: PS calls turnOffAllMachines on
|
||||
// every tick (every 2 s) once level < stopLevel. Without this guard,
|
||||
// each new shutdown call hits the still-running prior shutdown's
|
||||
// movement transitions and triggers abortCurrentMovement, which
|
||||
// bounces the pump back to 'operational' before the sequence loop
|
||||
// can reach stopping/coolingdown/idle. Net effect: pump never
|
||||
// actually shuts down. Track shutdown-in-flight per pump and skip
|
||||
// if already underway.
|
||||
if (!this._shutdownInFlight) this._shutdownInFlight = new Set();
|
||||
await Promise.all(Object.entries(this.machines).map(async ([machineId, machine]) => {
|
||||
if (this.isMachineActive(machineId)) { await machine.handleInput("parent", "execsequence", "shutdown"); }
|
||||
if (this._shutdownInFlight.has(machineId)) return;
|
||||
if (this.isMachineActive(machineId)) {
|
||||
this._shutdownInFlight.add(machineId);
|
||||
try {
|
||||
await machine.handleInput("parent", "execsequence", "shutdown");
|
||||
} finally {
|
||||
this._shutdownInFlight.delete(machineId);
|
||||
}
|
||||
}
|
||||
}));
|
||||
// Update measurements to zero so the parent (PS) sees the
|
||||
// outflow drop immediately — without this the PS keeps the
|
||||
|
||||
Reference in New Issue
Block a user