Wire Pause/Stop to the Sud state machine, with a resumable pause
components/sud.py: adds SudState.PAUSED. pause() freezes RAMPING/ HOLDING (the hold countdown and ramp-reached checks both no-op while PAUSED, since they're gated on the exact state they froze); start() now doubles as resume when paused. stop() aborts back to IDLE from any in-progress state, reusing the same reset logic as __init__/ upload() (factored into _reset_run_state()). tasks/sud.py: maps 'Pause'/'Stop' messages to the new methods, and turns the stirrer off on IDLE (not just DONE) so stop() actually silences it instead of leaving the last step's stirring running. client/brewpi_gui.py: wires the Pause/Stop toolbar actions, extends update_sud_actions() so Start doubles as Resume and Stop stays usable while paused, and freezes the forecast plot's progress line for the duration of a pause (tracked via accumulated paused time) instead of letting it drift ahead of actual progress.
This commit is contained in:
+32
-10
@@ -18,6 +18,7 @@ class SudState(Enum):
|
||||
HOLDING = 2
|
||||
WAIT_USER = 3
|
||||
DONE = 4
|
||||
PAUSED = 5
|
||||
|
||||
|
||||
def _merge_defaults(default, override):
|
||||
@@ -55,11 +56,8 @@ class Sud(AttributeChange):
|
||||
(self.name, self.description, self.schedule,
|
||||
self.pot_mass, self.pot_material) = self._parse_data(data)
|
||||
|
||||
self.index = -1
|
||||
self.hold_remaining = 0.0
|
||||
self.state = SudState.IDLE
|
||||
self.step = None
|
||||
self.user_message = None
|
||||
self._paused_from = None
|
||||
self._reset_run_state()
|
||||
|
||||
@staticmethod
|
||||
def _parse_data(data):
|
||||
@@ -78,6 +76,16 @@ class Sud(AttributeChange):
|
||||
|
||||
return name, description, schedule, pot_mass, pot_material
|
||||
|
||||
def _reset_run_state(self):
|
||||
"""Resets run-time progress back to a freshly-loaded, not-yet-started
|
||||
IDLE state. Shared by __init__, upload(), and stop()."""
|
||||
self.index = -1
|
||||
self.hold_remaining = 0.0
|
||||
self.state = SudState.IDLE
|
||||
self.step = None
|
||||
self.user_message = None
|
||||
self._paused_from = None
|
||||
|
||||
def download(self):
|
||||
"""Returns the sud.json document currently on disk, for a client to
|
||||
edit and hand back to upload()."""
|
||||
@@ -100,11 +108,7 @@ class Sud(AttributeChange):
|
||||
with open(self.path, 'w') as f:
|
||||
json.dump(data, f, indent='\t')
|
||||
|
||||
self.index = -1
|
||||
self.hold_remaining = 0.0
|
||||
self.state = SudState.IDLE
|
||||
self.step = None
|
||||
self.user_message = None
|
||||
self._reset_run_state()
|
||||
return True
|
||||
|
||||
def derive_plant_params(self, grain_mass, water_mass):
|
||||
@@ -125,11 +129,29 @@ class Sud(AttributeChange):
|
||||
}
|
||||
|
||||
def start(self):
|
||||
"""Starts a fresh run from IDLE, or resumes a paused one - whichever
|
||||
applies. No-op otherwise."""
|
||||
if self.state == SudState.PAUSED:
|
||||
self.state = self._paused_from
|
||||
self._paused_from = None
|
||||
return
|
||||
if self.state != SudState.IDLE:
|
||||
return
|
||||
self.index = -1
|
||||
self._advance()
|
||||
|
||||
def pause(self):
|
||||
"""Freezes progress (the hold countdown and ramp-reached checks both
|
||||
no-op while PAUSED) without losing where we are; start() resumes."""
|
||||
if self.state in (SudState.RAMPING, SudState.HOLDING):
|
||||
self._paused_from = self.state
|
||||
self.state = SudState.PAUSED
|
||||
|
||||
def stop(self):
|
||||
"""Aborts the run, discarding progress back to IDLE."""
|
||||
if self.state not in (SudState.IDLE, SudState.DONE):
|
||||
self._reset_run_state()
|
||||
|
||||
def confirm(self):
|
||||
if self.state == SudState.WAIT_USER:
|
||||
self._advance()
|
||||
|
||||
Reference in New Issue
Block a user