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
4.4 KiB
web/ (browser client) vs. client/brewpi_gui.py parity backlog
web/app.js ported the Manual tab's direct controls and the Progress tab
wholesale from client/brewpi_gui.py (see README.md's "Browser client").
Everything below is what that v1 pass deliberately left out - either
flagged as deferred in the plan, or only noticed once the port was done
and checked against the Qt source side by side.
-
No way to actually run a brew. There's no Start/Pause/Stop/ Confirm anywhere in
web/index.html-on_action_sud_start()/on_action_sud_pause()/on_action_sud_stop()(client/brewpi_gui.py: 868-875) are one-line{"Sud": {"Start"/"Pause"/"Stop": true}}sends, trivial to add as buttons;{"Sud": {"Confirm": true}}already needssudUserMessage/sudState(next item) to know when it's actually waiting on one. Until this exists, the Progress tab can only watch a run started from the desktop GUI (or a rawSud.Startsend from the browser console) - it's read-only. -
WAIT_USERnever surfaces to the user.sudUserMessageis tracked inapp.jsbut nothing ever shows it -show_user_message()(client/brewpi_gui.py:877-882) pops a modal the instantWAIT_USERis newly entered (prev_state != WAIT_USER) and sendsConfirmitself when the user dismisses it. Needs the same "newly entered" edge detection inonSudChanged()'sStatebranch (thewasRunningtracking there is close, but checks running-vs-not, not specifically theWAIT_USERtransition) plus a modal (a plain<dialog>works, no library needed) that sendsConfirmon close. -
No schedule management. Matches README.md's "Browser client" section, called out there as deliberately deferred rather than missing by oversight -
on_action_sud_new/_save/_load()(client/brewpi_gui.py:884-912) use native file dialogsweb/has no equivalent of yet. Load maps to<input type="file">+FileReader+{"Sud": {"Load": ...}}; Save to aBlob+<a download>of whatever the nextJsonpush contains; New is just the same hardcoded empty-docLoadQt sends, no dialog needed at all. -
No temperature-controller state/cooldown indicator. Qt shows the raw FSM state (
label_state.setText(msg['State'])- e.g."States.HOLD") and a separate blinking "Cool down" label specifically forStates.COOL(set_tc_cooling(),client/brewpi_gui.py:820-829, driven byon_tempctrl_changed()'s'State'branch).app.js'sonTempCtrlChanged()never readsmsg.Stateat all right now - worth a small label in the Controller panel, reusing the same 500ms blink-timer pattern the Progress tab's LEDs already have. -
No transient status notifications. Qt's status bar shows short-lived messages on certain events - e.g.
"Sud schedule updated: {name}"for 5s on everyNamepush (client/brewpi_gui.py:1043-1045).web/'s status line only ever shows the persistent Sud/env summaries; there's nowhere for one-shot events to surface at all. -
Nothing persists across reloads.
client/user_config.pykeeps the last ambient temperature and Sud file-dialog directory in~/.config/brewpi/gui.jsonacross restarts.web/'s ambient-temp field always starts blank until the firstSystem.AmbientTemppush;localStoragewould be the natural equivalent (and the host field could remember the last-used server too, which the desktop GUI doesn't even need since it's one app per machine). -
No reconnect handling. A dropped WebSocket (
ws.onclose) just flips the UI to "Disconnected" and stops - the user has to click Connect again by hand.WsClient(ws/client/ws_client.py, used by the desktop GUI) - check whether it already retries and mirror that, or add a simple backoff retry loop inconnect(). -
Automatic tab (forecast-vs-actual plot) and Plot tab (live strip charts) don't exist. Flagged in the original plan and in README.md's "Browser client" section as deferred pending a charting decision, not an oversight - listed here too so this file alone is a complete picture of the gap.
SudForecastPlot/RealtimePlot(client/brewpi_gui.py:121-258) are the reference for what each needs to show. -
No authentication. Also already called out in README.md - matches the WebSocket server's own complete lack of it, not a new gap, but worth a line here too since "browser, reachable from anywhere on the network" is a wider exposure than the desktop app ever was.