Repeating a service (or script)?

not sure if this helps, but it works:

  play_tune:
    alias: Play tune
    sequence:
      - service: script.tune
      - delay:
          seconds: >
           {{state_attr(states('sensor.tune_player'),'media_duration')|int}}
      - condition: state
        entity_id: input_boolean.loop_tune
        state: 'on'
#      - condition: template
#        value_template: >
#          {{is_state('input_boolean.loop_tune','on')}}
      - service: script.play_tune_loop

  play_tune_loop:
    alias: Play tune loop
    sequence:
      - service: script.tune
      - delay:
          seconds: >
           {{state_attr(states('sensor.tune_player'),'media_duration')|int}}
      - condition: state
        entity_id: input_boolean.loop_tune
        state: 'on'
#      - condition: template
#        value_template: >
#          {{is_state('input_boolean.loop_tune','on')}}
      - service: script.play_tune

@123

There is an option to turn off the python_script in a middle (let’s say that the for loop is already running),
From the automation that called to this python_script ?

Something like:

- service: homeassistant.turn_off
  entity_id: python_script.church_bells

Regards,
Alex.

You could just write wait_template in python: Have a loop in python and check the state(s) of whatever entities would be in the wait template every second (or some interval) until your condition is true, then proceed.

This exactly what I did, but I can’t change the “binary_sensor.tami_4_water_sensor” to off:

if hass.states.get('binary_sensor.tami_4_water_sensor').state == 'on':
  message = 'Pay attention, there is flooding behind Tammy Bar !'
else:
  message = 'Pay attention, there is flooding in the storage !'

for j in range(4):
  if hass.states.get('binary_sensor.tami_4_water_sensor').state == 'on':
    # Alexa tts message:
    hass.services.call('notify', 'alexa_media_alex_s_echo_dot', {'message':message, 'data' : {'type':'tts'}}, False)

    time.sleep(1)

What backs that binary_sensor? Is it MQTT, template, esphome? Maybe you could “hack” the origin of the sensor to turn it off.

Or have a completely separate entity, such as an input_boolean to trigger the script to exit regardless of the state of the sensor.

Can you provide an example? I read this and believed it was not possible.


EDIT
I misread your suggestion. I thought you were suggesting to use a literal wait_template. You are suggesting to emulate its functionality (i.e. use python code to check state of a given entity).

As for you question, the “binary_sensor.tami_4_water_sensor” is a xiaomi flooding sensor (zigbee).

I tried your suggestion to create and using an input_boolean to trigger the script to exit regardless of the state of the sensor, like shown in the the following code:
But it’s working, only if the first for loop iteration didn’t start yet, ones it’s started no option to stop the script.

for j in range(4):

  if hass.states.get('input_boolean.python_script_water_sensor_sirens_code').state == 'on':

    # Alexa tts message:

    hass.services.call('notify', 'alexa_media_alex_s_echo_dot', {'message':message, 'data' : {'type':'tts'}}, False)

    time.sleep(1)

Can you paste in the entire script so I can see it as a whole?

Sure.

The automation:

- alias: 'The house was flooded with water notification'
  trigger:
    platform: state
    entity_id:
      - binary_sensor.tami_4_water_sensor
      - binary_sensor.storage_water_sensor
    from: 'off'
    to: 'on'
  action:
    - service: python_script.water_sensor_sirens

The Python script: “water_sensor_sirens.py”

if hass.states.get('binary_sensor.tami_4_water_sensor').state == 'on':
  message = 'Pay attention, there is flooding behind Tammy Bar !'
else:
  message = 'Pay attention, there is flooding in the storage !'

for j in range(4):
  if hass.states.get('input_boolean.python_script_water_sensor_sirens_code').state == 'on':
    # Alexa tts message:
    hass.services.call('notify', 'alexa_media_alex_s_echo_dot', {'message':message, 'data' : {'type':'tts'}}, False)

    time.sleep(1)

    # Repeat for sirens/alarm:
    for i in range(5):
      hass.services.call('media_player', 'play_media', {'entity_id':'media_player.alex_s_echo_dot', 'media_content_type':'sound', 'media_content_id':'amzn_sfx_scifi_alarm_01'}, False)
      time.sleep(1)

How I’m turning off the input_boolean:

  trigger:
  ...
  action:
    - service: input_boolean.turn_off
      entity_id: input_boolean.python_script_water_sensor_sirens_code

It looks good on the surface but I see some spots for error trapping improvments. Are you getting errors in your logs?

No, don’t see any error.

Ok, so when you turn it off during loop 1, it still continues with loop 2 3 and 4? Or does it finish loop 1 but you want to stop it immediately?

Yes, when I turn it off during loop #1, it still continues with loop 2 to 4.
It’s o.k. with me to stop only after the current iteration will finish.
But it’s o.k. to stop immediately as well.

I’m wondering if the state machine passed to python scripts is stuck in stone. If that’s the case checking the state may not make a difference. I’d have to write a test case to verify, I don’t use them enough to know for sure.

I just added a break statement in each loop to bail out of the loops if the input_boolean is not on.

if hass.states.get('binary_sensor.tami_4_water_sensor').state == 'on':
  message = 'Pay attention, there is flooding behind Tammy Bar !'
else:
  message = 'Pay attention, there is flooding in the storage !'

for j in range(4):
  if hass.states.get('input_boolean.python_script_water_sensor_sirens_code').state != 'on':
    break

  # Alexa tts message:
  hass.services.call('notify', 'alexa_media_alex_s_echo_dot', {'message':message, 'data' : {'type':'tts'}}, False)
  time.sleep(1)

  # Repeat for sirens/alarm:
  for i in range(5):
    if hass.states.get('input_boolean.python_script_water_sensor_sirens_code').state != 'on':
      break

    hass.services.call('media_player', 'play_media', {'entity_id':'media_player.alex_s_echo_dot', 'media_content_type':'sound', 'media_content_id':'amzn_sfx_scifi_alarm_01'}, False)
    time.sleep(1)

Oops, I see …

!= instead of ==
And Break

devil is in the details, i assumed you were turning the toggle on and off…

In the original script, you were only doing stuff if the input boolean was on. In my changes, I’m breaking out of the loop if it is NOT on.

I see…

Thanks !

Checking …

This thought about the state machine is interesting. I would have expected that each time it was called, the state would be the most up-to-date version of that entity’s state. And I will continue to belive this until proven otherwise :slight_smile: