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
`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