Create a drop-down list from entities?

My new dishwasher is connectable via Home Connect so I thought I’d have a go at creating a card for it. I haven’t done anything much with HomeAssistant for some time, and have hardly any experience with cards at all. I managed to cobble together something that works, but I could do with some advice on improving it. Code so far is:

type: custom:vertical-stack-in-card
cards:
  - type: picture
    image: /local/images/dishwasher-top.jpg
    tap_action:
      action: none
    hold_action:
      action: none
  - type: entities
    card_mod:
      style: |
        ha-card {
          background-color: transparent;
          box-shadow: none;
          --ha-card-border-width: 0px;
        }      
    entities:
      - entity: none
        type: custom:template-entity-row
      - entity: switch.dishwasher_power
        name: Power
      - entity: binary_sensor.dishwasher_door
        name: Door
      - entity: sensor.dishwasher_operation_state
        name: State
      - entity: sensor.dishwasher_program_progress
        type: custom:template-entity-row
        name: Progress
        state: |
          {{ states(
            "sensor.dishwasher_program_progress") 
           }}%
      - entity: sensor.dishwasher_remaining_program_time
        type: custom:template-entity-row
        name: Finishing time (approx)
        state: |
          {% if states("sensor.dishwasher_remaining_program_time")
           != "unavailable" %}
            {{ as_timestamp(states(
            "sensor.dishwasher_remaining_program_time")) 
            | timestamp_custom("%H:%M") }}
          {%else%} N/A {%endif%}
      - entity: none
        type: custom:template-entity-row
      - entity: none
        type: custom:template-entity-row
  - type: picture
    image: /local/images/dishwasher-base.jpg
    tap_action:
      action: none
    hold_action:
      action: none
card_mod:
  style: |
    ha-card {
      background: #aaaba9;
      background-image: -webkit-linear-gradient( 
        right, #8f8f8d, #edebe8, #8f8f8d);      
      box-shadow: none;
    }

… and it renders like this:

My main question is about how best to handle the cleaning programmes. They are are exposed as a series of switches e.g. switch.dishwasher_program_eco50, switch.dishwasher_program_intensiv70 etc. and I don’t want to show each of those as separate controls on the card. Is it possible to create some sort of drop-down list containing each available programme name so that one can be selected, and then have a button that willl activate the chosen switch when pressed?

Secondly, I’m using some blank entities simply as space-fillers. Is there a better way to do that?

Any other tips, suggestions or comments welcome.

if this is the naming of all program switches, Id suggest creating a helper input_select with eco50, intensiv70 etc as options, and next a button that activates the particular switch, which would ofc need tp read the state of the input_select entity in template . (dont act upon selecting the program as you might not want it to do right away)
My preferred way would be select program + press activate

if you want to to be completely 100% core, you’d need to find a way to template that value in the action. could be a template switch, or a template sensor to have the action be, but maybe easiest would be a tiny script

tap_action:
  action: call-service
  confirmation:
    text: Are you sure you want to start the dishwasher program?
  service: script.turn_on
  target:
    entity_id: script.your_dishwasher_program

and that script would have the template to the input_select

sequence:
  service: switch.turn_on
  target:
    entity_id: >
      switch.dishwasher_program_{{states('input_select.dishwasher_program')}}

in that script, you could even add a condition to test for valid input, and current state of the selected switch.

you could also template the service, or simply make it toggle. Anything you want really :wink:

only thing you need to take care of is the correct capitalization and underscores in the states/templates, but that is relatively easy in dev tools template.

Myself, I always prefer nice input options in the frontend, so like
Eco 50, or Intensiv 70.

those would need to be sluggified (to get eco_50 and intensiv_70) in the template, or maybe even lose the space altogether.

the latter would then become

switch.dishwasher_program_{{states('input_select.dishwasher_program')|lower|replace(' ','')}}

or a bit more readable:

{% set selection = states('input_select.dishwasher_program')|lower|replace(' ','') %}
switch.dishwasher_program_{{selection}}

yeah, you could add some padding to the top of the .card-content element, and for the base image, why nog use the footer option of the entities card?

It would make the spacing a bit more robust and adaptive to the sceensize. Otoh, if this works for you, why not ? (I would Not use a custom card for the empty spot though, why not an empty core entity?

  - type: divider
    style:
      background: transparent
      height: 50px
1 Like

Thanks, and apologies for the delay in responding, been very busy with other stuff.

The input_select is exactly what I had in mind but didn’t know the term. Ideally I’d like to populate it from code e.g. in an Automation (because I think new programmes can be added) but I couldn’t find a way to return a list.

The naming of the switches is consistent and I certainly should be able to construct the switch names from user-friendly names. List UI elements I’ve used on other systems have supported both a value and a display name so when e.g. “Eco50” is selected the internal value of “dishwasher_program_eco50” can be retrieved. I guess there’s nothing like that in HomeAssistant’s input_select?

I had trouble getting an input_select to render as a drop-list until I discovered that the way it renders seems to depend on the type of card containing it. When placed in an Entities card it does display as a drop list, but in a singular Entity card it only shows the currently selected value. Is it supposed to behave like that?

I hadn’t come across “type: divider” or the footer option of the entities card, will take a look. I’ll have some other questions about layout too, but I’ll probably create a separate post for those.

that is totally possible, see what I do here:

automation:

  - id: auto_populate_hue_group_input_select
    mode: restart
    trigger:
      platform: event
      event_type: delayed_homeassistant_start
    action:
      service: input_select.set_options
      target:
        entity_id: input_select.hue_group
      data:
        options: >
          {{expand(label_entities('hue_groep'))|map(attribute='name')|sort|list}}

you have to create the input_select in the helpers menu, and give it 1 option to start-up…

Sorry, I didn’t give enough information. I got that far:

{{states.switch | selectattr(
  'entity_id', 'match', 'switch.dishwasher_program_*' )
  | map(attribute='name')
  | list 
}}

… produces:
['Dishwasher Program Intensiv70', 'Dishwasher Program Auto2', 'Dishwasher Program Eco50', 'Dishwasher Program PreRinse', 'Dishwasher Program NightWash', 'Dishwasher Program Kurz60', 'Dishwasher Program MachineCare']

But I want to strip the leading "Dishwasher Program " from each item. In straight Python I would probably use the split() function but I couldn’t find a way to use that as a filter so I tried using a loop, something like:

{% for x in states.switch | selectattr(
  'entity_id', 'match', 'switch.dishwasher_program_*' )
  | map(attribute='name') %}
    {{ x.split('Program ')[1] }}
{% endfor %}

That’s what I couldn’t make into a list. I’m afraid it’s all still a bit alien to me.

add a replace

|replace('Dishwasher Program ','')

so,

{{states.switch | selectattr(
  'entity_id', 'match', 'switch.dishwasher_program_*' )
  | map(attribute='name')
  | list 
  |replace('Dishwasher Program ','')
}}

and give it a try?

Aaarrrggghhh! I spent all my trying to find a filter version of the split() function and must have become so blinkered by it that I didn’t think to look at alternatives. Stupid mistake.

I’ve now found a list of Jinja filters which might stop me making the same mistake again. Thanks again.

In Settings → Devices & Services → Devices, is there a device that represents your dishwasher?

Alternatively, go to Settings → Devices & Services → Integrations, find Home Connect (I believe that’s what you mentioned is the dishwasher’s integration) and see if it indicates it has any devices.

The reason why I ask is because if your dishwasher is represented as a device, then it will have an associated set of entities (like switches, sensors, etc). Your template’s efficiency can be improved by getting all switches belonging to the device (dishwasher), as opposed to starting with states.switch (which is all switches in your system).

Yes, Dishwasher is a Device. Maximum efficiency isn’t really needed for this because it’s only likely to execute a few times a day at most and it’s perfectly fast enough starting with states.switch. That said, code gets re-used and the approach might get used somewhere where it does matter, so thanks for pointing it out. I don’t know if what worked for me is the cleanest implementation but for what it’s worth it’s this:

{{ expand(device_entities('my-dishwasher-device-id'))
  | selectattr('entity_id', 'match', 'switch.dishwasher_program_*' )
  | map(attribute='name')
  | list
  | replace('Dishwasher Program ','' )    
}}

Took me a while to find the device_id by the way, I ended up copying it from the device page’s URL. Is there a better way? I was surprised that it doesn’t appear in the Device Info section of its Device page.

Another way to do achieve the same result (without expanding all entities).

{{ device_entities('my-dishwasher-device-id')
  | select('match', 'switch.dishwasher_program_') 
  | map('state_attr', 'friendly_name')
  | list
  | replace('Dishwasher Program ', '')
}}

NOTE

For the match filter’s pattern, a final asterisk is implied. The following example demonstrates the result is the same with/without a terminating asterisk.

Thanks, that’s certainly nicer. It looked to me as if device_entites was just returning a list of entity_id strings and that I needed expand() to fetch the corresponding objects. I’m really just stumbling around without proper understanding of what I’m doing tbh. I think I found an example somewhere that used expand() so I tried it and got the desired result without checking what it’s actually doing. I’m no stranger to programming, but my experience is mostly with procedural languages where I can use debuggers or trace statements to figure out exactly what I’m dealing with. I haven’t really grasped HomeAssistant’s templating, I really ought to do some reading on the fundamentals.

By the way, what’s the difference between map(attribute='name') and map('state_attr', 'friendly_name')? It seems to matter.

Point taken about the implicit wildcard in match. Actually I noticed it while trying things out in the Template developer tool but presumably left the explicit asterisk in the code. No particular reason, although it might perhaps makes the intention clearer when I come back to it a long time later.