Template Select

How are Template Selects supposed to work? The documentation is pretty light on and I couldn’t find much else out there/here.

I see you define options, and state, and then along comes select_option to confuse me.

I had expected the Template Select was a read only entity whose state was one of several options. Pre-defining those possible options as options seems slightly unnecessary if the selected option just falls out of some equation/logic that defines state, but I can accept the existence of options. But what is select_option and how does it exist alongside state?

Would love to see an example of something in use if anyone has something they could share?

I’m talking philosophically/generally, but my immediate problem is that I just want an entity that derives its value from one of three or four options based on the time of day.

Can you link to the documentation you are looking at. I can’t even find it.

There’s an example here:

This is the service you use to set the current selection from the available configured options.

I’m looking here and there is a loose example lower in the page.

In vscode, the editor supports the documentations assertion that each of state, select_option, and options is mandatory.

If I simply want to say: “if now() is between x and y then FOO, else between y and z then BAR, else ZOO” I would have thought I’d write that template formula for state.

To reiterate what I said initially, defining options then seems somewhat redundant to me… but I’ll comply, and it does make it clearer in any case. But I don’t need a service to call some script anywhere (via select_option) if I can just define the state.

In any case, I’m stabbing in the dark because it seems there are literally no examples of this being used that Google can find me!

(I had seen the example you linked but struggled to get anything from it.)

I totally agree that they are under-documented and confusing, partly because they are very open-ended. I have a suspicion that they may be of little practical value to most users.

The basic function of state-based Template selects seems to be to make it so you do not have to create separate input select helpers and automations. If you want a single functional unit, they can be used like mini-automations with State triggers.

Semi-Practical Examples

Example 1: Proxy/Translate an Existing Select or Input Select entity

Integration-created Select entities may use options that are not labelled in a way that you like or that is easily understood. Or you may live in a bilingual household, and want to have a version in each language, but keep their states entrained.

  - select:
      - name: "Color Picker Translated"
        unique_id: color_selector_translated
        state: >
          {% set opt = states('select.color_selector') %}
          {% set mapper = {
            'Rojo': 'Red',
            'Azul': 'Blue',
            'Verde': 'Green',
            'Amarillo': 'Yellow',
            'Blanco': 'White'
          {{ mapper.get(opt) }}
        options: "{{['Red','Blue','Green','Yellow','White']}}"
          - service: select.select_option
              option: >
                {% set mapper = {
                  'Red': 'Rojo',
                  'Blue': 'Azul',
                  'Green': 'Verde',
                  'Yellow': 'Amarillo',
                  'White': 'Blanco'
                {{ mapper.get(option) }}
              entity_id: select.color_selector
        availability: "{{ state_attr('select.color_selector', 'options') is defined }}"
Example 2: Template Selects in place of an automation

I use this template select to switch sources on an old stereo receiver. The select_option sequence below saves the selected value to an input text helper and passes it along to a script that handles sending IR commands to the stereo receiver.

  - select:
      - name: "RCA Stereo Source"
        unique_id: rca_stereo_source_select
        state: "{{ states('input_text.rca_receiver_output') }}"
        options: "{{['Cable','CD','AUX','AM/FM','DVD']}}"
          - service: input_text.set_value
              entity_id: input_text.rca_receiver_output
              value: "{{ option }}"
          - service: script.rca_receiver_send_command
              command: "{{ option }}"
              repeats: 2
        availability: "{{ states('input_text.rca_receiver_output') is defined }}"
Example 3: Dynamic, Area-based Scene Selector

The following auto-populates a selector for all the scenes assigned to a given Area. The state and options are presented in the form of friendly names for UI usability. As above, the select_option sequence saves the selected value to an input text helper. Then the selected scene is turned on.

  - select:
      - name: "Basement Scenes"
        state: "{{ states('input_text.selected_basement_scene') }}"
        options: >
          | selectattr('domain', 'eq', 'scene')
          | map(attribute='name') | list }}
          - variables:
              entity: >
                {{ states.scene | selectattr('name', 'eq', option)
                |map(attribute='entity_id')|join }}
          - service: input_text.set_value
              entity_id: input_text.selected_basement_scene
              value: "{{ option }}"
          - service: scene.turn_on
              entity_id: "{{ entity }}"
Example 4: Partially Entrained Booleans

The following auto-populates a selector with all Input booleans entities that match a specific naming scheme. The state and options are presented in the form of entity IDs. The select_option sequence turns the selected entity ‘on’. Then the non-selected booleans are turned ‘off’.

  - select:
      - name: "Partially Entrained Booleans"
        state: >-
          {{ (expand(this.attributes.options
          | select('is_state', 'on')
          | list) | sort(attribute='last_changed', reverse=1)
          | map(attribute='entity_id')|list)[0] or
          (expand(this.attributes.options) | sort(attribute='last_changed', reverse=1)
          | map(attribute='entity_id')|list)[0]}}
          - service: input_boolean.turn_on
              entity_id: "{{ option }}"
          - variables:
              boolean: |
                {{ this.attributes.options |reject('eq', option)|list}}
          - service: input_boolean.turn_off
              entity_id: '{{ boolean }}'
        options: >
          {{ states.input_boolean
          | selectattr('object_id', 'match', 'test_bool_')
          | map(attribute='entity_id')
          | list }}

Template selects are not read-only… they are like Input select helpers, but the options: can be either static lists (like an Input select) or a list derived from a template.

Example 5: Merged Options Example

Maybe you already had two Input select helpers that are fully automated, but you want to combine them so there’s only one selector on your dashboard:

  - select:
      - name: "Merged Audio Selects"
        state: >
          | sort(attribute='last_changed', reverse=true)
          | map(attribute='state')
          | list | first}}
        options: >
          {{ state_attr('input_select.music_genres', 'options')
          + state_attr('input_select.radio_stations', 'options') }}
          - service: input_select.select_option
                - input_select.music_genres
                - input_select.radio_stations
              option: "{{ option }}"

The state: template defines their current value. As far as I can tell, it has to render as one of the items in the options: list or it will return “unavailable”.

select_option: is the analog to the Action section of an automation. It defines what to do when there is a new selection event.

That sounds like a job for a template sensor or a set of time of day sensors…

Mapper-based time of day sensor
  - sensor:
      - name: Time of Day
        state: >
          {% set a = today_at("05:00")%}
          {% set b = today_at("07:00")%}
          {% set c = today_at("12:00")%}
          {% set d = today_at("18:00") %}
          {% set e = today_at("20:00")%}
          {% set f = today_at("01:00")%}
          {% set map = {
          a < now() <= b: 'Early Morning',
          b < now() <= c: 'Morning',
          c < now() <= d : 'Afternoon',
          d < now() <= e: 'Evening',
          e < now() < f + timedelta(days=1): 'Night',
          today_at() < now() <= f: 'Night',
          f < now() <= a: 'Late Night'
          } %}
          {{ map.get(True) }}

Great, thank you, I had seen TOD sensors but wasn’t aware you could set state like that. It looked like it was purely hard-coded times.