Could really use some help with a script that uses an is_state_attr template

I am attempting to build a script that I can trigger from the Companion app that will determine the input source of my receiver and set it to accept input from a Wii, then if the script is triggered again it will set the input back to the HDMI input for our cable box.

For the life of me I cannot get the template to pass the basic YAML test on my configuration.yaml file. When testing the template in Developers Tools the template evaluates properly based on the input selected on the receiver. Yes, I really stink at templates!

I have not tested the script yet since I can’t get it to even load, so I am not sure if the rest of it is right or not but can troubleshoot it if I can get past this problem.

script:
  wii_control:          
    if:
      - alias: Yamaha not set to AV3
        "{{ not is_state_attr('media_player.yamaha_receiver','source','AV3') }}"
    then:
      - alias: Then set to AV3
        service: media_player.select_source
    target:
      entity_id: media_player.yamaha_receiver
    data:
      source: AV3
    else:
      - alias: Then set to AV1
        service: media_player.select_source
    target:
      entity_id: media_player.yamaha_receiver
    data:
      source: AV1

The resulting error that I just cannot make go away:

can not read an implicit mapping pair; a colon is missed at line 1172, column 81:
     ... ha_receiver','source','AV3') }}"
~~~

Your spacing is off…

alias: New Script
sequence:
  - if:
      - alias: Yamaha not set to AV3
        condition: template
        value_template: "{{ not is_state_attr('media_player.yamaha_receiver','source','AV3') }}"
    then:
      - alias: Then set to AV3
        service: media_player.select_source
        target:
          entity_id: media_player.yamaha_receiver
        data:
          source: AV3
    else:
      - alias: Then set to AV1
        service: media_player.select_source
        target:
          entity_id: media_player.yamaha_receiver
        data:
          source: AV1

I don’t know if that’s your issue but it’s off in your paste… And I don’t think you can have an alias above that shorthand if… I changed it to a template long hand

Wow… I really had that one screwed up! Here is what allowed the configuration.yaml to pass and save. And… it even worked the first time!

script:
  wii_control:
    alias: "Wii control"
    sequence:
      - if:
          - alias: Yamaha not set to AV3
            condition: template
            value_template: "{{ not is_state_attr('media_player.yamaha_receiver','source','AV3') }}"
        then:
          - alias: Then set to AV3
            service: media_player.select_source
            target:
              entity_id: media_player.yamaha_receiver
            data:
              source: AV3
        else:
          - alias: Then set to AV1
            service: media_player.select_source
            target:
              entity_id: media_player.yamaha_receiver
            data:
              source: AV1

If you’re interested, you can reduce the script to this:

script:
  wii_control:
    alias: "Wii control"
    sequence:
      - service: media_player.select_source
        target:
          entity_id: media_player.yamaha_receiver
        data:
          source: "AV{{ '3' if not is_state_attr('media_player.yamaha_receiver', 'source', 'AV3') else '1' }}"

Your original script simply changes the value of source and that can be done very easily with a template.

Ok, I think I have that template decoded in my mind. That is an amazing compression of code! I had expanded the script a little further to change the volume level of the receiver as the Wii puts out a much higher audio level.

I will not get to test this until later, but I think I have expanded it to take this into account and set the correct volume level.

  wii_control_2:
    alias: "Wii control 2"
    sequence:
      - service: media_player.select_source
        target:
          entity_id: media_player.yamaha_receiver
        data:
          source: "AV{{ '3' if not is_state_attr('media_player.yamaha_receiver', 'source', 'AV3') else '1' }}"
      - service: media_player.volume_set
        target:
          entity_id: media_player.yamaha_receiver
        data:
          volume_level: "0.{{ '72' if not is_state_attr('media_player.yamaha_receiver', 'source', 'AV3') else '25' }}"

Much thanks to you! HA has been a continual learning process for me for years… I am not a coder.

The “inline if” I posted above:

{{ 'Do this' if something == 'yes' else 'Do that' }}

is a shorter way of expressing the same logic as this:

{% if something == 'yes' %}
  Do this
{% else %}
  Do that
{% endif %}

However there’s yet another way to do the same thing called an “immediate if”:

{{ iif(something == 'yes, 'Do this', 'Do that') }}

Here’s your volume_level template using an immediate if:

{{ if not is_state_attr('media_player.yamaha_receiver', 'source', 'AV3'), 72, 25) }}

Which style to use is largely a personal choice. However there’s one thing you should know about iif and that it always evaluates the if_true and if_false statements (the other two styles don’t do that). Here’s an example of what I mean.

This divides 200 by x but only if the value of x is not zero. If it’s zero then it divides 200 by the value of y.

{{ 200/x if x != 0 else 200/y }}

Regardless of the value of x, even if it’s zero, this will perform both calculations before deciding which result to report. Naturally it can’t divide 200 by zero so the operation will fail with an error.

{{ iif(x != 0, 200/x, 200/y) }}

I will get this tested this evening and post my results. I really appreciate your time, this is by far the most complex script I have done.

The docs seem to indicate that your example should contain iif over if?

I have decided to go this route…

  wii_control_2:
    alias: "Wii control 2"
    sequence:
       - service: media_player.select_source
         target:
            entity_id: media_player.yamaha_receiver
         data:
            source: "AV{{ '3' if not is_state_attr('media_player.yamaha_receiver', 'source', 'AV3') else '1' }}"
       - service: media_player.volume_set
          target:
            entity_id: media_player.yamaha_receiver
          data:
            volume_level: "{{ iif not is_state_attr('media_player.yamaha_receiver', 'source', 'AV3'), '0.72', '0.25') }}"

My onscreen format may be off a space, for some reason when I copy from my configuration.yaml and paste here spacing is off?

You have taught me more by example and simple explaining that I have been able to glean from the docs on templates in many, many attempts! I am pretty good at complex automations even though I am sure many could be more compact than I write them. Choose has been a really nice option for me as the concept of triggers and conditions are very easy for me.

So, I have the following added, but when I reload scripts HA pops an error that really does not make sense at all.

Error:

Logger: homeassistant.config
Source: config.py:820
First occurred: September 2, 2022 at 11:33:44 PM (13 occurrences)
Last logged: 7:36:18 PM

Invalid config for [script]: [data] is an invalid option for [script]. Check: script->sequence->0->then->1->target->data. (See /config/configuration.yaml, line 1168).
Invalid config for [script]: [data] is an invalid option for [script]. Check: script->sequence->0->then->0->target->data. (See /config/configuration.yaml, line 1168).
Invalid config for [script]: Unable to determine action @ data['sequence'][0]['then'][0]. Got None. (See /config/configuration.yaml, line 1168).
Invalid config for [script]: template value should be a string for dictionary value @ data['sequence'][1]['data']. Got None. (See /config/configuration.yaml, line 1168).

The log entry refers to line 1168 which is my script: line in the configuration.yaml. This script actually starts at line 1203!

  wii_control_2:
    alias: "Wii control 2"
    sequence:
      - service: media_player.select_source
        target:
          entity_id: media_player.yamaha_receiver
        data:
          source: "AV{{ '3' if not is_state_attr('media_player.yamaha_receiver', 'source', 'AV3') else '1' }}"
      - service: media_player.volume_set
        target:
          entity_id: media_player.yamaha_receiver
        data:
          volume_level: "{{ iif not is_state_attr('media_player.yamaha_receiver', 'source', 'AV3'), .72, .25) }}"

If I comment out the service: media_player.volume_set line and the subsequent lines the error goes away…

I have also tried this to the same end…

volume_level: "0.{{ iif not is_state_attr('media_player.yamaha_receiver', 'source', 'AV3'), 72, 25) }}"

So, the volume level is entered in the range of 0.0 to 1.00. There is still something I am not understanding.

I think I got it… still have to test it, but saves and scripts load now…

volume_level: "0.{{ iif (not is_state_attr('media_player.yamaha_receiver', 'source', 'AV3'), 72, 25) }}"

Tested and works! Another tool for the toolbox and I am beginning to get the basics of.

Thanks for all of your help.

Change .72, .25 to 0.72, 0.25 because (in this case) they require a leading zero to be understood as floating point numbers.

{{ iif not is_state_attr('media_player.yamaha_receiver', 'source', 'AV3'), 0.72, 0.25) }}