Dynamically set script service based on variable

Hi,

I’m wondering if it’s possible to set the service within a script based on variables passed from another script. I know I can do this to set other parameters, such as entity_id, etc. But is it possible to use a variable to determine the service used?

I’ve tried this but no luck:

      - service: {% if media_player !='media_player.kitchen' %} tts.google_say {% else %} media_player.alexa_tts {% endif %}
        data_template:
          entity_id: '{{ media_player }}'
          message: "{{ states.sensor.house_message.state }}"

The entity_id and message section of this work perfectly if I set the service as either tts.google_say or media_player.alexa_tts but I get the following error when I try to set them dynamically:

Error loading /config/configuration.yaml: while scanning for the next token
found character '%' that cannot start any token
  in "/config/packages/speech/speech_processing.yaml", line 68, column 19

Your problem is most likely the fact that you aren’t using service_template. Can’t tell otherwise because you aren’t providing the full script, or the action you are using to call said script.

      - service_template: {% if media_player !='media_player.kitchen' %} tts.google_say {% else %} media_player.alexa_tts {% endif %}
        data_template:
          entity_id: '{{ media_player }}'
          message: "{{ states.sensor.house_message.state }}"
1 Like

Thanks. I wasn’t aware of service_template!

I had to use the below, but now it’s working.

      - service_template: >
          {% if media_player !='media_player.kitchen' %}
            tts.google_say
          {% else %}
            media_player.alexa_tts
          {% endif %}
        data_template:
          entity_id: '{{ media_player }}'
          message: "{{ states.sensor.house_message.state }}"
1 Like

Probably because the sevice_template that I provided wasn’t in double quotes.

Glad you got it working.

just to clarify what @petro said…

this would also work:

- service_template: "{% if media_player !='media_player.kitchen' %} tts.google_say {% else %} media_player.alexa_tts {% endif %}"

in a template if use a single line for the template you need to surround it in quotes, either single or double will work. But if you have quotes inside the template you have to use the opposite type on the outside.

If you make it a multi-line template by using the > like you did in the end you don’t need the quotes.

2 Likes

All I’m going to also say guys is “spacing is everything”. It took me several days just to find that homeassistant wasn’t picking up the entity_id because of indentation issues in data_template: line, yet no error was ever given. This might not have been your particular case, but it’s good to keep it in mind.

PS: entity_id doesn’t need quotes if not part of a function statement, such as {% if "entity_id" %}

make life easy on yourself:

  - service_template: >
      {% if media_player !='media_player.kitchen' %} tts.google_say
      {% else %} media_player.alexa_tts
      {% endif %}
    data_template:
      entity_id: >
        {{ media_player }}
      message: >
        {{ states('sensor.house_message') }}

@finity, @petro, can either of you see what’s wrong with this in my script?

- service: media_player.alexa_tts
data_template:
  entity_id: '{{ states.sensor.last_alexa.state }}'
  message: >
    The house temp is {{states('sensor.house_temp')}} degrees. The alarm is {{states('sensor.alarm_stat')}}.
    The alarm loop is {{states('sensor.loop')}}.
    {% if {{states('switch.bob_s_door_2')}}=='on' %} Bobs garage door is open.{% endif %}

If I take out the last line, the script loads fine. Otherwise it gets an error on load:

Invalid config for [script]: invalid template (TemplateSyntaxError: expected token ':', got '}') for dictionary value @ data['script']['test']['sequence'][0]['data_template']['message']. Got "The house temp is {{states('sensor.house_temp')}} degrees. The alarm is {{states('sensor.alarm_stat')}}. The alarm loop is {{states('sensor.loop')}}. {% if {{states('switch.bob_s_door_2')}}=='on' %} Bobs garage door is open.{% endif %}\n". (See /config/configuration.yaml, line 389). Please check the docs at https://home-assistant.io/components/script/

Service script/reload called.

Clearly I’m a noob at this, but I’ve run it through a yaml lint checker and it seems to be syntactically correct.

You have {{ … }} inside the “if” statement.

Also, if I remember correctly, there was a change recently that required there to be an “else” statement in any “if-endif” to prevent the script from erroring out if the “if” portion isn’t met.

try this:

    message: >
      {% if states('switch.bob_s_door_2') == 'on' %}
        The house temp is {{states('sensor.house_temp')}} degrees. The alarm is {{states('sensor.alarm_stat')}}. The alarm loop is {{states('sensor.loop')}}. Bobs garage door is open.
      {% else %}
        The house temp is {{states('sensor.house_temp')}} degrees. The alarm is {{states('sensor.alarm_stat')}}. The alarm loop is {{states('sensor.loop')}}.
      {% endif %}

Ugh, if that’s true its a bandaide masking the problem and will only cause more issues with support.

yeah, it’s possible I’m mis-remembering and I can’t find the thread(s) that i thought I saw that in. Maybe it wasn’t “it’s required” but maybe it was “it’s a good idea”. Either way it’s still a good idea if it makes sense to be able to do it. :slightly_smiling_face:

EDIT:

I think these might be the ones I’m (mis)remembering…

and this one that you were involved in:

So it doesn’t look like “required” is correct that I’ve found. thanks for keeping me honest. :wink:

Ah okay, that makes sense!

Hi, is it possible for a sensor to have a changeable list of attributes?

- sensor:
  - name: testTemplate
    attributes: "{{ ({states.sun.sun.state: states.sun.sun.attributes.next_rising}) }}"

this causes an Invalid config for [template]: expected a dictionary for dictionary value @ data['sensor'][6]['attributes']. error even though "{{ ({...}) }}}" returns a dictionary

No, but a single attribute can.