Difference choose and if

Hi everybody,

can you tell me the difference and/or best practice to choose between choose and just using if in automations?

I’m wondering whether or not I should change my existing automations, or just keep them as they are.

Below are two examples. These are not the same automation, but they work similarly: if triggered by id: abc, do - service: xyz; if triggered by id: 123, do -service: 456.

Example Old

alias: Unten/Arbeitszimmer/Heizung
description: ""
trigger:
  - platform: time
    at: input_datetime.unten_arbeitszimmer_heizung_00
    id: Zeit/00
    alias: Zeit/00
  - platform: time
    at: input_datetime.unten_arbeitszimmer_heizung_01
    id: Zeit/01
    alias: Zeit/01
condition: []
action:
  - if:
      - condition: trigger
        id: Zeit/00
    then:
      - service: climate.set_temperature
        data:
          temperature: "{{ states('input_number.unten_arbeitszimmer_heizung_00') | float }}"
        target:
          entity_id: >-
            climate.unten_arbeitszimmer_strasse,
            climate.unten_arbeitszimmer_vorne
    alias: Zeit/00
  - if:
      - condition: trigger
        id: Zeit/01
    then:
      - service: climate.set_temperature
        data:
          temperature: "{{ states('input_number.unten_arbeitszimmer_heizung_01') | float }}"
        target:
          entity_id: >-
            climate.unten_arbeitszimmer_strasse,
            climate.unten_arbeitszimmer_vorne
    alias: Zeit/01

Example New

alias: Unten/Arbeitszimmer/Lautsprecher
description: ""
trigger:
  - platform: state
    entity_id:
      - switch.unten_arbeitszimmer_rechner_arbeitszimmer_pc
    from: "off"
    to: "on"
    id: Rechner/An
    alias: Rechner/An
  - platform: state
    entity_id:
      - switch.unten_arbeitszimmer_rechner_arbeitszimmer_pc
    from: "on"
    to: "off"
    id: Rechner/Aus
    alias: Rechner/Aus
condition: []
action:
  - choose:
      - conditions:
          - condition: trigger
            id: Rechner/Aus
        sequence:
          - service: script.unten_arbeitszimmer_medialight_store
            data: {}
      - conditions:
          - condition: trigger
            id: Rechner/An
        sequence:
          - service: scene.turn_on
            target:
              entity_id: scene.unten_arbeitszimmer_rechts
            metadata: {}
          - service: switch.turn_on
            data: {}
            target:
              entity_id: switch.unten_arbeitszimmer_switch_lautsprecher
mode: single

Just for the looks, I like the old example better, simply because I can give aliases to each case, which looks nicer in the UI. The choose variant only displays Option <n>, which I personally do not like as much… but then again, these automations are meant to be created, then work (no constant modifications), so I don’t really need these aliases, in case choose is the better way to go.

What are your thoughts on this? Thank you in advance for your input.

1 Like

Often times there are multiple ways to accomplish the same thing. This is a great example.

My simple view - if the automation works reliably it’s good! Typically, once I have a working pattern using a construct, I’ll apply that same pattern to the next automation. Often times having consistency across the automations makes maintenance easier as you don’t have to remember the nuances.

Choose has been around longer, If is a recent 2022 addition

1 Like
  • choose is useful when you need to pick one of many choices .

  • if then else is useful when you need to pick one thing or another (or just one thing or not).

Obviously, the two techniques have overlapping applications. For example, you can use choose to pick one thing or another, just like if then else, but it will be more verbose.

Similarly, you can use a long-winded chain of if then else if then else if then etc to pick one of many choices but it will be less concise (and less legible) than a choose.


FWIW, your first example can be redesigned without the need for if then else or choose.

alias: Unten/Arbeitszimmer/Heizung
description: ""
trigger:
  - platform: time
    at:
      - input_datetime.unten_arbeitszimmer_heizung_00
      - input_datetime.unten_arbeitszimmer_heizung_01
condition: []
action:
  - variables:
      entity: "input_number.{{ trigger.to_state.object_id }}"
  - service: climate.set_temperature
    data:
      temperature: "{{ states(entity) | float(18) }}"
    target:
      entity_id: 
        - climate.unten_arbeitszimmer_strasse
        - climate.unten_arbeitszimmer_vorne
mode: single

I believe the second example can be reduced to this:

alias: Unten/Arbeitszimmer/Lautsprecher
description: ""
trigger:
  - platform: state
    entity_id:
      - switch.unten_arbeitszimmer_rechner_arbeitszimmer_pc
    from:
      - "off"
      - "on"
    to: 
      - "on"
      - "off"
condition: []
action:
  - variables:
      entities:
        - scene.unten_arbeitszimmer_rechts
        - switch.unten_arbeitszimmer_switch_lautsprecher
  - service: homeassistant.turn_on
    target:
      entity_id: >
        {{ entities if trigger.to_state.state == 'on' else
          'script.unten_arbeitszimmer_medialight_store' }}
mode: single
7 Likes

Taras has given a concise explanation of the use cases.

Personally, if I’m going to use this type of automation design, I only use Choose. This is partly out of habit since it’s been around longer, but it’s also because it is easier to add extra options/elif’s to a Choose if I discover or create new situations that need to be accounted for.

2 Likes

Thank you! This is such a great improvement.

1 Like

I had the same question as @prankousky and found this thread. But I have an additional question to clarify my understanding:

  • If you use the “choose” option, HA will go down the list in order and run the first option that applies and stop, whereas,
  • If you use the “If/Then/Else” option, HA will go down the list and run EVERY option that applies

Is that correct?

Yes, kind of… As long as they are both un-nested, a list of Choose actions behaves the same as a list of If/Then actions.

  • An individual If/Then offers up to 2 possible options. A max of 1 will be used.
  • An individual Choose action can offer dozens of options. A max of 1 will be used.

Hmm… So, I have an automation with 12 Trigger IDs and 8 options in the choose actions. But there are a couple of automations that should trigger more than one chosen action. I have the automation mode set to parallel, allowing it to run up to 10 concurrent runs. However, only the first automation of 2 that should run in the 8 available options will ever run.

I began to think that “choose” meant “choose an option,” not all that apply, and maybe using multiple “if then else” actions would allow HA to choose all that apply rather than just one. But before I took the time to change the automation, I came here to see if I could find more information.

So, I guess now my question is: Can multiple sequences in an automation be run from a single triggering event? If so, how? What am I doing wrong? Or must this be done through multiple automations?

1 Like

Neither Choose nor If/Then can do “all that apply” in a single action.

Either Choose or If/Then could do “all that apply” if you use multiple actions.

Yes, use multiple Choose actions, or templates, or move the sequences to scripts and call the script as needed… or a combination of any/all of those.

:man_shrugging: … Post your automation’s YAML configuration so we can see what you are talking about.

Only if you want to do it that way.

To clarify, when you say:

You mean, one single if/then with multiple if/thens nested within it and one single choose with 8 choose actions to choose from?

8 different “choose” and 8 different if/thens.

I presently have a single choose with 8 options and I was going to rebuild it to be either if/thens.

I don’t think there’s anything wrong with the automation itself, just my understanding on what to expect.

choose can run multiple area’s of an automation in parallel if you have non-blocking actions in your choose sections. mode: parallel does not dictate that, that dictates if the automation can be ran in parallel with itself.

If you want to run multiple things in parallel from a single automation, use choose that calls a script via the script.turn_on service, that is non-blocking. If you call the script by name, it will be blocking.

I think what you want here is:

- if (trigger1)
  actions:

- if (trigger2)
  actions:

- if (trigger 3 OR trigger2)
  actions:

That will allow multiple to be done based on what the conditions.

that won’t run them in parallel. There is only 2 ways to run conditions in parallel, that’s by using a non-blocking service call. Or using the parallel key, each with an if statement or choose.

Last night, based on @petro 's post, I rebuilt the automation. Now it is a single automation with all the triggers that fire three scripts depending on the trigger. Separating the scripts helped it work better, as one script can now stop the run of another script. So far, so good.

I understood that parallel runs do not refer to the number of actions from a single trigger, but with eight triggers, there were additional runs while previous actions were still running. The way I have set it up now, the mode is to restart, as the actions that would have otherwise run parallel are separated into different scripts.

So far, I think it’s doing what I want. I’ll report back later. Thanks for the input. It is really appreciated.