Skip to main content

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

MethodDescriptor kindEditableDescription
addInt(...)intYesWhole number values such as GPIO pins, positions, durations, counts and brightness.
addFloat(...)floatYesDecimal values such as calibration factors or thresholds.
addBool(...)boolYesFeature toggles and on/off settings.
addString(...)stringYesNames, labels and other text settings.
addReadonly(...)readonlyNoInformational values shown by tools but not editable.
addServoConfig(...)multiple int fieldsYesHelper 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

MethodDescription
.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:

MethodType
.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 keyMeaning
servo1PinGPIO pin for the servo.
servo1OpenPosition used for the open state.
servo1ClosedPosition used for the closed state.
servo1MinPulseUsMinimum pulse width.
servo1MaxPulseUsMaximum 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.

KeyLabelTypeNotes
nodeNameNode NamestringReboot required. Changes the ArmorLink node name.
bridgeModeGateway ModeboolReboot required. Enables gateway behavior.
bluetoothSetupEnable BluetoothboolReboot required. Enables BLE setup/app access.
bluetoothNameBluetooth NamestringReboot required. Visible when Bluetooth is enabled.
nodeLinkEnable Wireless CommunicationboolReboot required. Enables ESP-NOW communication.
nodeLinkChannelChannelintAdvanced, 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.