Question about nested scripts

I have a unified setup for my bedroom TV which includes a digital mixer. The mixer runs on CAT5 or WiFi connection. Because of logistics, I cannot run a cable to my bedroom; thus, connection is by WiFi, which takes 15-30s to connect after power is applied. Since there is no point in completing the script until the mixer is connected, I have a while loop in my script to check for the mixer (code shortened to highlight the issues):

mbr_rem_turn_on_tv:
  alias: MBR REM > Turn on TV
  sequence:
# run some tasks
  - action: input_select.select_first
    data: {}
    target:
      entity_id:
      - input_select.bedroom_eq
      - input_select.bedroom_pad
  - action: switch.turn_off
    data: {}
    target:
      entity_id: switch.mbr_ps_mp3_audio
  - action: switch.turn_on
    data: {}
    target:
      entity_id: switch.mbr_ps_xr12_mixer
      ...
# wait for the mixer to go live
  - repeat:
      while:
        - condition: template
          value_template: "{{ is_state('number.mbr_mixer_scene_current', 'unavailable') }}"
      sequence:
        - delay: "00:00:01"
# then do the rest of the tasks
  - action: remote.send_command
    data:
      num_repeats: 1
      command: power
    target:
      entity_id: remote.master_br_roku
      ...
      etc.

Here’s what happens:

  • If I call the script directly – ex: using a button to performa a call-service in custom:button-card – script.mbr_rem_turn_on_tv works perfectly, every time.

  • I want to add a sequence that turns on the TV when I press I button for Netflix, YouTube, etc. and the TV is off. If I call the script from inside another script, though, (see below) the While loop appears to only execute 1-2x, then carries on as if the mixer was connected (it is not) and completes the rest of the code. :confused:

mbr_rem_roku_shell_4:
  alias: MBR REM > Call Roku App4
  description: Turn on TV + Netflix
  mode: single
  sequence:
    - service: script.turn_on
      target:
        entity_id: script.mbr_rem_turn_on_tv
    - delay:
        seconds: 3
    - service: script.turn_on
      target:
        entity_id: script.mbr_rem_roku_app4

Does anyone know why this is happening?

TIA,
Bruce

Honestly Id use wait for template or wait for trigger with a timeout… Wayyyyy cleaner and you don’t get into loop hell.

This should be the link directly to it.

Id try to re-engineer the loop out then see if it starts behaving.

(I try to avoid loops at all costs, also long waits. A short wait for timeout won’t hurt you here)

Thanks for the tip. wait_template is a simpler approach … but the end result is the same. The script works perfectly when called directly. It drops through early if called from another script.

OK, I finally got it to work! There was something going with the two scripts executing in parallel – or nearly so – even though I used mode: single. I tried mode: queued which made things better, but not quite right. Maybe adding an if/then made things worse??

At any rate, this approach worked:

mbr_rem_roku_shell_1:
  alias: MBR REM > Call Roku App1
  description: Turn on TV + BritBox
  sequence:
    - service: script.mbr_rem_turn_on_tv
    - wait_template: "{{ is_state('script.mbr_rem_turn_on_tv', 'off') }}"
    - service: script.mbr_rem_roku_app1
  mode: single

I don’t know if I needed the wait_template, but it provides insurance. I then moved the if/then/else test to custom:button-card –

hold_action:
  action: call-service
  service: |
    [[[ if (states['input_number.tv2_active'].state >= 2)
      return "script.mbr_rem_roku_app1"
      else return "script.mbr_rem_roku_shell_1" ]]]

Perhaps the issue you are seeing is due to the way that HA executes scripts.

action: script.turn_on
entity_id:
  - script.one
  - script.two
  - script.three

… will run all three scripts in parallel.

- action: script.one
- action: script.two
- action: script.three

HA will wait for script one to finish before starting script two, and for two to finish before starting three.

2 Likes

The wait_template with a timeout is definitely the way to go for waiting for a power on cycle to land a WIFI connection, 2 actions below where NathanCU’s link lands you in the docs. personally I add a short delay after since I found that sometimes the next action can run before it’s fully set up.

- wait_template: "{{ has_value('number.mbr_mixer_scene_current')"
  timeout: "00:01:00"
- delay: 1

Equally important is understanding the difference between the 2 different ways to call a script as sparkydave points out. script.turn_on will execute and go on to the next action without caring about the script its calling, script.your_script will wait for your called script to complete before moving on tto the next action. Script Integration Docs

1 Like