SystemModule
Source:
SystemModule.h
SystemModule¶
src/core/SystemModule.h:76Inherits:
MoonModule
System-level diagnostics and device identity — always loaded, always visible in the UI.
Surfaces the live tick metrics (uptime, fps, tick time, free heap, PSRAM, largest allocatable block), the static hardware facts (chip, CPU clock + cores, SDK/IDF version, flash size, boot/reset reason, WiFi co-processor state), and owns the device's identity: its network name and its physical-hardware model.
Controls (ordered by change frequency):
-
Dynamic (every second):
uptime(progress),fps(derived from the Scheduler's tick time),tickTimeUs(average tick, microseconds),heap(progress: used / total internal),psram(progress: used / total, only when present),maxBlock(largest contiguous allocatable block). -
Configurable:
deviceName(defaultMM-XXXX, XXXX = last 4 hex of the MAC) anddeviceModel(display-only in the UI, pushed by tooling). -
Static (set at boot):
chip,cpu(core count, plus the running clock on ESP32 — read from the hardware so a misconfigured frequency is visible; desktop reports cores only),sdk,flash,bootReason,wifiCoproc, andpsramType(quad / octal, shown only on a PSRAM board — the interface mode the firmware drives the PSRAM in). On desktop the hardware-specific fields read "desktop" / "N/A".
wifiCoproc: shown only on boards whose radio is a separate chip (the ESP32-P4 with its on-board ESP32-C6 over esp_hosted); absent on native-radio targets (the platform returns an empty string and the control is not added). Reports the detected slave firmware version (C6 fw 2.12.9) when the link is up, or not detected when the C6 never completes its handshake / reports 0.0.0 — the signature of absent or incompatible C6 slave firmware. tick1s() re-queries it, so the state stays current if the link comes up after boot or the C6 is reflashed without a host reboot.
Device name:deviceName is the single network identity across the system — NetworkModule uses it as the mDNS hostname (<name>.local), the SoftAP SSID, and the DHCP hostname, and MoonDeck shows it in the device list. It is coerced to a valid, non-empty hostname every tick (sanitize + MAC fallback) so whatever the user typed or persistence restored, a live rename propagates everywhere within one tick — see tick1s(). The default MM-XXXX derives from the last 4 hex of the MAC.
Device model:deviceModel is the physical-hardware identity (which product this is, for example Olimex ESP32-Gateway Rev G) — the entry name from the device-model catalog. The device cannot self-identify its hardware, so this is pushed by tooling: the web installer sends it as an APPLY_OP``set op during provisioning, or MoonDeck over HTTP /api/control. The printable-ASCII rule (1..31 chars, 0x20–0x7E, no NUL) is a per-control validator on the descriptor, so every write path (HTTP, serial APPLY_OP, persistence load) runs it in the backend. See validateDeviceModel.
bootReason: the human-readable reset reason from platform::resetReason() (POWERON, SW, PANIC, INT_WDT, TASK_WDT, BROWNOUT, DEEPSLEEP; desktop always reports OK). The UI flags the reboot button with a red border when the value is one of PANIC / INT_WDT / TASK_WDT / BROWNOUT, indicating the prior boot ended unexpectedly.
PSRAM detection is derived, not flagged: ESP-IDF auto-detects the PSRAM chip at boot and merges its pool into the heap allocator, after which totalHeap() reports internal + PSRAM combined while totalInternalHeap() reports internal only — so totalHeap > totalInternal is the "PSRAM present" signal. Boards without PSRAM skip the psram control naturally, with no per-platform code path.
Children: accepts no user-added children — System is fixed infrastructure. Its child modules (Tasks, I2cScan, …) are wired by code in main.cpp and marked wired-by-code; user-added capability modules live under the Services container instead. (The deviceModel identity is a SystemModule control above, not a child module — SystemModule owns the device's identity, name + model, directly.)
Prior art: MoonLight — system diagnostics via REST API; device name used for mDNS.

Public Methods¶
inline void setScheduler(Scheduler * s)
virtual inline bool respectsEnabled() const override
: Diagnostics keep ticking regardless — disabling System hides uptime/heap/fps from the UI for no good reason, and the user can't easily re-enable.
virtual inline void setup() override
: Accepts no user-added children — System is fixed infrastructure.
virtual inline void defineControls() override
: defineControls MUST be idempotent and pure: only controls_.clear() + controls_.addX().
virtual inline void tick1s() override
inline constchar * deviceName() const
: The device's network identity (mDNS hostname, SoftAP SSID, DHCP hostname all derive from it).
inline constchar * deviceModel() const
: The physical-hardware identity (device-model catalog entry name), pushed by tooling.
Public Static Methods¶
static inline bool validateDeviceModel(constchar * value)
: Per-control validator for deviceModel, applied on EVERY write path (HTTP /api/control, APPLY_OP over serial, persistence load) via ControlDescriptor::validate.