Only use one of several fields: in script?

Hi!

I have recently started using scripts to streamline my automations. I have a script for when I need an automation to do notifications using notify and tts:

sequence:
  - parallel:
      - action: notify.notify
        data:
          message: "{{ message_notify }}"
      - action: media_player.turn_on
        target:
          entity_id: "{{ media_player }}"
        data: {}
      - action: media_player.volume_set
        target:
          entity_id: "{{ media_player }}"
        data:
          volume_level: "{{ volume_level }}"
      - delay:
          hours: 0
          minutes: 0
          seconds: 1
          milliseconds: 0
      - action: tts.speak
        data:
          media_player_entity_id: "{{ media_player }}"
          cache: false
          message: "{{ message_tts }}"
        target:
          entity_id: tts.google_translate_sv_se
alias: TTS
description: ""
mode: parallel
fields:
  message_tts:
    name: message_tts
    selector:
      text: null
  message_notify:
    name: message_notify
    selector:
      text: null
  media_player:
    name: media_player
    selector:
      entity:
        domain: media_player
        multiple: true
  volume_level:
    name: volume_level
    selector:
      number:
        min: 0
        max: 1

The script uses four different fields:, media_player (what entity that should play the TTS notification), message_tts (the message that should be read out using TTS), volume_level (settings the volume) and message_notify (the message that should be sent using notify).

I call the script like this in automations:

alias: Pelletsbrännare OK (dag)!
description: Announce when pellets burner is OK
triggers:
  - trigger: state
    entity_id: binary_sensor.vikingbio
    from: "on"
    to: "off"
    for: "00:00:05"
conditions:
  - condition: state
    entity_id: input_boolean.natt
    state: "off"
actions:
  - parallel:
      - action: script.tts
        data:
          media_player: media_player.kok
          message_notify: Pelletsbrännaren OK! Klockan är {{ now().strftime('%H:%M') }}
          message_tts: Pelletsbrännaren OK!
      - action: scene.turn_on
        target:
          entity_id: scene.pellets_pre_alarm
        data: {}
mode: restart
initial_state: true

This works and let me for example change the model for tts.speak easily.

However! Sometimes I don’t want to use specific fields:. For example, sometimes I only want a TTS, not a text notification. If I leave out a specific field like message_notify the action is still executed but with an empty message.

Is it possible to make it so that if the field is missing in an automation, the script do not use the action?

I once looked at doing notifications this way but decided I was over complicating things for no benefit. I had to specify so many variables in my script call action that it was less work to just call the tts or notification action whenever i needed it rather than bothering with the script.

1 Like

What’s the point of running a delay in parallel with all those actions…? I think you’re missing a sequence.

The easiest way is likely going to be templating the value for the actions’ enabled configuration variable based on whether the field variable has a value.

The next option would be to wrap every independent action or sequence in an If/Then action.

EDIT: I don’t know if it’s a bug or a Limited Templates thing, but I could not get the method of templating enabled to work in this situation.

1 Like

Yes, you’re right. A sequence was missing. The notify and tts actions should be separated and running in parallell:

sequence:
  - parallel:
      - action: notify.notify
        data:
          message: "{{ message_notify }}"
      - sequence:
          - action: media_player.turn_on
            target:
              entity_id: "{{ media_player }}"
            data: {}
          - action: media_player.volume_set
            target:
              entity_id: "{{ media_player }}"
            data:
              volume_level: "{{ volume_level }}"
          - delay:
              hours: 0
              minutes: 0
              seconds: 1
              milliseconds: 0
          - action: tts.speak
            data:
              media_player_entity_id: "{{ media_player }}"
              cache: false
              message: "{{ message_tts }}"
            target:
              entity_id: tts.google_translate_sv_se

I’m not very good using templates. I tried using:

value_template: "{{ message_notify | default('') | trim != '' }}"

but this did not seem to work. I don’t know why?

Yeah, perhaps but if you have a bunch of automations using TTS and you want to switch voice it’s a hassle to change everything manually.

The default() filter won’t provide a value if the preceding value is undefined unless you set the second argument to true as follows:

value_template: "{{ message_notify | default('',true) | trim != '' }}"

But, I would just check that the variable is defined:

  - if:
      - condition: template
        value_template: "{{ message_notify is defined }}"
    then:
      - action: notify.notify
        data:
          message: "{{ message_notify }}"
2 Likes

I have a script blueprint somewhere that checks if a field was passed in similar to what Drew did above, and if not it sees if there is an !input, and if not passes a default.
I’d have to search for it, but that’s the way I found to work that.

That was a much better solution than my attempt. For anyone trying something similiar, the script below now works as intended:

sequence:
  - parallel:
      - if:
          - condition: template
            value_template: "{{ message_notify is defined }}"
        then:
          - action: notify.notify
            data:
              message: "{{ message_notify }}"
      - if:
          - condition: template
            value_template: "{{ message_tts is defined }}"
        then:
          - sequence:
              - action: tts.clear_cache
                metadata: {}
                data: {}
              - action: media_player.turn_on
                target:
                  entity_id: "{{ media_player }}"
                data: {}
              - if:
                  - condition: template
                    value_template: "{{ volume_level is defined }}"
                then:
                  - action: media_player.volume_set
                    metadata: {}
                    data:
                      volume_level: "{{ volume_level }}"
                    target:
                      entity_id: "{{ media_player }}"
              - delay:
                  hours: 0
                  minutes: 0
                  seconds: 5
                  milliseconds: 0
              - action: tts.speak
                data:
                  media_player_entity_id: "{{ media_player }}"
                  cache: false
                  message: "{{ message_tts }}"
                target:
                  entity_id: tts.google_translate_sv_se
              - delay:
                  hours: 0
                  minutes: 0
                  seconds: 15
                  milliseconds: 0
              - action: media_player.turn_off
                metadata: {}
                target:
                  entity_id: "{{ media_player }}"
                data: {}
alias: TTS
description: ""
mode: parallel
fields:
  message_tts:
    name: message_tts
    selector:
      text: null
  message_notify:
    name: message_notify
    selector:
      text: null
  volume_level:
    name: volume_level
    selector:
      text: null
  media_player:
    name: media_player
    selector:
      entity:
        domain: media_player
        multiple: true