Saltar al contenido

Acciones que duran en el tiempo: retrasos, esperas y modos de ejecución

09/10/2026
Retrasos, esperas y modos de ejecución en Home Assistant

Este artículo puede contener enlaces de afiliado. Si compras desde estos enlaces, el precio para ti es el mismo y la tienda me paga una pequeña comisión que ayuda a mantener Tecnoyfoto.

← Capítulo 5 · Índice del curso

Hasta ahora nuestras acciones terminaban casi inmediatamente. Home Assistant encendía una luz, creaba una notificación o apagaba un interruptor y la ejecución llegaba al final. En cuanto añadimos un retraso o esperamos que cambie un sensor, la automatización puede permanecer activa durante segundos o minutos.

Entonces aparece una pregunta nueva: ¿qué debe ocurrir si vuelve a detectarse movimiento mientras la automatización anterior todavía está esperando?

En este capítulo construiremos una luz de pasillo. Se encenderá al detectar movimiento, esperará a que el sensor deje de detectarlo, mantendrá la luz treinta segundos más y la apagará. Compararemos esta solución con un temporizador fijo y estudiaremos los cuatro modos de ejecución: single, restart, queued y parallel.

OFERTAS · TIENDA OFICIAL

Descuentos en domótica SONOFF

Interruptores WiFi, relés, sensores, tiras LED y más. Las promociones cambian con frecuencia en la tienda oficial.

Cupón: TECNOYFOTO (10% de descuento al pagar)

Ver ofertas oficiales Enlace de afiliado · Tienda Sonoff

El requisito antes del YAML

La primera versión podría expresarse así:

Cuando haya movimiento, enciende la luz, espera sesenta segundos y apágala.

Es fácil de implementar:

alias: "Curso YAML - Luz de pasillo con retraso fijo"
triggers:
  - trigger: state
    entity_id: binary_sensor.course_hallway_motion
    from: "off"
    to: "on"
conditions: []
actions:
  - action: light.turn_on
    target:
      entity_id: light.course_living_room
  - delay:
      seconds: 60
  - action: light.turn_off
    target:
      entity_id: light.course_living_room
mode: single

Las acciones se ejecutan en orden. Home Assistant no empieza el delay y el apagado simultáneamente:

Encender luz → esperar 60 segundos → apagar luz

Durante el retraso la ejecución continúa activa, aunque no esté enviando órdenes.

Qué significa realmente delay

delay pausa la secuencia durante una duración. No observa el sensor ni revisa si sigue habiendo movimiento. Al finalizar el tiempo, continúa con la siguiente acción.

Podemos expresar una misma duración de distintas maneras:

- delay: 5
- delay: "00:00:05"
- delay:
    seconds: 5

Para principiantes, la forma con unidades resulta clara cuando combinamos tiempos:

- delay:
    minutes: 1
    seconds: 30

Un retraso es adecuado cuando el requisito depende de una duración conocida: esperar dos segundos entre dos órdenes, mantener una señal durante medio minuto o dar tiempo a un aparato para completar una transición.

No es la mejor representación cuando la frase real es «espera hasta que deje de haber movimiento». En ese caso no conocemos de antemano la duración; conocemos el acontecimiento que permite continuar.

El problema del retraso fijo en una zona con movimiento

Imagina que alguien entra en el pasillo, se detiene para buscar algo y continúa allí después de sesenta segundos. La automatización con delay apaga la luz porque el tiempo ha terminado. Nunca ha preguntado si el sensor sigue activo.

Podríamos aumentar el retraso a cinco minutos. Evitaríamos algunos apagados prematuros, pero la luz quedaría encendida cinco minutos después de una visita de diez segundos. Cambiar la cifra no resuelve la diferencia entre tiempo y estado.

El requisito más fiel sería:

Cuando haya movimiento, enciende la luz. Espera hasta que deje de haberlo. Mantén la luz treinta segundos adicionales y apágala.

Ahora tenemos dos esperas distintas:

  • Una espera de acontecimiento: el sensor cambia a off.
  • Una espera de tiempo: pasan treinta segundos.

Esperar otro trigger con wait_for_trigger

La secuencia puede escribirse así:

alias: "Curso YAML - Luz de pasillo por movimiento"
description: >-
  Enciende la luz con movimiento, espera a que termine y la mantiene
  treinta segundos adicionales.
triggers:
  - trigger: state
    entity_id: binary_sensor.course_hallway_motion
    from: "off"
    to: "on"
conditions: []
actions:
  - action: light.turn_on
    target:
      entity_id: light.course_living_room

  - wait_for_trigger:
      - trigger: state
        entity_id: binary_sensor.course_hallway_motion
        from: "on"
        to: "off"
    timeout:
      minutes: 10
    continue_on_timeout: false

  - delay:
      seconds: 30

  - action: light.turn_off
    target:
      entity_id: light.course_living_room
mode: restart

El trigger superior inicia la automatización cuando comienza el movimiento. wait_for_trigger, en cambio, es una acción dentro de la secuencia. Suspende esta ejecución hasta que ocurra uno de sus triggers internos.

En nuestro caso espera la transición contraria:

binary_sensor.course_hallway_motion: on → off

Cuando ocurre, la secuencia avanza al retraso de treinta segundos.

Trigger principal y trigger de espera ocupan lugares distintos

Las dos estructuras se parecen:

triggers:
  - trigger: state
- wait_for_trigger:
    - trigger: state

Pero no son intercambiables.

El trigger principal crea una nueva ejecución de la automatización. El trigger situado dentro de wait_for_trigger permite continuar una ejecución que ya existe.

Si colocáramos el final del movimiento como segundo trigger principal, cualquiera de los dos cambios iniciaría las acciones desde el principio. Al dejar de haber movimiento volveríamos a encender la luz antes de esperar. No describe el flujo deseado.

Por qué añadimos un timeout

Un sensor puede quedarse en on, desaparecer o no publicar la transición esperada. Sin límite, la automatización permanecería esperando indefinidamente.

timeout:
  minutes: 10
continue_on_timeout: false

El timeout establece un máximo de diez minutos. Si la transición ocurre antes, la espera termina normalmente. Si no ocurre, continue_on_timeout: false detiene la secuencia y evita llegar al apagado posterior.

Esta decisión es deliberada. Si el sensor lleva diez minutos sin confirmar el final del movimiento, no queremos fingir que lo ha confirmado. Preferimos terminar la ejecución sin apagar la luz y dejar una situación visible que podamos diagnosticar.

En otro caso podríamos elegir continue_on_timeout: true, que es el valor predeterminado, y continuar después del límite. La elección depende del resultado más seguro cuando falta el acontecimiento esperado.

Un timeout no convierte una espera en un delay. Sigue esperando primero el acontecimiento; el tiempo solo define cuándo dejar de esperarlo.

Los treinta segundos finales tienen otro propósito

Después de recibir off, añadimos:

- delay:
    seconds: 30

Este margen evita apagar inmediatamente cuando el sensor deja de detectar. Algunos sensores liberan el estado con rapidez o pueden tener breves interrupciones. Mantener la luz durante un pequeño periodo mejora la experiencia.

Pero ahora puede aparecer movimiento nuevo durante esos treinta segundos. La automatización anterior sigue activa dentro del delay y el trigger principal vuelve a producirse. Aquí entra en juego mode.

mode decide qué hacer con ejecuciones que se solapan

Los modos no cambian qué activa una automatización. Cambian cómo gestiona una nueva activación mientras todavía existe una ejecución anterior.

single: ignora la nueva ejecución

mode: single

Solo permite una ejecución. Si vuelve el movimiento durante los treinta segundos finales, el nuevo trigger se rechaza. La ejecución antigua completa su retraso y apaga la luz, aunque haya movimiento otra vez.

single es el modo predeterminado y funciona bien cuando una segunda ejecución no aportaría nada o cuando una operación no debe solaparse. En este caso no representa lo que espera una persona en el pasillo.

restart: cancela la anterior y empieza desde el principio

mode: restart

Una nueva activación detiene la ejecución actual y crea otra desde el principio, siempre que las condiciones superiores permitan iniciarla.

Si vuelve el movimiento durante el margen final:

  1. Se cancela el delay pendiente.
  2. La nueva ejecución vuelve a encender la luz.
  3. Espera otra vez a que el movimiento termine.
  4. Inicia un nuevo margen de treinta segundos.

Para nuestra luz de pasillo, restart expresa bien la idea de reiniciar el ciclo con actividad nueva.

queued: coloca las ejecuciones en cola

mode: queued
max: 10

La nueva ejecución espera a que terminen las anteriores. Conserva el orden, lo que es útil cuando cada acontecimiento debe procesarse y no puede ejecutarse en paralelo.

En la luz del pasillo puede provocar secuencias innecesarias: después de terminar la primera espera, otra ejecución empezaría desde el principio aunque el movimiento que la originó ya haya pasado. No es el modelo adecuado para mantener una luz según la actividad más reciente.

parallel: inicia ejecuciones independientes

mode: parallel
max: 10

Cada trigger inicia una ejecución independiente. Una ejecución antigua podría alcanzar su light.turn_off mientras otra todavía está esperando movimiento. El resultado sería una carrera: varias secuencias controlan la misma luz sin coordinarse.

El paralelismo tiene sentido cuando las ejecuciones son independientes, por ejemplo procesar avisos separados cuyos resultados no se pisan. No debemos elegirlo porque parezca más rápido.

Una comparación aplicada al pasillo

ModoMovimiento nuevo durante el margen final
singleSe ignora y la ejecución antigua puede apagar la luz
restartSe cancela el apagado pendiente y comienza un ciclo nuevo
queuedEl ciclo nuevo espera detrás del anterior
parallelAmbos ciclos continúan y pueden contradecirse

El modo no es una preferencia global del usuario. Se elige para cada automatización según cómo deben relacionarse sus ejecuciones.

Probar sin esperar diez minutos

Durante el desarrollo no necesitamos utilizar los tiempos definitivos. Podemos reducir temporalmente el timeout y el margen:

actions:
  # Acciones anteriores omitidas para concentrarnos en los tiempos de prueba.
  - wait_for_trigger:
      - trigger: state
        entity_id: binary_sensor.course_hallway_motion
        from: "on"
        to: "off"
    timeout:
      seconds: 20
    continue_on_timeout: false

  - delay:
      seconds: 5

Una prueba completa sería:

  1. Desactivar el movimiento y apagar la luz.
  2. Activar input_boolean.course_hallway_motion_detected.
  3. Comprobar que la luz se enciende.
  4. Mantener movimiento varios segundos y verificar que no se apaga.
  5. Desactivar el movimiento.
  6. Confirmar en la traza que termina wait_for_trigger y comienza el delay.
  7. Volver a activar movimiento antes de cinco segundos.
  8. Comprobar que restart cancela la ejecución anterior y la luz permanece encendida.

Cuando el comportamiento esté confirmado, restaura los treinta segundos y el timeout previsto.

Leer la línea temporal de la traza

En este capítulo la traza aporta algo que antes casi no se veía: duración.

El recorrido normal muestra:

Movimiento on
  → light.turn_on
  → wait_for_trigger esperando
Movimiento off
  → wait_for_trigger completado
  → delay de 30 segundos
  → light.turn_off

Si se alcanza el timeout con continue_on_timeout: false, la línea termina en la espera. Si vuelve el movimiento durante el delay con mode: restart, aparecerá una ejecución nueva y la anterior quedará cancelada.

No interpretes una ejecución cancelada por restart como un fallo automáticamente. Puede ser exactamente la política que hemos configurado.

Un límite importante: las esperas no son un estado permanente

Una ejecución activa vive dentro del motor de automatizaciones. Si Home Assistant se reinicia o recargas la automatización, la ejecución y su espera pueden perderse. Después del arranque no tiene por qué reanudar los segundos pendientes donde estaba.

Para luces de cortesía sencillas suele ser aceptable. Para plazos críticos o acontecimientos que deben sobrevivir a reinicios, se diseñan soluciones basadas en horas almacenadas, timers u otras entidades persistentes. Ese diseño pertenece a un nivel posterior, pero conviene no tratar delay como un calendario permanente.

Ejercicio: elige entre tiempo y acontecimiento

Para cada necesidad, decide primero si usarías delay, wait_for_trigger o un diseño diferente. Justifica la decisión antes de escribir YAML.

  1. Encender una luz durante exactamente tres segundos como señal visual.
  2. Esperar hasta que una puerta se cierre, con un límite de dos minutos.
  3. Apagar la luz cinco minutos después del último movimiento detectado.
  4. Ejecutar una acción mañana a las 08:00 aunque Home Assistant se reinicie esta noche.

Después completa la automatización del pasillo con estos requisitos:

  • Trigger al comenzar el movimiento.
  • Encender la luz.
  • Esperar a que termine el movimiento, máximo diez minutos.
  • Si se alcanza el límite, detener la secuencia.
  • Esperar treinta segundos adicionales.
  • Apagar la luz.
  • Reiniciar el ciclo si aparece movimiento nuevo.
Ver la solución explicada

La automatización completa es:

alias: "Curso YAML - Luz de pasillo por movimiento"
description: >-
  Enciende la luz con movimiento, espera a que termine y la mantiene
  treinta segundos adicionales.
triggers:
  - trigger: state
    entity_id: binary_sensor.course_hallway_motion
    from: "off"
    to: "on"
conditions: []
actions:
  - action: light.turn_on
    target:
      entity_id: light.course_living_room
  - wait_for_trigger:
      - trigger: state
        entity_id: binary_sensor.course_hallway_motion
        from: "on"
        to: "off"
    timeout:
      minutes: 10
    continue_on_timeout: false
  - delay:
      seconds: 30
  - action: light.turn_off
    target:
      entity_id: light.course_living_room
mode: restart

La señal visual exacta utiliza delay, porque la duración es el requisito. Cerrar una puerta utiliza wait_for_trigger y un timeout. «Cinco minutos después del último movimiento» puede resolverse con una secuencia reiniciable: cada nuevo movimiento reinicia el margen. Una ejecución para mañana a una hora concreta no debería depender de un delay que se pierde al reiniciar; necesita un trigger horario o un diseño persistente.

Qué debes llevarte de este capítulo

delay espera una duración sin observar el entorno. wait_for_trigger espera un acontecimiento dentro de una ejecución ya iniciada. Un timeout limita esa espera, y continue_on_timeout decide si la secuencia debe continuar cuando el acontecimiento no llega.

Al introducir esperas, varias ejecuciones pueden solaparse. single, restart, queued y parallel representan políticas diferentes; no existe un modo universalmente correcto. Para la luz del pasillo, restart permite que el movimiento nuevo cancele un apagado pendiente y reinicie el ciclo.

En el siguiente capítulo separaremos las secuencias reutilizables de los acontecimientos que las activan. Crearemos nuestro primer script y lo llamaremos desde una automatización y desde la interfaz sin duplicar las mismas acciones.

Continúa leyendo

Siguiente guía relacionada · 15 min de lectura

Cómo entiende Home Assistant tu casa: entidades, estados, atributos y acciones

← Capítulo 2 · Índice del curso Cuando miras una bombilla desde el salón, ves un dispositivo que puede estar encendido, apagado o iluminando…

Continuar con este artículo