Skip to main content

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 ArmorLink setup 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.