Aktionen im Helfer Schalter-Template

Moin,
Zum Testen habe ich einen Helfer vom Typ „Schalter-Template” erstellt. Der Schalter selbst funktioniert wie gewünscht. Nun wollte ich die Aktionen im Helfer nutzen, um weitere Geräte zu schalten. Leider erhalte ich bei der Ausführung der Aktionen Fehlermeldungen.

WARNING (MainThread) [homeassistant.helpers.service] Referenced entities input_boolean.schalter_test_bewaesserung are missing or not currently available

ERROR (MainThread) [homeassistant.components.websocket_api.http.connection] [140497951445280] Error handling message: Unable to determine action @ data[‘turn_on’][0]. Got None (invalid_format) хххх from fe80::74de:7c36:e65c:26d3 (Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0)

Seltsamerweise funktioniert es, wenn man auf die drei Punkte neben der Aktion drückt und dann auf „Aktion ausführen”.

Code in der Aktion

action: input_boolean.turn_on
data: {}
metadata: {}
target:
  entity_id: input_boolean.schalter_test_bewaesserung

Handelt es sich um ein Systemproblem von HA oder habe ich die Aktionen falsch parametriert? Letzteres kann eigentlich nicht der Fall sein, da ich über die GUI parametriert habe.

Meine Vermutung ist der Template Code und daß hier String und Date-Objekte miteinander verglichen werden. Hast Du diesen Code mit unterschiedlichen Konstellationen einmal getestet?

Zieh den Code doch testweise auseinander

{% set start_time = states('input_datetime.bewaesserung_starten') | today_at %}
{% set duration = states('input_number.bewaesserungszeit') | int(0) %}
{% set stop_time = start_time + timedelta(minutes=duration) %}
{% set now = now() %}

{{ start_time <= now <= stop_time }}

EDIT
Über das | today_at stolpere ich.


input_datetime ist schone ein Date-Object
Sollte es das sein?

Der Code an sich funktioniert, ich habe ihn sowohl im Template.yaml als auch in Helfer-Template getestet. Das ist der Code vom Helfer-Template. Da wird die Stop-Time berechnet, indem zur Startzeit im Format „datatime” die Zeitdauer als Integer addiert wird.

{% set target_time = (now() + timedelta(minutes=1)) | as_timestamp | timestamp_custom('%H:%M') %}  
      {% set start_time = states('input_datetime.bewaesserung_starten')  %} 
      {% set stop_time = (states('input_datetime.bewaesserung_starten') | today_at + timedelta(minutes=states('input_number.bewaesserungszeit') | int(0))).strftime('%H:%M') %}
      {{ start_time <= target_time <=  stop_time }}

Die Frage ist in diesem Thread entstanden.

Hm, Strings zum Uhrzeitvergleich nehmen? Da bin ich etwas skeptisch ob das immer geht. Ich würde immer Date-Objekte nehmen. Und diese today_at Geschichte aber da rate ich nur.
Ich bin gespannt was andere sagen und woran es am Ende liegt.

Hast du vielleicht eine andere Idee, wie man die Stopzeit berechnen kann?

Ich benutze folgenden Code schon lange und er funktioniert auch. Hier werden keine Strings, sondern datatime verglichen. Aus diesem Code ist auch der andere Code entstanden.

- binary_sensor:
  - name: "Timer EV Laden"
    unique_id: "timer_ev_laden" 
    state: >
      {% set target_time = (now() + timedelta(minutes=1)) | as_timestamp | timestamp_custom('%H:%M') %}      
      {% if states('input_datetime.ev_laden_ein') <= target_time < states('input_datetime.ev_laden_aus') %}
        true
      {% else %}
        false
      {% endif %}

Ich habe jetzt zum Testen einen Helfer-Template-Schalter mit einem einfachen Code erstellt, , um auszuschließen, dass das Problem am Code liegt.

{{ states("input_number.in_strom_l2") | int >= 50  }}

Ich bekomme auch die Fehlermeldung, also sollte es ein Systemproblem des HA sein.

:crayon:by HarryP: Zusammenführung Doppelpost (bei Änderungen oder hinzufügen von Inhalten bitte die „Bearbeitungsfunktion“ anstatt „Antworten“ zu nutzen)


Ja, ich kann das Bestätigen

{{ now().minute == 44 }}
  • Beim Erreichen der Minute 44 ging der Schalter AN aber die Lampe blieb AUS
  • Manuelles Anschalten über die 3 Punkte geht
  • Beim Erreichen der Minute 45 ging der Schalter AUS aber die Lampe blieb AN

Ich denke auch, daß ist ein HA Bug.
Workaround ist eine kleine Automatisation anstelle dieses Template Schalter.

Ich schau jetzt noch kurz nach Deiner Zeitfrage, melde mich gleich

EDIT:
Meine Lösung gefällt mir noch nicht nicht aber ich habe heute keine Lust mehr.
Aber von vorne
Ich habe diesen Code genommen und einige Zeiten durchprobiert.

{# ---------- Stringvergleich ---------- #}
{% set start_str = "23:00" %}
{% set jetzt_str = "23:30" %}
{% set end_str = "23:59" %}

Stringvergleich: {{ start_str <= jetzt_str < end_str }}

Insbesondere beim Wechsel in einen neuen Tag machen Stringvergleiche Probleme
Hier eine exemplarische Testtabelle

Ein möglicher besserer Code könnte sein.

{# ---------- Stringvergleich ---------- #}
{% set start_str = "23:00" %}
{% set jetzt_str = "23:30" %}
{% set end_str = "00:59" %}

Stringvergleich: {{ start_str <= jetzt_str < end_str }}

{# ---------- Timestampvergleich ---------- #}
{% set base_date = strptime("2025-01-01", "%Y-%m-%d") -%}
{% set start = strptime(start_str, "%H:%M").replace(year=base_date.year, month=base_date.month, day=base_date.day).timestamp() -%}
{% set end = strptime(end_str, "%H:%M").replace(year=base_date.year, month=base_date.month, day=base_date.day).timestamp() -%}
{% set jetzt = strptime(jetzt_str, "%H:%M").replace(year=base_date.year, month=base_date.month, day=base_date.day).timestamp() -%}

Timestampvergleich: 
{% if start == end %}
  false
{% elif start < end %}
  {{ start <= jetzt < end }}
{% else %}
  {% set end = end + 86400 %}
  {% if jetzt < start %}
    {% set jetzt = jetzt + 86400 %}
  {% endif %}
  {{ start <= jetzt < end }}
{% endif %}

Er geht aber mir gefällt er nicht. Mein Bauchgefühl sagt, es gibt eine bessere und simplere Alternative.
Gute Nacht :wink:

EDIT2:
Mit ein paar Stunden Abstand denke ich am Besten wäre es, es gar nicht erst zu Stringvergleichen kommen zu lassen.

1 „Gefällt mir“

Danke dir und gute Nacht!
Eine Frage, um morgen wach zu werden.
Ich habe einige Sachen in HA programmiert, habe aber immer wieder unterschiedliche Probleme, vor allem mit den Datentypen. Bei Float und Int ist alles klar. Jetzt zu dem, was ich da gebastelt habe: Du sagst, dass ich die Strings vergleichen. Das verstehe ich aber nicht.
Das ist doch kein String, die Variable “bewaesserung_starten” wurde als datetime definiert.

{% set start_time = states('input_datetime.bewaesserung_starten')  %} 

Genau dasselbe gilt für die Variable. Die kann doch kein String sein!

 {% set target_time = (now() + timedelta(minutes=1)) | as_timestamp | timestamp_custom('%H:%M') %} 

Das System kann doch String mit Datetime nicht vergleichen. Wie soll dieser Vergleich funktionieren, wenn die Variable „target_time” ein String wäre?

 {% if states('input_datetime.ev_laden_ein') <= target_time < states('input_datetime.ev_laden_aus') %}

today_at() funktioniert nur bei Uhrzeiten (—> today), und deswegen nur bei input datetimes, die nur Uhrzeit anbieten (nicht Tag + Uhrzeit)

Demgemäß kann man mit

{{ start_time <= now <= stop_time }}

nur Zeiten des heutigen Tages miteinander vergleichen.

1 „Gefällt mir“
states('von irgendwas') gibt immer einen String zurück

Aus diesem Grund siehst Du hier im Forum auch öfters Fehler weil User vergessen eine | float oder | int anzuhängen aber mit den Werten rechnen wollen.

{% set target_time = (now() + timedelta(minutes=1)) | as_timestamp | timestamp_custom('%H:%M') %} 

| timestamp_custom(‘%H:%M’) wandelt am Ende den Timestamp in einen String

- binary_sensor:
  - name: "Timer EV Laden"
    unique_id: "timer_ev_laden"
    state: >
      {% set target_time = (now() + timedelta(minutes=1)).timestamp() %}
      {% set ein = as_timestamp(states('input_datetime.ev_laden_ein')) %}
      {% set aus = as_timestamp(states('input_datetime.ev_laden_aus')) %}
      {{ ein <= target_time < aus }}

Das sollte den Vergleich von Timestamps bringen. Ich habe es nicht durchgetestet. Versuche es einmal.
Im Besten Fall funktioniert der Sensor genau so gut wie Dein voriger aber in Grenzfällen eben auch besser.

:crayon:by HarryP: Zusammenführung Doppelpost (bei Änderungen oder hinzufügen von Inhalten bitte die „Bearbeitungsfunktion“ anstatt „Antworten“ zu nutzen)

1 „Gefällt mir“

Noch was dazu gelernt, ich dachte, dass da die Uhrzeit vergliechen wird.

Ich habe es getestet, die Anweisung führt zu einer Fehlermeldung.

{% set aus = as_timestamp(states('input_datetime.ev_laden_aus')) %}

ValueError: Template error: as_timestamp got invalid input ‘20:00:00’ when rendering template '{## Imitate available variables: ##}

Ich bin schon wieder darüber gestolpert, daß Dein input_datetime.ev_laden_aus ein Datetime ohne Date ist also nur Uhrzeit…wie oben schon bei dem today_at().

Man müßte dem ein Datum mitgeben, anbieten würde sich von now().
Wenn das inhaltlich gerechtfertigt ist (= input_datetime.ev_laden_aus kann nie von gestern sein), dann könnte man das so machen:

{% set datetime_without_date = states('input_datetime.ev_laden_aus') %}
{% set basis_heute = now() %}
{% set aus = strptime(datetime_without_date, "%H:%M:%S").replace(year=basis_heute.year, month=basis_heute.month, day=basis_heute.day).timestamp() %}

Ansonsten denke ich morgen in Ruhe noch einmal nach.
Meine Frau sagt: Ist Schluß heute …

Danke. Ich lasse es so, wie es ist. Ob dabei Strings miteinander verglichen werden oder die Zeit, ist nicht relevant, Hauptsache es funktioniert.

Ich habe ein wenig herumexperimentiert, folgende Anweisung
states(‘input_datetime.bewaesserung_starten’) | today_at

liefert den Wert „2025-07-11 23:30:00+02:00”.

Wenn ich per Timedelta eine Stunde dazu addiere, erhalte ich 2025-07-12 00:30:00+02:00.
Also einen Tag später.

Die Anweisung
(now() ) lieferte den Wert 2025-07-11 06:56:00.192032+02:00.

Ich habe versucht, die Zeiten so zu vergleichen, es funktioniert

{% set target_time = (now() + timedelta(minutes=1)) %} 
{% set start_time = states('input_datetime.bewaesserung_starten') | today_at %} 
{% set zeit = timedelta(minutes=states('input_number.bewaesserungszeit') | int(0)) %}
{% set stop_time = start_time + zeit %}
{{ start_time <= target_time < stop_time }}

Das gefällt mir.

Ich hab auch etwas mit today_at() beschäftigt

Es nimmt die Uhrzeit des input_datetime und macht daraus ein Dateobjekt mit Basis des Datums von heute ähnlich wie meine Idee von oben aber besser.

Damit gilt aber auch die oben genannte Einschränkung: states(‘input_datetime.bewaesserung_starten’) darf inhaltlich nur eine Uhrzeit von heute sein, nicht gestern. Falls es eine Uhrzeit von gestern war, macht die Logik eine Uhrzeit von heute daraus.

Ich bin der Meinung, dass es nicht um gestern, sondern um morgen geht. Ich werde heute Nacht testen, ob es funktioniert. Besser wäre es allerdings zu sagen, ich werde morgen nachgucken, ob es funktioniert hat.

Setz doch beide Sensoren auf und dann kannst Du vergleichen.
start_time wird mit today_at() immer das Datum des momentanen Tages nehmen und darauf das Timedelta anwenden. Damit kann immer noch {{ start_time <= target_time < stop_time }} ein true ergeben.
Bis morgen :slight_smile:

Moin, der Schalte wurde um 0:00 Uhr ausgeschaltet, wie du gesagt hast.

Danke auch für diese Reise! Ich selbst habe auch dazugelernt

  • Nutze vorerst keine Schalter Templates sondern lieber eine Automatisation mehr
  • Stringvergleiche von Uhrzeiten funktionieren auch solange die Vergleiche sich auf den selben Tag beziehen
  • Es gibt ein today_at() Funktion was aus einem Uhrzeit String ein nutzbares Date-Objekt macht aber ein input_datetime ohne Datum voraussetzt und diesem dann das Datum von Heute zugrunde legt
  • Wie meisten kommt es wieder einmal auf Details an

Ich würde sagen, dass es besser ist, in der Template.yaml zu programmieren, als eine Automatisierung zu nutzen. Die Automatisierung hat einen entscheidenden Nachteil: Sie muss immer getriggert werden. Wenn wir beim Code für den Schalter bleiben: Wie willst du die Automatisierung triggern und vor allem wie oft?
Ursprünglich war dieser Code auch für die Template.yaml gedacht. Da der User, für den dieser Code gedacht war, jedoch keine Template.yaml hatte, habe ich die Lösung mit dem Helfer angeboten.
Nachdem ich mein HA jetzt auf den neuesten Stand gebracht habe, habe ich noch einmal die Aktion im Schalter-Template ausprobiert. Leider hat es nicht funktioniert, der Fehler wurde also nicht behoben.

Beim Experimentieren habe ich noch eine Funktion kennengelernt: Split. Mit dieser Funktion lässt sich ein String in einzelne Teile zerlegen, die dann als Integer aufgerufen werden können, um mit den Werten zu rechnen.

{% set start =  (states('input_datetime.bewaesserung_starten') | today_at ).strftime('%H:%M') .split(":") %}
{% set laufzeit = states('input_number.bewaesserungszeit') | int %}
{% set stop = ((start[0] | int * 60 + start[1] | int + laufzeit) / 60) |  round(2) %}

In der Variable start[0] stehen dann die Stunden und in start[1] die Minuten.

Ich würde genau den gleiche Template Code aus Deinem Schalter nehmen und diesen als Template Trigger der Automatisation hinterlegen. Wenn True → dann mache was.

Der Sensor in configuration.yaml oder ausgelagert in template.yaml prüft jede Minute ob Sensor true ergibt ist.

Das finde ich immer gut weil auch ich lerne nur so. Doku lesen ist gut und natürlich wichtig, ausprobieren bleibt schneller im Kopf hängen.

Ja, kann man mit Split() machen. Nur denke ich 2 Formatierungen sind unnötig. Bei einem Dateobjekt ist das Gute, daß HA damit Berechnungen anbietet wie dieses timedelta.