How to list multiple calendar event in a template

Hello,

I have carefully read your exchanges.
Unfortunately, I’m a newby with Home Assistant and I’m lost. I have a lot to learn …
I’m having trouble understanding and reproducing what you’ve done.

I have the same need than you.
I have a calendar with events under HA.
I need to access all events thru ESPhome.
The goal is to show all events for the further 3 days on an epaper screen.

Can you help me how to proceed ?

I am lost, I don’t undestand what I have to add in the diffrent .yaml file.

There are some things to add in

  • the sensor.yaml
  • the script.yaml
    There are some
  • automations
  • services

I am completly lost …

Service

I’m certainly not an expert but I have this setup based on input in this thread.

In automations.yaml I have this:

alias: Get events
description: ""
trigger:
  - platform: time_pattern
    minutes: "45"
condition: []
action:
  - service: calendar.list_events
    data:
      duration:
        hours: 168
        minutes: 0
        seconds: 0
    target:
      entity_id: calendar.family
    response_variable: fam_scheduled_events
  - service: calendar.list_events
    data:
      duration:
        hours: 168
        minutes: 0
        seconds: 0
    target:
      entity_id: calendar.garbage
    response_variable: gar_scheduled_events
  - service: calendar.list_events
    data:
      duration:
        hours: 168
        minutes: 0
        seconds: 0
    target:
      entity_id: calendar.ical_holidays
    response_variable: hol_scheduled_events
  - event: cal_scheduled_events
    event_data:
      scheduled_events: >-
        {{ fam_scheduled_events.events + gar_scheduled_events.events +
        hol_scheduled_events.events }}
mode: single

That will fetch all events from 3 separate calendars occurring in the next 7 days, runs every hour at min 45.

Then in configuration.yaml I have:

  - trigger:
      - platform: event
        event_type: cal_scheduled_events
    sensor:
      - name: Calendar Scheduled Events
        unique_id: calendar_scheduled_events
        state: "{{ trigger.event.data.scheduled_events | count() }}"
        attributes:
          scheduled_events: "{{ trigger.event.data.scheduled_events }}"
        icon: mdi:calendar

That will create a template sensor which triggers based on the automation above and creates a sensor with all the events.

In configuration.yaml I also have another template sensor to format the events (and combine with other data I send to my e-paper)

  - trigger:
      - platform: time_pattern
        # This will update every hour
        minutes: 0
    
    sensor:
      - name: Weatherman Data
        state: "OK"
        attributes:
          cal_family: >-
            {% set items = state_attr('sensor.calendar_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 = "I dag " %}
            {%- elif delta.days == 1 -%}
            {% set start = "I morgon " %}
            {%- elif delta.days == 2 -%}
            {% set start = "I övermorgon " %}
            {%- else -%}
            {% set start = as_timestamp(item.start) | timestamp_custom('%A %d %b ', default=0) %}
            {%- endif -%}
            {{ start + as_timestamp(item.start) | timestamp_custom('%H:%M', default=0) + " - " + as_timestamp(item.end) | timestamp_custom('%H:%M', default=0) + '~' }}
            {{item.summary + '~'}}
            {% endfor %}

That will update every hour and sort the events, also uses timedelta to format as “Today”, Tomorrow" and “Day after tomorrow” (but in swedish). It will output each start and end time and summary of the event separated with ~

Lastly, in my esphome folder I have display.yaml where I have this:

  - platform: homeassistant
    entity_id: sensor.weatherman_data
    attribute: cal_family
    id: cal_family

Takes the attribute from the previous template sensor and creates a text sensor in esphome.

And in the lambda section:

      char *strFam = strdup( id(cal_family).state.c_str() );
      char delim[] = "~";

      char *nxtStrFam = strtok(strFam, delim);

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

      nxtStrFam = strtok(NULL, delim);

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

Repeated for as many events I would like to display (fit) on my e-paper

Hi,

Thank you.
I had created all up to the the configuration file.

But I don’t see/find any sensor with my data !

I have this in the configuration.yaml file

template:
  - trigger:
      - platform: event
        event_type: calendar_events
    sensor:
      - name: Calendar Scheduled Events
        unique_id: calendar_scheduled_events
        state: "{{ trigger.event.data.scheduled_events.events | count() }}"
        attributes:
          scheduled_events: "{{ trigger.event.data.scheduled_events.events }}"
        icon: mdi:calendar'

I have this in my automations.yaml file

alias: Get events
description: ''
trigger:
   - platform: time_pattern
     minutes: /1
condition: []
action:
  - service: calendar.list_events
    data:
      duration:
        hours: 192
        minutes: 0
        seconds: 0
      start_date_time: '2023-09-06 00:00:00'
    target:
      entity_id: calendar.travail
    response_variable: scheduled_events
  - event: birthday_events
    event_data:
      scheduled_events: '{{ scheduled_events }}'
mode: single

Where should I find the results ?

You probably need to reboot, then you should have a sensor named sensor.calendar_scheduled_events
You can check in developer tools > states to find it.

Your sensor is listening for a different event than your automation is creating…

However, with today’s release of 2023.9, the intermediary automation is no longer necessary. Once you update, you can get rid of the automation and just use the following for your sensor.

template:
  - trigger:
      - platform: time_pattern
        minutes: /1
    action:
      - service: calendar.list_events
        data:
          duration:
            hours: 192
            minutes: 0
            seconds: 0
          start_date_time: "{{ today_at() }}"
        target:
          entity_id: calendar.travail
        response_variable: scheduled_events
    sensor:
      - name: Calendar Scheduled Events
        unique_id: calendar_scheduled_events
        state: "{{ scheduled_events.events | count() }}"
        attributes:
          scheduled_events: "{{ scheduled_events.events }}"
        icon: mdi:calendar'
1 Like

Hello,

Thank you Zinken fr your guide and explanation.
Now it’s working very fine !

Drew, so nice. I have installed the 2023.9 release and test the simplied implementation.
IT’s working very fine too !

Thank you guys for your help.

impressive, looks good.

can you help, need the next 5 events as “state” for esphome…

  • here i see only 3
  • can i add location?
  • how can i get a clear time and date?
Friseur
11.09.2023
16:30 - 17:30

i think i need a format for esphome like this (sample)

  - platform: homeassistant
    id: event01_summary
    entity_id: sensor.xxxx

  - platform: homeassistant
    id: event01_startdate
    entity_id: sensor.xxxx

  - platform: homeassistant
    id: event01_starttime
    entity_id: sensor.xxxx

  - platform: homeassistant
    id: event01_enddate
    entity_id: sensor.xxxx

  - platform: homeassistant
    id: event01_endtime
    entity_id: sensor.xxxx

is it possible, to observe more as one calendar? this here works not:

#-------------------------------------------------------------
# Display Kalender Events
#-------------------------------------------------------------
  - trigger:
      - platform: time_pattern
        minutes: /1
    action:
      - service: calendar.list_events
        data:
          duration:
            hours: 192
            minutes: 0
            seconds: 0
          start_date_time: "{{ today_at() }}"
        target:
          entity_id:
            - calendar.one
            - calendar.two
            - calendar.three
        response_variable: scheduled_events
    sensor:
      - name: Calendar Scheduled Events
        unique_id: calendar_scheduled_events
        state: "{{ scheduled_events.events | count() }}"
        attributes:
          scheduled_events: "{{ scheduled_events.events }}"
        icon: mdi:calendar'

10 comments up

You shouldn’t need to use namespace here for any of those. Just add the lists together, and you can use variables.

  - trigger:
      - platform: calendar
        event: end
        entity_id: calendar.a
      - platform: calendar
        event: end
        entity_id: calendar.b
      - platform: calendar
        event: end
        entity_id: calendar.c
      - platform: event
        event_type: event_template_reloaded
    action:
      - service: calendar.list_events
        data:
          duration:
            hours: 24
        target:
          entity_id:
            - calendar.a
        response_variable: agenda1
      - service: calendar.list_events
        data:
          duration:
            hours: 24
        target:
          entity_id:
            - calendar.b
        response_variable: agenda2
      - service: calendar.list_events
        data:
          duration:
            hours: 24
        target:
          entity_id:
            - calendar.c
        response_variable: agenda3
      - variables:
          all_events: >
            {{ agenda1.events + agenda2.events + agenda2.events }}
          events: >
            {{ all_events | selectattr('start', 'search', now().date() | string) | list }}
    sensor:
      - name: Next 24hr Events
        unique_id: custom_multical_todays_events
        state: "{{ events | count }}"
        attributes:
          scheduled_events: "{{ events }}"

and if you want to shorten the yaml, you can use anchors.

  - trigger:
      - <<: &cal_trigger
          platform: calendar
          event: end
        <<: &cal_a
          entity_id: calendar.a
      - <<: *cal_trigger
        <<: &cal_b
          entity_id: calendar.b
      - <<: *cal_trigger
        <<: &cal_c
          entity_id: calendar.c
      - platform: event
        event_type: event_template_reloaded
    action:
      - <<: &cal_action
          service: calendar.list_events
          data:
            duration:
              hours: 24
        target: *cal_a
        response_variable: agenda1
      - <<: *cal_action
        target: *cal_b
        response_variable: agenda2
      - <<: *cal_action
        target: *cal_c
        response_variable: agenda3
      - variables:
          all_events: >
            {{ agenda1.events + agenda2.events + agenda2.events }}
          events: >
            {{ all_events | selectattr('start', 'search', now().date() | string) | list }}
    sensor:
      - name: Next 24hr Events
        unique_id: custom_multical_todays_events
        state: "{{ events | count }}"
        attributes:
          scheduled_events: "{{ events }}"
2 Likes

thx for this code snipped. not easy for me to understand… i tried it with my calendar, but my entity is empty.

You’d have to post what you tried.

my code: (same as yours, only with my calendars)

#-------------------------------------------------------------
# Display Kalender Events
#-------------------------------------------------------------
  - trigger:
      - platform: calendar
        event: end
        entity_id: calendar.mil
      - platform: calendar
        event: end
        entity_id: calendar.ab
      - platform: calendar
        event: end
        entity_id: calendar.geburtstage
      - platform: event
        event_type: event_template_reloaded
    action:
      - service: calendar.list_events
        data:
          duration:
            hours: 24
        target:
          entity_id:
            - calendar.mil
        response_variable: agenda1
      - service: calendar.list_events
        data:
          duration:
            hours: 24
        target:
          entity_id:
            - calendar.ab
        response_variable: agenda2
      - service: calendar.list_events
        data:
          duration:
            hours: 24
        target:
          entity_id:
            - calendar.geburtstage
        response_variable: agenda3
      - variables:
          all_events: >
            {{ agenda1.events + agenda2.events + agenda2.events }}
          events: >
            {{ all_events | selectattr('start', 'search', now().date() | string) | list }}
    sensor:
      - name: Next 24hr Events
        unique_id: custom_multical_todays_events
        state: "{{ events | count }}"
        attributes:
          scheduled_events: "{{ events }}

no idea whats wrong ?

You’re missing a closing quote on the final line.

only a copy/paste error.

#-------------------------------------------------------------
# Display Kalender Events
#-------------------------------------------------------------
  - trigger:
      - platform: calendar
        event: end
        entity_id: calendar.mi 
      - platform: calendar
        event: end
        entity_id: calendar.abfall
      - platform: calendar
        event: end
        entity_id: calendar.geburtstage
      - platform: event
        event_type: event_template_reloaded
    action:
      - service: calendar.list_events
        data:
          duration:
            hours: 24
        target:
          entity_id:
            - calendar.mi 
        response_variable: agenda1
      - service: calendar.list_events
        data:
          duration:
            hours: 24
        target:
          entity_id:
            - calendar.abfall
        response_variable: agenda2
      - service: calendar.list_events
        data:
          duration:
            hours: 24
        target:
          entity_id:
            - calendar.geburtstage
        response_variable: agenda3
      - variables:
          all_events: >
            {{ agenda1.events + agenda2.events + agenda2.events }}
          events: >
            {{ all_events | selectattr('start', 'search', now().date() | string) | list }}
    sensor:
      - name: Next 24hr Events
        unique_id: custom_multical_todays_events
        state: "{{ events | count }}"
        attributes:
          scheduled_events: "{{ events }}" 

perhaps this syntax isnt correct. i dont know.
has anyone a other solution? thx in advance.

Hi, I have a question regarding the days I see.

This line gives me 3 days of events. today, tomorrow and the day after tomorrow:

state_attr('sensor.calendar_scheduled_events', 'scheduled_events') 

How would I be able to limit this to only see today and tomorrow ?

Actually I was putting chatgpt to work and got this as a solution:

{% set today = now().date() %}
{% set tomorrow = now().date() + timedelta(days=2) %}
{% set items = state_attr('sensor.calendar_scheduled_events', 'scheduled_events') | selectattr('start', 'ge', today.strftime('%Y-%m-%d')) | selectattr('start', 'lt', tomorrow.strftime('%Y-%m-%d')) | sort(attribute='start') %}

Seems to work. Any comments ?

When you create your sensor sensor.calendar_scheduled_events you use a service call calendar.list_events
There you can specify start_date_time, end_date_time or duration

That way you don’t have to filter the created sensor ‘sensor.calendar_scheduled_events’ it will already have the events for today and tomorrow if you use duration days: 2