feat(stats): ambient + 4TB USB SSD temperature graphs (v0.94.0) - #206
Merged
Conversation
Add two live temperature graphs to System → Stats alongside CPU/MEM/DISK: - Ambient: motherboard ACPI thermal zone (room-temperature proxy) - 4TB SSD: connected SanDisk Extreme Pro (NVMe behind an ASMedia USB bridge, invisible to `sensors`; read via `sudo smartctl -j -x -d sntasmedia`, device auto-detected via `lsblk -S`, cached 20s) Bars color cool→warm→hot by threshold. A note line surfaces the drive's lifetime SMART over-temp counters (warning_temp_time / critical_comp_time) — the persistent "has it ever overheated" record (0 min on NomadPC). /system/stats now also returns ambient_temp_c, ssd_temp_c, ssd_warning_time_min, ssd_critical_time_min (omitted when unavailable, so the rows hide on a Pi with no external drive or where smartctl is absent). Requires smartmontools (added to MINIPC-SETUP.md). Unit tests cover the ambient sentinel filtering, smartctl parse/cache, and endpoint shaping. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Cache failed SSD probes too (populated flag) so a missing/unresponsive smartctl no longer spawns a 10s-blocking subprocess on every 5s poll. - Re-detect the USB SSD each read (no permanent path cache) and prefer the disk whose model identifies it as the SanDisk Extreme Pro, via robust `lsblk -P` key=value parsing — survives reconnect / avoids matching the wrong USB disk. - Omit ssd_warning_time_min / ssd_critical_time_min from /system/stats when the drive doesn't report them (was serializing null), matching the other optional temp fields. - Tests: device-detection (prefer-SanDisk / fallback / non-usb / lsblk error), negative-cache (two failed reads = one subprocess), null-counter omission. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Guard shlex.split() parsing inside the try in _find_usb_ssd_device so a malformed lsblk line (unbalanced quote → ValueError) can't propagate up and 500 the whole /system/stats endpoint (defeating "never break stats"). - Clear a temp sparkline's history when its sensor goes absent, so a later reconnect starts a fresh graph instead of resuming a stale prefix. - Surface the SSD lifetime over-temp note if EITHER counter is reported (was keyed on warning alone). - Test: malformed-lsblk line returns None. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds two live temperature graphs to System → Stats, alongside CPU/MEM/DISK:
Bars color cool→warm→hot by threshold. A note line surfaces the drive's lifetime SMART over-temp counters — the persistent "has it ever overheated" record (0 min on NomadPC).
Why
The mini PC lives in a South Carolina room where the AC is left off for days (100°F+ ambient). The CPU sensor alone doesn't tell us whether the drives or the room are getting dangerously hot. This surfaces both.
How
The 4TB SSD is an NVMe drive behind an ASMedia USB bridge that
sensorscan't see — plain SAT/SCSI/JMicron passthrough all fail. It's read viasudo smartctl -j -x -d sntasmedia /dev/sda:lsblk -S -P(robust key=value parse), preferring the disk whose model identifies it as the SanDisk; re-detected each read so a reconnect that renames the node is picked up.sudo smartctlper request.smartctlexit code is a status bitmask — stdout JSON is parsed regardless.GET /system/statsnow also returnsambient_temp_c,ssd_temp_c,ssd_warning_time_min,ssd_critical_time_min(each omitted when unavailable).Deploy notes
smartmontools(already installed on NomadPC; added toMINIPC-SETUP.mdfor reprovisioning). Thenomadservice user has passwordless sudo..pychange → auto-deploy restartskj-controller(interrupts active playback).Testing
smartctl+psutil):{ambient_temp_c: 27.8, ssd_temp_c: 44, ssd_warning_time_min: 0, ssd_critical_time_min: 0}.Reviewed locally with CodeRabbit (3 findings addressed) + a fallback agent review (shlex-guard hardening).
@coderabbitai ignore