Repeating a service (or script)?

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:

yeah same. :man_shrugging: Unfortunately donā€™t have the time to test / verify

@SteveDinn

Oā€¦ It is still not stopping if the first loop iteration already fired.
Itā€™s looks link that it donā€™t check the if condition in each iteration.

I checked the the ā€œinput_boolean.python_script_water_sensor_sirens_codeā€ changed to off.