-
Notifications
You must be signed in to change notification settings - Fork 3
Configuration
Raft applications are configured using JSON, in three layered tiers.
Every Raft application has a single hierarchical JSON document that all SysMods read their settings from. Practically that document is assembled at runtime from up to three sources, with later sources overriding earlier ones.
This page describes those layers, how a SysMod fetches its slice, how runtime updates are persisted, and how to react to configuration changes. The underlying parser is documented in JSON / RaftJson, and advanced features in Advanced RaftJson.
| Layer | Source | Owned by | Mutability | Typical contents |
|---|---|---|---|---|
| 1. Compiled defaults | A const char* JSON literal compiled into flash (in RaftCoreApp.cpp) |
Framework | Read-only | Last-resort fallback values: SystemName, SysManager defaults, RICSerial framing bytes, ... |
| 2. SysType | The currently-selected SysType JSON, generated from systypes/ at build time and bound at startup |
App / build system | Effectively read-only at runtime | Pin assignments, default WiFi/BLE/Web settings, the DevMan.Devices list, feature toggles |
| 3. NV-mutable | A document persisted to ESP-IDF Non-Volatile Storage (NVS) in the namespace "sys"
|
App at runtime | Mutable via REST / SysMod APIs | Per-deployment overrides: WiFi credentials, friendly names, anything the user changes after the fact |
The wiring lives in RaftCoreApp and uses three RaftJson* objects:
RaftJsonNVS _systemConfig; // namespace "sys" — layer 3
RaftJson _sysTypeConfig; // — layer 2
RaftJson _defaultSystemConfig; // compiled-in JSON — layer 1
// In the constructor:
_sysTypeConfig.setChainedRaftJson(&_defaultSystemConfig);The "chain" mechanism is RaftJson's per-lookup fallback: when a path is not present in _sysTypeConfig, it is automatically retried in _defaultSystemConfig. See chaining for the precise semantics (in particular, the chain is followed at path-not-found boundaries — split layered config at object boundaries to avoid surprises).
_systemConfig (the NV layer, an instance of RaftJsonNVS) is what most SysMods are passed — it persists user-driven changes back to NVS automatically. The SysType layer is consulted for the build-time defaults of every section that has not been explicitly overridden in NVS.
Each RaftSysMod is constructed with a name and a reference to one of these top-level configurations. Internally the SysManager creates a RaftJsonPrefixed wrapper so the SysMod sees only the subtree under its own name.
For a SysMod called "NetworkManager", given:
the SysMod simply asks for unprefixed paths:
String ssid = configGetString("WiFiSSID", "");
long retry = configGetLong ("RetryMs", 1000);The prefixing is automatic. Within your SysMod use the configGet* helpers (which forward to _modConfig); only reach for the global config object when you genuinely need to read another module's section.
The numeric and string accessors are documented in JSON / RaftJson. For arrays, sub-objects, key enumeration and type queries see JSON / RaftJson — other helpful functions.
// systype.json (layer 2)
{
"SystemName": "WeatherStation",
"NetworkManager": { "WiFiAPMode": false },
"BLEManager": { "AdvertisingName": "WX-default" },
"ExampleSysMod": { "ExampleGpioPin": 4, "Period": 1000 }
}// In your SysMod (named "ExampleSysMod")
void setup() override
{
int pin = configGetInt ("ExampleGpioPin", -1);
long period = configGetLong ("Period", 500);
if (pin < 0) {
LOG_W(MODULE_PREFIX, "No pin configured");
return;
}
pinMode(pin, OUTPUT);
_periodMs = period;
}If the same key is later set in the NV layer (e.g. via REST), it shadows the SysType value the next time it is read.
Most SysMods expose getstatus / getsettings / setsettings REST endpoints that read and write their slice of the NV-mutable layer. A typical pattern from inside a SysMod:
// Persist the entire mutable slice for this module
String json = R"({"WiFiSSID":")" + newSsid + R"("})";
_sysManager.setMutableConfigForMod(modName(), json);The SysManager merges the new JSON into the appropriate spot in _systemConfig, calls setJsonDoc() on the underlying RaftJsonNVS (which writes through to NVS atomically), and then fires registered change callbacks.
Important properties:
- Whole-document writes. The NV layer is replaced wholesale on each persist; there is no in-place patch operation at the persistence layer. Read-modify-write happens above it.
- No restart required for most settings. Listeners receive a callback and re-read the keys they care about (see below).
- Some settings need a restart. Pin assignments and other build-time-baked values typically come from the SysType and cannot be changed via the NV layer. Affected SysMods will indicate this.
For BLE / WebSocket clients, runtime overrides are usually delivered via the same setsettings REST endpoint — see RaftCoreAPI and Built-in REST endpoint list.
A SysMod can register a callback that fires after the underlying NV document is replaced:
void setup() override
{
configRegisterChangeCallback([this]() {
// Re-read whatever you cached
_periodMs = configGetLong("Period", _periodMs);
LOG_I(MODULE_PREFIX, "Config changed, period now %ldms", _periodMs);
});
}Callbacks are not given any payload — they are a "something has changed, please re-read" signal. They run on the SysManager / NVS write context; keep them short and avoid blocking calls. Register multiple callbacks if you want logically separate handlers; there is no de-registration API so callback lifetime should match the SysMod's. See change callbacks for the underlying mechanism.
| Location | Purpose |
|---|---|
Compiled-in defaults in RaftCoreApp.cpp
|
The lowest fallback layer. Modify only if your derived RaftCoreApp needs different framework-level defaults. |
systypes/ |
Build-time configuration tree for each SysType. The active SysType becomes the layer-2 document at runtime. |
NVS namespace "sys"
|
Layer-3 persisted JSON. Inspect with RaftJsonNVS::debugShowNVSInfo(true). |
| Per-SysMod NVS namespaces | Some SysMods use additional RaftJsonNVS instances with their own namespaces for state that is logically separate from system config. |
To wipe all NV settings (factory reset), the standard mechanism is the reset REST endpoint or by erasing NVS at flash time. See RaftCoreAPI for the endpoints involved.
- JSON / RaftJson — path syntax and basic accessors.
- Advanced RaftJson — chaining, prefix views, NVS persistence, change callbacks.
- SysTypes and Top-Level SysType configuration — where the layer-2 document comes from.
- SysMods — the lifecycle within which configuration is consumed.
- RaftCoreAPI — REST endpoints that read and write configuration at runtime.
Getting Started
- Quick Start
- Architecture at a Glance
- Writing Your First SysMod
- Adding a Comms Channel
- Adding an I2C Device Type
- PlatformIO / Arduino
Scaffolding & Building
- Raft CLI
- SysTypes
- Top-Level SysType
- Build Process
- WebUI Build Pipeline
- File System
- Partitions & Flash
- Local Dev Libraries
- Library Developer Guide
Architecture
Built-in SysMods
- NetworkManager
- BLEManager
- WebServer
- MQTTManager
- SerialConsole
- CommandSerial
- CommandSocket
- CommandFile
- FileManager
- LogManager
- ESPOTAUpdate
- StatePublisher
- Remote Logging
- Data Source Registration
Comms & Protocols
- Stack Overview
- Comms Channels
- ProtocolExchange
- RICREST Protocol
- Real-Time Streams
- Adding REST Endpoints
- Built-in REST Endpoints
- File Download (OKTO)
- OTA Update Flow
Devices & Buses
- DeviceManager
- Device Manager REST API
- Device Factory & Classes
- Device Type Records
- Adding an I2C Device Type
- Device Data Publishing
- Data Logger
- I2C Bus
- I2C Device Scanning
- I2C ID & Polling
- MotorControl Overview
- MotorControl Config
- MotorControl Commands
Helpers
Reference
{ "NetworkManager": { "WiFiSSID": "home", "RetryMs": 5000 } }