Setting a variable during a sequence for use at end of that same sequence

Hi,

I’m writing a script to send TTS message to my media player, and setting a certain volume. I want to capture and restore the initial volume level but can’t figure out how to set it as a variable during the sequence.

This is the whole thing:

send_tts_to_mediaplayer:
  alias: Send TTS message to a mediaplayer
  description: Sends TTS message at chosen volume level and restores initial volume upon finishing
  fields:
    entity_id:
      name: Entity
      description: Choose target media player entity.
      required: true
      example: media_player.google_home_mini
      selector:
        entity:
          #device_class: speaker
    tts_message:
      name: Message
      description: TTS message to send
      required: true
      selector:
        text:
    tts_language:
      name: Language
      description: Set TTS language, default is English. (use lower caps such as 'nl' or 'de')
      selector:
        text:
    tts_volume_level:
      name: Message volume
      description: Volume level at which to play the TTS message.
      required: true
      default: 0.5
      selector:
        number:
          min: 0.1
          max: 1
          step: 0.1
  variables:
    # temporary
    initial_volume_level: 0.2
  sequence:

  # Turn on media player and wait for idle state
  - service: media_player.turn_on
    data:
      entity_id: "{{ entity_id }}"
  - wait_template: "{{ is_state(entity_id, 'idle') }}"

  # Check (and store) current volume
  - service: notify.persistent_notification
    data:
      message: "Current volume of {{entity_id}}: {{ state_attr(entity_id, 'volume_level') }}"

  # Set TTS volume level, send message and wait for idle state
  - service: media_player.volume_set
    data_template:
      entity_id: "{{ entity_id }}"
      volume_level: "{{ tts_volume_level }}"
  - service: tts.google_translate_say
    data_template:
      entity_id: "{{ entity_id }}"
      message: "{{ tts_message }}"
      language: "{{ tts_language }}"
  - wait_template: "{{ is_state(entity_id, 'idle') }}"

  # Restore initial volume level
  - service: media_player.volume_set
    data_template:
      entity_id: "{{ entity_id }}"
      volume_level: "{{ initial_volume_level }}"

I hope someone can help me out with this, or point me in the right direction.
And go easy on me, I’m learning :wink:

You can use a scene created on-the-fly to save whatever you need to save

- description: Sends TTS message at chosen volume level and restores initial volume upon finishing
  sequence:
  - service: scene.create
    data:
      scene_id: before
      snapshot_entities: 
        - media_player.home_mini_woonkamer

---------------------------------------
THIS IS WHERE TO DO EVERYTHING YOU WANT
---------------------------------------

  - service: scene.turn_on
    data:
      entity_id: scene.before

EDIT: script is sequence, not action

1 Like

I do this as well… I simply add this at the top of the script:-

variables:
  previous_volume_level: "{{ state_attr(media_player.somedevicename,'volume_level') }}"

The scene created on the fly will store all the attributes of all the entities that might change during the automation or the script.

It is a very powerful way to rollback to any previous state, in case of failure in the automation for exemple.

Of course, if you don’t want to restore the entity completely, but keep a part of what was done in the script but set back only a few of the attributes to their previous values, saving them in variables as you do is a possibility.

That’s great Olivier, the scene works perfectly. Never thought of using it this way :slight_smile:

I actually tried using a variable as per @Rofo 's suggestion at first, but it only works when the media player is already in on or idle state. When it is off, the volume_level state is not available to read. That’s why I’m waiting for idle state as one of the first steps in the sequence.

I think the scene idea is much better, although if the device is off and you can’t get the volume level, I’m not clear how the scene would be able to ?

I’m capturing the scene during the sequence after waiting for the media player to not be in the ‘off’ state. Setting it as a variable happens before the sequence starts and the device is possibly still off.

Waiting for it to not be in the ‘off’ state as opposed to it being in the ‘idle’ state, as I did before, means it will also work when the device is paused or playing media at the time.

 sequence:
  # Turn on media player and wait until it is not in 'off' state
  - service: media_player.turn_on
    data:
      entity_id: "{{ entity_id }}"
  - wait_template: "{{ is_state(entity_id, 'off') == false }}"
  # Create scene from snapshot to capture initial volume level
  - service: scene.create
    data:
      scene_id: mediaplayer_before
      snapshot_entities: 
      - "{{ entity_id }}"

[ DO STUFF ]

  # Turn on captured scene, restoring initial volume level and activity/stream
  - service: scene.turn_on
    data:
      entity_id: scene.mediaplayer_before

Added benefit of using the scene solution is that it also restores media that was playing when the message came through.

Great tip, though I still have the same problem I had with the old method : my homepod sporadically play music after execution even though they were not playing before :frowning: