Quien monta un Shelly 1 Gen3 en una puerta con un final de carrera en el Add-on acaba preguntando lo mismo: ¿cómo hago que la app diga «Abierto» y «Cerrado» en vez de «Encendido» y «Apagado»? Se puede, pero no donde se busca primero.
Ese interruptor es el relé, no la puerta
El toggle «Encendido/Apagado» es switch:0, la salida de relé que da el pulso al motor. La app no deja renombrar su estado, y no debería: el relé solo sabe que ha dado una orden, no si la puerta llegó a abrirse. La posición real la da el final de carrera cableado a DIGITAL IN del Plus Add-on, que el equipo expone como input:100.
http://<ip>/rpc/Input.GetStatus?id=100
Esa entrada tiene que estar configurada como interruptor (type: "switch"), no como pulsador: un interruptor tiene state —cerrado o abierto, ahora mismo—; un pulsador solo emite eventos de pulsación y no hay estado que mostrar. Si el estado sale al revés, invierte la entrada en su configuración:
http://<ip>/rpc/Input.SetConfig?id=100&config={"invert":true}
A partir de ahí hay dos formas de mostrarlo.
Opción A, sin código: la entrada como sensor de puerta
En la app Shelly Smart Control, abre el Shelly 1 Gen3, añade el periférico de entrada digital y, si tu versión lo ofrece, elige el tipo puerta/garaje. El estado aparece como una tarjeta con su icono y el texto de abierto/cerrado. Haz un ciclo completo para confirmar el sentido. Si la app no ofrece ese tipo, verás un contacto genérico activo/inactivo: entonces, la opción B.
Opción B, texto exacto: Boolean virtual + script
Los Gen3, y los Gen2/Plus con firmware actual, tienen Componentes Virtuales. Un boolean virtual tiene dos títulos —el del estado falso y el del verdadero— y una vista de etiqueta: justo una tarjeta que dice «Cerrado» o «Abierto». Se crea desde Componentes en la app o por RPC, y los virtuales se numeran desde 200:
http://<ip>/rpc/Virtual.Add?type="boolean"&config={"name":"Puerta","meta":{"ui":{"view":"label","titles":["Cerrado","Abierto"]}}}
El orden de titles es [falso, verdadero]. La respuesta devuelve el id; si es otro que 200, ajústalo en el script. Después, en Ajustes → Scripts, crea uno con este código, márcalo para ejecutar al arrancar y actívalo:
// Copia el final de carrera (input:100) a un Boolean virtual (boolean:200)
let ENTRADA = 100; // entrada digital del Add-on
let BOOLEANO = 200; // Componente Virtual «Puerta»
let INVERTIR = false; // true si sale al revés
function copia(estado) {
Shelly.call("Boolean.Set", { id: BOOLEANO, value: INVERTIR ? !estado : estado });
}
// Estado al arrancar el script
Shelly.call("Input.GetStatus", { id: ENTRADA }, function (r) {
if (r) copia(r.state);
});
// Cada cambio del final de carrera
Shelly.addStatusHandler(function (e) {
if (e.component === "input:" + ENTRADA && e.delta && e.delta.state !== undefined) {
copia(e.delta.state);
}
});
Hace dos cosas: copia el estado actual al arrancar —si no, la tarjeta mostraría un valor viejo hasta el primer movimiento— y, después, cada cambio de input:100 que le llega por el manejador de estado. Todo en local: sin internet, la tarjeta sigue al día. Por último, añade el Boolean a un grupo para que aparezca en la pantalla de inicio de la app.
Comprobaciones
- Ciclo completo de apertura y cierre: la tarjeta tiene que pasar de «Cerrado» a «Abierto» y volver. Un final de carrera mal alineado no llega a marcar.
- El toggle sigue siendo útil: es el que abre y cierra. Relé y estado son independientes.
- Si no ves la sección Componentes, actualiza el firmware.
Preguntas frecuentes
¿Puedo renombrar el «Encendido/Apagado» del relé?
No, y aunque pudieras sería engañoso: el relé encendido no garantiza que la puerta esté abierta.
¿Qué ID tiene la entrada del Add-on?
Normalmente input:100. Compruébalo en Componentes o con Shelly.GetComponents.
Resumen: el estado es input:100 en modo interruptor, no el relé; un boolean virtual con titles: ["Cerrado","Abierto"] y un script que copia uno en otro, al arrancar y en cada cambio.