Ah. I was lacking the id:
Thanks one more time.
The id
is important when merging state settings because they are an array. If you don’t use the id
then they are added to the array as new items. For example, if your template defines value: 'on'
and your button also defines value: 'on'
you will have 2 entries in your array for ‘on’ instead of one combined entry, and only one of them will be used (probably the one defined in the template because it is first in the final array). Merging states depends on the id
because merging by value
has significant challenges: the value
could be javascript, or even if value is a literal the operator
can be different and change the context what what the value
represents. A nice benefit of using the id
to merge state configs is that you don’t have to re-define the value
or operator
. This is especially useful when that value
is javascript in the template.
Thanks for the explanation. I was trying to leverage that a little further. My presence device (person.russell_smith) has several states (home, not_home, Work, Church (as defined by my zones)). I cast this to binary_sensor.russ_sensor to toggle home/away status. I thought it would be interesting to use the multi-status “person” device in my indicator. At first I thought I could do something like
- entity: person.russell_smith
name: Russ
template: standard-button
type: 'custom:button-card'
aspect_ratio: 1/1.07
styles:
name:
- font-size: 0.47em
state:
- value: home
id: value_on
name: Russ home
icon: 'mdi:home'
- value: not_home
id: value_off
name: Russ away
icon: 'mdi:home-outline'
variables:
text_color_off: yellow
- value: Work
id: value_off
name: Russ work
icon: 'mdi:office-building'
variables:
text_color_off: powderblue
- value: Church
id: value_off
name: Russ church
icon: 'mdi:church'
variables:
text_color_off: plum
but that didn’t work. So I added two more states to the standard_button:
state:
- id: value_on
value: '[[[ return variables.value_on ]]]'
styles:
card:
- background-color: '[[[ return variables.background_color_on ]]]'
name:
- color: '[[[ return variables.text_color_on ]]]'
icon:
- color: '[[[ return variables.text_color_on ]]]'
- opacity: 1
- id: value_off
value: '[[[ return variables.value_off ]]]'
styles:
card:
- background-color: '[[[ return variables.background_color_off ]]]'
name:
- color: '[[[ return variables.text_color_off ]]]'
icon:
- color: '[[[ return variables.text_color_off ]]]'
- opacity: 0.5
- id: value_2
value: '[[[ return variables.value_2 ]]]'
styles:
card:
- background-color: '[[[ return variables.background_color_2 ]]]'
name:
- color: '[[[ return variables.text_color_2 ]]]'
icon:
- color: '[[[ return variables.text_color_2 ]]]'
- opacity: 0.5
- id: value_3
value: '[[[ return variables.value_3 ]]]'
styles:
card:
- background-color: '[[[ return variables.background_color_3 ]]]'
name:
- color: '[[[ return variables.text_color_3 ]]]'
icon:
- color: '[[[ return variables.text_color_3 ]]]'
- opacity: 0.5
and then coded my indicator like this:
- entity: person.russell_smith
name: Russ
template: standard-button
type: 'custom:button-card'
aspect_ratio: 1/1.07
styles:
name:
- font-size: 0.47em
state:
- value: home
id: value_on
name: Russ home
icon: 'mdi:home'
- value: not_home
id: value_off
name: Russ away
icon: 'mdi:home-outline'
variables:
text_color_off: yellow
- value: Work
id: value_2
name: Russ work
icon: 'mdi:office-building'
- value: Church
id: value_3
name: Russ church
icon: 'mdi:church'
It works, but I’m not sure why I could just load into the value_off id array with the Work and Church values.
I think in your first yaml you just needed to remove the id
for Work and Church. You have id: value_off
for not_home
, Work
and Church
…effectively merging them together and clobbering the first 2 with the last one. You just need Work
and Church
to be added to the array as separate states. You only need the id’s if needing to configure the same states in multiple templates and/or the top level button. If you want to keep the id’s on them, make them unique.
I see… and now I understand just a tad more of the way this works.
Thank you.
I decided to do a similar thing with the garage “cover” as follows:
- entity: cover.garage_door_opener
template: standard-button
type: 'custom:button-card'
aspect_ratio: 1/1.3
styles:
name:
- font-size: 0.47em
state:
- value: open
id: value_on
name: Overhead open
- value: closed
id: value_off
name: Overhead closed
- value: opening
name: Overhead opening
icon: 'mdi:arrow-up-bold-box-outline'
- value: closing
name: Overhead closing
icon: 'mdi:arrow-down-bold-box-outline'
That all works wonderfully, but I also tried changing the background color for opening and closing by adding the lines
variables:
text_color_off: DarkCoral
right under the icon setting. That didn’t work. Any ideas?
I also added the code
tap_action:
action: call-service
service: cover.toggle
service_data:
entity_id: cover.garage_door_opener
So now, instead of calling up the “more information” window (which will actually let me open or close the door, but it needs one more tap to open and one more to close the window), a tap will toggle the door open or closed depending on its current state.
I don’t believe variables can be set in the state config. If you want to change the background color in a state config you need to use styles:
- value: opening
name: Overhead opening
icon: 'mdi:arrow-up-bold-box-outline'
styles:
card:
- background-color: DarkCoral
Oops. Right. Thanks again.
Is there some simple way to combine two binary items into a tri-state item?
To be specific, I already have a group.family that groups the people into one entity. It’s set in the default way so when anyone is home it’s state is home.
Here’s my indicator code:
- entity: group.family
name: Family
template: standard-button
type: 'custom:button-card'
aspect_ratio: 1/1.1
styles:
name:
- font-size: 0.47em
variables:
background_color_on: darkgrey
background_color_off: darkgrey
text_color_on: yellow
state:
- value: home
id: value_on
name: Some Home
icon: 'mdi:home-circle'
- value: not_home
id: value_off
name: All Away
icon: 'mdi:home-circle-outline'
All that works flawlessly and it’s all I need for automations because they only care whether no one is at home or anyone is home. For display purposes, though, it would be nice to have it change to “all home” when everyone is present. I can set up another group with the same entities, but using the “all” option so that it’s only home when everyone’s here, but is there a way to combine both entities into one button which would display as above in all situations except when everyone’s here and then it would display “all home” and possibly use a brighter color than yellow to call attention to the fact?
The other possibility is to throw out the current scheme and create a virtual sensor device with three states: 0-home, 1-some away, 2-all away, and then throw some code to count presences. (Either count everyone at home each time any presence changes – absolutely reliable, but processing intense, or count up and down based on when any of the presences changes from home to not or vice-versa – less processing intense, but could there be an error in the count when two presence changes occur nearly simultaneously (say in the likely situation when we all leave in the same vehicle?))
I actually figure this one out myself
What I did was set up an input_select with values of “none”,“some”, and “all”. In node-RED I created a flow which get triggered any time anyone comes home or leaves home. It then uses an entities node to get all my people (any entity_id that starts with person) as an array. Then I use a function that passes both the total number of people and a count of the filtered people whose state is “home”. I then set up text which is “none” (count=0), “all” (count=total), or “some” (whatever’s left) and set the option on my input_select using that. The input_select that is thus automated goes into a custom:button card as follows:
- entity: input_select.family_presence
name: Family
template: standard-button
type: 'custom:button-card'
aspect_ratio: 1/1.1
styles:
name:
- font-size: 0.47em
variables:
background_color_on: darkgrey
background_color_off: darkgrey
text_color_on: yellow
state:
- value: none
id: value_off
name: none Home
icon: 'mdi:home-circle-outline'
- value: some
id: value_on
name: some Home
icon: 'mdi:home-circle'
- value: all
name: all Home
icon: 'mdi:home-circle'
styles:
card:
- background-color: darkgrey
name:
- color: greenyellow
icon:
- color: greenyellow
Viola! I have an indicator that glows soft white when no one is home, yellow when someone is home, and green when everyone is home with icons and text to match the state.
I’m really enjoying being able to have such control over the interface.
Your logic to compare total and filtered counts is exactly what I was going to suggest. I don’t use node-red, but that sounds like a workable solution. An alternative to consider is a template sensor, which would avoid needing an input_select. The logic of finding entities starting with ‘person’ and doing the counting would be the same as what you did in node-red. Both approaches are equally effective.
A “template sensor”… I’m imagining something like:
sensor:
- platform: template
sensors:
family_sensor:
value_template: "{{ "none", "some", "all" }}"
icon_template: >-
{% if is_state('family_sensor', 'none') %}
mdi:home-outline
{% else %}
mdi:home
{% endif %}
Is that even close. (I’m still working my way through template lore.)
Along those lines, yes. The logic for value_template
can be the full logic of what you are doing in Node-Red instead of doing node-red and input_select at all.
Wow. I could benefit from a partial example of that kind of code within the template. (I’m not fluent in YAML yet. Node-RED lets me code in javascript.)
I have three person entities (person.russ, person.janette, and person.katie). I made use of a filter function that returns a subset of an array matching a criteria (item.state===‘home’). I also used .length (to return the number of items in the array). I would have used .substring(), but the entities node allows you to extract only those whose entity_id starts with “person” so I used that instead.
I hadn’t done this particular kind of template before, so I gave it a shot using the Template
tab in the Developer Tools
page of Home Assistant. It’s a great way to try out different templates and see what you get for results.
{% set items = states.person %}
{% set all = items|length %}
{% set home = items|map(attribute="state")|select("equalto","home")|list|length %}
{{ "nobody home" if home == 0 else "all home" if home == all else "some home" }}
The first line is getting all entities that are in the person
domain (i.e., the part of the entity_id before the dot). The second line just puts the length of that list into a variable to make the final logic easier to read. The third line maps the entities in the list to just their state values, then filters the list by value “home”, then re-casts to a list and counts it. The last line determines the state based on the value comparisons. I wasn’t expecting to have to re-cast the filter result to a list, but whatever object type the filter returns doesn’t have a length property so that seems necessary.
There are probably other good references out there, but my go-to references for jinja
scripting are the Home Assistant Templating page and the Jinja Documentation. It admittedly took me a while of using templates to get a handle on them, and I still have to research the syntax every time I’m making a new template.
Thanks. I’ll be gleaning over the links you listed and working with the Template tab a lot to see what else I can do with templating as opposed to simple automation. In every Home Automation system I’ve worked with before there was always a hard line between what you could do and what you couldn’t do because you weren’t in charge of the interface. The thing I like about HA is that this isn’t the case. The only caveat is the learning curve. As long as I stick to the line that I’ll do things when I can figure out how instead of artificially wanting it done now, I’ll be OK. (It’s already miles ahead of my old system.)
Here’s what I ended up with:
sensor:
- platform: template
sensors:
family_sensor:
value_template: >-
{% set items = states.person %}
{% set all = items|length %}
{% set home = items|map(attribute="state")|select("equalto","home")|list|length %}
{{ "none home" if home == 0 else "all home" if home == all else "some home" }}
icon_template: >-
{% if is_state('family_sensor', 'none') %}
mdi:home-outline
{% else %}
mdi:home
{% endif %}
I’m really liking the power of templating. The one downside is that it requires a reboot to reload configuration.yaml when I change something.
I haven’t moved the coloration yet. I’m thinking it’s better to have that in the Card Configuration anyway.
I’m thinking I might move the device templates to a template.yaml file to keep my configuration.yaml cleaner and I see myself adding a lot more of those clever templates over time.
No need to reboot if you’re on core 0.117.x (or maybe 0.116.x; I forget when they added it) you can use the “Reload Template Entities” link on the Configuration => Server Controls page.
I have my configuration.yaml split into multiple files. It’s nice to have smaller files to work with and easier to find what I’m looking for. I have enough entity configurations that I have a folder for each type (sensors, switches, etc.) and a file for each device (some files have more than one entity, but they are usually coming from same device source). I got some inspiration of how to organize my configs from frenck’s config repo, which is really comprehensive. This video that he did with Dr. ZZS is worth watching for great yaml organization tips.
I also recently started managing my dashboards as yaml files too, so that I can share content across different dashboards. My custom button card templates in total are over 1000 lines and it was getting to be annoying making changes in one dashboard and then having to copy-paste the whole set of templates to another dashboard via the raw configuration editor. Plus I was having to copy-paste a bunch of my dashboard cards between views and dashboards any time I changed one of them. Maintenance headache for sure. By taking manual control of the dashboards as files I am able to organize everything as separate files and use !include
to insert them into any dashboard. The tradeoff is not being able to edit them in the UI, but I can edit the files and choose the “Refresh” menu option to reload the changes. The “Refresh” option appears in the same place as the “Edit” option in the UI, in the triple-dot menu.
Regarding my previous comment about not being able to edit yaml file dashboards in the UI, I found a workaround for at least experimenting in the UI on a yaml file dashboard. You can’t save changes in the UI, but you can experiment with different settings and then copy the revised yaml to your appropriate file.