diff --git a/README.md b/README.md index af4c587..77e4e4e 100644 --- a/README.md +++ b/README.md @@ -1,99 +1,153 @@ # server-monitor-dash -A case-mounted touchscreen monitoring dashboard for self-hosted AI/inference -servers, built with [Textual](https://textual.textualize.io/). CPU, GPU, and -memory telemetry rendered "supercar dash" style — dense, glanceable, colour -thresholded — rather than a plain systems-monitoring readout. - -Runs directly under a TTY autologin session. No X, no display server, and no -GPU vendor lock-in for the interface itself (though GPU telemetry currently -assumes `nvidia-smi` — see **Status** below). +A case-mounted touchscreen monitoring dashboard for Cervello Elettrico +servers — CPU, GPU, and memory telemetry rendered "supercar dash" style, +built in Python with [Textual](https://github.com/Textualize/textual). --- -## Why +## Status: v0.0.2 — functional dashboard, navigation redesigned -Most server monitoring tools are built for a terminal you're SSH'd into, not -a small screen physically mounted in a case that someone actually looks at. -This project is the opposite bet: build something that's genuinely nice to -glance at from across a room, on a 5" panel, on hardware that's otherwise -running unattended. +The Dashboard section is fully functional — live per-core CPU, memory, +and GPU telemetry, refreshed once per second, with threshold-driven +colour (green → amber → red) applied consistently across every gauge. +The **Request Assistance** and **Switch to X** sections are stubs, +wired for later completion. -## Features +Navigation moved from tabs to a fixed touch-bar sidebar with up/down +buttons controlling a scrollable stack of full-screen sections — see +Design Notes below for why. -- **Live telemetry**: per-core CPU utilization, memory usage, GPU - temperature/utilization/power/fan speed -- **Threshold-driven colour** (green → amber → red) on key gauges, rather - than flat, undifferentiated numbers -- **Rolling history sparkline** for GPU temperature trend -- **Idle-blank behaviour**: screen goes solid black after 15 minutes with no - touch/key input, to protect the physical panel from always-on burn-in over - years of continuous operation — any input wakes it immediately -- **Tabbed layout**: Dashboard (functional), Request Assistance and Switch to - X (stubs — see Roadmap) +This is not yet a CE OS-compliant script (no test gates, no cleanup +trap — see the CE OS Scripting Style Guide). It remains a prototype for +iterating look, feel, and navigation, not a production deployment. + +--- ## Requirements -- Python 3.9+ -- [Textual](https://textual.textualize.io/) (`pip install textual - --break-system-packages`, or via `pipx`) -- `nvidia-smi` on `PATH` for GPU telemetry (CPU/memory panels work without - it — GPU panel degrades gracefully to zero rather than crashing if - `nvidia-smi` is unavailable or fails) +- Python 3.10+ +- [Textual](https://github.com/Textualize/textual) — + `pip install textual --break-system-packages` (or via `pipx`) +- Linux with `/proc/stat` and `/proc/meminfo` (CPU/memory stats — no + external dependency beyond the standard library for these) +- `nvidia-smi` on `PATH`, for GPU telemetry (gracefully degrades to zero + values if absent or if the query fails) -## Running +Target hardware: a 5" case-mounted touchscreen, e.g. the Waveshare 5" +HDMI LCD (800×480, resistive touch). See Design Notes for why resistive +touch specifically shaped this interface's navigation model. + +--- + +## Running it ```bash python3 server_dash.py ``` -Intended to run under a dedicated, unprivileged monitoring user's autologin -TTY session — not as root, and not as the account used for anything else on -the box. - -## Status - -This is an early, working prototype — the CPU/memory/GPU telemetry panel is -functional and tested; the two additional tabs are placeholders, not yet -implemented: - -| Tab | Status | -|---|---| -| Dashboard | Working — live CPU/mem/GPU telemetry | -| Request Assistance | Stub — will send a scripted notification email | -| Switch to X | Stub — will invoke a narrowly-scoped, sudoers-gated VT switch to a separate login, for on-demand GPU tuning access via a real X session | - -Not yet fully compliant with CE OS script conventions (no test gates, no -cleanup trap) — this is explicitly a prototype for iterating the interface -design, not a hardened production deployment. See the script's own header -comment for current detail. - -## Design notes - -- **GPU vendor**: currently NVIDIA-only via `nvidia-smi`. AMD/Intel GPU - support would need an equivalent backend behind the same `read_gpu_stats()` - interface — contributions welcome. -- **Colour thresholds** (`TEMP_THRESHOLDS`, `UTIL_THRESHOLDS` in-script) are - currently fixed defaults, not yet configurable per-deployment. Worth - externalizing to a config file if this is deployed across multiple - machines with different thermal profiles. -- **No hard dependency on a specific display size** — built for a 5" - case-mounted touchscreen, but Textual's layout should adapt reasonably to - other terminal sizes; untested on anything else so far. - -## Roadmap - -- [ ] Wire up Request Assistance (scripted outbound email, hostname in body) -- [ ] Wire up Switch to X (sudoers-scoped `chvt` wrapper, see script comment) -- [ ] Externalize colour thresholds to a config file -- [ ] Bring up to full CE OS script compliance (test gates, cleanup trap) -- [ ] Consider a non-NVIDIA GPU backend - -## License - -See [LICENSE](./LICENSE). +Designed to run under a dedicated, unprivileged monitoring user's +autologin session — no X server required for the dashboard itself. (The +**Switch to X** section, once wired up, is specifically for spinning up +X on demand for GPU tuning tools that do need it.) --- -*Built standing on the shoulders of billions of dwarves.* -*Created by John A. Hoeven with the ethical assistance of Claude AI.* +## Design notes + +### Navigation: touch-bar, not tabs, not free-scroll + +Earlier drafts used `TabbedContent`/`TabPane`. This was replaced with a +fixed-width touch-bar sidebar (up/down buttons) controlling a +`VerticalScroll` of `min-height: 100vh` sections, for two reasons: + +- **Touch-swipe fidelity on this specific hardware was never verified.** + Button-triggered navigation (`scroll_to_widget()`) removes the + dependency entirely rather than hoping raw swipe gestures arrive + cleanly from this touchscreen. +- **The client base includes people who may not have a full set of + fingers or thumbs on either hand** (small-factory environments). Touch + zones are deliberately oversized — roughly thumb-width, half the + screen's height — with a forgiving click margin extending past the + visible coloured bar, so an imprecise touch from any part of a hand + still registers. This is tested and confirmed working in the + assembled app, not just assumed. + +### Resistive touch is the right technology here, not a compromise + +Capacitive touch requires conductive bare skin and doesn't reliably +register gloves, prosthetics, or some scarred/grafted skin. Resistive +touch responds to pressure from anything — a knuckle, a gloved finger, +a stylus, a partial hand. Given the intended client base, resistive +touch and generously-sized, forgiving touch zones are a deliberate +accessibility choice, not a lesser alternative to capacitive. + +### Threshold colours + +Green → amber → red follows the same instinct as a car's tachometer +redline. Current GPU temperature thresholds (65°C amber, 75°C red) are +based on empirically observed thermal-error thresholds on constrained +hardware in this project — not arbitrary numbers. Applied consistently +to every gauge (GPU temp and util, all CPU cores, memory) — not just +one readout. + +### Data sources + +- **GPU stats** via `nvidia-smi`, same parsing approach as this + project's thermal-logging script — no Python NVIDIA-bindings + dependency. +- **CPU/memory stats** are pure standard library (`/proc/stat`, + `/proc/meminfo`) — the same low-level mechanism `btop` itself uses + under the hood, reimplemented in Python. + +### Idle-blank after 15 minutes + +Any keypress or click resets the timer; timeout shows a solid black +screen. A deliberate longevity choice — protects the physical display +from years of always-on burn-in — not just a power-saving nicety. + +--- + +## Known issues + +- `DashboardSection`, `RequestAssistanceSection`, and `SwitchToXSection` + are plain `Container`s, not `Screen`s — this is intentional (see + Design Notes in the code), not a leftover from the tab-based layout. +- Touch-bar width (currently 20 cells, visible bar 12 cells) was sized + by eye against real-world hand width, not calculated from the + display's physical dimensions — terminal UIs size in character cells, + not physical units, so this is expected to need on-hardware + calibration once mounted, not a precise spec. +- Raw touch-swipe (as opposed to button taps) has not been tested on + the actual touchscreen hardware — the design deliberately does not + depend on it working, but it hasn't been ruled in or out. + +--- + +## Roadmap + +- [ ] Wire up **Request Assistance** — scripted outbound email via + `smtplib` notifying the responsible admin, hostname included + automatically +- [ ] Wire up **Switch to X** — calls a narrowly-scoped, sudoers-gated + wrapper script that switches to a dedicated VT and drops to a + standard login prompt (password required) before X starts +- [ ] Confirm touch-bar sizing on real hardware once display is mounted +- [ ] Confirm touch controller reports as standard HID + (`lsusb`/`dmesg`/`evtest`) — some earlier Waveshare display + revisions used a non-standard protocol requiring a custom driver +- [ ] Bring the script up to full CE OS scripting style guide compliance + (test gates, cleanup handling) + +--- + +## Licence + +The Unlicense — see [LICENSE](./LICENSE). Commercial use explicitly +permitted, no attribution required — though if this is useful to you, +consider a mention. + +--- + +*Built standing on the shoulders of billions of dwarves* +*Created by John A. Hoeven with the ethical assistance of Claude AI* \ No newline at end of file