Where can I create macros for templates?

Okay, I’ll ask another question then: should we not use the macro feature of Jinja at all then in Home Assistant?
Well, it works, but the idea of a function is to be able to use it anywhere.

Several Mushroom cards allow the use of templates but unfortunately, there’s no entities (plural) card in the Mushroom collection.

So I use a default lovelace entities card together with the secondary-entity-row add-on which allows for templates in the secondary information of an entity in an entities card.

My use case is: I want to list ~30 (German) holiday dates. I use the Calendarific integration to create the sensors. They contain the number of days until the holiday. In the entities card I additionally want to display the exact date of that sensor, which is an attribute of the sensor. This works fine, in English:

The yaml code for the entities in the entities card looks like this for the first 3 of ~30 entities:

  - entity: sensor.cal_valentine_s_day
    type: custom:secondaryinfo-entity-row
    secondary_info: >-
      {{ as_timestamp(state_attr('sensor.cal_valentine_s_day', 'date')) |
      timestamp_custom('%A, %d.%m.%Y')  }}
  - entity: sensor.cal_rosenmontag
    type: custom:secondaryinfo-entity-row
    secondary_info: >-
      {{ as_timestamp(state_attr('sensor.cal_rosenmontag', 'date')) |
      timestamp_custom('%A, %d.%m.%Y')  }}
  - entity: sensor.cal_st_patrick_s_day
    type: custom:secondaryinfo-entity-row
    secondary_info: >-
      {{ as_timestamp(state_attr('sensor.cal_st_patrick_s_day', 'date')) |
      timestamp_custom('%A, %d.%m.%Y')  }}

If I want the weekday names in German I can use the tip you, @123, gave me. But because I don’t want to repeat that weekday names array and the additional code ~30 times for each date sensor entity in its secondary_info (it would look like this for every row:

{{ ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag'][as_datetime(state_attr('sensor.cal_karfreitag', 'date')).weekday()] }}, {{ as_datetime(state_attr('sensor.cal_karfreitag', 'date')).strftime('%d.%m.%Y') }}

), I thought I’d define this macro once

{% macro formatted_date(datesensorname) -%}
{% set thedate = as_datetime(state_attr(datesensorname, 'date')) %}
{{ 
['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag'][thedate.weekday()]
}}, {{ thedate.strftime('%d.%m.%Y') }}
{%- endmacro %}

… and have the individual lines of the entities card look like this then:

  - entity: sensor.cal_valentine_s_day
    type: custom:secondaryinfo-entity-row
    secondary_info: {{ formatted_date('sensor.cal_valentine_s_day') }}

Much shorter.

I don’t have a problem defining template sensors inside my configuration.yaml in the template: section. But as long as I can’t use that macro there, neither, I have nothing gained because I still have to write that long definition with the weekday names ~30 times, for each template sensor. Which is … quite … annoying … and … dumb.

So, there’s my specific use case. Eager to know what I can do about it.

Macros cannot be used across your system. They are only available in your single template.

You can approach this differently to remove the macro as well, with a template sensor, and yaml anchor.

template:
- trigger:
  - platform: time
    at: "00:00"
    variables: &date_variables
      entities:
      - sensor.cal_karfreitag
      - sensor.cal_valentine_s_day
      dates: >
        {% set ns = namespace(items=[]) %}
        {% for entity in entities %}
          {% set dt = state_attr(entity, 'date') | as_datetime %}
          {% set day =  ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag'][dt.weekday()] %}
          {% set day = day ~ ', ' ~ dt .strftime('%d.%m.%Y') %}
          {% set ns.items = ns.items + [ (entity, day) ] %}
        {% endfor %}
        {{ dict.from_keys(ns.items) }}
  - platform: homeassistant
    event: start
    variables: *date_variables
  sensor:
  - name: Holidays
    unique_id: holidays
    state: "{{ dates | count }}"
    attributes:
      dates: "{{ dates }}"

Your template in the card would be (it wouldn’t change for any of them).

  - entity: sensor.cal_valentine_s_day
    type: custom:secondaryinfo-entity-row
    secondary_info: "{{ state_attr('sensor.holidays', 'dates')[entity] }}"

EDIT: I’m just going to delete option 1.

2 Likes

WOW! :flushed: That’s beyond my skills, currently. But I’ll study it for sure! Always eager to learn something new and thus widen my horizon!
Thanks so much for your effort & help! Very much appreciated! :+1::+1: :pray: :raised_hands:

Almost works! :wink:
I see the new sensor sensor.holidays with its dates attribute value that contains all the single sensor.cal_* names and their exact dates in form of a JSON dictionary.

As we can see, accessing a single item’s date string (like we want it in the secondary info) works, too, for the example of sensor.cal_karfreitag in the screenshot.

However, that sensor’s entity name has to be put in (single) quotes, it has to be a string, when used as the index to that dictionary.

When we look at the template code in the lovelace entities card,

- entity: sensor.cal_valentine_s_day
  type: custom:secondaryinfo-entity-row
  secondary_info: "{{ state_attr('sensor.holidays', 'dates')[entity] }}"

… we see that the index in [ ] is not a string. And indeed, it doesn’t work:

However, my template coding knowledge is not (yet) sufficient to fix this. Putting single quotes around entity['entity'] – doesn’t work, of course. We need the quote characters and entity replaced with its value.
How can this be achieved?

Probably needs to be enitity.entity_id without quotes

Exactly. Write it once, create a shell script that blasts it out 31 times. Most of the time the shell script is just replacing an entity name. This way you can also change it later in one place and regenerate the other 31 instances.

Unfortunately not. :man_shrugging:

Sorry, it’s just what the card uses and that’s an old card lacking proper documentation about the variables that are supplied to the namespace. I’m taking guesses as to what is available. So try entity_id without quotes.

EDIT: Looking at the code, I don’t see how entity would fail. It assigns this._config.entity to the entity variable. So that should work, or entity.entity_id.

For testing, just make it

- entity: sensor.cal_valentine_s_day
  type: custom:secondaryinfo-entity-row
  secondary_info: "{{ entity }}"

and post the results here

Yup, had that idea, too. Outputs nothing, unfortunately … :disappointed:

well, when all else fails, just default to writing the entity_id twice.

- entity: sensor.cal_valentine_s_day
  type: custom:secondaryinfo-entity-row
  secondary_info: "{{ state_attr('sensor.holidays', 'dates')['sensor.cal_valentine_s_day'] }}"

:man_facepalming:

Of course! THAT works! :blush:

yeah, well I was trying to avoid that. But oh well. Not too much of a hassle. That custom card needs some love. I haven’t seen that dev in a about a year.

EDIT: Whelp, he’s still managing his cards, so maybe he doesn’t know about this issue.

Err, isn’t the “Entities Card” a core/official HA lovelace card? :flushed: I thought so …
(But we’re getting off-topic. :see_no_evil:)

You’re using custom:secondary info row, that’s what I’m referring to

Ahhh, I see! Sorry!

Thanks, I was already struggling for days to use anchors in templates. The variable indirection solved it :pray: