feat: show status line earlier and count energy without a running Sud

Both clients' status line only showed pot mass/water/energy once a Sud
schedule was loaded and running, leaving it blank/minimal at connect
time and while idle. Show it as early as possible instead, falling back
to config.json's Pot section (mass/water_mass/volumen) when no schedule
is loaded yet; step description/remaining-time still only appear once a
schedule is actually active.

web/app.js: updateStatusLine() now mirrors updatePotVisualization()'s
existing sudEmpty ? potConfig... : sud... pattern, and adds a Volume
figure that was previously only used for the pot-fill visualization.

client/brewpi_gui.py: same treatment, plus new sud_volumen tracking
(the desktop GUI had no volume concept at all before - added by reading
the doc's own pot.volumen with a config fallback, since Sud._parse_data()
doesn't return it). The System message's 'Pot' key now also refreshes
the status label immediately so it doesn't wait for some unrelated
message to trigger a repaint.

tasks/sud.py: energy was only accumulated outside IDLE/DONE, so a
manually-driven heater with no Sud loaded/started never counted toward
the total shown in either client. Now counts in every state except
DONE - IDLE banks into a stable index -1 that's never shown per-step
(Progress tab only covers the schedule's own indices) but is included
in the status line's summed total.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M2ierBoxW3v7nUbDw3M2pE
This commit is contained in:
2026-07-06 10:45:55 +02:00
co-authored by Claude Sonnet 5
parent 57677d7881
commit 6d1429daca
3 changed files with 88 additions and 57 deletions
+30 -22
View File
@@ -479,31 +479,39 @@ function updatePotVisualization() {
function updateStatusLine() {
const el = document.getElementById('sud-status-line');
if (sudSchedule.length === 0) {
const w = potConfig.water_mass || 0;
el.textContent = w > 0 ? `No schedule ${w} L water` : '';
return;
}
let text = '';
let grain = sudGrainMass, water = sudWaterMass;
if (sudStepDescr) {
// +1: sudStepIndex is the 0-based index Sud.index uses, but the
// Progress tab's step-plates (createStepPlate()) label 1-based -
// match it here, same fix as client/brewpi_gui.py's
// update_status_step_label().
text = `Step ${sudStepIndex + 1}: ${sudStepDescr}`;
if (sudStepType === 'hold') {
const remaining = Math.max(sudHoldRemaining, 0);
text += ` (${Math.floor(remaining / 60)}:${String(Math.floor(remaining % 60)).padStart(2, '0')} remaining)`;
}
if (sudStepIndex !== null && sudStepIndex >= 0 && sudStepIndex < sudSchedule.length) {
const step = sudSchedule[sudStepIndex];
grain = step.grain_mass || 0;
water = step.water_mass || 0;
// Before any schedule is loaded, fall back to config.json's Pot
// section (via potConfig) so the status line already shows pot mass/
// water/volume/energy as soon as the System message arrives - same
// sudEmpty ? potConfig... : sud... pattern as updatePotVisualization()
// above. Step description/remaining-time only exist once a schedule
// is actually loaded, so they stay inside the sudEmpty===false branch.
let grain = 0, water = potConfig.water_mass || 0;
let pot = potConfig.mass || 0;
let volumen = potConfig.volumen || 0;
if (!sudEmpty) {
grain = sudGrainMass;
water = sudWaterMass;
pot = sudPotMass;
volumen = sudVolumen;
if (sudStepDescr) {
// +1: sudStepIndex is the 0-based index Sud.index uses, but the
// Progress tab's step-plates (createStepPlate()) label 1-based -
// match it here, same fix as client/brewpi_gui.py's
// update_status_step_label().
text = `Step ${sudStepIndex + 1}: ${sudStepDescr}`;
if (sudStepType === 'hold') {
const remaining = Math.max(sudHoldRemaining, 0);
text += ` (${Math.floor(remaining / 60)}:${String(Math.floor(remaining % 60)).padStart(2, '0')} remaining)`;
}
if (sudStepIndex !== null && sudStepIndex >= 0 && sudStepIndex < sudSchedule.length) {
const step = sudSchedule[sudStepIndex];
grain = step.grain_mass || 0;
water = step.water_mass || 0;
}
}
}
const pot = sudPotMass;
const massText = `Pot: ${pot.toFixed(2)} kg, Water: ${water.toFixed(2)} kg, Grain ${grain.toFixed(2)} kg, total ${(pot + water + grain).toFixed(2)} kg`;
const massText = `Pot: ${pot.toFixed(2)} kg, Water: ${water.toFixed(2)} kg, Grain ${grain.toFixed(2)} kg, total ${(pot + water + grain).toFixed(2)} kg, Volume ${volumen.toFixed(1)} L`;
text = text ? `${text} ${massText}` : massText;
const elapsedText = `Elapsed ${elapsed !== null ? formatDuration(elapsed) : '-:--:--'}`;
const totalEnergyKwh = (Object.values(energyByStep).reduce((a, b) => a + b, 0) + energyCurrent) / 1000.0;