Update README: browser layout, iPad/Safari, WebSocket disconnect

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 15:36:08 +02:00
co-authored by Claude Sonnet 4.6
parent 0f31cc41cc
commit 2020207af0
+19
View File
@@ -80,6 +80,14 @@ ws/ Minimal WebSocket pub/sub layer: server
(single- and multi-user), client, and a
keyed message dispatcher (e.g. "Sensor",
"Heater", "TempCtrl", "Stirrer", "Pot", "Sud").
Abrupt client disconnects (no WebSocket close
frame — the normal case for browser tab closes
and Safari session teardowns) are handled
gracefully: `User.send()` catches
`ConnectionClosed` silently, and `handler_recv()`
exits cleanly on it, so a vanishing client never
produces an uncaught exception or "connection
handler failed" log noise.
scripts/demos/ Standalone, eyeballed-plot demos (matplotlib)
exercising components/* in isolation — pid/,
@@ -610,6 +618,17 @@ for the desktop app's native file dialogs), Start/Pause/Stop, and Confirm
(a plain `<dialog>` pops with the step's message on `WAIT_USER` and sends
Confirm when dismissed) are all wired up.
The page carries a `<meta name="viewport">` tag so Safari and other mobile
browsers render at device CSS pixels rather than the 980 px virtual layout
they otherwise default to — essential for touch usability on iPad. The
header is a two-row layout: the top row holds the host address input,
Connect button, connection status, and the three large (76 × 76 px)
circular transport buttons (Start/Pause/Stop) with the countdown to their
right; the New/Load/Save file buttons occupy their own row directly below.
The LCD panel (Temperature/Heat rate/Power) uses a four-column grid, with
unit labels (°C, °C/min, W) in a dedicated column to the right of the Soll
value rather than embedded in the row labels.
The browser client applies the "state is server-only" principle strictly
throughout `web/app.js`: every slider, readout, and checkbox is updated
only when a push arrives from the server, never speculatively on user