“Open/Closed” in the Shelly app: the limit switch on a virtual component

Anyone who fits a Shelly 1 Gen3 to a gate with a limit switch on the Add-on ends up asking the same thing: how do I make the app say “Open” and “Closed” instead of “On” and “Off”? It can be done, but not where you look first.

That toggle is the relay, not the gate

The “On/Off” toggle is switch:0, the relay output that pulses the motor. The app does not let you rename its state, and it should not: the relay only knows it gave a command, not whether the gate actually opened. The real position comes from the limit switch wired to the Plus Add-on’s DIGITAL IN, which the device exposes as input:100.

http://<ip>/rpc/Input.GetStatus?id=100

That input must be configured as a switch (type: "switch"), not a button: a switch has a state — closed or open, right now —; a button only emits press events and has no state to show. If the state reads the wrong way round, invert the input in its configuration:

http://<ip>/rpc/Input.SetConfig?id=100&config={"invert":true}

From there, there are two ways to show it.

Option A, no code: the input as a door sensor

In the Shelly Smart Control app, open the Shelly 1 Gen3, add the digital input peripheral and, if your version offers it, choose the door/garage type. The state appears as a card with its icon and open/closed text. Run a full cycle to confirm the direction. If the app does not offer that type, you will see a generic active/inactive contact: then, option B.

Option B, exact text: virtual Boolean + script

Gen3, and Gen2/Plus on current firmware, have Virtual Components. A virtual boolean has two titles — one for the false state and one for the true — and a label view: exactly a card that says “Closed” or “Open”. Create it from Components in the app or over RPC; virtual components are numbered from 200:

http://<ip>/rpc/Virtual.Add?type="boolean"&config={"name":"Gate","meta":{"ui":{"view":"label","titles":["Closed","Open"]}}}

The order of titles is [false, true]. The response returns the id; if it is not 200, adjust it in the script. Then, under Settings → Scripts, create one with this code, tick run on startup and enable it:

// Copy the limit switch (input:100) to a virtual Boolean (boolean:200)
let INPUT   = 100;    // the Add-on's digital input
let BOOLEAN = 200;    // the "Gate" virtual component
let INVERT  = false;  // true if it reads the wrong way round

function copy(state) {
  Shelly.call("Boolean.Set", { id: BOOLEAN, value: INVERT ? !state : state });
}

// State when the script starts
Shelly.call("Input.GetStatus", { id: INPUT }, function (r) {
  if (r) copy(r.state);
});

// Every change of the limit switch
Shelly.addStatusHandler(function (e) {
  if (e.component === "input:" + INPUT && e.delta && e.delta.state !== undefined) {
    copy(e.delta.state);
  }
});

It does two things: copies the current state when it starts — otherwise the card would show a stale value until the first movement — and then every change of input:100 that reaches it through the status handler. All local: with no internet, the card stays current. Finally, add the Boolean to a group so it appears on the app’s home screen.

Checks

  • A full cycle of opening and closing: the card must go from “Closed” to “Open” and back. A misaligned limit switch never triggers.
  • The toggle is still useful: it is what opens and closes. Relay and state are independent.
  • If you do not see the Components section, update the firmware.

Frequently asked questions

Can I rename the relay’s “On/Off”?

No, and even if you could it would mislead: the relay being on does not mean the gate is open.

What id does the Add-on input have?

Normally input:100. Check under Components or with Shelly.GetComponents.

In short: the state is input:100 in switch mode, not the relay; a virtual boolean with titles: ["Closed","Open"] and a script that copies one to the other, at startup and on every change.