Adding New Settings
Section titled “Adding New Settings”Relevant source files
- main/core/commands/esp0.cpp
- main/core/commands/esp100.cpp
- main/core/commands/esp132.cpp
- main/core/commands/esp133.cpp
- main/core/commands/esp281.cpp
- main/core/commands/esp400.cpp
- main/core/commands/esp950.cpp
- main/core/esp3d_commands.cpp
- main/core/esp3d_settings.cpp
- main/core/includes/esp3d_commands.h
- main/core/includes/esp3d_settings.h
- main/core/includes/esp3d_settings_defs.inc
- main/target/cnc/fluidnc/esp3d_target_settings_defs.inc
This guide explains how to add new persistent settings to the Pibot CNC Pendant firmware using the X-macro based settings system. Settings are stored in NVS (Non-Volatile Storage) and can optionally be configured via INI files during firmware updates.
Overview of the Settings System
Section titled “Overview of the Settings System”The settings system uses X-macros for compile-time code generation, producing type-safe enums, metadata tables, and validation checks from a single definition. Settings are categorized into:
- Core settings (main/core/includes/esp3d_settings_defs.inc#43-250) - System, network, services, UI, and authentication.
- Target settings (main/target/cnc/fluidnc/esp3d_target_settings_defs.inc#21-240) - CNC/firmware-specific settings like jog steps, probe configuration, or tool change behavior.
All settings are managed by the ESP3DSettings class (main/core/esp3d_settings.cpp#180-181) with automatic NVS persistence and schema versioning. The global instance is named esp3dXsettings (main/core/esp3d_settings.cpp#62).
Sources:main/core/includes/esp3d_settings.h#107-113main/core/esp3d_settings.cpp#62main/core/esp3d_settings.cpp#127-130
X-Macro Pattern Architecture
Section titled “X-Macro Pattern Architecture”The X-macro pattern allows defining each setting once using the ESP3D_SET_DEF macro, which expands multiple times during compilation to generate different code artifacts.
Natural Language to Code Entity Mapping (Architecture)
Section titled “Natural Language to Code Entity Mapping (Architecture)”Title: Settings System Entity Mapping
Sources:main/core/includes/esp3d_settings.h#102-113main/core/esp3d_settings.cpp#115-125main/core/esp3d_settings.cpp#156-160
Step 1: Define Your Setting
Section titled “Step 1: Define Your Setting”Setting Definition Syntax
Section titled “Setting Definition Syntax”ESP3D_SET_DEF(enum_name, // Identifier used in code (e.g., esp3d_baud_rate) "nvs_key", // NVS storage key (max 15 chars, e.g., "sys_baud") type, // byte_t, integer_t, string_t, ip_t, float_t size, // Max size (bytes for byte/int, string length) "default_value", // Default as string ini_info) // INI_ENTRY("section", "key") or NO_INIExample: Adding a Target Feature Flag
Section titled “Example: Adding a Target Feature Flag”Add to main/target/cnc/fluidnc/esp3d_target_settings_defs.inc:
ESP3D_SET_DEF(esp3d_new_feature_enabled, "tgt_new_feat", byte_t, 1, "1", INI_ENTRY("pendant", "New_feature_enabled"))Sources:main/core/includes/esp3d_settings_defs.inc#34-40main/core/includes/esp3d_settings.h#168-178main/target/cnc/fluidnc/esp3d_target_settings_defs.inc#39-44
Step 2: NVS Key Rules and Validation
Section titled “Step 2: NVS Key Rules and Validation”NVS Key Constraints
Section titled “NVS Key Constraints”| Rule | Requirement | Rationale |
|---|---|---|
| Maximum length | 15 characters | ESP-IDF NVS API limitation (main/core/esp3d_settings.cpp#158-159) |
| Uniqueness | Must be globally unique | Prevents storage collisions |
| Naming convention | Use prefixes | sys_, net_, tgt_, jog_ (main/core/includes/esp3d_settings_defs.inc#15main/target/cnc/fluidnc/esp3d_target_settings_defs.inc#15) |
Compile-Time Validation
Section titled “Compile-Time Validation”The system automatically validates NVS keys at compile time using static_assert within an anonymous namespace in the implementation file (main/core/esp3d_settings.cpp#157-159):
#define ESP3D_SET_DEF_VALIDATE(enum_name, nvs_key, type, size, default_val, ini_section, ini_key) \ static_assert(const_strlen(nvs_key) <= NVS_KEY_MAX_LEN, \ "NVS key '" nvs_key "' exceeds 15 character limit");Sources:main/core/esp3d_settings.cpp#145-174main/core/includes/esp3d_settings_defs.inc#12-16
Step 3: Setting Types and Sizes
Section titled “Step 3: Setting Types and Sizes”Type Reference (main/core/includes/esp3d_settings.h#151-162)
Section titled “Type Reference (main/core/includes/esp3d_settings.h#151-162)”| Type | C Type | Size Field | Use Case |
|---|---|---|---|
byte_t | uint8_t | 1 | Boolean flags, small enums |
integer_t | uint32_t | 4 | Baud rates, ports, intervals |
string_t | char[] | Max length | SSIDs, passwords, hostnames |
ip_t | uint32_t | 4 | IPv4 addresses (main/core/includes/esp3d_settings.h#156) |
float_t | char[] | 15 | Floating point values (stored as string) |
Sources:main/core/includes/esp3d_settings.h#151-162main/core/includes/esp3d_settings.h#171-173
Step 4: Reading and Writing Settings
Section titled “Step 4: Reading and Writing Settings”Settings are accessed via the global esp3dXsettings instance (main/core/esp3d_settings.cpp#62).
Data Flow Diagram
Section titled “Data Flow Diagram”Title: Setting Access Flow
Implementation Example
Section titled “Implementation Example”#include "esp3d_settings.h"
// Reading an integer settinguint32_t baud = esp3dXsettings.readUint32(ESP3DSettingIndex::esp3d_baud_rate);
// Writing a string settingesp3dXsettings.writeString(ESP3DSettingIndex::esp3d_sta_ssid, "MyNetwork");Sources:main/core/esp3d_settings.cpp#57main/core/esp3d_settings.cpp#62main/core/esp100.cpp#80-82main/core/esp100.cpp#208-209
Step 5: Exposing in ESP400 Command
Section titled “Step 5: Exposing in ESP400 Command”The [ESP400] command exports settings to external clients (WebUI, Serial) in JSON or text format (main/core/commands/esp400.cpp#98-100). To include your setting:
- Define Labels/Values: Add string arrays for the UI labels if it’s a list-type setting (main/core/commands/esp400.cpp#32-36).
- Dispatch: Call
dispatchSetting()in theESP400function (main/core/commands/esp400.cpp#128-134).
// Example in esp400.cpp for a list settingif (!dispatchSetting(json, "system/system", ESP3DSettingIndex::esp3d_baud_rate, "baud", BaudRateList, BaudRateList, sizeof(BaudRateList) / sizeof(char*), -1, -1, -1, nullptr, true, target, requestId)) { esp3d_log_e("Error sending response to clients");}Sources:main/core/commands/esp400.cpp#32-36main/core/commands/esp400.cpp#128-134main/core/commands/esp400.cpp#160-166
Step 6: Implementing Manual Command Handlers
Section titled “Step 6: Implementing Manual Command Handlers”For settings that require immediate action (like changing baud rates or themes), specific ESP commands are implemented in the ESP3DCommands class (main/core/includes/esp3d_commands.h#34).
Command Processing Flow
Section titled “Command Processing Flow”Title: ESP Command to Settings Update Flow
Sources:main/core/esp3d_commands.cpp#135-142main/core/commands/esp281.cpp#31-108main/core/commands/esp132.cpp#29-86
Step 7: Schema Versioning
Section titled “Step 7: Schema Versioning”When adding or modifying settings, you must update the versioning system to ensure NVS is correctly initialized.
- Major Version: Increment in
ESP3D_SETTINGS_VERSION_MAJORif you change the size or type of an existing setting. This triggers a full reset of all settings to defaults duringcheckSchemaVersion()(main/core/esp3d_settings.cpp#240-244). - Minor Version: Increment in
ESP3D_SETTINGS_VERSION_MINORif you add a new setting. This preserves existing settings while initializing the new one (main/core/esp3d_settings.cpp#248-251).
Sources:main/core/esp3d_settings.cpp#233-257main/core/includes/esp3d_settings_version.h#1-10