Configuration Example
This example shows a 0.4.0-style module with system setup, user configuration, servo configuration, profiles and actions.
Complete Example
#include <ArmorLink.h>
ArmorLinkModule module(
"Helmet",
ArmorLinkModuleType::Helmet
);
struct HelmetConfig {
int servoCount = 2;
int openingDurationMs = 700;
int closingDurationMs = 700;
bool detachServos = true;
int servoDetachDelayMs = 1000;
ArmorLinkServoConfig servo1{16, 10, 158, 500, 2400};
ArmorLinkServoConfig servo2{26, 170, 22, 500, 2400};
ArmorLinkServoConfig servo3{-1, 90, 90, 500, 2400};
bool eyesEnabled = true;
int eyesPin = 25;
bool eyeFlickerEnabled = true;
int eyeFlickerCount = 3;
bool innerLightsEnabled = true;
int innerLightsPin = 27;
int innerLightsBrightness = 255;
};
HelmetConfig config;
void toggleFaceplate()
{
ArmorLink.info("Toggle faceplate");
}
void setup()
{
Serial.begin(115200);
module.profileTarget("muehliindustries.armorlink.helmet.v1");
module.profileName("Iron Patriot Generic Helmet");
module.config().addInt("servoCount", &config.servoCount, 2)
.label("Servo Count")
.section("Faceplate")
.tooltip("How many servos move the faceplate.")
.rebootRequired()
.range(2, 3)
.step(1);
module.config().addInt("openingDurationMs", &config.openingDurationMs, 700)
.label("Opening Duration")
.section("Faceplate")
.tooltip("How long the faceplate takes to open.")
.semantic("servo.openingDuration")
.semanticGroup("faceplate")
.range(100, 5000)
.step(50);
module.config().addInt("closingDurationMs", &config.closingDurationMs, 700)
.label("Closing Duration")
.section("Faceplate")
.tooltip("How long the faceplate takes to close.")
.semantic("servo.closingDuration")
.semanticGroup("faceplate")
.range(100, 5000)
.step(50);
module.config().addBool("detachServos", &config.detachServos, true)
.label("Detach Servos")
.section("Faceplate")
.tooltip("Turns off servo power after movement to reduce noise and heat.");
module.config().addInt("servoDetachDelayMs", &config.servoDetachDelayMs, 1000)
.label("Servo Detach Delay")
.section("Faceplate")
.range(0, 10000)
.step(100);
module.config()
.addServoConfig("servo1", &config.servo1)
.section("Servo 1")
.gpio(16)
.openPosition(10)
.closedPosition(158)
.pulseRange(500, 2400);
module.config()
.addServoConfig("servo2", &config.servo2)
.section("Servo 2")
.gpio(26)
.openPosition(170)
.closedPosition(22)
.pulseRange(500, 2400);
module.config()
.addServoConfig("servo3", &config.servo3)
.section("Servo 3")
.visibleWhen("servoCount", 3)
.gpio(-1)
.openPosition(90)
.closedPosition(90)
.pulseRange(500, 2400);
module.config().addBool("eyesEnabled", &config.eyesEnabled, true)
.label("Enabled")
.section("Eyes")
.tooltip("Turns the eye LEDs on or off.")
.rebootRequired();
module.config().addInt("eyesPin", &config.eyesPin, 25)
.label("GPIO")
.section("Eyes")
.visibleWhen("eyesEnabled", true)
.range(-1, 48)
.step(1)
.rebootRequired();
module.config().addBool("eyeFlickerEnabled", &config.eyeFlickerEnabled, true)
.label("Flicker after Closing")
.section("Eyes");
module.config().addInt("eyeFlickerCount", &config.eyeFlickerCount, 3)
.label("Flicker Count")
.section("Eyes")
.visibleWhen("eyeFlickerEnabled", true)
.range(1, 20)
.step(1);
module.config().addBool("innerLightsEnabled", &config.innerLightsEnabled, true)
.label("Enabled")
.section("Inner Lights")
.rebootRequired();
module.config().addInt("innerLightsPin", &config.innerLightsPin, 27)
.label("GPIO")
.section("Inner Lights")
.visibleWhen("innerLightsEnabled", true)
.range(-1, 48)
.step(1)
.rebootRequired();
module.config().addInt("innerLightsBrightness", &config.innerLightsBrightness, 255)
.label("Brightness")
.section("Inner Lights")
.visibleWhen("innerLightsEnabled", true)
.range(0, 255)
.step(1);
module.config().addReadonly("firmwareName", "ArmorLink Helmet")
.label("Firmware")
.section("System");
module.config().addReadonly("firmwareVersion", "1.0")
.label("Firmware Version")
.section("System");
module.actions()
.add("toggleFaceplate")
.label("Toggle Faceplate")
.section("Faceplate")
.command("Facemask", "toggle")
.stylePrimary()
.onExecute([] {
toggleFaceplate();
});
ArmorLinkOptions options;
options.nodeName = "Helmet";
options.enableGateway = true;
options.enableBle = true;
options.enableEspNow = true;
options.bleName = "ArmorLink Helmet";
options.enableSerialCommands = true;
ArmorLink.begin(module, options);
}
void loop()
{
ArmorLink.loop();
}
What This Exposes
The descriptor contains:
- The built-in
ArmorLinksetup section. - Faceplate timing and behavior fields.
- Servo 1, Servo 2 and optional Servo 3 sections.
- Eye and inner light sections.
- Firmware information.
- A Faceplate action.
- Profile metadata for compatible cloud/community profiles.
Why Use Semantics?
Fields such as servo.openingDuration, servo.gpio and servo.openPosition are still normal config fields. The semantic metadata helps setup tools provide specialized controls without hard-coding firmware-specific keys.