Templating If statement doesn't work after first elif statement

Been at this for a while and can’t figure it out. It’s supposed to turn off all other input booleans then the one that was just turned on but it only works for the first two statements and the rest have zero effect on each other.

Any insights would be appreciated

alias: 'Start Entertainment' 
trigger:
   platform: state
   entity_id:
     - input_boolean.watchcable
     - input_boolean.watchamazon
     - input_boolean.watchnetflix
     - input_boolean.watchvudu
     - input_boolean.watchplex
     - input_boolean.watchmovies
     - input_boolean.playpc
     - input_boolean.playps
     - input_boolean.playswitch
     - input_boolean.listenmusic
   from: 'off'
   to: 'on'
action:
  - service: input_boolean.turn_off
    data_template:
      entity_id: >
        {% if trigger.entity_id != "input_boolean.watchcable" %}input_boolean.watchcable
        {% elif trigger.entity_id != "input_boolean.listenmusic" %}input_boolean.listenmusic
        {% elif trigger.entity_id != "input_boolean.watchamazon" %}input_boolean.watchamazon
        {% elif trigger.entity_id != "input_boolean.watchnetflix" %}input_boolean.watchnetflix
        {% elif trigger.entity_id != "input_boolean.watchvudu" %}input_boolean.watchvudu
        {% elif trigger.entity_id != "input_boolean.watchplex" %}input_boolean.watchplex
        {% elif trigger.entity_id != "input_boolean.watchmovies" %}input_boolean.watchmovies 
        {% elif trigger.entity_id != "input_boolean.playpc" %}input_boolean.playpc
        {% elif trigger.entity_id != "input_boolean.playps" %}input_boolean.playps
        {% else %}input_boolean.playswitch
        {%- endif %}

May be more elegant ways, but this might do the trick:

alias: 'Start Entertainment' 
trigger:
   platform: state
   entity_id:
     - input_boolean.watchcable
     - input_boolean.watchamazon
     - input_boolean.watchnetflix
     - input_boolean.watchvudu
     - input_boolean.watchplex
     - input_boolean.watchmovies
     - input_boolean.playpc
     - input_boolean.playps
     - input_boolean.playswitch
     - input_boolean.listenmusic
   from: 'off'
   to: 'on'
action:
  - service: input_boolean.turn_off
    data_template:
      entity_id: >
        {% set l = ["input_boolean.watchcable",
                    "input_boolean.listenmusic",
                    "input_boolean.watchamazon",
                    "input_boolean.watchnetflix",
                    "input_boolean.watchvudu",
                    "input_boolean.watchplex",
                    "input_boolean.watchmovies",
                    "input_boolean.playpc",
                    "input_boolean.playps",
                    "input_boolean.playswitch"] %}
        {% for x in l if x != trigger.entity_id %}
          {% if not loop.first %},{% endif %}{{ x }}
        {% endfor %}

Or maybe even:

alias: 'Start Entertainment' 
trigger:
   platform: state
   entity_id:
     - input_boolean.watchcable
     - input_boolean.watchamazon
     - input_boolean.watchnetflix
     - input_boolean.watchvudu
     - input_boolean.watchplex
     - input_boolean.watchmovies
     - input_boolean.playpc
     - input_boolean.playps
     - input_boolean.playswitch
     - input_boolean.listenmusic
   from: 'off'
   to: 'on'
action:
  - service: input_boolean.turn_off
    data_template:
      entity_id: >
        {% set l = ["input_boolean.watchcable",
                    "input_boolean.listenmusic",
                    "input_boolean.watchamazon",
                    "input_boolean.watchnetflix",
                    "input_boolean.watchvudu",
                    "input_boolean.watchplex",
                    "input_boolean.watchmovies",
                    "input_boolean.playpc",
                    "input_boolean.playps",
                    "input_boolean.playswitch"] %}
        {{ l | select('ne', trigger.entity_id) | join(',') }}

FWIW, the reason it didn’t work is because an if ... elif ... else statement will only pick one case, the first one that is true. You would need individual if statements, but that really won’t work because of the way templates and the entity_id parameter work.

@pnbruckner Thanks!

Your first solution worked perfectly, I tried the second one but it would break functionality and in a pattern I couldn’t quite figure out. Also thanks for explaining why it didn’t work. I saw other examples of long If statements but didn’t think about that.

While I have your attention is there a way to use something like this

 {{expand('group.tv_inputs') | map(attribute='entity_id') | list }}

to replace the hard coded entity list?

Thanks again, I appreciate the assist

This by chance isn’t for Harmony, is it?

It should be equivalent to the first. It uses the select filter to “pass through” only the elements of the list that are not equal (ne) to trigger.entity_id, then joins the elements of the resulting list using the string ',' using the join filter. It should work the same, but be a little more efficient, than the first solution.

But it’s really a question of style, so whichever you prefer. :slight_smile:

You can’t use the expand function because it results in a list of State Objects, not entity_id’s. But you could do:

{% set l = state_attr('group.tv_inputs', 'entity_id') %}

In fact, you could then just do:

action:
  - service: input_boolean.turn_off
    data_template:
      entity_id: >
        {{ state_attr('group.tv_inputs', 'entity_id')
           | select('ne', trigger.entity_id) | join(',') }}

I have a harmony but this is not purely for harmony purposes.

Yeah, it just seems like you’re trying to make ‘radio’ buttons. I.E. Buttons that are on, but all other paired buttons are off.

And if this is the case, I recommend investigating template switches because you won’t be running into goofy issues. For example, if you attempt to use these booleans to turn on and off a harmony activity, you will run into circular feedback. You’ll attempt to turn on activity A which will turn off all the other activities. So then you send to your remote a turn on a, but also turn off b, c, d, e, etc. This causes all sorts of problems for the harmony.

For whatever reason, the other options result in the boolean that is on turning off after a brief moment am I missing something?

That’s a good point. All of this is really just to get HaDashboard buttons that show what is and isn’t on currently. If there is a better way to do that I’d love to hear it

But if I don’t attach the off function of the harmony to the input_boolean I shouldn’t run into that issue right?

Can’t explain that. Are you sure you entered it correctly?

Ok, I went back through and got all of them working except the last one

action:
  - service: input_boolean.turn_off
    data_template:
      entity_id: >
        {{ state_attr('group.tv_inputs') | select('ne', trigger.entity_id) | join(',') }}

not sure why, I tried moving it up and double quoting it since it was a single line and it still did not work.

I’ll come back to it and see if I can’t figure out what issue is. But the rest were dumb mistakes by me and I’m sure that one is too.

Thanks again for your help. I am curious what the ‘ne’ is doing.

Oops, that’s my bad. Typo. I’ll go back and fix…

(I forgot the second parameter – 'entity_id' – to the state_attr function in the last snippet of code.)

Just check the documentation:

https://jinja.palletsprojects.com/en/master/templates/#list-of-builtin-tests

Thanks again

Yep, you are correct. But you could always just make a template switch for each activity. Each switch will work for on and off, and all the other switches will react.

Here’s an example.

switch:
  - platform: template
    switches:
        # TV HARMONY ACTIVITY
        tv:
          value_template: "{{ is_state_attr('remote.living_room', 'current_activity', 'TV') }}"
          turn_on:
            service: remote.turn_on
            data:
              entity_id: remote.living_room
              activity: 'TV'
          turn_off:
            service: remote.turn_on
            data:
              entity_id: remote.living_room
              activity: 'PowerOff'

No automation, all done in a single switch. Shows up as a single toggle in the UI.

EDIT: How it works:

Turning the switch on will call the turn_on service. Turning the switch off will call the turn_off service. The state that is displayed in the UI does not reflect you pressing on or off, it reflects the state of harmony. So if harmony’s current activity is equal to the activity in question, the switch will appear on. Therefore you won’t get a feedback loop like you would with input booleans. You also don’t need the automation in this thread.

2 Likes

Interesting I was looking at switches before I jumped into this, I am using scripts to augment the harmony and do a few extra things. I never really liked the Harmony interface for delays and triggering other things.

That might not be the best way of doing things.

It’s good to see things like this as I’m just starting out. There’s so many ways to do things in HA I’m constantly learning something that makes me rethink things I’ve already done.

Thanks @petro