Help needed with templating in script to select media player

Need help with a specific use case I have. Losing WAF because TTS alerts interrupt the music streams when playing on our google home, which couldn’t then be resumed. I actually have two devices reasonably close to each other (home + chromecast audio), so I figured I would divert the TTS message to which ever wasn’t already playing, and temporarily mute the one already playing. Music then continues when the message is finished speaking.

However I am doing something wrong, probably because I am trying to nest script calls and pass arguments between too many scripts. See 4 scripts below: one is just to test the function. The next script is supposed to work out if a media player is playing and divert the message to the other one via one of two scripts.

No syntax errors, or log errors, just nothing happens when I run the test script. I guess the argument isn’t being passed through to the final scripts correctly.

Any ideas on what I am doing wrong, or how I should be approaching this would be gratefully accepted.

speak_message_test:
  alias: test the new speak function
  sequence: 
    - service: script.speak_message
      data:
         message: "This is a test"
        
        
        
speak_message:
  alias: Message - speak on best device
  sequence:        
    - service: script.turn_on
      data_template:
        message: "{{ message }}"  
        entity_id: >-
          {% if is_state('media_player.kitchen', 'playing') %}
            script.speak_message_dining
          {% else %}
            script.speak_message_kitchen
          {% endif %}       
      
        

speak_message_kitchen:
  alias: Message - speak on kitchen
  sequence:
    - service: media_player.volume_mute
      data:
        entity_id: media_player.dining_room_speaker
        is_volume_muted: true
    - service: tts.google_say
      entity_id: media_player.kitchen
      data_template:
        message: "{{ message }}"  
    - delay: '00:00:08'
    - service: media_player.volume_mute
      data: 
        entity_id: media_player.dining_room_speaker
        is_volume_muted: false
      
      
speak_message_dining:
  alias: Message - speak on dining room
  sequence:
    - service: media_player.volume_mute
      data: 
        entity_id: media_player.kitchen
        is_volume_muted: true
    - service: tts.google_say
      entity_id: media_player.dining_room_speaker
      data_template:
        message: "{{ message }}"
    - delay: '00:00:08'  
    - service: media_player.volume_mute
      data: 
        entity_id: media_player.kitchen
        is_volume_muted: false      

At first glance it looks a bit over complicated :slight_smile:
First question is what TTS are you going to play? Is there any chance you could save the message in an input_text and read from it instead of parsing messages across several scripts?

Also for your delay, I’m guessing your TTS message length may not always be exactly 8 sec, so instead you could have a wait_template:
- wait_template: " {{ states.media_player.kitchen.state != "playing" }}"

also you might be able to get away with a single script to play and mute. i’ve not tested this but should be close enough and give you a good idea on what needs doing:

  sequence:
    - service: media_player.volume_mute
      data_template: 
        entity_id: >
          {% if states.media_player.kitchen.state == "playing" %} media_player.kitchen
          {% else %} media_player.dining_room_speaker
          {% endif %}
      is_volume_muted: true
    - service: tts.google_say
      data_template:
        entity_id: >
          {% if states.media_player.kitchen.state == "playing" %} media_player.dining_room_speaker
          {% else %} media_player.kitchen
          {% endif %}
        message: "{{ message }}"
    - wait_template: >
      {% if states.media_player.kitchen.attributes.is_volume_muted == "true" %}
      {{ states.media_player.dining_room_speaker.state != "playing" }}
      {% else %}
      {{ states.media_player.dining_room_speaker.state != "playing" }}
      {% endif %}
    - service: media_player.volume_mute
      data_template: 
        entity_id: >
          {% if states.media_player.kitchen.attributes.is_volume_muted == "true" %} media_player.kitchen
          {% else %} media_player.dining_room_speaker
          {% endif %}
        is_volume_muted: false

Brilliant! Thanks for your help.
I fixed a couple of small typos and indents and it works perfectly! - almost.
I had to add a small pause or the delay in the TTS kicking in wouldn’t allow the wait template conditions enough time and it would never wait.
Have pasted it below for those who it may help. I am still experiencing an issue where the kitchen never unmutes, because the wait_template never seems to complete. Working through that.

speak_message_test:
  alias: test the new speak function
  sequence: 
    - service: script.speak_message
      data:
        message: "This is a test"
        

speak_message:
  alias: speak on unused player
  sequence:
    - service: media_player.volume_mute
      data_template: 
        entity_id: >
          {% if states.media_player.kitchen.state == "playing" %} media_player.kitchen
          {% else %} media_player.dining_room_speaker
          {% endif %}
        is_volume_muted: true
    - service: tts.google_say
      data_template:
        entity_id: >
          {% if states.media_player.kitchen.state == "playing" %} media_player.dining_room_speaker
          {% else %} media_player.kitchen
          {% endif %}
        message: "{{ message }}"
    - delay: '00:00:02'     
    - wait_template: >
        {% if states.media_player.kitchen.attributes.is_volume_muted == "true" %}
          {{ states.media_player.dining_room_speaker.state != "playing" }}
        {% else %}
          {{ states.media_player.kitchen.state != "playing" }}
        {% endif %}
    - service: media_player.volume_mute
      data_template: 
        entity_id: >
          {% if states.media_player.kitchen.attributes.is_volume_muted == "true" %} media_player.kitchen
          {% else %} media_player.dining_room_speaker
          {% endif %}
        is_volume_muted: false

Got it ! The lines
{% if states.media_player.kitchen.attributes.is_volume_muted == “true” %}
shouldn’t have the inverted commas around true.
Should be
{% if states.media_player.kitchen.attributes.is_volume_muted == true %}
Works like a charm! Thanks for your help @lolouk44

I like @lolouk44’s solution, but i’m wondering why you didn’t simplify this in a ‘media player speak’ script. I get the single place 1 script, but if you want to perform more actions or you get another media player, changing the script would be a bitch. If you just make a script and pass the entity_ids and message, you won’t have to change much in the future:

speak_message:
  alias: Message - speak on best device
  sequence:        
    - service: script.turn_on
      data_template:
        message: "{{ message }}"
        speak_device: >
          {% if is_state('media_player.kitchen', 'playing') %}
            media_player.dining_room_speaker
          {% else %}
            media_player.kitchen
          {% endif %}
        mute_device: >
          {% if is_state('media_player.kitchen', 'playing') %}
            media_player.kitchen
          {% else %}
            media_player.dining_room_speaker
          {% endif %}
        entity_id: script.media_player_speak
media_player_speak:
  alias: Message from media player
  sequence:
    - service: media_player.volume_mute
      data_template: 
        entity_id: "{{ mute_device }}"
        is_volume_muted: true
    - service: tts.google_say
      data_template:
        entity_id: "{{ speak_device }}"
        message: "{{ message }}"
    - delay: '00:00:08'  
    - service: media_player.volume_mute
      data_template: 
        entity_id: "{{ mute_device }}"
        is_volume_muted: false

Then the only logic that needs to be changed is in the first script.

Just my 2 cents. I like being lazy in the future.

I may be wrong (feel free to slap me) but if indeed you add speakers, you’ll have to rework the script considerably to compute with 2+ devices needing muting and then unmuting?

I do like your approach to simplify the script though, while writing the above I was already thinking of a v2 script that would assign variables for the device to mute and the device to play on. HA is way too addictive :wink:

Yeah, I was thinking about that after I made the post. You could always add more variables to the scripts! Honestly, I’ve moved towards appdaemon to handle all this stuff because it’s just easier to add complexity.

1 Like