🔹 Auto-entities - Automatically fill cards with entities

Should be:

type: custom:auto-entities
card:
  type: custom:mini-graph-card
filter:
  template: >-
    {{ states.sensor |
       selectattr('entity_id','search','[xiaomi,mijia]_.*_co2') |
       map(attribute='entity_id') |
       list }}

Here the destination card has the “entities” option - which is filled by generated list of entities.

BUT - it may be not just a list, it could be a list of DICTS:

  template: >-
    {% for ENTITY_ID in states.sensor | selectattr('entity_id','search','[xiaomi,mijia]_.*_co2') | map(attribute='entity_id') | list -%}
        {{
          {
            'entities': ENTITY_ID,
            'name': 'xyz'
          }
        }},
    {%- endfor %}


So, in your example you misplaced a comma.

My example with m-e-r was exactly about generating a list of dicts.

1 Like

Ah, thank you!

I was just about to test

{% set ns = namespace(list=[]) %}
{% for item in states.sensor | selectattr('name', 'match', 'Xiaomi Humidity') %}
    {% set ns.list = ns.list + [ item.entity_id ] %}
{% endfor %}
{{ ns.list | to_json }}

But it then looks like I cannot create multiple cards with just one entity of the list per card? It is rather an alternative, template based approach to using

include:
  - name: 'Xiaomi Humidity*'

?

Sorry, do not understand.

I was hoping to create a list of entity_ids using auto-entities and then have one mini-graph-card created per entity_id.
So not one line per entity_id but one entire mini-graph-card per entity_id.

I actually found a thread where they successfully do this with mini-graph-card.

The only thing I cannot figure out is how to apply this also to cards like apexcharts-card.

I think this has to do with cards needing entities vs. entity_ids or something. I am not sure.

When I try to apply this approach to apexcharts-cardI get an error message

type: custom:auto-entities
card:
  type: grid
  columns: 2
card_param: cards
filter:
  include:
    - name: Sony*ENERGY Power*
      options:
        type: custom:apexcharts-card
        series: 
          - "this.entity_id"

It looks like the entity_id is passed twice due to the series: but without it apexcharts-card will report the series item missing.

type: custom:auto-entities
card:
  type: vertical-stack
card_param: cards
filter:
  template: >-
    {% for ENTITY_ID in states.sensor |
    selectattr('entity_id','search','[xiaomi,mijia]_.*_co2') |
    map(attribute='entity_id') | list -%}
        {{
          {
            'type': 'custom:mini-graph-card',
            'entities': [
              {
                'entity': ENTITY_ID,
                'color': 'magenta'
              }
            ],
            'show': {
              'points': true,
              'fill': 'fade'
            },
            'hours_to_show': 0.5,
            'points_per_hour': 120
          }
        }},
    {%- endfor %}


Here a collected list of useful posts.

1 Like

I am not sure whether to continue this in this thread or if it would be better to move, but I am not sure which card thread would be the correct one :thinking:

So, I have used your code to create a grid with mutliple, auto-generated charts (happy to share the full code in case anybody is interested!).

Now your code already uses jinja templating plus Python dictionary, if I understand correctly. At least those were the two syntaxes that seemed to work.

If I want to past a template to one of the dictionary values, can this somehow be done directly by using the template inside the dict or do I always have to create a variable outside the dict and then use the var inside?

Let’s say as a simple example I want to use a count as a value.

{{ states.sensor | selectattr('name','search','Sony.*ENERGY Power.*') | map(attribute='entity_id') | list | count }}

in

'header':   {
  'title': {{ states.sensor | selectattr('name','search','Sony.*ENERGY Power.*') | map(attribute='entity_id') | list | count }}
}

This is not working right now, but is it because I made a syntax mistake (e.g. mark as a template inside dictionary) or because it has to be passed into the dictionary from the outside?

I wanted to set it on the outside like

filter:
  template: >-
    {% set DECIMALS = (states.sensor | selectattr('name','search','Sony.*ENERGY Power.*') | map(attribute='entity_id') | list | count) %}
    {% for ENTITY_ID in states.sensor   | selectattr('name','search','Xiaomi
    Humidity.*')   | map(attribute='entity_id')  | list -%}  {{
      {
        'type': 'custom:apexcharts-card',
.
.
.

with

'decimals': DECIMALS,

but well… no luck.

Surely it will not work - you are trying to use a template inside a template:

{{
  ...
  {{ ...}}
  ...
}}

Should be like:

  template: >-
    {% set COUNT = ... -%}
    {%- for ENTITY_ID in ... -%} 
        {{
          {
            'type': 'custom:mini-graph-card',
            'entities': [
              {
                'entity': ENTITY_ID,
                'color': 'magenta',
                'name': 'xxx ' + COUNT | string,
              }
            ],
            ...
          }
        }},
    {%- endfor %}

Here a COUNT is used for every item; adapt this way for your own case.
And note:

 'name': 'xxx ' + COUNT | string,

for a proper conversion, otherwise you will have

ALWAYS CHECK YOUR TEMPLATES IN DEV-TOOLS !!!

1 Like

Ah, that may have been why it did not work when I tried without the brackets.

I also tried it as a number value in the yaxis decimal places without the brackets but it did nothing.
Even tried “forcing it” with Number() and with parseFloat().

I will try again :slight_smile:

Would it then even be possible to do an if expression inside a template?
The non dict version

    graph_span: |-
      ${
        if (states['input_boolean.end_datetime_now'].state == 'on' && states['input_boolean.start_datetime_24h'].state == 'on')
          { 24 +'h' }
        else if (states['input_boolean.end_datetime_now'].state == 'on' && states['input_boolean.start_datetime_24h'].state == 'off')
          { ((states['sensor.timestamp'].state-states['input_datetime.start_datetime'].attributes.timestamp)/60/60).toFixed(2)+'h' }
        else
          { ((states['input_datetime.end_datetime'].attributes.timestamp-states['input_datetime.start_datetime'].attributes.timestamp)/60/60).toFixed(2)+'h' }
      }

or would I need to move this outside the template and do something like

{% if (states['input_boolean.end_datetime_now'].state == 'on' && states['input_boolean.start_datetime_24h'].state == 'on') %}
    set GRAPH_SPAN = 24 +'h' 
{% else if (states['input_boolean.end_datetime_now'].state == 'on' && states['input_boolean.start_datetime_24h'].state == 'off') %}
    set GRAPH_SPAN = ((states['sensor.timestamp'].state-states['input_datetime.start_datetime'].attributes.timestamp)/60/60).toFixed(2)+'h'
{% else %}
    set GRAPH_SPAN = ((states['input_datetime.end_datetime'].attributes.timestamp-states['input_datetime.start_datetime'].attributes.timestamp)/60/60).toFixed(2)+'h'
{% endif %}
.
.
    'graph_span': GRAPH_SPAN,

Are you talking about apexchart?
Cannot help, sorry, not using)))

In this example yes. But it is a general question.

Can an entire

{% if (states['input_boolean.end_datetime_now'].state == 'on') %}
    {% set GRAPH_SPAN = '24' + 'h' %}
{% elif states['input_boolean.end_datetime_now'].state == 'on' %}
    {% set GRAPH_SPAN = ((states['sensor.timestamp'].state-states['input_datetime.start_datetime'].attributes.timestamp)/60/60).toFixed(2)+'h' %}
{% else %}
    {%set GRAPH_SPAN = ((states['input_datetime.end_datetime'].attributes.timestamp-states['input_datetime.start_datetime'].attributes.timestamp)/60/60).toFixed(2)+'h' %}
{% endif %}

be placed inside a template or will I always have to do such if expressions on the outside and pass the result into the template as a variable?

Yes, I think

1 Like

Can you think of a way of automatically changing the color for each entity (without knowing how many entities there will be)?

What do you mean?

How I can see it in a simple case:
– entities card has X number of rows
– each row has an unique color (let it be a text color for simplicity)
– each unique color is defined based on a count of items - i.e. dependingly on the count some particular item may get a different color every time

So, I was thinking of adding something like

{% set colors = ['orange', 'green', 'blue', 'red', 'yellow'] %}
{% for COLOR in colors %}
  // your card creation loop here

    {%- for ENTITY_ID in ... -%} 
        {{
          {
            'type': 'custom:mini-graph-card',
            'entities': [
              {
                'entity': ENTITY_ID,
                'color': COLOR,
                'name': 'xxx ' + COUNT | string,
              }
            ],
            ...
          }
        }},
    {%- endfor %}

{% endfor %}

But I would need to change the color in the same loop as the creation of the entities.

So COLOR and ENTITY_ID need to use the same counter.

  1. To address a specific color you may use
`color`: colors[loop.index]

I only do not recall how arrays are used in jinja - starting from 1 or from 0 (like in C).

  1. If you have an upper bound for a count of items (100 for instance) - then define an array with 100 elements. Or define a formula like “color_for_item(index_of_item)”. The latter way may give an effect “same item has similar colors” (like “shades of same red”) if you define that formula accordingly (also, if an order is same).
1 Like

Working nicely, Ildar, thank you.

It is index0 to start with in Jinja :slight_smile:

Can you think of a way to modify the code so the user can select to populate one card with all entities instead of creating one card per entity? The user input part is of course easy, but the code needs some kind of if expression or something to tell the card to populate rather than create new :thinking:

Elaborate.
1 picture is better than 100 words)

Switching from

to this

by changing this

type: custom:auto-entities
card:
  type: grid
  columns: 1
card_param: cards
filter:
  template: >-

    // create ns.list

    // if input_text.merge_vs_split.state = 'split'  then create two cards with one entity each (bottom picture)
    // else create one card with two entities (bottom picture)

    {% for item in ns.list -%}  {{
      {                                              // from here on the code should ideally be the shared by both
        'type': 'custom:apexcharts-card',
        'series': [ {
            'entity': item,
            'yaxis_id': 'first',
            'color': colors[loop.index0],
            'show': {
              'in_chart': true,
              'in_brush': true }
            } ],

depending on whether user changes input_text.merge_vs_split state to ‘merge’ or ‘split’

  1. Adding many graphs into one card is defined here: consolidation post → many graphs
  2. Switching between “many entities on 1 card” & “many cards in 1 stack” cannot be done in auto-entities. Use conditional cards like “state-switch” or a conventional Conditional card.