How to lock automation from restarting itself

Question

How can I prevent an automation from restarting if I want the state to be temporarily locked?

I have an automation for motion triggered Christmas lights, but I have a switch condition to prevent it from turning on if I manually turned off the lights. Thank you @CentralCommand for your explanation here Manual override of automation - #2 by CentralCommand

Goal

I’m trying to have a motion light that I can prevent from turning itself on if I turn them off via the UI or Alexa.

The Automation

alias: "Christmas: Lights on while home"
description: >-
  Goal is to have it not turn lights on if i manually turn off. Haven't figured
  out how to prevent restart triggered by motion during the manual off holding
  window.
trigger:
  - platform: state
    entity_id: alarm_control_panel.ha_alarm
  - platform: state
    entity_id:
      - group.upstairs_motion_sensors
    to: "on"
  - platform: state
    entity_id:
      - switch.mobile_plug
    to: "off"
condition: []
action:
  - choose:
      - conditions:
          - condition: or
            conditions:
              - condition: state
                entity_id: alarm_control_panel.ha_alarm
                state: armed_away
              - condition: state
                entity_id: alarm_control_panel.ha_alarm
                state: armed_night
        sequence:
          - service: switch.turn_off
            target:
              entity_id: switch.mobile_plug
            data: {}
      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.to_state.context.parent_id == none and
              trigger.to_state.state == 'off' }}
        sequence:
          - wait_for_trigger:
              - platform: state
                entity_id:
                  - switch.mobile_plug
                to: "on"
            timeout:
              hours: 3
              minutes: 0
              seconds: 0
              milliseconds: 0
    default:
      - service: switch.turn_on
        data: {}
        target:
          area_id: switch.mobile_plug
        enabled: true
      - delay:
          hours: 0
          minutes: 30
          seconds: 0
          milliseconds: 0
      - service: switch.turn_off
        data: {}
        target:
          area_id: switch.mobile_plug
mode: restart

So the section has the goal of preventing the automation from restarting (for 3 hours or if I manually turn it on again) if I just manually turned it off.

      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.to_state.context.parent_id == none and
              trigger.to_state.state == 'off' }}
        sequence:
          - wait_for_trigger:
              - platform: state
                entity_id:
                  - switch.mobile_plug
                to: "on"
            timeout:
              hours: 3
              minutes: 0
              seconds: 0
              milliseconds: 0

The problem

Right now the automation is in restart mode. I don’t think it should be in single mode because that would prevent the motion timer from restarting and would prevent the manual off from happening. I don’t think it should be in queue mode because it would not always have the latest action next.

Any thoughts?

So I mean step 1 is probably remove all the waits and delays. Using delays and restarts to block execution with a run mode just makes things very confusing in my opinion. Plus it creates bugs anytime HA restarts or the automation is reloaded since then existing running instances are immediately stopped.

From my understanding of what you’re doing here I’d probably do it something like this:

alias: "Christmas: Lights on while home"
description: >-
  Goal is to have it not turn lights on if i manually turn off. Haven't figured
  out how to prevent restart triggered by motion during the manual off holding
  window.
trigger:
  - platform: state
    entity_id: alarm_control_panel.ha_alarm
    to:
      - armed_away
      - armed_night
  - id: motion
    platform: state
    entity_id:
      - group.upstairs_motion_sensors
    to: "on"
  - id: timed_out
    platform: template
    value_template: >-
      {% set changed = expand('group.upstairs_motion_sensors') | selectattr('state', 'eq', 'on')
              | map(attribute='last_changed') | sort(reverse=true) | first %}
      {{ is_state('switch.mobile_plug', 'on') and (
            states.switch.mobile_plug.last_changed < now() - timedelta(hours=3)
            or states.switch.mobile_plug.context.parent_id is none
              and changed < now() - timedelta(minutes=30)
          ) }}
action:
  - choose:
      - alias: "Christmas off"
        conditions:
          - or:
              - "{{ trigger.id == 'timed_out' }}"
              - "{{ states('alarm_control_panel.ha_alarm') in ['armed_away', 'armed_night'] }}"
        sequence:
          - service: switch.turn_off
            target:
              entity_id: switch.mobile_plug
      - alias: "Christmas on"
        conditions:
          - "{{ trigger.id == 'motion' }}"
          - or:
            - "{{ states.switch.mobile_plug.context.parent_id is not none }}"
            - "{{ states.switch.mobile_plug.last_changed < now() - timedelta(hours=3) }}"
        sequence:
          - service: switch.turn_on
            target:
              entity_id: switch.mobile_plug

So what happens here is this:

  1. When you arm the house or when the house is already armed and one of the other triggers happens it simply turns off the christmas lights and does nothing else
  2. When the motion sensor trips it turns on the christmas lights IF the lights were last changed via an automation or its been 3 hours since they were manually changed last.
  3. If the christmas lights have been on for 3 hours or they’re on and it’s been 30 minutes since motion was last detected upstairs then turn them off

This automation does not rely on any waits or delays it simply triggers when last changed crosses thresholds. This means you don’t have to worry about which mode to use and what happens when the automation itself is turned off or whatever. If the automation is turned off everything just stays as is until it is turned back on. And if HA restarts or automations are reloaded then the automation just keeps working normally.

I should note I did make a couple changes to your logic. Feel free to reject them, I can help you adjust the logic if needed to do that:

  1. Your automation only allowed someone to manually override the lights to be off. In mine a user can manually override the lights to be on or off and then they return to being automated after 3 hours.
  2. Your automation would turn off the christmas lights if someone was moving around upstairs going from motion sensor to motion sensor but never actually allowing the motion sensor group to turn off. Mine will turn the lights off if its been 30 minutes since any motion sensor in the group has been turned on.

Wow, that is a different way of thinking about the problem. I’ve never done an automation that uses the time it last ran as a trigger.

I understand the logic and will run what you wrote as-is and see how it does. Now you’re going to make me start writing automation in this style!