Skip to content

SystemStatusModule

Exposes runtime system metrics as live display controls in the frontend. Introduced in Release 2, Sprint 1.


What it does

SystemStatusModule counts hot-path ticks in loop() and samples system metrics in loop1s() (called by the Scheduler at ~1 Hz). Each sample queries heap usage and computes a live fps value from the tick counter delta since the previous sample, then updates read-only display controls that the frontend renders as green text.

No state is persisted — all values are runtime-only metrics.


Controls

All controls are display type — rendered as read-only green text in the frontend, live-updated via WebSocket, never POST'd.

Dynamic — updated every ~1 s (via loop1s())

Key Description PC
fps Tick rate over the last ~1 s sample window
uptime_s Seconds elapsed since setup()
heap_free_kb Current free internal heap (KB) ✓ (via statvfs)
heap_min_kb Minimum free internal heap since boot (KB) 0 (not available)
max_alloc_kb Largest contiguous free block (KB); fragmentation indicator 0
core_temp CPU core temperature (°C) 0

Static — set once in setup()

Key Description PC
cpu_freq_mhz CPU clock frequency (MHz) 0
cpu_cores Number of CPU cores 0
total_heap_kb Total internal heap size (KB) 0
flash_size_mb Flash chip total size (MB) 0
flash_speed_mhz Flash chip clock speed (MHz) 0
sketch_kb Firmware size in flash (KB) 0
free_sketch_kb Remaining flash available for OTA (KB) 0
reset_reason Last reset cause code (esp_reset_reason_t int) 0

Identity — string, set once in setup()

Key Description PC
firmware_version Firmware version string; set via FIRMWARE_VERSION build flag (default "dev") "dev"
firmware_date Build date as YYYYMMDD string; derived from __DATE__ at compile time
sdk_version ESP-IDF version string from ESP.getSdkVersion() ""
chip_model Chip model and silicon revision, e.g. "ESP32-S3 Rev 2" ""

Platform notes

ESP32: heap_min_kb uses heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL) — this is an ESP-IDF heap scan that walks the free-block list. It takes ~10 ms on the very first call (during startup), settling to ~0.3 ms avg thereafter. This causes a max_ms spike of ~10 ms for SystemStatusModule in the first timing report, which is expected and not a concern.

PC: heap_min_kb is always 0.0 — reliable minimum-free tracking is not available cross-platform.


What cannot be matched from MoonLight's SystemStatusModule

The following fields from MoonLight/lib/framework/SystemStatusModule.cpp are not included because they are framework-specific or require data not available at runtime:

Field Reason
arduino_version No standard runtime API; ARDUINO macro is an integer, not a version string
flash_chip_mode String — QIO / DIO / QOUT; not exposed by Arduino ESP32
cpu_reset_reason Verbose string version of reset_reason; would require a lookup table
psram_* / psram_mode Conditionally present; mode is a string (OPI/QSPI)
heap_info_app / heap_info_dma Multi-field struct with emoji health string
lps_all / lps_effects / lps_drivers MoonLight-specific loop-per-second counters

Footprint (ESP32)

Sprint 1a (4 controls) Sprint 1b (14 controls) Sprint 1c (18 controls)
Static (classSize()) 272 B 536 B 224 B
controls_ heap 0 B (embedded in struct) 0 B (embedded 16 × 28 B) 560 B (lazy-allocated, 20-slot buffer)
RAM total 11.3% (37 KB / 320 KB) 11.3% (37 KB / 320 KB) 11.3% (37 KB / 320 KB)
Flash total 51.9% (680 KB / 1280 KB) 52.1% (683 KB / 1280 KB) 52.2% (684 KB / 1280 KB)

Sprint 1b embedded controls_[16] in the struct (+448 B vs Sprint 1a). Sprint 1c switches to lazy heap allocation: classSize() drops from 536 B to 224 B (array removed from struct); the 20-slot buffer (560 B) moves to heap. The struct gains 130 B of char[] string buffers (sdkVersion_[72], chipModel_[32], etc.), which is why Sprint 1c classSize is larger than Sprint 1a's 272 B.


Build and run results

ESP32 (Sprint 1c, 16×16, 18 controls): avg 0.011 ms, max 0.41 ms (500 ms sample gate), ~88 K fps own. Tick rate with all modules: ~145 fps at 1 000 ticks, ~133 fps at 2 000 ticks.

PC (Sprint 1c, 16×16, --count 5000, 18 controls): avg 0.0001 ms, ~14 M fps own. Adds negligible overhead.

See Release 2 — Observable, Hierarchical, and Network-Ready for sprint-by-sprint results and comparisons.


Source

Test coverage

System Status — LogLevel parsing, heapSize calculations, lifecycle, control count, healthReport keys after 1-second sampling.

Stateful Module — progress/button control types, sensitive reboot button, string controls.

Live: test0 — Infrastructure Modules — SystemStatusModule present on every device before each live test run.