Not all calendar events listing

I’ve written a script to fetch my agenda items and store them in input_text.agenda_summary_tomorrow for use in a TTS automation later in the day. While the script works, it only retrieves the first event from each calendar.

If events are spread across different calendars, they are listed correctly. However, when multiple events exist within the same calendar, only the first one is stored.

How can I modify my script to correctly list all events from each calendar in input_text.agenda_summary_tomorrow?

alias: 📅 Load tomorrow's events
description: Extract tomorrow's events and save them to input_text.agenda_summary_tomorrow.
trigger:
  - at: "00:00:00"
    platform: time
action:
  - service: input_text.set_value
    target:
      entity_id: input_text.agenda_summary_tomorrow
    data:
      value: ""
  - variables:
      tomorrow: "{{ (now() + timedelta(days=1)).strftime('%Y-%m-%d') }}"
      calendars:
        - calendar.family
        - calendar.waste_collection
        - calendar.personal_1
        - calendar.paper_recycling
        - calendar.plastic_recycling
        - calendar.private_2
  - repeat:
      for_each: "{{ calendars }}"
      sequence:
        - variables:
            start_time: "{{ state_attr(repeat.item, 'start_time') | default('') }}"
            message: "{{ state_attr(repeat.item, 'message') | default('') }}"
        - choose:
            - conditions:
                - condition: template
                  value_template: "{{ start_time[:10] == tomorrow and message != '' }}"
              sequence:
                - service: input_text.set_value
                  target:
                    entity_id: input_text.agenda_summary_tomorrow
                  data:
                    value: >
                      {% set current = states('input_text.agenda_summary_tomorrow') %}
                      {{ [current, message ~ (" om " + start_time[11:16] if start_time[11:16] != "00:00" else "")] | select('!=', '') | join(', ') }}
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ states('input_text.agenda_summary_tomorrow') == '' }}"
        sequence:
          - service: input_text.set_value
            target:
              entity_id: input_text.agenda_summary_tomorrow
            data:
              value: "Geen afspraken voor morgen."
mode: single

Kind regards

Instead of iterating over calendar entities (which each have only one state, thus one appointment), use the action to ask all events in a specific period for the calendar entities you need. Then you get one response with all appointments for all calendars. Then extract the messages from that. The below example from the docs gets the data, try it in developer tools to see what it returns.

action: calendar.get_events
target:
  entity_id:
    - calendar.school
    - calendar.work
data:
  duration:
    hours: 24
response_variable: agenda
1 Like

i got it to print a massive block of text to the agenda response_variable but now having big troubel to get it to process the text

alias: Extract Tomorrow's Events (Fixed Parsing)
description: >
  Retrieve appointments for tomorrow, display the final processed text
  in a persistent_notification, and write to input_text.
triggers:
  - at: "00:00:00"
    trigger: time
actions:
  - target:
      entity_id:
        - calendar.family
        - calendar.waste_collection
        - calendar.personal
        - calendar.paper_recycling
        - calendar.plastic_recycling
        - calendar.additional_calendar
    data:
      start_date_time: >-
        {{ (now().astimezone() + timedelta(days=1)).replace(hour=0, minute=0,
        second=0) }}
      duration:
        hours: 24
    response_variable: agenda
    action: calendar.get_events
  - target:
      entity_id: input_text.agenda_summary_tomorrow
    data:
      value: >
        {% set events_list = [] %}
        {% for cal_name, cal_data in agenda.items() %}
          {% if 'events' in cal_data and cal_data['events'] %}
            {% for event in cal_data['events'] %}
              {% set time = event['start'][11:16] %}
              {% set summary = event['summary'] %}
              {% set events_list = events_list + [ summary ~ ' at ' ~ time ] %}
            {% endfor %}
          {% endif %}
        {% endfor %}
        {{ events_list | join(', ') if events_list else "No appointments for tomorrow." }}
    action: input_text.set_value
mode: single

keeps returning
No appointments for tomorrow.

You need to use a namespace, because the inner assignment is in a different scope:

{% set ns = namespace(events_list = []) %}
...
{% set ns.events_list = ns.events_list + [ summary ~ ' at ' ~ time ] %}

Try in developer tools first, with the output copied from the action tab.