From 6640d99e4f7ea234dddb422d958ca2a6205076fb Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Sun, 28 Jun 2026 12:36:24 +0200 Subject: [PATCH] README: refresh docs for heater shutdown, resume fix, browser countdown - HeaterTask.shutdown() on DONE/IDLE: document the _on_end callback, power-zero, TC disable, and ClosedLoop:false broadcast to clients. - Resume with inherited temperature: document _paused_temp_soll fallback for steps that carry no temperature of their own. - Browser client additional features: update Header countdown (now three rows: total/ramp/hold, always h:mm:ss) and describe the step-plate Ramp/Hold green countdown and configured hold-duration field. Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01SH2D4LRuCnhLSzoYerAfJX --- README.md | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7c08003..22b1ebd 100644 --- a/README.md +++ b/README.md @@ -347,9 +347,15 @@ in closed-loop mode (the default) and disabled in open-loop mode. This is wired up in `server/brewpi.py` via `heater_task.set_on_closed_loop_changed(tc.set_enabled)`, and fired once at startup from `HeaterTask.on_process()` so the TC is live immediately. -`SudTask` no longer manages the TC's enabled state — its -`on_state_changed()` only stops the stirrer when a run ends. See "Heater -control modes" below. +`SudTask` no longer manages the TC's enabled state directly; instead, when +a run ends (state reaches `DONE` or `IDLE` — whether the schedule completed +or Stop was pressed), it fires an `_on_end` callback that calls +`HeaterTask.shutdown()`: this zeros `power_soll`, disables the TC, switches +`closed_loop` to `False`, and broadcasts `{ClosedLoop: false}` to all clients +so their checkboxes uncheck immediately. Re-enabling for manual use after a +stop requires the user to check the Closed-loop checkbox again (or the +next `Start` press does it automatically — see "Heater control modes"). See +"Heater control modes" below. ### Heater control modes @@ -380,7 +386,11 @@ browser tab is immediately reflected in every other connected client. On every resume from pause, `SudTask.recv()` restores the current step's schedule parameters (temperature setpoint, heat rate, stirrer) before the run continues, overwriting any manual adjustments the user made while -paused. +paused. Steps that carry no `temperature` of their own (`temperature=None` +— they inherit whatever the previous step left the TC targeting) are +handled via `_paused_temp_soll`: the setpoint is saved the moment Pause is +pressed and restored as a fallback on resume, so the TC always snaps back +to the correct target even for inherited-temperature steps. ### Forecast vs. actual duration @@ -614,10 +624,21 @@ Additional features beyond the initial port: Sud is paused or stopped; auto-reset to Closed-loop on play. Slider enable/disable follows the mode: temperature setpoint and heat rate active in Closed-loop + not running; heater power active in Open-loop + - not running. -- **Header countdown**: step remaining and total remaining timers, - displayed in accent-coloured monospace next to the transport buttons, - derived from `forecast_step_starts`/`StepStarts`. + not running. When a run ends (DONE or Stop), `HeaterTask.shutdown()` + fires automatically — the checkbox unchecks, power goes to 0, TC is + disabled (see "Heater control modes" above). +- **Header countdown**: three monospace rows next to the transport buttons, + always in `h:mm:ss` format: *total* (time until the schedule finishes), + *ramp* (ramp phase remaining for the current step — total step span minus + the configured hold duration), and *hold* (`Sud.hold_remaining` pushed + live from the server). All three derive from `forecast_step_starts`/ + `StepStarts`; "ramp" shows `0:00:00` once the hold phase begins. +- **Step-plate countdowns**: each plate's top-right shows the remaining + ramp time in green digits. The active step overrides this with a "Ramp + h:mm:ss" or "Hold h:mm:ss" prefix (same element reused for both phases). + Configured hold duration (`hold.duration` formatted as `h:mm:ss`) is + shown as a static field on each plate; steps with no hold phase show + "Hold —". - **Controls always reflect server values**: sliders and readouts track every server push unconditionally — there are no "initial sync only" guards that could leave a control stale after a reconnect or while