Random sprinkler automation

Tags: #<Tag:0x00007fc41de7e0a8>

Hi there, I’m pretty new to Home Assistant, but it already won my heart. Yesterday I found myself turning on and off sprinklers, as my 3yo likes to get under the sprinklers, making him chase from one sprinkler to the other. He loved it but I had manually to do all the turning-on/off. Today I spent my day finding an automation script that would do that for me with no success.

So far I created an input_boolean, which is going to be checked and as long as the condition is true, the automation would continue to loop, cycling through the four sprinklers I have. I also have a slider_input, where I can set the duration in seconds for a sprinkler to be on.

I guess my error lies in the scripts.yaml and the automation.yaml. Hope that someone can point me in the right direction.

my configuration.yaml

input_number:
  sprinkler_timer_seconds:
    min: 0
    max: 20
input_boolean:
  game_sprinklers_state:

my automation.yaml

- alias: game_loop
  trigger:
    platform: state
    entity_id:
      - input_boolean.game_sprinklers_state
    to: "on"
  action:
    service: script.open_a_sprinkler

and my scripts.yaml

open_a_sprinkler:
  sequence:
    - alias: "Open a random sprinkler for x seconds"
      repeat:
        while:
          - condition: state
            entity_id:
              - input_boolean.game_sprinklers_state
            state: "on"
          # Don't do it too many times
          - condition: template
            value_template: "{{ repeat.index <= 50 }}"
        sequence:
          - service: switch.turn_on
            entity_id: 'switch.{{["terracesprinkler","terracesprinkler2","middlesprinkler","gatesprinkler"]|random}}'

Actually, your automation as written will very quickly turn them all on in random order and then continue to do that until the input_boolean is turned off (or 50 iterations occur, which will happen very quickly). In other words, all sprinklers will be turned on within moments of the automation being triggered and never get turned off.

I imagine this is not how you want it to work. Can you elaborate on how it should work.

  • Each sprinkler should be turned on for the number of seconds specified by the input_number and then turned off?
  • If the random function chooses to turn on a sprinkler that is already on, and counting down its seconds, then it should be skipped and not turned on again (which would reset its countdown)?
  • Each sprinkler is on for X seconds but what is the interval for random to select the next sprinkler to turn on? After a sprinkler counts down and is turned off? That behavior would only allow for one sprinkler to be on at a time.

Unfortunately, it’s not working, and thanks for pointing out blind spots. Even after removing the iteration limit, it’s still the same.

  • Yes
  • Ideally, an active sprinkler should not be included in the next random selection, leaving 3 sprinklers to be chosen in each cycle.
  • I thought the input slider “sprinkler_timer_seconds” defines also when a new sprinkler is to be chosen.

Ideally, after turning on a switch, one of the four sprinklers should run for n seconds, which is defined by an input slider. After n seconds the active sprinkler should be turned off and one of the remaining three sprinklers should be turned on for n seconds. The previous sentence is the looping part. Once the switch is turned off, the loop should break, and after the last cycle, no sprinklers should be active anymore.

In other words, it should be whack-a-mole game, where the sprinklers are the mole, and my kid the hammer. I have switch to turn it on or off, and a slider to define how long a sprinkler will be on.

Hope that helps.

Try this:

- alias: game_loop
  id: game_loop
  mode: restart
  trigger:
  - platform: state
    entity_id: input_boolean.game_sprinklers_state
  action:
  - variables:
      all_sprinklers: ["switch.terracesprinkler","switch.terracesprinkler2","switch.middlesprinkler","switch.gatesprinkler"]
  - repeat:
      while: '{{ is_state("input_boolean.game_sprinklers_state", "on") and repeat.index <= 50 }}'
      sequence:
      - variables:
          sprinkler: '{{ all_sprinklers | random }}'
      - service: switch.turn_on
        target:
          entity_id: '{{ sprinkler }}'
      - delay: '{{ states("input_number.sprinkler_timer_seconds") }}'
      - service: switch.turn_off
        target:
          entity_id: '{{ sprinkler }}'
  - service: switch.turn_off
    target:
      entity_id: '{{ all_sprinklers }}'

How it works

The moment you turn on input_boolean.game_sprinklers_state it will:

  • randomly select a sprinkler
  • turn it on
  • leave it on for the duration of input_number.sprinkler_timer_seconds
  • turn it off

It will repeat this cycle as long as input_boolean.game_sprinklers_state is left on or until 50 iterations (fail-safe to prevent it running all day long).

When you turn off input_boolean.game_sprinklers_state, it immediately aborts the repeat-while and turns off all sprinklers (another fail-safe to ensure none of the sprinklers are accidentally left on).

While the automation is executing, you can manually adjust the duration of input_number.sprinkler_timer_seconds. Whatever change you make will affect the next iteration of the repeat-while.

If you want a bit more randomness, you can replace this:

      - delay: '{{ states("input_number.sprinkler_timer_seconds") }}'

with this:

      - delay: '{{ range(5, 21) | random }}'

For each iteration, it will turn on the sprinkler for a random duration varying from 5 to 20 seconds (not 21 but 20, that’s how the range() function works).


NOTE

In operation, it may not always “feel” random. Sometimes the same sprinkler will be on for than one iteration. That’s because:

  • There are only four sprinklers.
  • For each iteration, the same set of four are used for random selection (meaning even the one that was already on can be chosen again).

I encountered this perception of ‘poor randomness’ when making pool lights change color. Even though it had a set of eight colors to choose from, sometimes the same color was chosen twice. In terms of randomness, that is entirely possible but, to the human eye, seeing the same color persist for twice as long as normal didn’t “feel” random.

The solution was to first shuffle the colors in random order, then select each color in sequence. After the last color was displayed, the process is repeated (i.e. colors shuffled again and each color displayed in sequence). This gives the perception of ‘better randomness’.

To illustrate the difference, let’s use a deck of cards:

Method 1:

  1. Randomly select a card from the deck.
  2. Put it back exactly where you got it.
  3. Repeat.

Method 2:

  1. Shuffle the deck.
  2. Select the top card from the deck.
  3. Select the next top card and continue until all cards have been dealt.
  4. Repeat.

The second method ensures the same card cannot be drawn twice in succession. The entire deck must be dealt (at the very least) before the same card can be drawn again.

Thank you very much. It worked like a charm. Trying to improve it a bit more like setting the iteration through an input slider etc.

Thanks again.

This father can go to sleep in peace now.

1 Like