How to list multiple calendar event in a template

Good work, how come your date is formatted differently?
My output:
image

It’s because I have ‘all day’ events. I think your Garys Test (takes 30 mins) and Nurve Test for Gary (3 hours) make the difference and goes to timedate (YYYY-MM-DD:HH:MM:SS+Timezone). Because your baby girl (or gf/wife is 38 weeks pregnant?) is a ‘all day’ event it will only give back the YYYY-MM-DD.

Arr got ya, I didn’t realise you had all day events, I am trying to work out how to format the events to ready 9.30pm today at the moment it speaks out a mess of numbers :slight_smile:

I have been playing around with this template but cannot get it working. I use gmail to notify me of the output, but the script does not change the formatting, do you have any idea? I know some words are in German but I don’t think that should make any difference at the moment?

service: notify.gmail
data:
  target: [email protected]
  title: Daily agenda for {{ now().date() }}
  message: >-
    {%- if garys_agenda.events %}
      {%- for event in garys_agenda.events if event.start is defined -%}
        {%- set start = event.start | as_datetime | as_local -%}
        {%- set end = event.end | as_datetime | as_local -%}
        {%- if start > now() and start - now() < timedelta(days=1) %}     
          Am {{ tage[start.weekday()] }} den {{ start.strftime('%d/%m/%Y') }}
          {%- if end - start == timedelta(days=1) %} ganztägig
          {%- else %} um {{ start.strftime('%H:%M %p') }} bis {{ end.strftime('%H:%M %p') }}
          {%- endif %} ist {{ event.summary }}
          {%- if event.description is defined %}
          Hinweise, {{ event.description }}
          {%- endif -%}
          {%- if event.location is defined %}
          Ort, {{ event.location }}
          {% endif -%}
        {% endif -%}  
      {%- endfor %}
    {%- endif -%}' Garys agenda for today:  {% for event in garys_agenda.events
    %}  {{ event.start}}:  {{event.summary }}  {% endfor %}
enabled: true

The data in the scheduled_events attribute is not in the most convenient format and it’s due to something I forgot to include in the example I posted above (which I have now corrected).

In the Trigger-based Template Sensor, change this line:

scheduled_events: "{{ trigger.event.data.scheduled_events }}"

to this:

scheduled_events: "{{ trigger.event.data.scheduled_events.events }}"

Wait until the automation updates the scheduled_events attribute and you’ll see that the attribute’s data will be simplified to a list (as opposed to a dictionary). This simplification will allow this line in the macro to work correctly and eliminate the error message you had received.

{% for e in state_attr('sensor.gary_scheduled_events', 'scheduled_events') %}

I suggest you implement the small correction to the Trigger-based Template Sensor that I posted above. It will simplify the format of the data in the scheduled_events attribute to a list, like this:

scheduled_events: 
  - start: '2023-08-22'
    end: '2023-08-22'
    summary: Robin test (YYYY)
  - start: '2023-08-22'
    end: '2023-08-22'
    summary: L test (YYYY)
  - start: '2023-08-22'
    end: '2023-08-22'
    summary: N test (YYYY)
  - start: '2023-08-22'
    end: '2023-08-22'

You can use a Markdown Card containing this (after you make the suggested modification I described):

{% for e in state_attr('sensor.birthday_events', 'scheduled_events') %}
{{ e.start}}: {{ e.summary }}
{% endfor %}

I’ve applied the small changes and it works! Thanks a lot @123!

Next step: Create a notification on the same date when a start is the same as the current date at specific times. I want to populate a push notifications with title Birthday(s) today, and message the name(s) of the event(s). Any tips how to do this?

HI guys, I’ve struggled to find an answer across multiple posts and forums.

but I have persevered and combined multiple suggestions into a solution that works for me as a morning agenda for the day.

Step 1 - go to google calendar, click the 3 dots on the calendar you want, settings > scroll to bottom - copy ICAL Link

Step 2 - go to HAC > search for ICAL and download and install

Step 3 - Reboot HA

Step 4 - Go to Integrations > Add > ICAL

Step 5 - Paste your ICAL Link you copied earlier and set number of events to grab, I used 10 as I would never have more than 10 events to check, do note it checks multiple days, so if have only 5 tasks over a week, it will list them across the week for you

Step 6 - Wait for about 1-2 minutes for the sensors to populate

now you can built your template for your text to speech

here is my template I wrote … I only need 4 or so but you can adapt it for more if you like
the code has IF functions to determine if the event is today and alexa or google will say the event is at 8 today instead of the day of the week etc.

Its not perfect yet but its working!

Your next 4 events .. at {{ as_timestamp(state_attr('sensor.ical_carl_event_0' |string, "start")) | timestamp_custom('%H:%M') }} {% if (now().date() + timedelta(days=0))  | string  ==
 as_timestamp(state_attr('sensor.ical_carl_event_0' |string, "start")) |timestamp_custom('%Y-%m-%d')   %}Today {% else %} {{ as_timestamp(state_attr('sensor.ical_carl_event_0' |string, "start")) | timestamp_custom('%A') }} 
{% endif %}   
.. {{ state_attr('sensor.ical_carl_event_0' |string, "summary") }} ..
 and at {{ as_timestamp(state_attr('sensor.ical_carl_event_1' |string, "start")) | timestamp_custom('%H:%M') }}

{% if (now().date() + timedelta(days=0))  | string  ==
 as_timestamp(state_attr('sensor.ical_carl_event_1' |string, "start")) |timestamp_custom('%Y-%m-%d')   %}Today {% else %} {{ as_timestamp(state_attr('sensor.ical_carl_event_1' |string, "start")) | timestamp_custom('%A') }} 
{% endif %}   
 .. {{ state_attr('sensor.ical_carl_event_1' |string, "summary") }}
 then at {{ as_timestamp(state_attr('sensor.ical_carl_event_2' |string, "start")) | timestamp_custom('%H:%M') }} 

{% if (now().date() + timedelta(days=0))  | string  ==
 as_timestamp(state_attr('sensor.ical_carl_event_2' |string, "start")) |timestamp_custom('%Y-%m-%d')   %}Today {% else %} {{ as_timestamp(state_attr('sensor.ical_carl_event_2' |string, "start")) | timestamp_custom('%A') }} 
{% endif %}    .. {{ state_attr('sensor.ical_carl_event_2' |string, "summary") }}
 and finally at  {{ as_timestamp(state_attr('sensor.ical_carl_event_3' |string, "start")) | timestamp_custom('%H:%M') }} 

{% if (now().date() + timedelta(days=0))  | string  ==
 as_timestamp(state_attr('sensor.ical_carl_event_3' |string, "start")) |timestamp_custom('%Y-%m-%d')   %}Today {% else %} {{ as_timestamp(state_attr('sensor.ical_carl_event_3' |string, "start")) | timestamp_custom('%A') }} 
{% endif %}    .. {{ state_attr('sensor.ical_carl_event_3' |string, "summary") }}  

This code produces text like this

Your next 4 events at 08:30 Today blah blah
and at 09:30 Today blah blah
then at 19:30 Today blah blah
and finally at 09:00 Tuesday … blah blah

the . . in the code is a breather for alexa so they speaks normally instead of rattling it off like a robot :slight_smile:

I hope this helps you guys!

1 Like

Taras - Awesome - Just like magic, yep macro now works, learning a lot, reading a lot thank you.
I have spent many hours trying to get the day and date formatted from events using your code above, in what way do you implement it? The german makes it a little harder to understand for me :slight_smile:
But what I can gather is your redefining the output then will use another template to call the info? is that correct or am I off base?

are you responding to me or a different post? :slight_smile:

Sorry Carlos your post came in as I was typing to Taras, looking at yours now.

In case you missed it, it’s now possible to get events from a calendar natively; there’s no need to install any third-party applications.

If that’s what you want to do then it can be done without the use of calendar.list_events. What you described can be achieved with a Calendar Trigger.

If you mean the example in this post, then read the post prior to it. You’ll see I took someone else’s example (containing German text) and simplified its templates.

You’ll need to explain what you want exactly.

I would like to format the event times, when the TTS reads it out so that Tuesday @ 4pm etc at the moment I have
image

For determining if a date is today, tomorrow, in X days, etc then you may want to consider using these custom macros:

1 Like

Okay thanks, I will have a read

Thanks for the tip!

I used a different approach, because I would like to send multiple notifications. I’m now using this automation at a given time:

automation:
  - alias: "Notify Events for Today"
    trigger:
      platform: time
      at: "08:00:00"
    action:
      service: notify.your_notification_service
      data:
        title: "Today's Events"
        message: >-
          {% set today = now().strftime('%Y-%m-%d') %}
          {% set events_today = state_attr('sensor.gary_scheduled_events', 'scheduled_events') | selectattr('start', 'eq', today) | list %}
          {% for e in events_today %}
          {{ e.summary }}
          {% endfor %}

This works like a charm!

Next step is cleaning up code (using correct names for this service) and I’ll put a ‘how to’ on this topic.

automation:
  - alias: "Notify Events for Today"
    trigger:
      platform: time
      at: "08:00:00"
    action:
      service: notify.your_notification_service
      data:
        title: "Today's Events"
        message: >-
          {% for e in state_attr('sensor.robin_scheduled_events', 'scheduled_events')
            | selectattr('start', 'eq', now().strftime('%Y-%m-%d')) %}
          {{ e.summary }}
          {% endfor %}
1 Like

Thanks guys for the inspiration, I could not figure out the easy time approach, I resolved it by just inserting a timestamp similar to Robin.

    Garys Agenda for today: {% for e in
    state_attr('sensor.garys_agenda','scheduled_events') %}
      {{ as_timestamp(e.start) | timestamp_custom ('%A %H:%M %p') }}: {{ e.summary }} {% endfor %}

    Christines Aganda for today: {% for e in
    state_attr('sensor.christines_agenda', 'scheduled_events') %}
      {{ as_timestamp(e.start) | timestamp_custom ('%A %H:%M %p') }}: {{ e.summary }} {% endfor %}
1 Like