A new HTML/CSS/JS client, added next to client/brewpi_gui.py rather than replacing it, speaking the exact same WebSocket pub/sub protocol - no server-side protocol changes needed. server/brewpi.py gains a --http-port (default 8080) stdlib http.server.ThreadingHTTPServer, in its own daemon thread and deliberately decoupled from the existing asyncio WebSocket server, serving web/ statically. v1 covers the Manual tab (direct heater/stirrer/controller control) and the new Progress tab - the two most actionable surfaces, neither needing a charting library. web/app.js ports the relevant logic from brewpi_gui.py directly: components/sud.py's _build_step()/ _merge_defaults() for resolving the raw schedule doc, and the StepPlate/_update_step_plates()/update_status_step_label() logic behind the Progress tab and status line. Deliberately deferred rather than stubbed (see web/TODO.md for the full parity backlog against the Qt GUI): Sud control actions (Start/ Pause/Stop/Confirm), the Automatic tab's forecast plot and the Plot tab's live strip charts, Sud file management, and auth (matching the WebSocket server's own existing lack of it). No new Python dependencies - functools/threading/http.server are all stdlib. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qvu5giu7gvRCyEWzf2Vpx
100 lines
2.7 KiB
HTML
100 lines
2.7 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>BrewPi</title>
|
|
<link rel="stylesheet" href="style.css">
|
|
</head>
|
|
<body>
|
|
|
|
<header id="connection-bar">
|
|
<label>Host <input id="host" type="text"></label>
|
|
<button id="btn-connect">Connect</button>
|
|
<span id="conn-status" class="status-disconnected">Disconnected</span>
|
|
</header>
|
|
|
|
<div id="lcd-panel">
|
|
<div class="lcd-row lcd-header">
|
|
<div class="lcd-label"></div>
|
|
<div>Ist</div>
|
|
<div>Soll</div>
|
|
</div>
|
|
<div class="lcd-row">
|
|
<div class="lcd-label">Temperature [°C]</div>
|
|
<div class="lcd" id="lcd-temp-ist">--</div>
|
|
<div class="lcd" id="lcd-temp-soll">--</div>
|
|
</div>
|
|
<div class="lcd-row">
|
|
<div class="lcd-label">Heat rate [°C/min]</div>
|
|
<div class="lcd" id="lcd-rate-ist">--</div>
|
|
<div class="lcd" id="lcd-rate-soll">--</div>
|
|
</div>
|
|
<div class="lcd-row">
|
|
<div class="lcd-label">Power [W]</div>
|
|
<div class="lcd" id="lcd-power-ist">--</div>
|
|
<div class="lcd" id="lcd-power-soll">--</div>
|
|
</div>
|
|
</div>
|
|
|
|
<nav id="tabs">
|
|
<button class="tab-btn active" data-tab="manual">Manual</button>
|
|
<button class="tab-btn" data-tab="progress">Progress</button>
|
|
</nav>
|
|
|
|
<main>
|
|
<section id="tab-manual" class="tab-content active">
|
|
<div class="panel">
|
|
<h3>Controller</h3>
|
|
<label><input type="checkbox" id="tc-enabled"> Enabled</label>
|
|
<label>Temperature [°C]
|
|
<input type="range" id="temp-soll" min="0" max="100" step="1" disabled>
|
|
<span id="temp-soll-readout">--</span>
|
|
</label>
|
|
<label>Heat rate [°C/min]
|
|
<input type="number" id="heatrate-soll" min="0" max="3" step="0.1" disabled>
|
|
</label>
|
|
</div>
|
|
<div class="panel">
|
|
<h3>Heater</h3>
|
|
<label><input type="checkbox" id="heater-activate"> Activate</label>
|
|
<label>Power [W]
|
|
<input type="range" id="heater-power" min="0" max="100" step="1">
|
|
<span id="heater-power-readout">--</span>
|
|
</label>
|
|
</div>
|
|
<div class="panel">
|
|
<h3>Stirrer</h3>
|
|
<label><input type="checkbox" id="stirrer-activate"> Activate</label>
|
|
<label>Speed [%]
|
|
<input type="range" id="stirrer-speed" min="0" max="100" step="1">
|
|
<span id="stirrer-speed-readout">--</span>
|
|
</label>
|
|
</div>
|
|
<div class="panel">
|
|
<h3>Environment</h3>
|
|
<label>Ambient [°C]
|
|
<input type="number" id="ambient-temp" step="0.1">
|
|
</label>
|
|
<div id="pot-reset-row" class="hidden">
|
|
<label>Pot [°C]
|
|
<input type="number" id="pot-temp" step="0.1">
|
|
</label>
|
|
<button id="btn-pot-reset">Reset</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="tab-progress" class="tab-content">
|
|
<div id="step-plates"></div>
|
|
</section>
|
|
</main>
|
|
|
|
<footer>
|
|
<div id="sud-status-line"></div>
|
|
<div id="env-status-line"></div>
|
|
</footer>
|
|
|
|
<script src="app.js"></script>
|
|
</body>
|
|
</html>
|