Moin
Ich hatte Spaß an dem Beitrag Renten-Countdown und war über das Interesse an einem Renten-Countdown überrascht. Am Ende tauchte der Kommentar auf.
Erst dachte ich, ohjee wird ja immer besser aber ich scripte gerne.
Momentane Umsetzung
Wie es funktioniert:
- Man gibt ein Suchwort ein (Wildcard Suche im Titel der Termine)
- Man wählt in einem Dropdown Helfer seinen Kalender aus.
- Man sagt, wieviel Jahre in der Zukunft die Termine geprüft werden sollen
- Man klickt auf Start Button und es
- startet die Suche nach passenden Terminen
- beim ersten Treffer wird der Starttermin des Termines genommen und damit oberer Countdown gestartet.
- Man öffnet die obere Markdownkarte und gibt im Code den Titel ein
{% set CoundownTitel = 'Zahnarzt' %} - Sobald der Countdown abgelaufen, wird dies entsprechend angezeigt.
Wie initial nachbauen:
- input_text.countdown_kalender_termintext anlegen (Minimalmenge kann bei 0 belassen werden, fange das im Code ab)
- input_select.selectbox_meinekalender anlegen und mit Deinen Kalendernamen befüllen. z.B. heißt die Entity “calendar.1sonos_alle_boxen” aber Du trägst nur “1sonos_alle_boxen” in. Icon auswählen was nachher auf dem Dashboard zu sehen sein soll
- input_number.countdown_kalenderjahre anlegen und Minimalwert auf 1 setzen, Icon auswählen was nachher auf dem Dashboard zu sehen sein soll
- input_datetime.countdown_start_date anlegen als Datum und Uhrzeit
- Ein Script “om_scr_tech_finde_naechsten_termin” anlegen mit unterem Code. Das Script sucht nach Terminen und setz den Helfer input_datetime.countdown_start_date entsprechend.
Zusammenfassung
sequence:
- variables:
kalendername: |
calendar.{{states('input_select.selectbox_meinekalender')}}
suchtext: |
{{states('input_text.countdown_kalender_termintext') | lower}}
kalenderjahre: |
{{states('input_number.countdown_kalenderjahre')}}
startzeit: |
{{ now() }}
endzeit: |
{{ as_datetime(startzeit) + timedelta(days=kalenderjahre * 365) }}
- if:
- condition: template
value_template: "{{states('input_text.countdown_kalender_termintext') | count == 0}}"
then:
- action: input_text.set_value
metadata: {}
data:
value: Bitte ein Suchwort eingeben!
target:
entity_id: input_text.countdown_kalender_termintext
- stop: Kein Suchwort vorhanden!
- action: calendar.get_events
metadata: {}
data:
start_date_time: "{{startzeit}}"
end_date_time: "{{endzeit}}"
target:
entity_id: "{{kalendername}}"
response_variable: termine
- variables:
starttermin: >-
{% set TerminGefunden = false %} {% set events = termine.values() |
map(attribute='events') | list | first %} {% set ns =
namespace(found=false) %} {% for e in events %}
{% if not ns.found and suchtext | string in e.summary | lower %}
{{ e.start }}
{% set ns.found = true %}
{% endif %}
{% endfor %}
- if:
- condition: template
value_template: "{{starttermin != ''}}"
then:
- action: input_datetime.set_datetime
metadata: {}
data:
datetime: "{{starttermin}}"
target:
entity_id: input_datetime.countdown_start_date
enabled: true
else:
- action: input_text.set_value
metadata: {}
data:
value: Keinen passenden Termin gefunden!
target:
entity_id: input_text.countdown_kalender_termintext
- action: input_datetime.set_datetime
metadata: {}
data:
date: "2025-01-01"
target:
entity_id: input_datetime.countdown_start_date
alias: om_scr_tech_finde_naechsten_termin
description: >-
## Script sucht in einem Kalender nach einen bestimmten Termin und speichert
dessen Starttermin in einen Datumshelfer
mode: restart
- Auf dem Dashboard legt Ihr einen neuen Abschnitt an und kopiert über Bearbeiten diesen Code ein
Zusammenfassung
type: grid
cards:
- type: heading
icon: mdi:archive-clock-outline
heading: Kalender Countdown
heading_style: subtitle
- type: markdown
content: >-
{# Code Version 1.0 #}
{% set CoundownTitel = 'Zahnarzt' %}
{# --- Layout Parameter --- #}
{% set fontsize_zahlen = 6 %}
{% set fontsize_worte = 4 %}
{% set fontsize_slider = 5 %}
{% set spaltenbreite = 100 %}
{% set IconCode_active = '<ha-icon icon="mdi:heart-multiple"></ha-icon>'
%}
{# --- Start Datums --- #}
{% set TargetDate =
as_local(as_datetime(states('input_datetime.countdown_start_date'))) %}
{% set Abgelaufen = now() > TargetDate %}
{# --- Hilfe für Darstellung Zieldatum --- #}
{# Wandelt englische Monate/Tage in dt #}
{% set wochentag = {
'Monday': 'Montag', 'Tuesday': 'Dienstag', 'Wednesday': 'Mittwoch',
'Thursday': 'Donnerstag', 'Friday': 'Freitag', 'Saturday': 'Samstag', 'Sunday': 'Sonntag'
}[TargetDate.strftime('%A')] %}
{% set monat = {
'January': 'Januar', 'February': 'Februar', 'March': 'März', 'April': 'April',
'May': 'Mai', 'June': 'Juni', 'July': 'Juli', 'August': 'August',
'September': 'September', 'October': 'Oktober', 'November': 'November', 'December': 'Dezember'
}[TargetDate.strftime('%B')] %}
{% set TargetDate_title = wochentag ~ ', ' ~ TargetDate.day ~ '. ' ~ monat
~ ' ' ~ TargetDate.year ~ ' um ' ~ TargetDate.hour ~ ':' ~
TargetDate.minute ~ ' Uhr' %}
{# --- Berechnung der verbleibenden Zeit --- #}
{% if Abgelaufen == false %}
{% set time_str = time_until(as_datetime(TargetDate), 5) %}
{# Default Werte Null weil die Funktion time_until keine Leerzeiten anzeigt, z.B. im selben Monat steht nicht "0 months" sondern nichts #}
{% set years_tmp = namespace(val=0) %}
{% set months_tmp = namespace(val=0) %}
{% set days_tmp = namespace(val=0) %}
{% set hours_tmp = namespace(val=0) %}
{% set minutes_tmp = namespace(val=0) %}
{# prüft ob der zeitraum vorkommt und nimmt diesen oder bleibt bei default 0 #}
{% for part in time_str.split(' ') %}
{% if 'year' in part %}
{% set years_tmp.val = time_str.split(' ')[loop.index0 - 1] | int %}
{% elif 'month' in part %}
{% set months_tmp.val = time_str.split(' ')[loop.index0 - 1] | int %}
{% elif 'day' in part %}
{% set days_tmp.val = time_str.split(' ')[loop.index0 - 1] | int %}
{% elif 'hour' in part %}
{% set hours_tmp.val = time_str.split(' ')[loop.index0 - 1] | int %}
{% elif 'minute' in part %}
{% set minutes_tmp.val = time_str.split(' ')[loop.index0 - 1] | int %}
{% endif %}
{% endfor %}
{% set years = years_tmp.val %}
{% set months = months_tmp.val %}
{% set days = days_tmp.val %}
{% set hours = hours_tmp.val %}
{% set minutes = minutes_tmp.val %}
{# --- Positionsberechnung --- #}
{% if years > 0 %}
{% set position_slider = 1 %}
{% elif months > 0 %}
{% set position_slider = 2 %}
{% elif days > 0 %}
{% set position_slider = 3 %}
{% elif hours > 0 %}
{% set position_slider = 4 %}
{% else %}
{% set position_slider = 5 %}
{% endif %}
{% endif %}
{# --- Darstellung --- #}
<font size=6>{{ CoundownTitel }}</font>
<font size=4>{{ TargetDate_title }}</font>
{% if Abgelaufen == false %}
<table border=0>
<tr>
<td width={{ spaltenbreite }}><center><font size={{ fontsize_zahlen }}>{{ years }}</font></center></td>
<td width={{ spaltenbreite }}><center><font size={{ fontsize_zahlen }}>{{ months }}</font></center></td>
<td width={{ spaltenbreite }}><center><font size={{ fontsize_zahlen }}>{{ days }}</font></center></td>
<td width={{ spaltenbreite }}><center><font size={{ fontsize_zahlen }}>{{ hours }}</font></center></td>
<td width={{ spaltenbreite }}><center><font size={{ fontsize_zahlen }}>{{ minutes }}</font></center></td>
</tr>
<tr>
<td width={{ spaltenbreite }}><center><font size={{ fontsize_worte }}>Jahre</font></center></td>
<td width={{ spaltenbreite }}><center><font size={{ fontsize_worte }}>Monate</font></center></td>
<td width={{ spaltenbreite }}><center><font size={{ fontsize_worte }}>Tage</font></center></td>
<td width={{ spaltenbreite }}><center><font size={{ fontsize_worte }}>Stunden</font></center></td>
<td width={{ spaltenbreite }}><center><font size={{ fontsize_worte }}>Minuten</font></center></td>
</tr>
<tr>
<td width={{ spaltenbreite }}><center><font size={{ fontsize_slider }}>{{ IconCode_active if position_slider == 1 else '' }}</font></center></td>
<td width={{ spaltenbreite }}><center><font size={{ fontsize_slider }}>{{ IconCode_active if position_slider == 2 else '' }}</font></center></td>
<td width={{ spaltenbreite }}><center><font size={{ fontsize_slider }}>{{ IconCode_active if position_slider == 3 else '' }}</font></center></td>
<td width={{ spaltenbreite }}><center><font size={{ fontsize_slider }}>{{ IconCode_active if position_slider == 4 else '' }}</font></center></td>
<td width={{ spaltenbreite }}><center><font size={{ fontsize_slider }}>{{ IconCode_active if position_slider == 5 else '' }}</font></center></td>
</tr>
</table>
{% else %}
Der Countdown ist abgelaufen!
{% endif %}
card_mod:
style: |
ha-card {
background: rgba(50, 50, 50, 0.25); /* 0,25=25% Deckung */
color: white;
box-shadow: none;
}
- type: heading
icon: mdi:cog-outline
heading_style: subtitle
heading: Einstellungen
- type: entities
entities:
- entity: input_text.countdown_kalender_termintext
name: Suchtext
secondary_info: none
card_mod:
style: |
:host {
--state-icon-color: white;
}
- entity: input_select.selectbox_meinekalender
name: Kalender
card_mod:
style: |
:host {
--state-icon-color: white;
}
- entity: input_number.countdown_kalenderjahre
name: Wieviele Jahre ?
card_mod:
style: |
:host {
--state-icon-color: white;
font-size: 11pt !important;
}
show_header_toggle: true
state_color: false
card_mod:
style: |
ha-card {
background: rgba(50, 50, 50, 0.25);
color: white;
--card-primary-color: white;
box-shadow: none;
}
- show_name: true
show_icon: true
type: button
name: Start
grid_options:
columns: full
rows: 2
hold_action:
action: none
tap_action:
action: perform-action
perform_action: script.turn_on
target:
entity_id: script.om_scr_tech_finde_naechsten_termin
card_mod:
style: |
ha-card {
height: 30px !important;
}
Und dann probiert und paßt alles an was Ihr anpassen wollt.
Ideen, was man noch verändern könnte:
- Layout
- Andere Elemente für Text, Selectbox und Button Jahre verwenden
- Einstellungen ein-/ausblenden
- Kalernamen in der Selectbox schöne Namen geben und dann im Script ein Mapping schöner Name zu ID machen.
- Anstelle in der Markdown Karte den Titel manuell ausgeben könnte dort auch automatisiert der komplette Termin-Titel stehen oder die ersten 20 Zeichen etc.
Bitte meldet mir gefundene Fehler und/oder postet Eure Veränderungen und Screenshots.
Ich bin gespannt.










