Repeating a service (or script)?

** UNTESTED **

As said, without a wait template it’s going to try and play the next iteration over the top of the last. But it should work for other things.

This would just generate a gigantic string.

action:
  - service_template:
    "media_player.play_media
     data:
       <data>
     media_player.play_media
     data:
       <data>
     ...
     ...
    "

Then home assistant would complain about the lack of serivce and data fields :frowning:

2 Likes

I just realized now that this will not work, a template will always only return a single string.

1 Like

Ah, so it would.

It’s a shame you can’t have “naked” templates, i.e. outside an entity or service.

There’s a feature request here that should be voted for if you haven’t already and want easy loops:

Easily done with the python_script integration.

church_bells.py

service_data = {'entity_id':'media_player.alex_s_echo_dot', 'media_content_type':'sound', 'media_content_id':'amzn_sfx_church_bell_1x_02'}
for i in range(10):
  hass.services.call('media_player', 'play_media', service_data, False)
  time.sleep(2)

Adjust sleep(2) to the number of seconds needed to allow for the playing of the media content.

Automation simply becomes this:

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

Instead of using time.sleep can you use a wait template to wait for the media player to finish playing?

1 Like

Thanks.
looks good,
I’ll try it.

Thanks,
This is working fine for me.
I just need to think how to turn it off after 20 iteration.

If there is a way to do that, I don’t know how. The python_script integration supports python code and wait_template is something specific to Jinja2 templating in Home Assistant.

Here’s my concept of creating loops.
I replaced your binary_sensor.storage_water_sensor with an input_boolean as it’s easier to test and also used persistent_notification.create service to get a feedback.
The number of loops (10) is hardcoded but it’s easy to change the code so it would take it from say, input_number and that way you’ll have a configurable loop :wink:

I put it in a package:

loop:
  counter:
    loop:

  input_boolean:
    loop:

  automation:
  - alias: 'test loop'
    trigger:
      - platform: state
        entity_id: input_boolean.loop
        from: 'off'
        to: 'on'
      - platform: event
        event_type: automation_loop
    action:
      - service: persistent_notification.create
        data_template:
          message: >
            {{ states('counter.loop') }}
      - service_template: >
          counter.{{ 'increment' if states('counter.loop')|int < (10-1) else 'reset' }}
        data:
          entity_id: counter.loop
      - condition: template
        value_template: >
          {{ 0 < states('counter.loop')|int < 10 }}
      - event: automation_loop

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