Macro examples — starter recipes
Ready-to-run recipes for the most common single-actuator jobs. Each one is the Code view of a macro. To use one:
- Open Macros → New Macro, pick a target gateway, and switch to the Code tab.
- Paste the recipe.
- Replace every
<…DeviceId>placeholder with one of your devices on that gateway (the editor lists them). - Adjust the parameters at the top if you like, then tap Run.
New to macros? Read Macros — program your devices first.
Reading the syntax
Every value in a macro is one of:
- a plain number —
{ "lit": 3000 }(3000) - a parameter you declared up top —
{ "param": "ON_MS" } - a variable you set while running —
{ "var": "duty" } - a live sensor reading —
{ "tag": { "deviceRef": "<sensorDeviceId>", "tag": "temperature" } }
wait is in milliseconds. repeat runs its body a fixed number of times — there are no
infinite loops. That's all you need for the recipes below.
Pulse a relay for N seconds
For: an irrigation burst, a door strike, a timed pump — turn an output on, wait, turn it off.
Needs: an On/Off actuator (gpio-digital-out).
{
"params": [
{ "name": "ON_MS", "type": "number", "default": 3000, "min": 0, "max": 600000 }
],
"blocks": [
{ "type": "digital_write", "deviceRef": "<relayDeviceId>", "value": { "lit": 1 } },
{ "type": "wait", "ms": { "param": "ON_MS" } },
{ "type": "digital_write", "deviceRef": "<relayDeviceId>", "value": { "lit": 0 } }
]
}
Blink an output ×N (status beacon / wiring test)
For: flashing a lamp or buzzer a set number of times — handy for testing wiring or signalling.
Needs: an On/Off actuator (gpio-digital-out).
{
"params": [
{ "name": "BLINKS", "type": "number", "default": 5, "min": 1, "max": 1000 }
],
"blocks": [
{ "type": "repeat", "count": { "param": "BLINKS" }, "body": [
{ "type": "digital_write", "deviceRef": "<relayDeviceId>", "value": { "lit": 1 } },
{ "type": "wait", "ms": { "lit": 500 } },
{ "type": "digital_write", "deviceRef": "<relayDeviceId>", "value": { "lit": 0 } },
{ "type": "wait", "ms": { "lit": 500 } }
] }
]
}
Staggered sequential power-up
For: bringing several loads up one at a time so they don't all inrush together, then logging it.
Needs: three On/Off actuators (gpio-digital-out).
{
"params": [],
"blocks": [
{ "type": "digital_write", "deviceRef": "<relay1DeviceId>", "value": { "lit": 1 } },
{ "type": "wait", "ms": { "lit": 1000 } },
{ "type": "digital_write", "deviceRef": "<relay2DeviceId>", "value": { "lit": 1 } },
{ "type": "wait", "ms": { "lit": 1000 } },
{ "type": "digital_write", "deviceRef": "<relay3DeviceId>", "value": { "lit": 1 } },
{ "type": "emit", "message": "Powered up", "severity": "info" }
]
}
Timed dimmer scene
For: an "evening light" — set a dimmer to a level, hold it, then switch off automatically.
Needs: a Level actuator (gpio-pwm). Duty is 0–255.
{
"params": [
{ "name": "LEVEL", "type": "number", "default": 180, "min": 0, "max": 255 },
{ "name": "HOLD_MS", "type": "number", "default": 60000, "min": 0, "max": 600000 }
],
"blocks": [
{ "type": "pwm_write", "deviceRef": "<dimmerDeviceId>", "duty": { "param": "LEVEL" } },
{ "type": "wait", "ms": { "param": "HOLD_MS" } },
{ "type": "pwm_write", "deviceRef": "<dimmerDeviceId>", "duty": { "lit": 0 } }
]
}
Two-step lamp scene (60% → 100%)
For: easing a light up in two stops instead of snapping straight to full.
Needs: a Level actuator (gpio-pwm). 153 ≈ 60%, 255 = 100% of 255.
{
"params": [],
"blocks": [
{ "type": "pwm_write", "deviceRef": "<dimmerDeviceId>", "duty": { "lit": 153 } },
{ "type": "wait", "ms": { "lit": 2000 } },
{ "type": "pwm_write", "deviceRef": "<dimmerDeviceId>", "duty": { "lit": 255 } }
]
}
PWM step levels (25 → 50 → 75 → 100%)
For: running a dimmer or variable-speed fan through its range — a quick calibration/test.
Needs: a Level actuator (gpio-pwm).
{
"params": [
{ "name": "STEP_MS", "type": "number", "default": 1500, "min": 0, "max": 600000 }
],
"blocks": [
{ "type": "pwm_write", "deviceRef": "<dimmerDeviceId>", "duty": { "lit": 64 } },
{ "type": "wait", "ms": { "param": "STEP_MS" } },
{ "type": "pwm_write", "deviceRef": "<dimmerDeviceId>", "duty": { "lit": 128 } },
{ "type": "wait", "ms": { "param": "STEP_MS" } },
{ "type": "pwm_write", "deviceRef": "<dimmerDeviceId>", "duty": { "lit": 191 } },
{ "type": "wait", "ms": { "param": "STEP_MS" } },
{ "type": "pwm_write", "deviceRef": "<dimmerDeviceId>", "duty": { "lit": 255 } }
]
}
Park a servo to a preset position
For: returning a servo to a known angle (centre, "home", a stowed position) and logging it.
Needs: a Position actuator (gpio-servo, firmware 1.4.0+).
1500 µs is centre; most hobby servos run ~1000–2000 µs.
{
"params": [
{ "name": "PARK_US", "type": "number", "default": 1500, "min": 500, "max": 2500 }
],
"blocks": [
{ "type": "servo_write", "deviceRef": "<servoDeviceId>", "us": { "param": "PARK_US" } },
{ "type": "emit", "message": "Servo parked", "severity": "info" }
]
}
Servo sweep min ↔ max ×N
For: a wiper, a scanning sensor mount, or a gauge needle that sweeps back and forth.
Needs: a Position actuator (gpio-servo, firmware 1.4.0+).
{
"params": [
{ "name": "MIN_US", "type": "number", "default": 1000, "min": 500, "max": 2500 },
{ "name": "MAX_US", "type": "number", "default": 2000, "min": 500, "max": 2500 },
{ "name": "SWEEPS", "type": "number", "default": 5, "min": 1, "max": 1000 },
{ "name": "DWELL_MS", "type": "number", "default": 600, "min": 0, "max": 600000 }
],
"blocks": [
{ "type": "repeat", "count": { "param": "SWEEPS" }, "body": [
{ "type": "servo_write", "deviceRef": "<servoDeviceId>", "us": { "param": "MAX_US" } },
{ "type": "wait", "ms": { "param": "DWELL_MS" } },
{ "type": "servo_write", "deviceRef": "<servoDeviceId>", "us": { "param": "MIN_US" } },
{ "type": "wait", "ms": { "param": "DWELL_MS" } }
] }
]
}
Stepper jog forward & back
For: nudging a stepper rail out and back — a mini version of the camera slider.
Needs: a Move actuator (gpio-stepper, firmware 1.2.0+). dir 1 =
forward, 0 = reverse; speeds are µs per step (smaller = faster). The full slider lives in
Macros — program your devices.
{
"params": [
{ "name": "DISTANCE", "type": "number", "default": 2000, "min": 0, "max": 1000000 },
{ "name": "MAX_SPEED_US", "type": "number", "default": 220, "min": 50, "max": 100000 },
{ "name": "MIN_SPEED_US", "type": "number", "default": 900, "min": 50, "max": 100000 },
{ "name": "RAMP_STEPS", "type": "number", "default": 200, "min": 0, "max": 100000 }
],
"blocks": [
{ "type": "move", "deviceRef": "<stepperDeviceId>", "steps": { "param": "DISTANCE" }, "dir": { "lit": 1 }, "maxSpeedUs": { "param": "MAX_SPEED_US" }, "minSpeedUs": { "param": "MIN_SPEED_US" }, "rampSteps": { "param": "RAMP_STEPS" } },
{ "type": "wait", "ms": { "lit": 300 } },
{ "type": "move", "deviceRef": "<stepperDeviceId>", "steps": { "param": "DISTANCE" }, "dir": { "lit": 0 }, "maxSpeedUs": { "param": "MAX_SPEED_US" }, "minSpeedUs": { "param": "MIN_SPEED_US" }, "rampSteps": { "param": "RAMP_STEPS" } },
{ "type": "wait", "ms": { "lit": 300 } }
]
}
Stepper homing nudge
For: sending a stage slowly toward a hard stop / limit before a run, then logging "Homed". Runs at
a single slow speed (min = max, no ramp).
Needs: a Move actuator (gpio-stepper, firmware 1.2.0+).
{
"params": [
{ "name": "HOME_STEPS", "type": "number", "default": 4000, "min": 0, "max": 1000000 },
{ "name": "HOME_SPEED_US", "type": "number", "default": 1500, "min": 50, "max": 100000 }
],
"blocks": [
{ "type": "move", "deviceRef": "<stepperDeviceId>", "steps": { "param": "HOME_STEPS" }, "dir": { "lit": 0 }, "maxSpeedUs": { "param": "HOME_SPEED_US" }, "minSpeedUs": { "param": "HOME_SPEED_US" } },
{ "type": "emit", "message": "Homed", "severity": "info" }
]
}
Pulse a Modbus coil (VFD / PLC start)
For: momentarily energising a coil — a start command to a VFD or PLC, a latch, etc.
Needs: an RS485/Modbus device (rs485 or modbus-tcp). fc 5 writes a single coil; point
address at the coil you want.
{
"params": [
{ "name": "PULSE_MS", "type": "number", "default": 2000, "min": 0, "max": 600000 }
],
"blocks": [
{ "type": "modbus_write", "deviceRef": "<modbusDeviceId>", "fc": 5, "address": 0, "value": { "lit": 1 } },
{ "type": "wait", "ms": { "param": "PULSE_MS" } },
{ "type": "modbus_write", "deviceRef": "<modbusDeviceId>", "fc": 5, "address": 0, "value": { "lit": 0 } }
]
}
Write a Modbus register (setpoint)
For: pushing a value into a holding register — a speed/temperature setpoint or a config word.
Needs: an RS485/Modbus device (rs485 or modbus-tcp). fc 6 writes a single register; set
address to the register and SETPOINT to the value.
{
"params": [
{ "name": "SETPOINT", "type": "number", "default": 1500, "min": 0, "max": 65535 }
],
"blocks": [
{ "type": "modbus_write", "deviceRef": "<modbusDeviceId>", "fc": 6, "address": 100, "value": { "param": "SETPOINT" } },
{ "type": "emit", "message": "Setpoint written", "severity": "info" }
]
}
Ready for logic, sensor reads, and loops with math? See Macro examples — advanced.