How to list multiple calendar event in a template

@Didgeridrew (sorry, the answer function and the mention with the help of @ seems redundant).

I would like to summarize all appointments of the next 72h of my three existing calendars and output them in one entity.

Unfortunately, I have no idea how to program, so I used the modules available here for my code.

However, I strongly suspect that an error has crept in here, because nothing is displayed.
The source of the error seems to me to be the merging of the three scheduled_events under “schedulded_events:”.

Unfortunately, I can’t solve this on my own and would therefore like some help.

Is it correct that I insert this code completely into my sensor.yaml?
Do I need another entry in my configuration.yaml?

I would be very grateful if someone could help me!

Attached is the code:

  - trigger:
      - platform: time_pattern
        minutes: /1
    action:
      - service: calendar.list_events
        data:
          duration:
            hours: 72
            minutes: 0
            seconds: 0
          start_date_time: "{{ today_at() }}"
        target:
          entity_id: calendar.familie
        response_variable: familie_scheduled_events
      - service: calendar.list_events
        data:
          duration:
            hours: 72
            minutes: 0
            seconds: 0
          start_date_time: "{{ today_at() }}"
        target:
          entity_id: calendar.soraneu_gmail_com
        response_variable: soraneu_scheduled_events
      - service: calendar.list_events
        data:
          duration:
            hours: 72
            minutes: 0
            seconds: 0
          start_date_time: "{{ today_at() }}"
        target:
          entity_id: calendar.viking1144_vk_gmail_com
        response_variable: viking_scheduled_events
    sensor:
      - name: Calendar Scheduled Events
        unique_id: calendar_scheduled_events
        state: "{{ scheduled_events.events | count() }}"
        attributes:
          scheduled_events: "{{ familie_scheduled_events.events + soraneu_scheduled_events.events +
        viking_scheduled_events.events }}"
        icon: mdi:calendar'

I wish you a happy new year!
Best regards

No, this configuration does not belong in sensor.yaml. The current method for configuring template sensors, which allow triggers and actions, uses template as its top-level key, not sensor. You can either create a template: block in your configuration.yaml file, or use the !include tag to have your template integration-based configuration split to their own file(s)

Also, the available calendar services have been updated to address the issue of returning data from multiple calendars in one call. The service calendar.list_events is being phased out and will be remove in 2024.6. Instead use calendar.get_events.

template:
  - trigger:
      - platform: time_pattern
        minutes: /1
    action:
      - service: calendar.list_events
        data:
          duration:
            hours: 72
            minutes: 0
            seconds: 0
          start_date_time: "{{ today_at() }}"
        target:
          entity_id: 
            - calendar.familie
            - calendar.soraneu_gmail_com
            - calendar.viking1144_vk_gmail_com
        response_variable: calendars
      - variables:
          ev_list: |
            {% set ns = namespace(cal_events=[]) %}
            {%- for key, value in calendars.items() %}
              {%- for event in value.events %}
                {%- set ns.cal_events = ns.cal_events + [event] %}
              {%- endfor %}
            {%- endfor %}
            {{ ns.cal_events | sort(attribute='start') | list }}
    sensor:
      - name: Calendar Scheduled Events
        unique_id: calendar_scheduled_events
        state: "{{ ev_list | count }}"
        attributes:
          scheduled_events: "{{ ev_list }}"
        icon: mdi:calendar'
1 Like

First of all, I wish you a happy new year!
You are my hero! With this code it definitely worked and I have already made the appropriate adjustments to calendar.get_events.
Now I have added or displayed the entity calendar_scheduled_events on my dashboard using a condition card in which an entity card is integrated. Unfortunately, I can only see how many appointments are pending, but not in how many days and also not what this appointment is called (value from line “summary”).
What do I have to change to display this accordingly?

Best regards



You’re not going to get what you want with an Entity card. You can get something basic with Markdown.

type: entity-filter
entities:
  - sensor.calendar_scheduled_events
state_filter:
  - operator: ">"
    value: 0
card:
  title: Upcoming Calendar Events
  type: markdown
  content: >-
    {%- for l in config.entities %}
    {% for e in state_attr(l.entity, 'events')%}
      \- {{e.start }}: {{e.summary }}
    {% endfor -%}
    {%- endfor -%}

But, you might be better off using a purpose-built card, like Atomic Calendar Revive to handle displaying calendars/events.

maybe someone here has an idea how to get whole-day events of tomorrow only?

Hello, I would like a trigger for an automation?
one from the list of attributes.

For example, the “summary: 900 test”

Can you help me?

I’m using the template from hpoperator but the events are not sorted. I tried some variants but the events are not sorted.

See the template here:

- trigger:
    - platform: time_pattern
      minutes: /1
  action:
    - service: calendar.get_events
      data:
        duration:
          hours: 720
          minutes: 0
          seconds: 0
        start_date_time: "{{ today_at() }}"
      target:
        entity_id: calendar.familienkalender
      response_variable: scheduled_events
    - variables:
        ev_list: |
          {% set ns = namespace(cal_events=[]) %}
          {%- for key, value in calendars.items() %}
            {%- for event in value.events %}
              {%- set ns.cal_events = ns.cal_events + [event] %}
            {%- endfor %}
          {%- endfor %}
          {{ ns.cal_events | sort(attribute='start') | list }}
  sensor:
    - name: Familienkalender Events
      unique_id: familienkalender_events
      state: "{{ ev_list | count }}"
      attributes:
        scheduled_events: "{{ ev_list }}"
      icon: mdi:calendar'

Not sure if this will work for you, but maybe change to the below and remove your other sort?

{%- for event in value.events|sort(attribute='start') %}

I don’t see how that is working at all… The template that defines the event list variable isn’t referencing your response variable.

2 Likes

Hello Everyone,

I have added local calendar integration and added two events in the single calendar which repeats monthly.

eg.

Event 1 is due date for electricity bill.
Event 2 is due date for water bill.

Kindly guide how to create two sensors for each event and get how many days are left for the next event.

{{ (state_attr('calendar.events', 'start_time') | as_timestamp - today_at('00:00') | as_timestamp)/(60*60*24) }}

The above returns the days left for the first event only. How to get for both the events ?

Thank you.

I used an SSD1306 OLED screen
I took the liberty of using your solution, my code looks as follows:

      - id: page9
        lambda: |-
          // Print next four collection
          char *strFam = strdup(id(cal_garbage).state.c_str());
          char delim[] = "~";

          char *nxtStrFam = strtok(strFam, delim);

          if (nxtStrFam != NULL && strlen(nxtStrFam) > 0) {
            it.printf(4, 0, id(font3), TextAlign::TOP_LEFT, "%s", nxtStrFam);
          }

          nxtStrFam = strtok(NULL, delim);

          if (nxtStrFam != NULL && strlen(nxtStrFam) > 0) {
            it.printf(128, 0, id(font3), TextAlign::TOP_RIGHT, "%s", nxtStrFam);
          }

          nxtStrFam = strtok(NULL, delim);

          if (nxtStrFam != NULL && strlen(nxtStrFam) > 0) {
            it.printf(0, 17, id(font3), TextAlign::TOP_LEFT, "%s", nxtStrFam);
          }

          nxtStrFam = strtok(NULL, delim);

          if (nxtStrFam != NULL && strlen(nxtStrFam) > 0) {
            it.printf(128, 17, id(font3), TextAlign::TOP_RIGHT, "%s", nxtStrFam);
          }

          nxtStrFam = strtok(NULL, delim);

          if (nxtStrFam != NULL && strlen(nxtStrFam) > 0) {
            it.printf(0, 34, id(font3), TextAlign::TOP_LEFT, "%s", nxtStrFam);
          }

          nxtStrFam = strtok(NULL, delim);

          if (nxtStrFam != NULL && strlen(nxtStrFam) > 0) {
            it.printf(128, 34, id(font3), TextAlign::TOP_RIGHT, "%s", nxtStrFam);
          }

          nxtStrFam = strtok(NULL, delim);

          if (nxtStrFam != NULL && strlen(nxtStrFam) > 0) {
            it.printf(0, 63, id(font3), TextAlign::BASELINE_LEFT, "%s", nxtStrFam);
          }

          nxtStrFam = strtok(NULL, delim);

          if (nxtStrFam != NULL && strlen(nxtStrFam) > 0) {
            it.printf(128, 63, id(font3), TextAlign::BASELINE_RIGHT, "%s", nxtStrFam);
          }

this is one of ten screens that shows/renders every 93 seconds.
Unfortunately, the problem I have with it is that this code overflows the RAM memory and the ESP32 restarts approximately every 3 hours and 20 minutes.

Does this code generate some variable that fills the RAM memory and should be removed during the next rendering cycle?

My configuration.yaml.:

  - trigger:
      - platform: time_pattern
        # This will update every hour
        hours: "/6"
    sensor:
      - name: Garbage Data
        icon: mdi:calendar
        state: "OK"
        attributes:
          cal_garbage: >-
            {% set items = state_attr('sensor.garbage_scheduled_events', 'scheduled_events') | sort(attribute='start') %}
            {%- for item in items -%}
            {% set delta = (item.start) | as_datetime | as_local - today_at() %}
            {%- if delta.days == 0 -%}
            {% set start = "Dzisiaj " %}
            {%- elif delta.days == 1 -%}
            {% set start = "Jutro " %}
            {%- elif delta.days == 2 -%}
            {% set start = "Pojutrze " %}
            {%- else -%}
            {% set start = as_timestamp(item.start) | timestamp_custom('%d %b ', default=0) %}
            {%- endif -%}
            {{start + '~'}}
            {{item.summary + '~' }}
            {% endfor %}

Have you ever had a problem with RAM overflowing?

1 Like

May I ask for you advice? When I create an automation based on you code the “ev_list” variable remains empty without any errors.
My Code:

alias: Get Events
description: ""
trigger: []
condition: []
action:
  - service: calendar.get_events
    target:
      entity_id:
        - calendar.xxx
        - calendar.yyy
    data:
      duration:
        hours: 170
        minutes: 0
        seconds: 0
    response_variable: calendars
  - variables:
      ev_list: |
        {% set ns = namespace(cal_events=[]) %}
        {%- for key, value in calendars.items() %}
          {%- for event in value.events %}
            {%- set ns.cal_events = ns.cal_events + [event] %}
          {%- endfor %}
        {%- endfor %}
        {{ ns.cal_events | sort(attribute='start') | list }}
mode: single

What does the Trace show?

1 Like

FWIW, here’s another way to do the same thing. The result is a sorted list of consolidated calendar events. However, if you couldn’t get Didgeridrew’s code to work then it’s unlikely this will.

  - variables:
      ev_list: |
        {{ calendars.values() | map(attribute='events')
          | sum(start=[]) | sort(attribute='start') }}
2 Likes

Thanks it was my fault - I looked at the wrong step. Thanks for your reply anyway!

Works like a charm, thanks for the hint!
Do you know by any chance if it’s possible to group the events by date?
I want to try to get a ePaper/ESP32 to display a weekly agenda and a grouping by date would be amazing.

The example currently produces a list of calendar events sorted by starting date (and time). What exactly do you mean by “grouping” them by date?

Sorry, I’m still in the process of thinking on how to implement my ePaper Calendar.
Would it be possible to convert it into a string in the process? So for example a string like this:
“Startdate-Starttime-Enddate-Endtime-Subject-Calendarname;”
→ Then I could append all strings, transfert that to the esp, split it there and show it on the display?

Did you get the answer for this question?. I am in the the same process as yours.
I have a ecalendar in a epaper display run by an ESP32. I communicate with HA through MQTT. I am trying to find a way to convert the calendar events into a JSON (?) to send it through the MQTT.

Unfortunatley no. I’m struggeling to get the touchscreen working of my epaper display. This is more or les on hold right now. Nevertheless, if you find a way I’m more than happy to hear it!