Best way to manage visually an input_select linked to scene in lovelace?

Hi,

I created 4 scenes for my office. One of them is always active.
I create an input_select & automations to activate the appropriate scene upon selection done in the input_select.

I would like now to add a visual bar in lovelace with 4 buttons (one for each scene) and have the button icon (or colored) for the scene that is active. So visually I always see the scene that is considered as active.

I did not found any controls to add that easily. I would like to avoid creating unnecessary sensor etc…

What is the recommended pattern to use for such a need that I think should be common.

Thank you

This custom button card can change colour depending on the state of another entity:

Quite a lot of options to get your head around but once you get the hang of it, a very powerful card.

I will test that, thank you for the tip. It seems to be indeed what I need.

What a tool box !
It works perfectly.

I use a engine of mine to instantiate the below template in my lovelace.yaml

- type: custom:button-card
  icon: {{ j.icon }}
  tap_action:
    action: call-service
    service: input_select.select_option
    service_data:
      entity_id: input_select.state_bureau
      option: '{{ j.newstate }}'
  hold_action:
    action: more-info
  show_icon: true
  show_name: true
  entity: input_select.state_bureau
  name: {{ j.newstatelabel }}
  styles:
    card:
      - background-color: rgb(59,64,72)
  state:
    - value: "{{ j.newstate }}"
      styles:
        card:
          - background-color: white
          - color: rgb(59,64,72)
        icon:  
          - color: rgb(59,64,72)
 

Here is how I declare/include a template in my yaml
Here is my code (I use a small script on my side to instantiate it 4 times).
If someone is interested on this engine, let me know…

- type: horizontal-stack
  cards:
    #include scene_bureau_blocks.yaml,{"#block": "2", "newstate":"homeworking", "newstatelabel":"Homeworking", "icon":"mdi:seat"}
    #include scene_bureau_blocks.yaml,{"#block": "2", "newstate":"day", "newstatelabel":"Day", "icon":"mdi:weather-sunny"}
    #include scene_bureau_blocks.yaml,{"#block": "2", "newstate":"evening", "newstatelabel":"Evening", "icon":"mdi:weather-night"}
    #include scene_bureau_blocks.yaml,{"#block": "2", "newstate":"sleep_all", "newstatelabel":"Sleep", "icon":"mdi:power-plug-off"}

2 Likes

I am interested in this. I have an input_select that I would like to be able to change state with nice visuals.

Mine is called time_of_day containing
Preparing
Breakfast
Daytime
Bedtime

Right now users push a button which pops up a drop down and they select a new value. Not very appealing visually.

thanks

Nice. The custom button card also supports templates. You define all the common parameters in a template file at the top of your Lovelace config then call the template and only add the different options. Like so:

Template

button_card_templates:
  binary_sensor_button:
    aspect_ratio: 4/3
    hold_action:
      action: none
    label: |
      [[[ entity.last_changed ]]]
    show_last_changed: true
    show_name: true
    show_state: true
    state:
      - styles:
          icon:
            - color: var(--paper-item-icon-active-color)
          state:
            - color: var(--paper-item-icon-active-color)
        value: >
          [[[ return entity.attributes.value && entity.attributes.value in [
          'on', 'disarmed','home'] ]]]
      - styles:
          state:
            - color: var(--secondary-text-color)
        value: 'off'
      - icon: 'mdi:alert'
        styles:
          card:
            - border: 'solid 1px #7f7f7f'
            - box-shadow: none
          icon:
            - color: '#ff0000'
            - opacity: 0.4
          label:
            - color: '#7f7f7f'
          name:
            - color: '#7f7f7f'
        value: unavailable
    styles:
      card:
        - box-shadow: none
        - border-radius: 10px
        - padding: 6px 6px 6px 6px
        - margin: 0% 0% 0% 0%
        - '--paper-card-background-color': 'rgba(0, 0, 0, 0)'
      grid:
        - grid-template-areas: '"n n n" "i s s" "l l l"'
        - grid-template-rows: auto 33% auto
        - grid-template-columns: 33% auto auto
      icon:
        - width: 28px
        - padding: 0px 0px 0px 0px
        - margin: 0% 0% 0% 0%
      label:
        - justify-self: left
        - font-size: 12px
        - padding: 0px 0px 0px 0px
        - color: var(--secondary-text-color)
      name:
        - justify-self: left
        - font-size: 14px
        - padding: 0px 0px 0px 0px
        - color: var(--primary-text-color)
      state:
        - justify-self: left
        - font-size: 12px
        - padding: 0px 0px 0px 3px
        - color: var(--secondary-text-color)
    tap_action:
      action: more-info
  day_button:
    color_type: icon
    hold_action:
etc...

Lovelace Card

entities:
  - card_type: horizontal-stack
    cards:
      - entity: binary_sensor.smoke_comms
        template: binary_sensor_button
        type: 'custom:button-card'
      - entity: binary_sensor.smoke_hall
        template: binary_sensor_button
        type: 'custom:button-card'
      - entity: binary_sensor.smoke_lounge
        template: binary_sensor_button
        type: 'custom:button-card'
      - entity: binary_sensor.smoke_rumpus
        template: binary_sensor_button
        type: 'custom:button-card'
    type: 'custom:hui-element'
show_header_toggle: false
style:
  .: |
    ha-card {
      border: solid 1px var(--border-color);
      background: url("/local/background/card_bg_{{states('input_select.select_theme')}}.png");
    }
    ha-card div.card-header {
      padding-top: 8px;
      padding-bottom: 36px;
    }
title: Smoke Sensors
type: entities

Screenshot_2020-06-16 Overview - Home Assistant

1 Like

FWIW my use of input_selects & button-card on my overview dashboard.

2 Likes

Excellent! This is the exact spirit of my custom engine, I could have used this here indeed.
My home brew version is more generic allowing me to do this everywhere in all my yaml (config, sensor, automations, lovelace,…)

This can be done with the wonderful Lovelace: Button card.

For the back-end part:

  • You need an input-select setup, you have apparently
  • You need automations so that each time you change the “input-select”, the right scene is set or action executed.

For the front-end:

  • Create a horizontal-stack that will contain your 4 buttons
  • Add 4 blocks in it of type a custom:button-card

Here is my setup expanded.
You have to change the icon/label & action to execute when button is pressed.
This includes the “state logic” to adapt button back-color when the selection of the input-select matchs a given value associated with the button.

And the component allows a lot more…check the doc.

The “template” as proposed by Tom_I is a even a more cleaner way to avoid copy of 4 times the same layout.

          - type: horizontal-stack
            cards:
              - type: custom:button-card
                icon: mdi:seat
                tap_action:
                  action: call-service
                  service: input_select.select_option
                  service_data:
                    entity_id: input_select.state_bureau
                    option: 'homeworking'
                hold_action:
                  action: more-info
                show_icon: true
                show_name: true
                entity: input_select.state_bureau
                name: Homeworking
                styles:
                  card:
                    - background-color: rgb(59,64,72)
                state:
                  - value: "homeworking"
                    styles:
                      card:
                        - background-color: white
                        - color: rgb(59,64,72)
                      icon:  
                        - color: rgb(59,64,72)
                      
              - type: custom:button-card
                icon: mdi:weather-night
                tap_action:
                  action: call-service
                  service: input_select.select_option
                  service_data:
                    entity_id: input_select.state_bureau
                    option: 'day'
                hold_action:
                  action: more-info
                show_icon: true
                show_name: true
                entity: input_select.state_bureau
                name: Day
                styles:
                  card:
                    - background-color: rgb(59,64,72)
                state:
                  - value: "day"
                    styles:
                      card:
                        - background-color: white
                        - color: rgb(59,64,72)
                      icon:  
                        - color: rgb(59,64,72)
                      
              - type: custom:button-card
                icon: mdi:weather-sunny
                tap_action:
                  action: call-service
                  service: input_select.select_option
                  service_data:
                    entity_id: input_select.state_bureau
                    option: 'evening'
                hold_action:
                  action: more-info
                show_icon: true
                show_name: true
                entity: input_select.state_bureau
                name: Evening
                styles:
                  card:
                    - background-color: rgb(59,64,72)
                state:
                  - value: "evening"
                    styles:
                      card:
                        - background-color: white
                        - color: rgb(59,64,72)
                      icon:  
                        - color: rgb(59,64,72)
                      
              - type: custom:button-card
                icon: mdi:power-plug-off
                tap_action:
                  action: call-service
                  service: input_select.select_option
                  service_data:
                    entity_id: input_select.state_bureau
                    option: 'sleep_all'
                hold_action:
                  action: more-info
                show_icon: true
                show_name: true
                entity: input_select.state_bureau
                name: Sleep
                styles:
                  card:
                    - background-color: rgb(59,64,72)
                state:
                  - value: "sleep_all"
                    styles:
                      card:
                        - background-color: white
                        - color: rgb(59,64,72)
                      icon:  
                        - color: rgb(59,64,72)

2 Likes

I’d be interested in that to reduce some repetitive cards I have. There’s a custom “de-cluttering” card I was going to investigate at some stage.

This my engine (python)

import os
import sys
import datetime 
import json

cintIndent = 2
__location__ = ""

def readfile(location , filenamein):
    filein = open(os.path.join(location,filenamein) ,"r")
    text = filein.readlines()
    filein.close()
    return text

def processFile(location,filenamein, fileout, prefix = "", intblock = 0, intsublock = 0, j={}, jinja = True):

    filein = open(os.path.join(location,filenamein) ,"r")
    lines = filein.readlines()
    filein.close()

    #Check for END
    blnKeep = True
    sublines = []
    for line in lines:
        if line[0:3] == "END":
            blnKeep = False
        if blnKeep:
            sublines.append (line)
    lines = sublines

    #Cleaning to only keep one of the underlying block
    if intblock > 0:
        currentblock = 0
        sublines = []
        for line in lines:
            if line[0] == "-":
                currentblock +=1
            if currentblock == intblock and (line [0] == "-" or line [0] == " "):
                sublines.append(line)
        lines = sublines

    if intsublock > 0:
        currentblock = 0
        sublines = []
        for line in lines:
            line = line[cintIndent:]
            if line[0] == "-":
                currentblock +=1
            if currentblock == intsublock and (line [0] == "-" or line [0] == " "):
                sublines.append(line)
        lines = sublines

    for line in lines:
        if "#include" in line:
            remainingline,command = line.split("#include")
            recursionfile,j = parseCommand(command.replace("\n",""))
            x = j['#block'].split(",")
            intblock = int(x[0])
            intsublock = int(x[1])
            jinja4child = j["#jinja"]
            processFile(location, recursionfile.strip(),fileout, prefix + remainingline, intblock,intsublock, j, jinja4child)            
        else:
            if jinja:
                proceesedline = replaceLogic(line,j)
            else:
                proceesedline = line
            fileout.write(prefix + proceesedline)

            if len(line) == 0 :
                fileout.write('\n')
            else:
                if line[-1] != '\n':
                    fileout.write('\n')

def replaceLogic(line,j):
    #for key in j:
    #    line = line.replace(key,j[key])
    #return line
    from jinja2 import Template
    tm = Template(line)
    newtm = tm.render(j=j) + '\n'
    return newtm

def parseCommand(command):
    # xxxx.yaml,{'#block': '1,1', 'v1': 145, 'v2': 'abc'}
    mylist = command.split(",",1)
    file = mylist[0]
    if len(mylist) == 1:
        mylist.append('{"#block": "0,0"}')
    j = json.loads(mylist[1])
    j["#block"] = j["#block"] + ",0,0\n"

    if not "#jinja" in j:
        j["#jinja"] = True
    else:
        j["#jinja"]= (j["#jinja"] == "True")
    return file,j

def main(location, inputfile, outputfull):
    
    print("-" * 80)
    print("location  : " + location)
    print("inputfile : " + inputfile)
    print("outputfull: " + outputfull)
    print("-"*80)

    fileout = open(outputfull,"w")
    processFile(location,inputfile,fileout)
    fileout.close()

    filein = open(outputfull ,"r")
    lines = filein.readlines()
    filein.close()
    now = datetime.datetime.now()

    fulltext = "".join(lines)
    #pyperclip.copy(fulltext)
    print("lines     : " + str(len(lines)))
    print("Bytes     : " + str(len(fulltext)))
    print("Timestamp : " + now.strftime('%Y-%m-%d %H:%M:%S'))
    print("-"*80)

if __name__ == "__main__":
    
    if len(sys.argv) == 1:
        location = os.path.dirname(__file__)
        inputfile ="input.yaml"
        outputfull = os.path.join(location,"output.yaml")
    else:
        location = os.path.dirname(sys.argv[1])
        inputfile =os.path.basename(sys.argv[1])
        outputfull = sys.argv[2]

    ##FOR DEBUGGING WHEN NEEDED
    if 1==2:
        location="y:\\development\\Hass.io\\config\\tools\\yamlsensor"
        inputfile= "main_binary.yaml" 
        outputfull = "y:\\development\\Hass.io\\config\\auto_binary_sensor.yaml"

    main(location,inputfile , outputfull)

Usage:
python yamlmerge.py main_binary.yaml auto_binary_sensor.yaml

It takes 2 arguments: an input file & an output file
The input file is a yaml file like you want where you can use a new keyword “#include
The output file is the final output file where the #include has been replaced using potentially jinja2 logic if needed. You can also pass key/value pairs to the #include commands

Example of a simple input file (the main_binary.yaml):

########################################
#
# Trend
#
########################################

- platform: trend
  sensors:
    #include binary_sensor_trend.yaml,{"#block":"0","location":"salon", "sensor":"sensor.nest_temperature", "#jinja": "True"}
    #include binary_sensor_trend.yaml,{"#block":"0","location":"hall", "sensor":"sensor.zigate_00158d00034f8c03_temperature"}
    #include binary_sensor_trend.yaml,{"#block":"0","location":"sdb", "sensor":"sensor.zigate_00158d000358edfa_temperature"}
    #include binary_sensor_trend.yaml,{"#block":"0","location":"chparents", "sensor":"sensor.zigate_00158d0003590e7a_temperature"}
    #include binary_sensor_trend.yaml,{"#block":"0","location":"chmorgane", "sensor":"sensor.zigate_00158d0003a279c2_temperature"}
    #include binary_sensor_trend.yaml,{"#block":"0","location":"bureaumorgane", "sensor":"sensor.zigate_00158d0003a27993_temperature"}
    #include binary_sensor_trend.yaml,{"#block":"0","location":"bureau", "sensor":"sensor.zigate_00158d0003a28772_temperature"}

and the template for the “binary_sensir_trend.yaml”

{{ j.location }}_temp_rising:
  entity_id: {{ j.sensor }}
  max_samples: 3
  device_class: 'heat'

Paremeters:
#block allows to refer to the “block” you want to insert (this is an easy way if you one files with 10 templates to say the block you want to use, if omitted the full file will be injected)
All the other json are key/value blocks.
Every single row injected will be send to a jinja2 engine allowing to make the replace/computation logic needed.
I used also a special “#jinja” : “False” for rare case where you don’t want to use the jinja logic

The #include is recurside.

I used this to generate a view for horizontal display and another view for vertical display
having only 2 different mains both including the same blocks but in a different “main mayout”

Quick & dirty explanation so apologize in advance :wink:

1 Like

One of the reason I created the engine, I had to include 7 times the following blocks with the right parameter changes… a nightmare.

Here is the “one template” that I instantiate 7 times using the #include

- entity: sensor.{{ j.zigate }}_temperature
  style:
    left: {{ j.left }}%
    top: {{ j.top }}%
  title: température
  type: state-label
- entity: sensor.{{ j.zigate }}_humidity
  style:
    left: {{ j.left }}%
    top: {{ j.top+ (7/j.size) }}%
  title: humidité
  type: state-label
- conditions:
    - entity: binary_sensor.{{ j.trendname }}_temp_rising
      state: 'on'
  elements:
    - icon: mdi:thermometer-chevron-up
      style:
        left: {{ j.left-(11/j.size) }}%
        top: {{ j.top+(4/j.size) }}%
        '--paper-item-icon-color': red
      type: state-icon
      entity: binary_sensor.{{ j.trendname }}_temp_rising
      state_color: false
  type: conditional
- conditions:
    - entity: binary_sensor.{{ j.trendname }}_temp_rising
      state: 'off'
  elements:
    - icon: mdi:thermometer-chevron-down
      style:
        left: {{ j.left-(11/j.size) }}%
        top: {{ j.top+(4/j.size) }}%
        '--paper-item-icon-color': blue
      type: state-icon
      entity: binary_sensor.{{ j.trendname }}_temp_rising
      state_color: false
  type: conditional

And in my main lovelace.yaml

...
  - entity: sensor.chauffage_e2_watts
    style:
      left: 82.21804511278195%
      top: 89.5%
    tap_action:
      action: toggle
    type: state-label
#####################################
#BUREAU Temperature
  #include fullthermo.yaml,{"#block": "0","zigate": "zigate_00158d0003a28772","left": 80.2,"top": 75,"trendname": "bureau","size":2 }
...
#####################################


I know this is 4+ years old, but are you able to share the code? This is awesome but I have no idea where to start, and am relatively inexperienced with front end development.

I created recently a GitHub, just in case… have a look at

This is my first one, and still need to learn how to do a correct GitHub setup but the code & examples are working…

Hi, Can you please share the code for this… It’s awesome

Did you figure this out?

The code is fully on GitHub . This is a batch file written in Python. You provide the file you want in input (typically a reworked YAML file) and an output file you want to produce. You run the python script & magic happens :slight_smile:

https://github.com/csacre/yaml-builder-for-HA

very inspiring - need to look into that!

Thank you very much

@DeanKellham ,any chance to share the code for the input_select and how you do it with the conditional card?
I can get the conditional card, but wondering if the expanded list is tied to the input_select entity automatically