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:

  1. Open Macros → New Macro, pick a target gateway, and switch to the Code tab.
  2. Paste the recipe.
  3. Replace every <…DeviceId> placeholder with one of your devices on that gateway (the editor lists them).
  4. 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:

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.