Help with While Loop Action

Hello,
I’m trying to understand how the While Loop action is supposed to work. I use an automation that notifies me the wash is done and to move the clothes to the dryer. It will loop every 9 minutes until the washing machine door is opened, which sets an input boolean. This helper is then used as the condition to break the loop and continue with the rest of the automation.

In practice, the boolean is changed in between the next run of the loop (within the 9 minute window). The last loop will run even though the while condition is broken, then move on to the next action. My preference would be for the last loop to start, the condition evaluates as false, then skips the sequence of actions within the loop and moves on to the next action.

The description for the While Loop from HA docs seems to support my expectations:

This form accepts a list of conditions that are evaluated before each time the sequence is run. The sequence will be run as long as the condition(s) evaluate to true.

Am I doing something wrong? Is my expectation on how the While Loop works wrong? Is there a better way of achieving what I’m after?

Here is the yaml for the actions in my automation.

description: "Wash is done alert"
mode: single
triggers: []
conditions: []
actions:
  - data: {}
    target:
      entity_id: input_boolean.door_open
    action: input_boolean.turn_off
  - repeat:
      sequence:
        - delay:
            hours: 0
            minutes: 9
            seconds: 0
            milliseconds: 0
        - metadata: {}
          data:
            message: Wet Clothes in the Washing Machine.
            title: Laundry
          action: script.mobile_notification_greg
      while:
        - condition: state
          entity_id: input_boolean.door_open
          state: "off"
        - alias: Don't repeat more than 15 times
          condition: template
          value_template: "{{ repeat.index <= 15 }}"
    enabled: true
  - metadata: {}
    data:
      message: Good job moving the clothes.
      title: Laundry
    action: script.mobile_notification_greg

Where is your trigger? Using automations without a trigger can lead to unreliable function. If your intent is to fire the automation via a service call/action you should use a Script instead or an Automation.

Regarding the While loop…

I think have misunderstood the docs or structured your actions inappropriately. In your automation the flow is as follows:

  1. Check conditions
  2. Run Sequence
    2a. Delay
    2b. Run Notification Script
  3. Go back to #1

The conditions are not checked while the loop is in the middle of a run… i.e. they are not checked after the delay.

There are a few options to have the conditions checked before the notification, the two easiest would be:

  1. Add a condition between the delay and the notification so they are checked immediately before the notification.
Adding Conditions in the Run
description: "Wash is done alert"
mode: single
triggers: []
conditions: []
actions:
  - data: {}
    target:
      entity_id: input_boolean.door_open
    action: input_boolean.turn_off
  - repeat:
      sequence:
        - delay:
            hours: 0
            minutes: 9
            seconds: 0
            milliseconds: 0
        - condition: state
          entity_id: input_boolean.door_open
          state: "off"
        - alias: Don't repeat more than 15 times
          condition: template
          value_template: "{{ repeat.index <= 16 }}"
        - metadata: {}
          data:
            message: Wet Clothes in the Washing Machine.
            title: Laundry
          action: script.mobile_notification_greg
      while:
        - condition: state
          entity_id: input_boolean.door_open
          state: "off"
        - alias: Don't repeat more than 15 times
          condition: template
          value_template: "{{ repeat.index <= 15 }}"
    enabled: true
  - metadata: {}
    data:
      message: Good job moving the clothes.
      title: Laundry
    action: script.mobile_notification_greg
  1. Move the notification so it happens before the delay.
Rearrange the Run
description: "Wash is done alert"
mode: single
triggers: []
conditions: []
actions:
  - data: {}
    target:
      entity_id: input_boolean.door_open
    action: input_boolean.turn_off
  - repeat:
      sequence:
        - metadata: {}
          data:
            message: Wet Clothes in the Washing Machine.
            title: Laundry
          action: script.mobile_notification_greg
        - delay:
            hours: 0
            minutes: 9
            seconds: 0
            milliseconds: 0
      while:
        - condition: state
          entity_id: input_boolean.door_open
          state: "off"
        - alias: Don't repeat more than 15 times
          condition: template
          value_template: "{{ repeat.index <= 15 }}"
    enabled: true
  - metadata: {}
    data:
      message: Good job moving the clothes.
      title: Laundry
    action: script.mobile_notification_greg
1 Like

Thanks @Didgeridrew! - I removed the trigger from this post just to keep it simple to read. The automation triggers perfectly based on a power sensing outlet. If power drops below a certain threshold, this automation will trigger.

So I understand the looping logic better, you say…

When are the conditions checked within a loop?

Regardless, I’ll try your alternative suggestions!

Hi Greg, I’m doing exactly the same just by using the power draw from the plug.
When it goes below a certain value, that’s the trigger and you don’t need to loop anything.

Thanks @Nick4 - the loop is to nag me with a text alert until I actually move the clothes to the dryer. Otherwise, I’ll get the alert once and usually forget about it. :wink:

Only when you add them there. Neither the Repeat While or Repeat Until actions check the conditions within the sequence of the Repeat.

If you want a more immediate reaction you could add a trigger for the input boolean changing to “on” and set the automation mode to restart. It requires a bit more conditional logic, but it feels more responsive because it can break through the delay.

description: "Wash is done alert"
mode: restart
triggers:
  - id: power
    trigger: #Your original trigger
  - id: door
    trigger: state
    state: "on"
    entity_id: input_boolean.door_open
conditions: 
  - or:
      - condition: trigger
        id: power
      - alias: Prevent actions based on the boolean trigger when automation isn't already active.
        condition: template
        value_template: "{{this.attributes.current > 0}}"
actions:
  - if:
      - condition: trigger
        id: power
    then:
      - action: input_boolean.turn_off
        data: {}
        target:
          entity_id: input_boolean.door_open
      - repeat:
          sequence:
            - delay: "00:09:00"
            - metadata: {}
              data:
                message: Wet Clothes in the Washing Machine.
                title: Laundry
              action: script.mobile_notification_greg
            - alias: Kill Automation if washer isn't attended to
              condition: template
              value_template: "{{ repeat.index == 15 }}"
            - stop: "No one took the clothes out of the washer"
          while:
            - condition: state
              entity_id: input_boolean.door_open
              state: "off"
            - alias: Don't repeat more than 15 times
              condition: template
              value_template: "{{ repeat.index <= 15 }}"
  - metadata: {}
    data:
      message: Good job moving the clothes.
      title: Laundry
    action: script.mobile_notification_greg

ah. that makes sense. And a good idea for breaking through the delay. Thanks.

Men… :crazy_face:

1 Like