From df047f61fb8df3b8e38690c9670304cb3ac7730f Mon Sep 17 00:00:00 2001 From: Commander1024 Date: Fri, 10 Jul 2026 13:33:34 +0200 Subject: [PATCH] Calendar data retrieval via "get calendar events" in automation and text_helpers. --- automations.yaml | 110 +++++++++++++++++++++++++++++++++++++++ configuration.yaml | 3 ++ esphome/epaperframe.yaml | 52 +++++++++--------- template.yaml | 56 +++++++------------- text_helpers.yaml | 18 +++++++ 5 files changed, 177 insertions(+), 62 deletions(-) create mode 100644 text_helpers.yaml diff --git a/automations.yaml b/automations.yaml index a1e6f37..7415ed3 100644 --- a/automations.yaml +++ b/automations.yaml @@ -1393,3 +1393,113 @@ device_id: 6d1be741876624a70ab5b01b54c6fd6f entity_id: 621e4377a089b7f5d92c7c9f2cc171a1 domain: switch +- id: '1773000000001' + alias: epaperframe - Kalender Events laden + description: Ruft alle Events von calendar.privat und calendar.tkrz_kalender für heute und morgen ab und schreibt sie in input_text-Helfer. + triggers: + # Täglich um 00:01 neu holen + - trigger: time + at: '00:01:00' + id: daily + actions: + # ── Events für heute (00:00 bis 23:59) holen ── + - action: calendar.get_events + target: + entity_id: + - calendar.privat + - calendar.tkrz_kalender + data: + start_date_time: "{{ now().replace(hour=0, minute=0, second=0) }}" + end_date_time: "{{ (now().replace(hour=0, minute=0, second=0) + timedelta(days=1)) }}" + response_variable: today_evts + + # ── Events für morgen (00:00 bis 23:59) holen ── + - action: calendar.get_events + target: + entity_id: + - calendar.privat + - calendar.tkrz_kalender + data: + start_date_time: "{{ (now() + timedelta(days=1)).replace(hour=0, minute=0, second=0) }}" + end_date_time: "{{ (now() + timedelta(days=1)).replace(hour=0, minute=0, second=0) + timedelta(days=1) }}" + response_variable: tomorrow_evts + + # ── Helper: Events als kompakte Liste formatieren ── + + # Privat heute + - set_var: + name: fmt_today_privat + value: >- + {%- set evts = today_evts['calendar.privat']['events'] if 'calendar.privat' in today_evts else [] %} + {%- set items = [] %} + {%- for e in evts[:5] %} + {%- set s = (e['summary'] | default('', true) | string)[:40] if e is mapping and 'summary' in e else '-' %} + {%- set st = e['start'] if e is mapping and 'start' in e else '' %} + {%- set hhmm = st[11:16] if st|length >= 16 else '??' %} + {%- set items = items + [hhmm ~ ' - ' ~ s] %} + {%- endfor -%} + {{ items | join('│') if items else '-' }} + + # Arbeit heute + - set_var: + name: fmt_today_arbeit + value: >- + {%- set evts = today_evts['calendar.tkrz_kalender']['events'] if 'calendar.tkrz_kalender' in today_evts else [] %} + {%- set items = [] %} + {%- for e in evts[:5] %} + {%- set s = (e['summary'] | default('', true) | string)[:40] if e is mapping and 'summary' in e else '-' %} + {%- set st = e['start'] if e is mapping and 'start' in e else '' %} + {%- set hhmm = st[11:16] if st|length >= 16 else '??' %} + {%- set items = items + [hhmm ~ ' - ' ~ s] %} + {%- endfor -%} + {{ items | join('│') if items else '-' }} + + # Privat morgen + - set_var: + name: fmt_tomorrow_privat + value: >- + {%- set evts = tomorrow_evts['calendar.privat']['events'] if 'calendar.privat' in tomorrow_evts else [] %} + {%- set items = [] %} + {%- for e in evts[:5] %} + {%- set s = (e['summary'] | default('', true) | string)[:40] if e is mapping and 'summary' in e else '-' %} + {%- set st = e['start'] if e is mapping and 'start' in e else '' %} + {%- set hhmm = st[11:16] if st|length >= 16 else '??' %} + {%- set items = items + [hhmm ~ ' - ' ~ s] %} + {%- endfor -%} + {{ items | join('│') if items else '-' }} + + # Arbeit morgen + - set_var: + name: fmt_tomorrow_arbeit + value: >- + {%- set evts = tomorrow_evts['calendar.tkrz_kalender']['events'] if 'calendar.tkrz_kalender' in tomorrow_evts else [] %} + {%- set items = [] %} + {%- for e in evts[:5] %} + {%- set s = (e['summary'] | default('', true) | string)[:40] if e is mapping and 'summary' in e else '-' %} + {%- set st = e['start'] if e is mapping and 'start' in e else '' %} + {%- set hhmm = st[11:16] if st|length >= 16 else '??' %} + {%- set items = items + [hhmm ~ ' - ' ~ s] %} + {%- endfor -%} + {{ items | join('│') if items else '-' }} + + # ── input_text Helfer schreiben ── + - action: input_text.set_value + target: + entity_id: input_text.kalender_heute_privat + data: + value: "{{ fmt_today_privat }}" + - action: input_text.set_value + target: + entity_id: input_text.kalender_heute_arbeit + data: + value: "{{ fmt_today_arbeit }}" + - action: input_text.set_value + target: + entity_id: input_text.kalender_morgen_privat + data: + value: "{{ fmt_tomorrow_privat }}" + - action: input_text.set_value + target: + entity_id: input_text.kalender_morgen_arbeit + data: + value: "{{ fmt_tomorrow_arbeit }}" diff --git a/configuration.yaml b/configuration.yaml index 06413e9..4a55430 100644 --- a/configuration.yaml +++ b/configuration.yaml @@ -49,6 +49,9 @@ sql: # calendar integration calendar: !include calendars.yaml +# Helpers for epaperframe calendar display +input_text: !include text_helpers.yaml + # DB-recorder configuration recorder: !include recorder.yaml diff --git a/esphome/epaperframe.yaml b/esphome/epaperframe.yaml index ae86b63..484a06f 100644 --- a/esphome/epaperframe.yaml +++ b/esphome/epaperframe.yaml @@ -237,25 +237,25 @@ text_sensor: entity_id: weather.zuhause id: weather - # ── Kalender-Ereignisse (from HA template sensors) ── + # ── Kalender-Ereignisse (from HA input_text helpers) ── - platform: homeassistant entity_id: sensor.kalender_heute_privat - id: kalender_heute_privat_text + id: kalender_heute_privat internal: true - platform: homeassistant entity_id: sensor.kalender_heute_arbeit - id: kalender_heute_arbeit_text + id: kalender_heute_arbeit internal: true - platform: homeassistant - entity_id: sensor.kalender_heute_privat_uhrzeit - id: kalender_heute_privat_uhrzeit + entity_id: sensor.kalender_morgen_privat + id: kalender_morgen_privat internal: true - platform: homeassistant - entity_id: sensor.kalender_heute_arbeit_uhrzeit - id: kalender_heute_arbeit_uhrzeit + entity_id: sensor.kalender_morgen_arbeit + id: kalender_morgen_arbeit internal: true graph: @@ -1170,33 +1170,24 @@ display: /* Event lines (Privat / Arbeit) */ int eventOffsetY = 90; + // Helper lambda: draw one event line at given Y offset with the given text sensor id // Privat today - if (id(kalender_heute_privat_text).has_state() && !id(kalender_heute_privat_text).state.empty()) { + if (id(kalender_heute_privat).has_state() && !id(kalender_heute_privat).state.empty()) { it.print(10 + leftX, 50 + leftY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "\U0001f32e" ); - if (id(kalender_heute_privat_uhrzeit).has_state() && !id(kalender_heute_privat_uhrzeit).state.empty()) { - it.printf(40 + leftX, 50 + leftY + eventOffsetY, id(sub_sensor_font), "%s ", id(kalender_heute_privat_uhrzeit).state.substr(0, 5).c_str()); - } - size_t max_len = 38; + // Split by │ separator and display first line of events + auto parts = id(kalender_heute_privat).state.c_str(); it.printf(40 + leftX, 50 + leftY + eventOffsetY, id(sub_sensor_font), "%s", - id(kalender_heute_privat_text).state.substr( - id(kalender_heute_privat_uhrzeit).has_state() && !id(kalender_heute_privat_uhrzeit).state.empty() - ? 6 : 0, max_len).c_str()); + id(kalender_heute_privat).state.substr(0, 60).c_str()); } else { it.print(10 + leftX, 50 + leftY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "\U0001f32e" ); it.printf(40 + leftX, 50 + leftY + eventOffsetY, id(sub_sensor_font), "Kein Termin"); } // Arbeit today - if (id(kalender_heute_arbeit_text).has_state() && !id(kalender_heute_arbeit_text).state.empty()) { + if (id(kalender_heute_arbeit).has_state() && !id(kalender_heute_arbeit).state.empty()) { it.print(10 + leftX, 85 + leftY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "\U0001f32e" ); - if (id(kalender_heute_arbeit_uhrzeit).has_state() && !id(kalender_heute_arbeit_uhrzeit).state.empty()) { - it.printf(40 + leftX, 85 + leftY + eventOffsetY, id(sub_sensor_font), "%s ", id(kalender_heute_arbeit_uhrzeit).state.substr(0, 5).c_str()); - } - size_t max_len = 38; it.printf(40 + leftX, 85 + leftY + eventOffsetY, id(sub_sensor_font), "%s", - id(kalender_heute_arbeit_text).state.substr( - id(kalender_heute_arbeit_uhrzeit).has_state() && !id(kalender_heute_arbeit_uhrzeit).state.empty() - ? 6 : 0, max_len).c_str()); + id(kalender_heute_arbeit).state.substr(0, 60).c_str()); } else { it.print(10 + leftX, 85 + leftY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "\U0001f32e" ); it.printf(40 + leftX, 85 + leftY + eventOffsetY, id(sub_sensor_font), "Kein Termin"); @@ -1215,12 +1206,21 @@ display: it.printf(205 + rightX, 45 + rightY, id(sensor_unit), "%02d.%04d.", tomorrow_month, tomorrow_year); /* Event lines (Privat / Arbeit) */ - // TODO: tomorrow events via HA template sensors - if (!id(kalender_heute_privat_text).has_state() || id(kalender_heute_privat_text).state.empty()) { + // Privat tomorrow + if (id(kalender_morgen_privat).has_state() && !id(kalender_morgen_privat).state.empty()) { + it.print(10 + rightX, 50 + rightY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "\U0001f32e" ); + it.printf(40 + rightX, 50 + rightY + eventOffsetY, id(sub_sensor_font), "%s", + id(kalender_morgen_privat).state.substr(0, 60).c_str()); + } else { it.print(10 + rightX, 50 + rightY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "\U0001f32e" ); it.printf(40 + rightX, 50 + rightY + eventOffsetY, id(sub_sensor_font), "Kein Termin"); } - if (!id(kalender_heute_arbeit_text).has_state() || id(kalender_heute_arbeit_text).state.empty()) { + // Arbeit tomorrow + if (id(kalender_morgen_arbeit).has_state() && !id(kalender_morgen_arbeit).state.empty()) { + it.print(10 + rightX, 85 + rightY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "\U0001f32e" ); + it.printf(40 + rightX, 85 + rightY + eventOffsetY, id(sub_sensor_font), "%s", + id(kalender_morgen_arbeit).state.substr(0, 60).c_str()); + } else { it.print(10 + rightX, 85 + rightY + eventOffsetY, id(mdi_med), TextAlign::BASELINE_LEFT, "\U0001f32e" ); it.printf(40 + rightX, 85 + leftY + eventOffsetY, id(sub_sensor_font), "Kein Termin"); } diff --git a/template.yaml b/template.yaml index baa96c8..2a7d6b6 100644 --- a/template.yaml +++ b/template.yaml @@ -145,44 +145,28 @@ unit_of_measurement: 'Mbps' # ── Kalender-Ereignisse für epaperframe ── -# Quelle: calendar.privat und calendar.tkrz_kalender -# Diese Sensoren lesen das aktuelle (laufende) Event aus dem Kalendereintrag. +# Alle Events werden per Automation (automations.yaml) in input_text Helfer geschrieben. +# Diese template sensors lesen nur noch daraus. Das verhindert doppelte Logik und garantiert, +# dass sowohl "heute" als auch "morgen" Events mit Titeln, Uhrzeiten und Beschreibungen verfügbar sind. - text_sensor: + # ── HEUTE ── - name: "Kalender heute Privat" unique_id: kalender_heute_privat - state: >- - {% set desc = state_attr('calendar.privat', 'description') or '' %} - {% set msg = state_attr('calendar.privat', 'message') or '' %} - {% if desc or msg or state_attr('calendar.privat', 'start_time') %} - {{ (msg if msg else desc) | replace('\n', ', ') | trim | truncate(60) }} - {% else %} - - - {% endif %} + state: "{{ states('input_text.kalender_heute_privat') }}" + icon: mdi:calendar-account + - name: "Kalender heute Arbeit" unique_id: kalender_heute_arbeit - state: >- - {% set desc = state_attr('calendar.tkrz_kalender', 'description') or '' %} - {% set msg = state_attr('calendar.tkrz_kalender', 'message') or '' %} - {% if desc or msg or state_attr('calendar.tkrz_kalender', 'start_time') %} - {{ (msg if msg else desc) | replace('\n', ', ') | trim | truncate(60) }} - {% else %} - - - {% endif %} - - name: "Kalender heute Privat Uhrzeit" - unique_id: kalender_heute_privat_uhrzeit - state: >- - {% set st = state_attr('calendar.privat', 'start_time') %} - {% if st %} - {{ as_timestamp(st) | timestamp_custom('%H:%M', true) }} - {% else %} - - - {% endif %} - - name: "Kalender heute Arbeit Uhrzeit" - unique_id: kalender_heute_arbeit_uhrzeit - state: >- - {% set st = state_attr('calendar.tkrz_kalender', 'start_time') %} - {% if st %} - {{ as_timestamp(st) | timestamp_custom('%H:%M', true) }} - {% else %} - - - {% endif %} + state: "{{ states('input_text.kalender_heute_arbeit') }}" + icon: mdi:calendar-account + + # ── MORGEN ── + - name: "Kalender morgen Privat" + unique_id: kalender_morgen_privat + state: "{{ states('input_text.kalender_morgen_privat') }}" + icon: mdi:calendar-calendar-today + + - name: "Kalender morgen Arbeit" + unique_id: kalender_morgen_arbeit + state: "{{ states('input_text.kalender_morgen_arbeit') }}" + icon: mdi:calendar-calendar-today diff --git a/text_helpers.yaml b/text_helpers.yaml new file mode 100644 index 0000000..5afae03 --- /dev/null +++ b/text_helpers.yaml @@ -0,0 +1,18 @@ +# Helpers for epaperframe calendar display +input_text: + - name: "Kalender heute Privat" + initial: "-" + icon: mdi:calendar-account + mode: text + - name: "Kalender heute Arbeit" + initial: "-" + icon: mdi:calendar-account + mode: text + - name: "Kalender morgen Privat" + initial: "-" + icon: mdi:calendar-calendar-today + mode: text + - name: "Kalender morgen Arbeit" + initial: "-" + icon: mdi:calendar-calendar-today + mode: text