Fix elapsed showing --:-- at DONE, and energy not reset on restart
sud_elapsed_seconds is intentionally reset to None once a run leaves a running state (it gates the forecast plot's dynamic-vs-static view switch) - but the status bar/Progress tab reused it too, so they lost the final total exactly when it mattered most: right as the run finished. Added sud_elapsed_last, which only ever gets overwritten by a real 'Elapsed' push and is reset on a fresh Start/Load, for those two displays to use instead. Separately, a fresh Start (restarting an already-loaded, now IDLE/ DONE schedule) never sent a new Load, so SudTask's energy bookkeeping - previously only reset in the Load handler - kept showing the previous run's banked totals until each step was revisited. Now also reset on a fresh Start (not a Pause->resume, which should keep it). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qvu5giu7gvRCyEWzf2Vpx
This commit is contained in:
+46
-10
@@ -438,6 +438,16 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
# load, which used to make the live trace visibly drift from the
|
# load, which used to make the live trace visibly drift from the
|
||||||
# forecast.
|
# forecast.
|
||||||
self.sud_elapsed_seconds = None
|
self.sud_elapsed_seconds = None
|
||||||
|
# The last real 'Elapsed' value seen, full stop - unlike
|
||||||
|
# sud_elapsed_seconds above, never reset back to None once the run
|
||||||
|
# leaves a running state (that's specifically what the forecast
|
||||||
|
# plot's dynamic-vs-static view switch needs - see _elapsed_min()),
|
||||||
|
# so the status bar/Progress tab can still show where the run
|
||||||
|
# actually ended up rather than "--:--" the moment it finishes.
|
||||||
|
# Reset on a fresh Start/Load (see on_sud_changed()/
|
||||||
|
# update_sud_forecast()) - a new run's total shouldn't open by
|
||||||
|
# showing the previous one's.
|
||||||
|
self.sud_elapsed_last = None
|
||||||
self.sud_name = ''
|
self.sud_name = ''
|
||||||
self.sud_schedule = []
|
self.sud_schedule = []
|
||||||
self.sud_pot_mass = 0
|
self.sud_pot_mass = 0
|
||||||
@@ -1039,6 +1049,19 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
if self.sud_state in SUD_RUNNING_STATES and self.sud_elapsed_seconds is None:
|
if self.sud_state in SUD_RUNNING_STATES and self.sud_elapsed_seconds is None:
|
||||||
self.sud_elapsed_seconds = 0.0
|
self.sud_elapsed_seconds = 0.0
|
||||||
|
self.sud_elapsed_last = 0.0
|
||||||
|
# A genuine fresh start (excludes Pause->resume, which
|
||||||
|
# never hits this branch - sud_elapsed_seconds is
|
||||||
|
# already non-None throughout a pause) means whatever
|
||||||
|
# energy the previous run banked belongs to that run,
|
||||||
|
# not this one - mirrors tasks/sud.py's SudTask.recv()
|
||||||
|
# resetting its own server-side bookkeeping on the same
|
||||||
|
# event. The server will overwrite these with the
|
||||||
|
# now-reset real figures within a tick or two regardless,
|
||||||
|
# this just avoids a stale flash of the old run's totals
|
||||||
|
# in between.
|
||||||
|
self.sud_energy_by_step = {}
|
||||||
|
self.sud_energy_current = 0.0
|
||||||
# Start the dynamic forecast's measured-history trace
|
# Start the dynamic forecast's measured-history trace
|
||||||
# fresh for this run.
|
# fresh for this run.
|
||||||
self.forecast_history = []
|
self.forecast_history = []
|
||||||
@@ -1093,6 +1116,13 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
self.sud_hold_remaining = msg['HoldRemaining']
|
self.sud_hold_remaining = msg['HoldRemaining']
|
||||||
self.update_status_step_label()
|
self.update_status_step_label()
|
||||||
elif "Elapsed" in key:
|
elif "Elapsed" in key:
|
||||||
|
# Unlike sud_elapsed_seconds below, kept regardless of
|
||||||
|
# dynamic-view mode - see its own comment for why - so the
|
||||||
|
# status bar/Progress tab still have the real final total
|
||||||
|
# once a run finishes rather than "--:--".
|
||||||
|
self.sud_elapsed_last = msg['Elapsed']
|
||||||
|
self._update_step_plates()
|
||||||
|
self.update_status_step_label()
|
||||||
# Sud.elapsed resets to 0 on every fresh Load too (not just
|
# Sud.elapsed resets to 0 on every fresh Load too (not just
|
||||||
# on an actual run start - see components/sud.py's
|
# on an actual run start - see components/sud.py's
|
||||||
# _reset_run_state()) and broadcasts unconditionally - only
|
# _reset_run_state()) and broadcasts unconditionally - only
|
||||||
@@ -1115,8 +1145,6 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
# at x=0.
|
# at x=0.
|
||||||
if not self.forecast_history and self.plot_temp_ist and msg['Elapsed'] < FRESH_RUN_ELAPSED_THRESHOLD_S:
|
if not self.forecast_history and self.plot_temp_ist and msg['Elapsed'] < FRESH_RUN_ELAPSED_THRESHOLD_S:
|
||||||
self.forecast_history.append((msg['Elapsed'] / 60.0, self.plot_temp_ist))
|
self.forecast_history.append((msg['Elapsed'] / 60.0, self.plot_temp_ist))
|
||||||
self._update_step_plates()
|
|
||||||
self.update_status_step_label()
|
|
||||||
elif "Forecast" in key:
|
elif "Forecast" in key:
|
||||||
self.on_sud_forecast_received(msg['Forecast'])
|
self.on_sud_forecast_received(msg['Forecast'])
|
||||||
elif "Energy" in key:
|
elif "Energy" in key:
|
||||||
@@ -1185,15 +1213,17 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
pot, water, grain, pot + water + grain)
|
pot, water, grain, pot + water + grain)
|
||||||
text = text + " " + mass_text if text else mass_text
|
text = text + " " + mass_text if text else mass_text
|
||||||
# Sums, not just the active step's own figures: total process time
|
# Sums, not just the active step's own figures: total process time
|
||||||
# is just self.sud_elapsed_seconds (Sud's own tick-counted total -
|
# is just self.sud_elapsed_last (Sud's own tick-counted total -
|
||||||
# every step's time, including any WAIT_USER dwell, already adds
|
# every step's time, including any WAIT_USER dwell, already adds
|
||||||
# up into it sequentially with no gaps); total energy has no such
|
# up into it sequentially with no gaps) - sud_elapsed_seconds
|
||||||
# single running counter server-side (see tasks/sud.py's SudTask -
|
# itself would go back to "--:--" the moment a run finishes, see
|
||||||
# energy is banked per step, not accumulated as one grand total),
|
# its own comment, which is exactly when this total matters most.
|
||||||
# so it's summed here from every finished step's own Wh total
|
# Total energy has no such single running counter server-side
|
||||||
# plus whatever the currently active one has used so far.
|
# (see tasks/sud.py's SudTask - energy is banked per step, not
|
||||||
|
# accumulated as one grand total), so it's summed here from every
|
||||||
|
# finished step's own Wh total plus the currently active one.
|
||||||
elapsed_text = "Elapsed {}".format(
|
elapsed_text = "Elapsed {}".format(
|
||||||
_format_duration(self.sud_elapsed_seconds) if self.sud_elapsed_seconds is not None else "--:--")
|
_format_duration(self.sud_elapsed_last) if self.sud_elapsed_last is not None else "--:--")
|
||||||
total_energy_kwh = (sum(self.sud_energy_by_step.values()) + self.sud_energy_current) / 1000.0
|
total_energy_kwh = (sum(self.sud_energy_by_step.values()) + self.sud_energy_current) / 1000.0
|
||||||
energy_text = "Energy {:.2f} kWh".format(total_energy_kwh)
|
energy_text = "Energy {:.2f} kWh".format(total_energy_kwh)
|
||||||
text = "{} {} {}".format(text, elapsed_text, energy_text)
|
text = "{} {} {}".format(text, elapsed_text, energy_text)
|
||||||
@@ -1245,6 +1275,7 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
self.step_actual_frozen = {}
|
self.step_actual_frozen = {}
|
||||||
self.sud_energy_by_step = {}
|
self.sud_energy_by_step = {}
|
||||||
self.sud_energy_current = 0.0
|
self.sud_energy_current = 0.0
|
||||||
|
self.sud_elapsed_last = None
|
||||||
self._rebuild_step_plates()
|
self._rebuild_step_plates()
|
||||||
self.update_sud_actions()
|
self.update_sud_actions()
|
||||||
self.update_status_step_label()
|
self.update_status_step_label()
|
||||||
@@ -1287,7 +1318,12 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
mash schedule is at most a handful of steps."""
|
mash schedule is at most a handful of steps."""
|
||||||
if not self.step_plates:
|
if not self.step_plates:
|
||||||
return
|
return
|
||||||
current_elapsed = self.sud_elapsed_seconds if self.sud_elapsed_seconds is not None else 0.0
|
# sud_elapsed_last, not sud_elapsed_seconds - the latter resets to
|
||||||
|
# None the moment a run finishes (see its own comment), which
|
||||||
|
# would otherwise make every finished step's remaining time jump
|
||||||
|
# back to its full duration right when the run ends instead of
|
||||||
|
# staying at 0:00.
|
||||||
|
current_elapsed = self.sud_elapsed_last if self.sud_elapsed_last is not None else 0.0
|
||||||
starts = self.sud_forecast_step_starts
|
starts = self.sud_forecast_step_starts
|
||||||
n = len(self.step_plates)
|
n = len(self.step_plates)
|
||||||
for i, plate in enumerate(self.step_plates):
|
for i, plate in enumerate(self.step_plates):
|
||||||
|
|||||||
@@ -430,6 +430,14 @@ class SudTask(ATask):
|
|||||||
# whatever temperature existed back at Load (time passed,
|
# whatever temperature existed back at Load (time passed,
|
||||||
# possibly manual heating in between).
|
# possibly manual heating in between).
|
||||||
fresh_start = self.sud.state in (SudState.IDLE, SudState.DONE)
|
fresh_start = self.sud.state in (SudState.IDLE, SudState.DONE)
|
||||||
|
if fresh_start:
|
||||||
|
# Belongs to the run that just ended (Stop, or running
|
||||||
|
# the schedule through to DONE), not the one about to
|
||||||
|
# begin - a Pause->resume (fresh_start False) keeps it,
|
||||||
|
# same as the forecast above.
|
||||||
|
self.energy_step_accum_j = 0.0
|
||||||
|
self.energy_by_step = {}
|
||||||
|
self._energy_index = None
|
||||||
self.sud.start()
|
self.sud.start()
|
||||||
if fresh_start:
|
if fresh_start:
|
||||||
asyncio.create_task(self.send_forecast(self.sud.save()))
|
asyncio.create_task(self.send_forecast(self.sud.save()))
|
||||||
|
|||||||
Reference in New Issue
Block a user