1. Home
  2. Installations
  3. Dimming with an input module

Installations

Dimming with an input module

Dim one dimmer or twenty from one wired button, with no IP addresses to keep.

Updated August 2026

What this does

A wired button on an input module controls one or more dimmers somewhere else in the building. Press to toggle, hold to dim, double-press for full brightness — all from a single button.

The messages travel over Local Network Messaging, a multicast group on the local network. That is the part worth understanding: the input module does not address a dimmer, it addresses a group. Every dimmer on that group reacts at the same moment.

Nothing is configured with an IP address. Devices can be given new addresses by the router, be replaced, or be added to the group later, and nothing has to be edited.

Requirements

Input device Shelly I4 Gen3 or Gen4, or Shelly 1 Mini Gen4
Dimmers Shelly Dimmer Gen3, Gen4, Pro Dimmer 1PM/2PM or DALI Dimmer Gen3
Firmware 2.0.0 or newer on every device
Switch Momentary spring switch on the input
Network All devices on the same local network

The Shelly 1 Mini Gen4 is the interesting option. Where only one button is needed it is smaller and cheaper than an I4, and only its input is used — the relay output stays unconnected. That is not waste; it is the cheapest way to put a wired button anywhere there is 230 V.

Set up the LNM group

Three things have to be true: both ends belong to the same group, and both have RPC enabled.

1
Dimmer

Create the group on each dimmer

In the dimmer’s web interface, open Local Network Messaging and create an instance.

  • Instance id: 200
  • Multicast address: 239.255.0.1:3333
  • RPC enabled: yes

The address matters. 239.255.0.0/16 is site-local scope — the narrowest private range, designed never to leave a single network. It is Shelly’s own recommendation and the safest choice in a home or office.

Repeat on every dimmer that should follow this button. They all use the same instance id and the same address.

2
Input module

Create the same group on the input device

Same settings: instance id 200, address 239.255.0.1:3333, RPC enabled.

RPC must be on at both ends — on the sender to be allowed to send at all, and on each receiver to execute what arrives. Without it on the sender, LNM.Call returns error -109 and nothing leaves the device.

TX is not needed. Transmit broadcasts a device’s own status; that is a different feature, and this setup does not use it.

A device never receives its own messages, and receivers never forward what they receive, so there is no risk of a message loop.

3
Input module

Set the input to button mode

On the input device, open the input you are using and set Input mode to Button.

This is what produces the four events the script listens for: single push, double push, long push and release. In Switch mode you get only two, and dimming becomes impossible.

Install the script

The script runs on the input device, not on the dimmer.

Dimming needs it, and it is worth knowing why: holding a button to dim requires remembering which direction the last hold went, and knowing the moment the button is released. Actions cannot do either — no webhook exposes the release event, and an action has no memory between presses. Everything else on this page could be built from Actions alone; hold-to-dim cannot.

/**
 * One-button dimming over Local Network Messaging.
 *
 * Runs on the input device — a Shelly I4 Gen3/Gen4 or a Shelly 1 Mini Gen4 —
 * and drives one or more dimmers on the same LNM group. No IP addresses.
 *
 *   single push  = toggle on/off
 *   double push  = on at 100 % brightness
 *   hold         = dim, reversing direction on each new hold
 *   release      = stop dimming
 *
 * Requires firmware 2.0.0 or newer on every device, and an LNM instance with
 * rpc_enable set to true at both ends.
 */

// ===== CONFIGURATION =====
// One entry per input, in order. Set an entry to null to leave that input
// unused. A Shelly 1 Mini Gen4 has one input, so only the first entry applies.
//   lnm   — the LNM instance id on THIS device (200-299)
//   light — the light component id on the receiving dimmer (0 = first output)
//
// To use more buttons on an I4, replace a null with its own entry. Give each
// button a different lnm id if it should control a different group of dimmers.
let inputs = [
  { lnm: 200, light: 0 },
  null,
  null,
  null
];

let fadeRate = 4;   // 1 is slowest, 5 is fastest
// ===== END CONFIGURATION =====

let dimming = [false, false, false, false];
// Starts true so the first hold after a restart dims DOWN. Holding up on a
// light already at 100 % looks like the script is not working.
let goingUp = [true, true, true, true];

function send(cfg, method, params) {
  params.id = cfg.light;
  Shelly.call("LNM.Call", { id: cfg.lnm, method: method, params: params },
    function (result, code, message) {
      if (code) print("LNM.Call failed: " + code + " " + message);
    });
}

Shelly.addEventHandler(function (event) {
  try {
    if (typeof event.info.event === 'undefined') return true;

    let i = event.info.id;
    let ev = event.info.event;
    let cfg = inputs[i];
    if (!cfg) return true;

    // Release always ends a dim cycle, whatever else is going on.
    if (dimming[i] && ev === 'btn_up') {
      dimming[i] = false;
      send(cfg, "Light.DimStop", {});
      return true;
    }

    if (ev === 'single_push') {
      send(cfg, "Light.Toggle", {});

    } else if (ev === 'double_push') {
      send(cfg, "Light.Set", { on: true, brightness: 100 });

    } else if (ev === 'long_push') {
      dimming[i] = true;
      goingUp[i] = !goingUp[i];
      send(cfg, goingUp[i] ? "Light.DimUp" : "Light.DimDown", { fade_rate: fadeRate });
    }

  } catch (e) {
    print("Error in event handler: " + e.message);
  }
});

Install it as described in how to add a script, and enable run on startup — or it stops at the first power cut and does not come back.

Configure it

Only the top block needs editing. One entry per input, in order:

  • lnm — the instance id you created, 200 in this guide
  • light — which output on the receiving dimmer, 0 for the first

The template has one active entry and three set to null, so a Shelly 1 Mini Gen4 works unedited. On an I4, replace a null with its own entry for each button you want to use. Give a button its own lnm id if it should drive a different group of dimmers.

fadeRate sets dimming speed from 1 to 5.

Test and hand over

Four things, in this order:

  1. Single press — the light toggles
  2. Double press — full brightness
  3. Hold — the light dims. The first hold after installing dims down, then alternates on each new hold
  4. Release — dimming stops where you let go

With several dimmers on the group, confirm they move together rather than one after another. That simultaneity is what the group buys you; if one lags, it is on a different instance id or a different multicast address.

Watch the console on the first run. Every failure prints, and the most common one names itself: error −109 means RPC is not enabled on the sender.

Tips & troubleshooting

  • Nothing happens at all? Check RPC is enabled at both ends, and that both devices are on 2.0.0 or newer.
  • The first hold seems to do nothing. It is dimming down from a light already at full. Hold again to reverse.
  • Only some dimmers react. They are not all on the same instance id and multicast address. The address must match exactly, port included.
  • Use one group per room, not one for the house. Groups are free, and a group that spans everything means every button reaches every light.
  • Document the instance id in the handover. A group is invisible from the outside — the next electrician cannot deduce it from the wiring.