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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SH2D4LRuCnhLSzoYerAfJX
This commit is contained in:
2026-06-28 12:36:24 +02:00
co-authored by Claude Sonnet 4.6
parent e43d47252e
commit 6640d99e4f
+29 -8
View File
@@ -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 wired up in `server/brewpi.py` via
`heater_task.set_on_closed_loop_changed(tc.set_enabled)`, and fired once `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. at startup from `HeaterTask.on_process()` so the TC is live immediately.
`SudTask` no longer manages the TC's enabled state — its `SudTask` no longer manages the TC's enabled state directly; instead, when
`on_state_changed()` only stops the stirrer when a run ends. See "Heater a run ends (state reaches `DONE` or `IDLE` — whether the schedule completed
control modes" below. 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 ### 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 On every resume from pause, `SudTask.recv()` restores the current step's
schedule parameters (temperature setpoint, heat rate, stirrer) before the schedule parameters (temperature setpoint, heat rate, stirrer) before the
run continues, overwriting any manual adjustments the user made while 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 ### 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 Sud is paused or stopped; auto-reset to Closed-loop on play. Slider
enable/disable follows the mode: temperature setpoint and heat rate enable/disable follows the mode: temperature setpoint and heat rate
active in Closed-loop + not running; heater power active in Open-loop + active in Closed-loop + not running; heater power active in Open-loop +
not running. not running. When a run ends (DONE or Stop), `HeaterTask.shutdown()`
- **Header countdown**: step remaining and total remaining timers, fires automatically — the checkbox unchecks, power goes to 0, TC is
displayed in accent-coloured monospace next to the transport buttons, disabled (see "Heater control modes" above).
derived from `forecast_step_starts`/`StepStarts`. - **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 - **Controls always reflect server values**: sliders and readouts track
every server push unconditionally — there are no "initial sync only" every server push unconditionally — there are no "initial sync only"
guards that could leave a control stale after a reconnect or while guards that could leave a control stale after a reconnect or while