diff --git a/sude/GuiTest.json b/sude/GuiTest.json index c006116..a7e3ea2 100644 --- a/sude/GuiTest.json +++ b/sude/GuiTest.json @@ -7,7 +7,8 @@ "L": 0.2, "Td": 30, "grain_mass": 5.21, - "water_mass": 22 + "water_mass": 22, + "volumen": 30 }, "default": { "step": { diff --git a/sude/GuiTest_no_user.json b/sude/GuiTest_no_user.json index ced0796..602bb84 100644 --- a/sude/GuiTest_no_user.json +++ b/sude/GuiTest_no_user.json @@ -7,7 +7,8 @@ "L": 0.2, "Td": 30, "grain_mass": 5.21, - "water_mass": 22 + "water_mass": 22, + "volumen": 30 }, "default": { "step": { diff --git a/sude/sud_0010.json b/sude/sud_0010.json index a11ec22..67cb538 100644 --- a/sude/sud_0010.json +++ b/sude/sud_0010.json @@ -7,7 +7,8 @@ "L": 0.2, "Td": 30, "grain_mass": 0, - "water_mass": 22 + "water_mass": 22, + "volumen": 30 }, "default": { "step": { diff --git a/sude/sud_0010_downloaded.json b/sude/sud_0010_downloaded.json index 7797480..75b16a4 100644 --- a/sude/sud_0010_downloaded.json +++ b/sude/sud_0010_downloaded.json @@ -7,7 +7,8 @@ "L": 0.2, "Td": 30, "grain_mass": 0, - "water_mass": 22 + "water_mass": 22, + "volumen": 30 }, "default": { "step": { diff --git a/sude/sud_0020.json b/sude/sud_0020.json index 836bd6d..2e67c7d 100644 --- a/sude/sud_0020.json +++ b/sude/sud_0020.json @@ -7,7 +7,8 @@ "L": 0.2, "Td": 30, "grain_mass": 0, - "water_mass": 10 + "water_mass": 10, + "volumen": 30 }, "default": { "step": { diff --git a/web/app.js b/web/app.js index 8973d8d..919f001 100644 --- a/web/app.js +++ b/web/app.js @@ -43,6 +43,7 @@ let sudName = ''; let sudPotMass = 0; let sudGrainMass = 0; let sudWaterMass = 0; +let sudVolumen = 0; let sudEmpty = true; let sudLastLoadedDoc = null; let sudState = null; @@ -127,14 +128,16 @@ function buildStep(number, defaults, rawStep) { } function parseSudDoc(doc) { + const pot = doc.pot || {}; const stepDefaults = (doc.default && doc.default.step) || {}; const schedule = (doc.steps || []).map((raw, i) => buildStep(i + 1, stepDefaults, raw)); return { name: doc.Name || '', schedule: schedule, - potMass: doc.pot_mass || 0, - grainMass: doc.grain_mass || 0, - waterMass: doc.water_mass || 0, + potMass: pot.mass || 0, + grainMass: pot.grain_mass || 0, + waterMass: pot.water_mass || 0, + volumen: pot.volumen || 0, }; } @@ -262,6 +265,56 @@ function updateStepPlates() { }); } +// --- Pot visualization --- + +function wavePathD(x1, x2, y, amplitude, wavelength) { + let d = `M ${x1} ${y.toFixed(1)}`; + for (let x = x1 + 3; x <= x2; x += 3) { + const yw = y + amplitude * Math.sin(2 * Math.PI * (x - x1) / wavelength); + d += ` L ${x} ${yw.toFixed(1)}`; + } + return d; +} + +function currentStepWaterMass() { + if (sudStepIndex !== null && sudStepIndex >= 0 && sudStepIndex < sudSchedule.length) { + return sudSchedule[sudStepIndex].water_mass || 0; + } + return sudWaterMass; +} + +function updatePotVisualization() { + // Thermometer mercury column (0°C = y=174, 100°C = y=28, tube length = 146) + const tubeBottom = 174; + const tubeLen = 146; + const temp = plotTempIst !== null ? Math.max(0, Math.min(100, plotTempIst)) : 0; + const mercuryH = (temp / 100) * tubeLen; + document.getElementById('thermo-mercury').setAttribute('y', (tubeBottom - mercuryH).toFixed(1)); + document.getElementById('thermo-mercury').setAttribute('height', mercuryH.toFixed(1)); + document.getElementById('thermo-temp-label').textContent = + plotTempIst !== null ? plotTempIst.toFixed(1) + ' °C' : '--'; + + // Water fill + const waterFillEl = document.getElementById('water-fill'); + const waterWaveEl = document.getElementById('water-wave'); + const potInnerTop = 30; + const potInnerBottom = 172; + const potInnerH = potInnerBottom - potInnerTop; // 142 + + if (sudEmpty || sudVolumen <= 0) { + waterFillEl.setAttribute('height', '0'); + waterWaveEl.setAttribute('d', ''); + return; + } + + const fillFraction = Math.min(1, Math.max(0, currentStepWaterMass() / sudVolumen)); + const waterH = fillFraction * potInnerH; + const waterTop = potInnerBottom - waterH; + waterFillEl.setAttribute('y', waterTop.toFixed(1)); + waterFillEl.setAttribute('height', waterH.toFixed(1)); + waterWaveEl.setAttribute('d', wavePathD(63, 177, waterTop, 3, 28)); +} + // --- Status line - mirrors update_status_step_label(). --- function updateStatusLine() { @@ -345,6 +398,7 @@ function updateSudForecast(doc) { sudPotMass = parsed.potMass; sudGrainMass = parsed.grainMass; sudWaterMass = parsed.waterMass; + sudVolumen = parsed.volumen; sudEmpty = sudSchedule.length === 0; if (isNewSchedule) { sudStepDescr = null; @@ -362,6 +416,7 @@ function updateSudForecast(doc) { rebuildStepPlates(); updateStatusLine(); updateSudActions(); + updatePotVisualization(); document.title = sudName ? `BrewPi - ${sudName}` : 'BrewPi'; } @@ -450,6 +505,7 @@ function onTempCtrlChanged(msg) { plotTempIst = ist.Temp; document.getElementById('lcd-temp-ist').textContent = ist.Temp.toFixed(1); updateStepPlates(); + updatePotVisualization(); } if ('Rate' in ist) { document.getElementById('lcd-rate-ist').textContent = ist.Rate.toFixed(1); @@ -504,6 +560,7 @@ function onSudChanged(msg) { sudStepType = step.Type; updateStatusLine(); updateStepPlates(); + updatePotVisualization(); } else if (key === 'HoldRemaining') { sudHoldRemaining = msg.HoldRemaining; updateStatusLine(); diff --git a/web/index.html b/web/index.html index f9fd52f..bc8cf8c 100644 --- a/web/index.html +++ b/web/index.html @@ -45,6 +45,73 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 100 + + + 50 + + + 0 °C + + + -- + +
+