System Info, Control & Service
The SystemInfo class is a set of static getters over the corresponding
ESP-IDF calls: the chip model, revision, core count and feature flags, the
ESP-IDF version, the application description embedded in the image (project
name, version, build date and time, ELF SHA-256), the running and boot
partitions with the OTA image state, the reset reason, uptime, base MAC, flash
and PSRAM sizes, CPU frequency and the free / lowest-free heap.
collect() gathers everything into one Snapshot and to_string()
renders a boot-banner style summary.
The SystemControl class restarts the device: reboot() (esp_restart),
and reboot_to_bootloader() which sets the chip’s force download boot
flag in its always-on register and restarts, so the next boot stays in the
ROM download mode instead of running the app — what holding the BOOT strap
during a reset does, without a button. The device then re-enumerates as the
ROM’s own flashing interface (the USB CDC / DFU device on the ESP32-S2 / -S3
native USB port; USB-Serial-JTAG on the ESP32-C3 / -C6 / -H2 / -C5 / -C61 /
-H21 / -P4), ready for esptool / idf.py flash. The classic ESP32 has
no software path (only the GPIO0 strap): bootloader_reboot_supported() is
false there and the call fails with operation_not_supported. The
*_after(delay) variants restart from a detached thread so a reply can
leave the transport first.
By default the reset tears the USB connection down and the ROM enumerates its
device afresh, which works for any application. On the ESP32-S2 / -S3 the ROM
can instead keep the USB peripheral’s state across the reset
(SystemControl::BootloaderOptions::usb_persist, passed through as
SystemService::Config::usb_persist) so the host sees no re-plug. This is
opt-in and off by default: the ROM only expects it from an application
whose USB device is ROM-CDC/DFU-compatible (ESP-IDF’s ROM USB console driver,
which is what performs the same sequence — usb_dc_prepare_persist() then
the persist flag — before its own reboot into the bootloader). A TinyUSB
composite device such as the espp examples’ vendor + CDC has different
descriptors, and persisting it can leave the host with a stale enumeration
the bootloader cannot serve; leave the option off there.
The SystemService class serves both over any byte stream as a
dispatcher module (espp.system v1,
module id 7 by default; Config::module moves an instance and hosts find
it through discovery by its protocol id). GET_INFO answers with a list of
tagged records ([tag u8][len u8][value]) a host decodes while skipping
tags it does not know, so fields can be added without a version bump. Every
reply echoes the request frame’s correlation id, so a host that stamps its
requests can pair replies with them and drop stale ones.
REBOOT and REBOOT_TO_BOOTLOADER reply OK first and restart after
the requested delay (clamped to Config::min_restart_delay). Both are
guarded: Config::allow_reboot / allow_bootloader switch them off, the
optional on_reboot_request callback can veto a specific request (an
application with a motor running can refuse or defer), and the bootloader
restart is refused on chips without a software path. The INFO
capabilities record tells a host up front which of the two it may offer.
The hosted espp System Console web app speaks
the protocol over WebUSB (vendor interface) or Web Serial (CDC, where
it doubles as a serial monitor): a device-info panel, the two restart buttons
(with an in-page confirmation), and — when the device also advertises the
monitor component’s MonitorService — heap-region
gauges and a live, sortable task table with a stream toggle.
API Reference
Header File
Classes
-
class SystemInfo
Static accessors for the identity and status of the running system: the chip, the ESP-IDF version, the application description (project name, version, build date / time, ELF SHA-256), the running / boot partitions and OTA state, the reset reason, uptime, base MAC, flash and PSRAM sizes, CPU frequency and heap figures.
Everything is a thin, allocation-light wrapper over the corresponding ESP-IDF call so it can be used from any task. collect() gathers it all into one Snapshot (what espp::SystemService reports to a host) and to_string() renders a human-readable summary for logs.
SystemInfo Example
// Boot banner: everything SystemInfo knows, in one string. logger.info("System:\n{}", espp::SystemInfo::to_string()); logger.info("Reboot into the bootloader is {} on this chip", espp::SystemControl::bootloader_reboot_supported() ? "supported" : "NOT supported"); // The OTA and core-dump engines, shared by the per-transport services below. // A panic core-dumps to the `coredump` partition (sdkconfig / partitions.csv) // and is reported here on the next boot; the coredump console downloads / // erases it. OTA alternates between ota_0 / ota_1 with host-driven rollback // confirmation, exactly as the ota example does. espp::CoreDump core_dump({.log_level = espp::Logger::Verbosity::INFO}); const std::string crash_report = core_dump.format_report(); if (crash_report.empty()) logger.info("Clean boot history (reset reason: {})", espp::CoreDump::reset_reason_name(espp::CoreDump::reset_reason())); else logger.error("Previous abnormal reset:\n{}", crash_report); espp::Ota ota({.reject_same_version = false, .log_level = espp::Logger::Verbosity::INFO}); if (ota.is_pending_verify()) logger.warn("This image is PENDING VERIFY (first boot after an OTA update): it rolls back on " "the next reset unless the host confirms it (MARK_VALID from the OTA console)"); // USB composite device: a vendor/WebUSB function and a CDC function, both // carrying the same framed protocol. espp::UsbDevice::Config usb_cfg; usb_cfg.pid = 0x0d37; // distinct from the espp default so the webapp filter is specific usb_cfg.manufacturer = "espp"; usb_cfg.product = "espp System"; usb_cfg.log_level = espp::Logger::Verbosity::WARN; espp::UsbDevice::CdcFunction cdc; cdc.interface_name = "espp System (CDC)"; usb_cfg.cdc = cdc; espp::UsbDevice::VendorFunction vendor; vendor.interface_name = "espp System (WebUSB)"; vendor.webusb = true; // advertise BOS / WebUSB / MS OS 2.0 descriptors vendor.landing_page_url = "esp-cpp.github.io/espp/apps/system_console.html"; usb_cfg.vendor = vendor; espp::UsbDevice usb(usb_cfg); // Replies go back on the stream the request came in on: one send function // per transport. Both services share each transport and only serialize // their OWN frames (a streamed monitor event and a system reply come from // different tasks), so every device->host write on a transport goes through // one application-level mutex; write_vendor / write_cdc are all-or-nothing // per call, so a frame is never truncated or interleaved. std::mutex vendor_tx_mutex, cdc_tx_mutex; auto vendor_send = [&](std::span<const uint8_t> frame) { std::lock_guard<std::mutex> lock(vendor_tx_mutex); usb.write_vendor(frame); }; auto cdc_send = [&](std::span<const uint8_t> frame) { std::lock_guard<std::mutex> lock(cdc_tx_mutex); usb.write_cdc(frame); }; // The application decides whether a reboot may happen right now: this demo // permits every request and logs it. A real application would refuse (or // defer) while, say, a motor is running or a file is being written. auto reboot_request = [&](espp::SystemService::RebootKind kind) { logger.warn("Host requested a {}; allowing it", kind == espp::SystemService::RebootKind::Bootloader ? "reboot into the bootloader" : "reboot"); return true; }; // One service instance per transport (they are cheap; each replies on its // own stream). Declared BEFORE the workers that call into them. espp::SystemService vendor_system({.send = vendor_send, .on_reboot_request = reboot_request, .log_level = espp::Logger::Verbosity::INFO}); espp::SystemService cdc_system({.send = cdc_send, .on_reboot_request = reboot_request, .log_level = espp::Logger::Verbosity::INFO}); espp::MonitorService vendor_monitor( {.send = vendor_send, .task_config = {.name = "monitor_v", .stack_size_bytes = 6 * 1024}, .log_level = espp::Logger::Verbosity::INFO}); espp::MonitorService cdc_monitor( {.send = cdc_send, .task_config = {.name = "monitor_c", .stack_size_bytes = 6 * 1024}, .log_level = espp::Logger::Verbosity::INFO}); // OTA and core dump: one service per transport over the shared engines (each // OtaService only touches the session IT began, so the two cannot interfere). espp::OtaService vendor_ota(ota, {.send = vendor_send, .log_level = espp::Logger::Verbosity::INFO}); espp::OtaService cdc_ota(ota, {.send = cdc_send, .log_level = espp::Logger::Verbosity::INFO}); espp::CoreDumpService vendor_coredump( core_dump, {.send = vendor_send, .log_level = espp::Logger::Verbosity::INFO}); espp::CoreDumpService cdc_coredump( core_dump, {.send = cdc_send, .log_level = espp::Logger::Verbosity::INFO}); // One DispatcherWorker per byte stream: a bounded receive queue + worker // task feeding its Dispatcher, so the services never run on the TinyUSB // task. Registering a service routes its module to it and advertises it for // discovery; serve_discovery() answers the hub's ListModules query. // On an RX overflow the OTA service aborts a transfer it owned and tells the // host (an OTA image with dropped bytes is unusable). espp::DispatcherWorker vendor_link( {.send = vendor_send, .on_overflow = [&]() { vendor_ota.on_rx_overflow(); }, .task_config = {.name = "system_rx_vendor", .stack_size_bytes = 8192}}); espp::DispatcherWorker cdc_link( {.send = cdc_send, .on_overflow = [&]() { cdc_ota.on_rx_overflow(); }, .task_config = {.name = "system_rx_cdc", .stack_size_bytes = 8192}}); vendor_link.register_module(vendor_system); vendor_link.register_module(vendor_monitor); vendor_link.register_module(vendor_ota); vendor_link.register_module(vendor_coredump); cdc_link.register_module(cdc_system); cdc_link.register_module(cdc_monitor); cdc_link.register_module(cdc_ota); cdc_link.register_module(cdc_coredump); vendor_link.serve_discovery(usb_cfg.product); cdc_link.serve_discovery(usb_cfg.product);
Public Static Functions
-
static inline const char *chip_model_name(esp_chip_model_t model)
Chip model name for an esp_chip_model_t (“ESP32-S3”, …).
-
static inline const char *reset_reason_name(esp_reset_reason_t reason)
Human-readable name for an esp_reset_reason_t.
-
static inline const char *ota_state_name(uint8_t state)
Human-readable name for an OTA image state byte (Snapshot::ota_state).
-
static inline esp_chip_info_t chip_info()
Chip information (model, revision, cores, features).
-
static inline std::string idf_version()
The ESP-IDF version string the app was built with.
-
static inline const esp_app_desc_t &app_description()
The application description embedded in the running image.
-
static inline std::string running_partition()
Label of the partition the running app was loaded from (”” if unknown).
-
static inline std::string boot_partition()
Label of the partition the bootloader will boot next (”” if unknown).
-
static inline uint8_t ota_state()
OTA image state of the running partition (esp_ota_img_states_t as a byte; 0xFF when the app runs from a factory partition or the state cannot be read).
-
static inline esp_reset_reason_t reset_reason()
Why the chip last reset.
-
static inline uint64_t uptime_ms()
Milliseconds since boot.
-
static inline std::array<uint8_t, 6> base_mac()
The chip’s base (factory-programmed) MAC address.
-
static inline uint32_t flash_size()
Size of the main SPI flash in bytes (0 if it cannot be read).
-
static inline uint32_t psram_size()
Size of the PSRAM in bytes (0 without PSRAM / with CONFIG_SPIRAM off).
-
static inline uint32_t cpu_mhz()
Current CPU frequency in MHz.
-
static inline uint32_t free_heap()
Free heap in bytes (default capabilities).
-
static inline uint32_t min_free_heap()
Lowest free heap since boot, in bytes.
-
static inline std::string to_string(const Snapshot &s)
A multi-line human-readable summary of a Snapshot.
-
static inline std::string to_string()
Collect and format in one call (for a boot banner).
-
struct Snapshot
Everything collect() gathers.
Public Members
-
std::string chip_model
e.g. “ESP32-S3”
-
uint16_t chip_revision = {0}
MXX: major * 100 + minor.
-
uint8_t cores = {0}
CPU core count.
-
uint32_t chip_features = {0}
CHIP_FEATURE_* bitmask.
-
std::string idf_version
e.g. “v6.1”
-
std::string project_name
CMake project name.
-
std::string app_version
PROJECT_VER.
-
std::string build_date
compile date
-
std::string build_time
compile time
-
std::array<uint8_t, 32> elf_sha256 = {}
SHA-256 of the application ELF.
-
std::string running_partition
label of the partition the app runs from
-
std::string boot_partition
label of the partition the bootloader will boot next
-
uint8_t ota_state = {0xFF}
esp_ota_img_states_t of the running partition; 0xFF = n/a
-
uint8_t reset_reason = {0}
esp_reset_reason_t
-
uint64_t uptime_ms = {0}
time since boot
-
std::array<uint8_t, 6> mac = {}
base MAC address
-
uint32_t flash_size = {0}
bytes
-
uint32_t psram_size = {0}
bytes (0 = none / disabled)
-
uint32_t cpu_mhz = {0}
current CPU frequency
-
uint32_t free_heap = {0}
bytes
-
uint32_t min_free_heap = {0}
bytes, lowest since boot
-
std::string chip_model
-
static inline const char *chip_model_name(esp_chip_model_t model)
Header File
Classes
-
class SystemControl
Restart control: a plain reboot, and a reboot into the ROM bootloader’s download (serial flashing) mode.
reboot_to_bootloader() sets the chip’s “force download boot” flag in its always-on register and restarts, so the next boot stays in the ROM download mode instead of running the app — exactly what holding the BOOT strap during a reset does, without touching a button. The device then re-enumerates as the ROM’s own flashing interface: the USB CDC / DFU device on the ESP32-S2 / -S3 native USB port, or USB-Serial-JTAG on the ESP32-C3 / -C6 / -H2 / -C5 / -C61 / -H21 / -P4 — so `esptool` / `idf.py flash` can program it. On the classic ESP32 there is no software path (only the GPIO0 strap): bootloader_reboot_supported() is false and reboot_to_bootloader() fails with operation_not_supported.
**USB persistence (S2 / S3, opt-in)**: by default the reset tears the USB connection down and the ROM enumerates its CDC / DFU device afresh, which works for any application. The ROM can instead keep the USB peripheral’s state across the reset (BootloaderOptions::usb_persist), so the host sees no re-plug — but the ROM only expects that from an application whose USB device is ROM-CDC/DFU-compatible (the same descriptors the ROM exposes, as ESP-IDF’s ROM USB console has); a TinyUSB composite device (the espp examples: vendor + CDC) has different descriptors, and persisting it can leave the host with a stale enumeration the bootloader cannot serve. Leave it off unless the application runs on the ROM USB console driver.
Both functions restart immediately; use the delayed variants (or espp::SystemService, which replies before restarting) when a reply must leave the transport first.
Public Types
-
using BootloaderOptions = SystemBootloaderOptions
Options for the reboot into download mode (see SystemBootloaderOptions).
Public Static Functions
-
static inline constexpr bool bootloader_reboot_supported()
Whether reboot_to_bootloader() is implemented for this chip.
-
static inline void reboot()
Restart the chip (esp_restart()); does not return.
-
static inline bool reboot_to_bootloader(std::error_code &ec, const BootloaderOptions &options = {})
Restart into the ROM bootloader’s download mode.
- Parameters:
ec – Set to operation_not_supported on chips without a software path (classic ESP32); then returns false without restarting.
options – See BootloaderOptions (USB persistence is opt-in).
- Returns:
Does not return on success; false on failure.
-
static inline void reboot_after(std::chrono::milliseconds delay)
Restart after a delay, from a detached thread, so the caller can finish (e.g. send a reply) first. Returns immediately.
-
static inline bool reboot_to_bootloader_after(std::chrono::milliseconds delay, std::error_code &ec, const BootloaderOptions &options = {})
Restart into download mode after a delay, from a detached thread. Returns immediately; false (nothing scheduled) if unsupported.
-
using BootloaderOptions = SystemBootloaderOptions
Header File
Classes
-
class SystemService : public espp::BaseComponent
Serves espp::SystemInfo and espp::SystemControl over any framed byte stream (dispatcher module 7 by default; see Config::module).
GET_INFO answers with a tagged-record snapshot (see detail/system_protocol.hpp; hosts skip tags they do not know). REBOOT and REBOOT_TO_BOOTLOADER reply OK first and restart after the requested delay (at least Config::min_restart_delay, so the reply leaves the transport) from a detached thread — the same pattern as OtaService’s post-update restart. Both are guarded: Config::allow_reboot / allow_bootloader switch them off (ERROR “not permitted”), the optional Config::on_reboot_request
callback can veto a specific request (an application with a motor running can refuse or defer), and REBOOT_TO_BOOTLOADER is refused with “not
supported” on chips without a software download-mode path (classic ESP32). The INFO capabilities record tells a host up front which of the two it may offer.
**Threading**: an internal mutex covers the parser and request handling; the `send` callback and the veto callback run after it is released. Drive one instance from one context per byte stream (a Dispatcher / DispatcherWorker, or a single task calling feed()).
SystemService Example
// Boot banner: everything SystemInfo knows, in one string. logger.info("System:\n{}", espp::SystemInfo::to_string()); logger.info("Reboot into the bootloader is {} on this chip", espp::SystemControl::bootloader_reboot_supported() ? "supported" : "NOT supported"); // The OTA and core-dump engines, shared by the per-transport services below. // A panic core-dumps to the `coredump` partition (sdkconfig / partitions.csv) // and is reported here on the next boot; the coredump console downloads / // erases it. OTA alternates between ota_0 / ota_1 with host-driven rollback // confirmation, exactly as the ota example does. espp::CoreDump core_dump({.log_level = espp::Logger::Verbosity::INFO}); const std::string crash_report = core_dump.format_report(); if (crash_report.empty()) logger.info("Clean boot history (reset reason: {})", espp::CoreDump::reset_reason_name(espp::CoreDump::reset_reason())); else logger.error("Previous abnormal reset:\n{}", crash_report); espp::Ota ota({.reject_same_version = false, .log_level = espp::Logger::Verbosity::INFO}); if (ota.is_pending_verify()) logger.warn("This image is PENDING VERIFY (first boot after an OTA update): it rolls back on " "the next reset unless the host confirms it (MARK_VALID from the OTA console)"); // USB composite device: a vendor/WebUSB function and a CDC function, both // carrying the same framed protocol. espp::UsbDevice::Config usb_cfg; usb_cfg.pid = 0x0d37; // distinct from the espp default so the webapp filter is specific usb_cfg.manufacturer = "espp"; usb_cfg.product = "espp System"; usb_cfg.log_level = espp::Logger::Verbosity::WARN; espp::UsbDevice::CdcFunction cdc; cdc.interface_name = "espp System (CDC)"; usb_cfg.cdc = cdc; espp::UsbDevice::VendorFunction vendor; vendor.interface_name = "espp System (WebUSB)"; vendor.webusb = true; // advertise BOS / WebUSB / MS OS 2.0 descriptors vendor.landing_page_url = "esp-cpp.github.io/espp/apps/system_console.html"; usb_cfg.vendor = vendor; espp::UsbDevice usb(usb_cfg); // Replies go back on the stream the request came in on: one send function // per transport. Both services share each transport and only serialize // their OWN frames (a streamed monitor event and a system reply come from // different tasks), so every device->host write on a transport goes through // one application-level mutex; write_vendor / write_cdc are all-or-nothing // per call, so a frame is never truncated or interleaved. std::mutex vendor_tx_mutex, cdc_tx_mutex; auto vendor_send = [&](std::span<const uint8_t> frame) { std::lock_guard<std::mutex> lock(vendor_tx_mutex); usb.write_vendor(frame); }; auto cdc_send = [&](std::span<const uint8_t> frame) { std::lock_guard<std::mutex> lock(cdc_tx_mutex); usb.write_cdc(frame); }; // The application decides whether a reboot may happen right now: this demo // permits every request and logs it. A real application would refuse (or // defer) while, say, a motor is running or a file is being written. auto reboot_request = [&](espp::SystemService::RebootKind kind) { logger.warn("Host requested a {}; allowing it", kind == espp::SystemService::RebootKind::Bootloader ? "reboot into the bootloader" : "reboot"); return true; }; // One service instance per transport (they are cheap; each replies on its // own stream). Declared BEFORE the workers that call into them. espp::SystemService vendor_system({.send = vendor_send, .on_reboot_request = reboot_request, .log_level = espp::Logger::Verbosity::INFO}); espp::SystemService cdc_system({.send = cdc_send, .on_reboot_request = reboot_request, .log_level = espp::Logger::Verbosity::INFO}); espp::MonitorService vendor_monitor( {.send = vendor_send, .task_config = {.name = "monitor_v", .stack_size_bytes = 6 * 1024}, .log_level = espp::Logger::Verbosity::INFO}); espp::MonitorService cdc_monitor( {.send = cdc_send, .task_config = {.name = "monitor_c", .stack_size_bytes = 6 * 1024}, .log_level = espp::Logger::Verbosity::INFO}); // OTA and core dump: one service per transport over the shared engines (each // OtaService only touches the session IT began, so the two cannot interfere). espp::OtaService vendor_ota(ota, {.send = vendor_send, .log_level = espp::Logger::Verbosity::INFO}); espp::OtaService cdc_ota(ota, {.send = cdc_send, .log_level = espp::Logger::Verbosity::INFO}); espp::CoreDumpService vendor_coredump( core_dump, {.send = vendor_send, .log_level = espp::Logger::Verbosity::INFO}); espp::CoreDumpService cdc_coredump( core_dump, {.send = cdc_send, .log_level = espp::Logger::Verbosity::INFO}); // One DispatcherWorker per byte stream: a bounded receive queue + worker // task feeding its Dispatcher, so the services never run on the TinyUSB // task. Registering a service routes its module to it and advertises it for // discovery; serve_discovery() answers the hub's ListModules query. // On an RX overflow the OTA service aborts a transfer it owned and tells the // host (an OTA image with dropped bytes is unusable). espp::DispatcherWorker vendor_link( {.send = vendor_send, .on_overflow = [&]() { vendor_ota.on_rx_overflow(); }, .task_config = {.name = "system_rx_vendor", .stack_size_bytes = 8192}}); espp::DispatcherWorker cdc_link( {.send = cdc_send, .on_overflow = [&]() { cdc_ota.on_rx_overflow(); }, .task_config = {.name = "system_rx_cdc", .stack_size_bytes = 8192}}); vendor_link.register_module(vendor_system); vendor_link.register_module(vendor_monitor); vendor_link.register_module(vendor_ota); vendor_link.register_module(vendor_coredump); cdc_link.register_module(cdc_system); cdc_link.register_module(cdc_monitor); cdc_link.register_module(cdc_ota); cdc_link.register_module(cdc_coredump); vendor_link.serve_discovery(usb_cfg.product); cdc_link.serve_discovery(usb_cfg.product);
Public Types
-
enum class RebootKind : uint8_t
Which restart a host asked for (passed to Config::on_reboot_request).
Values:
-
enumerator Reboot
plain restart
-
enumerator Bootloader
restart into the ROM download mode
-
enumerator Reboot
-
using send_fn = std::function<void(std::span<const uint8_t> frame)>
Transmits one encoded reply frame to the host.
-
using reboot_request_fn = std::function<bool(RebootKind kind)>
Asked (outside the lock) before a permitted reboot is acknowledged; return false to veto it (the host gets ERROR “refused by the application”).
Public Functions
-
inline uint8_t module_id() const
The dispatcher module id this service answers on (Config::module).
-
inline Dispatcher::ModuleInfo module_info() const
Discovery metadata for registering this service on a Dispatcher.
-
inline uint32_t capabilities() const
The capabilities bitmask GET_INFO reports (kCapReboot / kCapBootloader).
-
inline std::vector<uint8_t> build_info() const
Build the INFO payload (a SystemInfo snapshot as tagged records).
-
inline void handle(const espp::stream_frame::Frame &frame)
Dispatcher entry point: handle one routed frame. Frames for other modules and reply-flagged frames are ignored, so this can be registered directly: `dispatcher.register_module(service)`.
-
inline void feed(std::span<const uint8_t> data)
Feed received transport bytes (standalone use, without a Dispatcher).
-
inline bool handle_frame(uint8_t type, std::span<const uint8_t> payload, std::optional<uint16_t> correlation = std::nullopt)
Handle one already-parsed request frame.
Note
The `send` and veto callbacks run after the internal mutex is released.
- Parameters:
correlation – The request frame’s correlation id, if it carried one; every reply echoes it so the host can pair them.
- Returns:
true if the type belongs to the system protocol (a reply was sent), false if it was ignored.
-
inline const std::string &get_name() const
Get the name of the component
Note
This is the tag of the logger
- Returns:
A const reference to the name of the component
-
inline void set_log_tag(const std::string_view &tag)
Set the tag for the logger
- Parameters:
tag – The tag to use for the logger
-
inline espp::Logger::Verbosity get_log_level() const
Get the log level for the logger
See also
See also
- Returns:
The verbosity level of the logger
-
inline void set_log_level(espp::Logger::Verbosity level)
Set the log level for the logger
See also
See also
- Parameters:
level – The verbosity level to use for the logger
-
inline void set_log_verbosity(espp::Logger::Verbosity level)
Set the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls set_log_level
- Parameters:
level – The verbosity level to use for the logger
-
inline espp::Logger::Verbosity get_log_verbosity() const
Get the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls get_log_level
- Returns:
The verbosity level of the logger
-
inline void set_log_rate_limit(std::chrono::duration<float> rate_limit)
Set the rate limit for the logger
See also
Note
Only calls to the logger that have _rate_limit suffix will be rate limited
- Parameters:
rate_limit – The rate limit to use for the logger
Public Static Attributes
-
static constexpr uint8_t kModule = espp::detail::system_protocol::kModule
Default dispatcher module id (7). Only a routing key: Config::module serves on any id, and the hosted system console finds it through discovery (by kProtocol).
-
static constexpr const char *kProtocol = espp::detail::system_protocol::kProtocol
Stable protocol identifier + version advertised through discovery.
-
struct Config
Configuration for the SystemService.
Public Members
-
uint8_t module = {kModule}
Dispatcher module id this instance answers on (and stamps on its replies). A routing key only: hosts find whichever id is chosen through discovery (by kProtocol), so any id 0x00..0xEF is fine.
-
bool allow_reboot = {true}
Serve REBOOT (else ERROR “not permitted”).
-
bool allow_bootloader = {true}
Serve REBOOT_TO_BOOTLOADER (else ERROR “not permitted”).
-
bool usb_persist = {false}
Keep the USB peripheral’s state across a REBOOT_TO_BOOTLOADER reset (ESP32-S2 / -S3 ROM only; see SystemControl::BootloaderOptions). Off by default: the ROM re-enumerates its CDC / DFU device on its own, which is right for a TinyUSB (vendor / CDC composite) application; enable only when the application’s USB device is ROM-CDC/DFU-compatible.
-
reboot_request_fn on_reboot_request = {nullptr}
Optional veto for a specific reboot request; called after the allow_* checks, outside the lock. nullptr = every permitted request proceeds.
-
std::chrono::milliseconds min_restart_delay = {250}
Lower bound on the delay between the OK reply and the restart, so the reply reaches the host even when it asked for 0 ms.
-
uint8_t module = {kModule}
-
enum class RebootKind : uint8_t