Configuration API
ArmorLink 0.4.0 exposes module settings through a JSON descriptor that is consumed by the ArmorLink App and the Web Node Configurator.
Configuration fields are registered in firmware, persisted on the node, restored after reboot, and can be edited remotely through BLE, ESP-NOW routing, or the serial configurator.
For the conceptual overview, see Configuration.
Basic Example
int brightness = 120;
bool eyesEnabled = true;
String nodeLabel = "Helmet";
module.config()
.addInt("brightness", &brightness, 120)
.label("Brightness")
.section("Lighting")
.tooltip("How bright the LEDs are.")
.range(0, 255)
.step(1)
.onIntChange([](int value) {
applyBrightness(value);
});
module.config()
.addBool("eyesEnabled", &eyesEnabled, true)
.label("Eyes")
.section("Lighting");
module.config()
.addString("nodeLabel", &nodeLabel, "Helmet")
.label("Node Label")
.section("System")
.rebootRequired();
Supported Field Types
| Method | Descriptor kind | Editable | Description |
|---|---|---|---|
addInt(...) | int | Yes | Whole number values such as GPIO pins, positions, durations, counts and brightness. |
addFloat(...) | float | Yes | Decimal values such as calibration factors or thresholds. |
addBool(...) | bool | Yes | Feature toggles and on/off settings. |
addString(...) | string | Yes | Names, labels and other text settings. |
addReadonly(...) | readonly | No | Informational values shown by tools but not editable. |
addServoConfig(...) | multiple int fields | Yes | Helper that registers GPIO, open/closed positions and pulse range for a servo. |
All editable fields default to entity: "config" and command: <key> unless overridden.
Field Builders
addInt
int volume = 20;
module.config()
.addInt("volume", &volume, 20)
.label("Volume")
.range(0, 30)
.step(1);
Integer fields are persisted automatically and are the preferred type for GPIO pins, servo positions, durations, counts and brightness values.
addFloat
float gain = 1.0f;
module.config()
.addFloat("gain", &gain, 1.0f)
.label("Gain")
.range(0.1f, 5.0f)
.step(0.1f);
addBool
bool flickerEnabled = true;
module.config()
.addBool("flickerEnabled", &flickerEnabled, true)
.label("Flicker after Closing");
addString
String nodeName = "Helmet";
module.config()
.addString("nodeName", &nodeName, "Helmet")
.label("Node Name")
.rebootRequired();
String fields are useful for node names, Bluetooth names and profile-facing labels.
addReadonly
module.config()
.addReadonly("firmwareVersion", "0.4.0")
.label("Firmware Version")
.section("System");
Readonly fields appear in the descriptor and App, but cannot be changed by the user.
Metadata Methods
| Method | Description |
|---|---|
.label("...") | User-facing field label. |
.section("...") | Groups fields and actions in the App/configurator. |
.description("...") | Longer description text. |
.tooltip("...") | Short helper text used by setup tools. |
.unit("ms") | Display unit for numeric values. |
.range(min, max) | Minimum and maximum allowed value. |
.step(value) | Step size used by editors. |
.advanced() | Marks a field as advanced. |
.rebootRequired() | Marks a setting that requires reboot to fully apply. |
.visibleWhen("key", value) | Shows a field only when another field has a matching value. |
.semantic("...") | Machine-readable meaning for smarter UIs. |
.semanticGroup("...") | Groups related semantic fields, for example all values for one servo. |
.persist("key") | Overrides the NVS key used for persistence. |
.editable() / .readonly() | Overrides editability. |
Conditional Fields
visibleWhen(...) lets a descriptor express dependent settings.
module.config()
.addInt("eyeFlickerCount", &config.eyes.flickerCount, 3)
.label("Flicker Count")
.section("Eyes")
.visibleWhen("eyeFlickerEnabled", true)
.range(1, 20)
.step(1);
The descriptor contains:
"visibleWhen": {
"key": "eyeFlickerEnabled",
"equals": "true"
}
Reboot Required Fields
Use .rebootRequired() for settings that change startup-time behavior, hardware initialization or transport setup.
Typical examples:
- Node name
- Gateway mode
- Bluetooth enable/name
- ESP-NOW enable/channel
- GPIO assignments
- Servo count
- LED count
The value is still stored immediately. The flag tells tools to ask the user for a reboot before expecting the new hardware setup to be active.
Change Callbacks
Callbacks run after a value is changed through ArmorLink.
module.config()
.addBool("innerLightsEnabled", &config.innerLights.enabled, true)
.onBoolChange([](bool enabled) {
setInnerLightsEnabled(enabled);
});
Supported callbacks:
| Method | Type |
|---|---|
.onIntChange([](int value) { ... }) | int |
.onFloatChange([](float value) { ... }) | float |
.onBoolChange([](bool value) { ... }) | bool |
.onStringChange([](const String& value) { ... }) | string |
Servo Config Helper
ArmorLink 0.4.0 includes a servo configuration helper for setup tools and profile editors.
ArmorLinkServoConfig servo1{16, 10, 158, 500, 2400};
module.config()
.addServoConfig("servo1", &servo1)
.section("Servo 1")
.gpio(16)
.openPosition(10)
.closedPosition(158)
.pulseRange(500, 2400);
This registers these fields:
| Field key | Meaning |
|---|---|
servo1Pin | GPIO pin for the servo. |
servo1Open | Position used for the open state. |
servo1Closed | Position used for the closed state. |
servo1MinPulseUs | Minimum pulse width. |
servo1MaxPulseUs | Maximum pulse width. |
The generated fields include servo semantics so tools can provide servo-aware controls. See Servo Config API.
System Configuration Fields
ArmorLink automatically registers an ArmorLink section unless your firmware already defines fields with the same keys.
| Key | Label | Type | Notes |
|---|---|---|---|
nodeName | Node Name | string | Reboot required. Changes the ArmorLink node name. |
bridgeMode | Gateway Mode | bool | Reboot required. Enables gateway behavior. |
bluetoothSetup | Enable Bluetooth | bool | Reboot required. Enables BLE setup/app access. |
bluetoothName | Bluetooth Name | string | Reboot required. Visible when Bluetooth is enabled. |
nodeLink | Enable Wireless Communication | bool | Reboot required. Enables ESP-NOW communication. |
nodeLinkChannel | Channel | int | Advanced, range 1..13, visible when wireless is enabled. |
Descriptor Fields
A 0.4.0 descriptor contains module metadata and sections:
{
"module": "Helmet",
"name": "Helmet",
"moduleVersion": "1.0",
"armorLinkVersion": "0.4.0",
"profileName": "Iron Patriot Generic Helmet",
"profileTarget": "muehliindustries.armorlink.helmet.v1",
"supportsPartialConfigGet": false,
"supportsConfigSet": true,
"moduleType": "Helmet",
"sections": []
}
Each section contains fields and actions arrays.
Transport
Config descriptors can be requested through:
- BLE via the ArmorLink App.
- ESP-NOW through a Gateway when configuring a paired module.
- Serial/Web Serial through the Web Node Configurator.
Large descriptors are chunked. Serial config descriptors are wrapped in @ALF:CONFIG_BEGIN and @ALF:CONFIG_END frames. BLE descriptors use config_meta, config_chunk and config_end events.