Using templates for input_select.set_options (populating options within an input selector)

Thanks @petro I’ll give this a try. This looks much cleaner.

The other issue I found is that when the list gets refreshed (as I had it every 6 hours or on restart) it deletes my previous selection, even though it may still be in the new list and returns just the top one. I think I’ll have to change it to a script instead of an automation and just manually run when I change my Sonos playlists and want the new list to appear.

@petro

Looks like it doesn’t properly format it for lists and seems to just put it all in one long string because I get the following in my log when trying to run: State max length is 255 characters.

Try a comma

data_template:
  options: >
    {% for item in state_attr('media_player.sonos_living_room', 'source_list') %}
    - {{ item }},
    {% endfor %}

Same issue. It doesn’t like to respect lists in templates

I came to the same conclusion. I couldn’t build a working JSON-type array either.

I ended up using your example, but with a small tweak so that I don’t get errors when referring to more items than existed.

- service: input_select.set_options
  data_template:
    entity_id: input_select.syno_players
    options:
      - 'Not Set'
      - '{% if states.sensor.synoplayers.attributes.data.players[0] is not defined %}NA{%else%}{{states.sensor.synoplayers.attributes.data.players[0].name}}{%endif%}'
      - '{% if states.sensor.synoplayers.attributes.data.players[1] is not defined %}NA{%else%}{{states.sensor.synoplayers.attributes.data.players[1].name}}{%endif%}'
      - '{% if states.sensor.synoplayers.attributes.data.players[2] is not defined %}NA{%else%}{{states.sensor.synoplayers.attributes.data.players[2].name}}{%endif%}'
      - '{% if states.sensor.synoplayers.attributes.data.players[3] is not defined %}NA{%else%}{{states.sensor.synoplayers.attributes.data.players[3].name}}{%endif%}'
      - '{% if states.sensor.synoplayers.attributes.data.players[4] is not defined %}NA{%else%}{{states.sensor.synoplayers.attributes.data.players[4].name}}{%endif%}'
      - '{% if states.sensor.synoplayers.attributes.data.players[5] is not defined %}NA{%else%}{{states.sensor.synoplayers.attributes.data.players[5].name}}{%endif%}'
      - '{% if states.sensor.synoplayers.attributes.data.players[6] is not defined %}NA{%else%}{{states.sensor.synoplayers.attributes.data.players[6].name}}{%endif%}'
1 Like

I just ran into this same issue myself. I was able to workaround it by calling the Home Assistant APi with JSON that’s created by a template. After you create the rest_command, you just need to call the service rest_command.workaround_set_options.

rest_command:
  workaround_set_options:
    url: "http://hassio/homeassistant/api/services/input_select/set_options"
    method: POST
    headers:
      content-type: application/json
    content_type: application/json
    payload: >-
      {
        "entity_id": "input_select.my_input_select",
        "options": [
      {%- for item in states.sensor %}
          "{{ item.entity_id }}"{% if not loop.last %}, {% endif %}
      {%- endfor %}
        ]
      }
4 Likes

Perfect! That’s what we were after! And also now that I can see how we can do ‘for each’ loops in templating, the sky is the limit - cheers!

EDIT - I got this to work too. I had to include Authentication in the headers. I have a bash script populating an HTTP Sensor with a JSON array of all the remote speakers available to my Synology Audio Station. so your approach was perfect for me; it captures any remote speakers in that HTTP sensor JSON and pops them through to my input select, I am very happy to get this nailed!

rest_command:
  update_syno_players:
    url: "http://localhost:8123/api/services/input_select/set_options"
    method: POST
    headers:
      content-type: application/json
      x-ha-access: MyHassHTTPpassword
    content_type: application/json
    payload: >-
      {
        "entity_id": "input_select.syno_players",
        "options": [
      {%- for item in states.sensor.synoplayers.attributes.data.players %}
          "{{ item.name }}"{% if not loop.last %}, {% endif %}
      {%- endfor %}
        ]
      }
1 Like

Mine took a little bit of re-working, for instance “item.name” resulted in errors so had to change to as below. But much cleaner code than I was using. Thanks.

rest_command:
  update_sonos_playlists:
    url: "http://localhost:8123/api/services/input_select/set_options"
    method: POST
    headers:
      content-type: application/json
      x-ha-access: !secret http_password
    content_type: application/json
    payload: >-
      {
        "entity_id": [
          "input_select.options_morning_music", "input_select.options_morning_music_sunday", "input_select.options_morning_music_monday", "input_select.options_morning_music_tuesday", "input_select.options_morning_music_wednesday", "input_select.options_morning_music_thursday", "input_select.options_morning_music_friday", "input_select.options_morning_music_saturday", "input_select.options_morning_music_guest", "input_select.options_all_speakers_source", "input_select.options_dinner_music_source", "input_select.options_vacation_music", "input_select.options_night_music"
        ],
        "options": [
      {%- for item in state_attr('media_player.sonos_living_room', 'source_list') %}
          "{{item}}"{% if not loop.last %}, {% endif %}
      {%- endfor %}
        ]
      }
2 Likes

Yeah when anyone calls each ‘item’ of an array (as in: ‘for item in [array]’) , the ‘item’ will have different sub-attributes in different scenarios.

Notorious needed ‘item.entity_id’. I needed ‘item.name’, whereas you just needed the ‘item’ object itself.

The ‘Templates’ area of the Home Assistant UI is perfect for getting all this stuff right.

Apologies if you knew all this already - I just wanted to explain in case it helps someone

2 Likes

how could i use this to list all attributes and their values of a single sensor? struggling a bit with these loops…

I’m not sure of what you are after, but I’ll do my best to answer this

So - given that the goal of this thread was to populate an input_select list, the ideal information source to achieve this would be a list of things, AKA an array.

In my case I created a sensor deliberately to provide this list/array - sensor.synoplayers - which is essentially a JSON payload containing a list of available wireless speakers within it.

“for item in states.sensor.synoplayers.attributes.data.players” basically means "for each player in the sensor list, process it and call it ‘item’ ". The rest of the logic ensures that a comma is added unless after the last item in the list.

The result is the JSON style payload we use to set the ‘input_select’ options. The logic takes the source JSON array from my sensor, and uses it to fill the “options” that the input_select.syno_players requires. By specifying {{ item.name }} I am only populating it with the remote speakers names.

payload: >-
  {
    "entity_id": "input_select.syno_players",
    "options": [
  {%- for item in states.sensor.synoplayers.attributes.data.players %}
      "{{ item.name }}" {% if not loop.last %}, {% endif %}
  {%- endfor %}
    ]
  }

…ends up as…

payload: >-
  {
    "entity_id": "input_select.syno_players",
    "options": [
  "Player1",
  "Player2",
  "Player3"
    ]
  }

…which dynamically sets the input_select with speakers that are actually available and working - the very goal I created the OP for :slight_smile:

I hope that helps some…

2 Likes

thanks!
i realize i might have deviated a little… but thought with a smal adaptation the template could be changed to disclose all attributes of a single entity:

in this case the sensor.control_room_motion_sensor:

49

so I would be after the template bit of your code, not as much the setting the options part. Along the lines of:

{%- for attributes in states(‘sensor.control_room_motion_sensor.attributes’) %}
“{{ attributes.name, attributes.value }}” {% if not loop.last %}, {% endif %}
{%- endfor %}

which now renders:

54

while the attributes are:

must be a small thing in the template…

1 Like

You can get attributes like this…

{% for attribute in states.sun.sun.attributes %}
{{ attribute }} = {{ states.sun.sun.attributes[attribute] }}
{% endfor %}
1 Like

well, i was close… not.

thank you @NotoriousBDG, again.

{% for attribute in states.sensor.control_room_motion_sensor.attributes %}
{{ attribute }} = {{ states.sensor.control_room_motion_sensor.attributes[attribute] }}
{% endfor %} 

was kinda hoping that specifying the entity a second time wouldn’t have to be necessary. this seems somewhat more hard coded, not as templatative as the other loops-construction. Gets the job done though.
cool.

1 Like

Check out #4 on mysmarthome/jinja_helpers at master · skalavala/mysmarthome · GitHub. Perhaps that’s closer to what you’re looking for.

1 Like

indeed, thank you! great resource.
seems not really easier, but has the advantage of the more flexible template. Will certainly give that further study. on my list: 3, 4, 7, 10 (needs some extra work), 11, 12… wow, this is really great stuff for the dev-toolbox

1 Like

@NotoriousBDG, checking one of these:

{{ states | map(attribute=‘domain’) |list | unique | list}}

would you know of a way to list all components used in the setup? They tend to get buried in more then 1 configuration file, a template finding all of them would be way useful. Of course ‘platform’ isnt an attribute of ‘state’, but something similar would be much appreciated.

Unfortunately this method works on a collection of objects - all with similarly named attributes. I can’t see how the method could be made to work the way you want - i.e. cycling through all the attributes in a single object . It looks like Notorious has spelt it all out well though anyway :slight_smile:

The only way I know of is via the REST API.

https://developers.home-assistant.io/docs/en/external_api_rest.html#get-api-config

1 Like

this is exactly what I am looking for, but I cant get in… in no way I have been able to get the curl command correct yet, or even get into the https://base_address:8123/api/?api_password=My_API_Password
tried both the duckdns (which is forwarded already), or the hassio.local:8123/api