ich bekomme es einfach nicht hin. Das Problem ist, dass ich einfach nur das nachmache was mir Oern geschrieben hat. Bei mir hakt es an einfachsten Übertragungen. Mir fehlt es grundsätzlich am Wissen.
Mein Sensor heißt
859_Sonoff_SNZB-02WD_Garten
Die Entität für die Temperatur heißt
sensor.859_sonoff_snzb_02wd_garten_temperature
Ich bekomme den Code in den Entwickleroptionen schon nicht hin, um die Temperatur anzeigen zu lassen.
Eine Entität hat immer genau einen State. Zusätzlich zu dem State kann die Entität auch noch Attribute haben. Bei diesem Sensor ist die Temperatur kein Attribut, wie Du auf dem folgenden Screenshot sehen kannst, es ist der State des Sensors. Das erkennt man u.a. auch an der device_class: temperature.
Wenn Du mit state_attr(‘…’, ‘…’) ein Attribut abfragst, dass nicht existiert, bekommst Du als Rückgabewert none zurück. Das ist bei Deinem Sensor der Fall. Ein Attribut namens Temperature gibt es nicht, also bekommst Du none zurück. Die erste Zeile, die Du genannt hast, ist hier die korrekte:
An dieser Stelle funktioniert beides, anzuraten wäre aber die zweite Version mit {{ state_attr(..)}}, weil bei dieser Art Abfrage HA immer etwas zurückgibt - und wenn es nur none ist! Bei der ersten Variante kann es passieren, dass HA Dir eine Fehlermeldung um die Ohren haut:
Die kannst Du von dem Sonoff auch nicht bekommen. Weil bei dem Sensor die Temperatur kein Attribut ist. Bei diesem Sensor ist die Temperatur der state.
Es gibt Entitäten. Jede Entität hat einenstate. Der state kann ein Zustand wie on oder off sein, z.B. bei einem Schalter. Oder ein state von 0% bis 100%, z.B. für eine Batterie. Oder eine (beliebige) Zahl, z.B. eine Temperatur. Wie bei Deinem Sensor. Da ist der state eine Zahl.
Wenn eine Entität mehrere Werte liefern kann, dann ist einer davon der state. Da eine Entität aber nur genau einen state haben kann, müssen die anderen als Attribut bereitgestellt werden.
Nehmen wir nochmal die Lampe. Bei der Lampe ist die interessanteste Information, ob sie ein- oder ausgeschaltet ist. Deshalb ist diese Information der state. Der State kann on oder off sein. Die Leuchtstärke und Lichtfarbe können nun, weil der state ja bereits belegt ist, nur noch als Attribut bereitgestellt werden.
Der interessanteste Wert (D)eines Temperatursensor ist … ? Natürlich die Temperatur. Deshalb ist der state die Temperatur! Du kannst ihn dir ja mal unter
Entwicklerwerkzeuge → Zustände
angucken. Wenn der Sensor noch weitere Werte erfassen kann, z.B. die Luftfeuchtigkeit, dann werden diese als Attribut bereitgestellt. Weil der state … ? … richtig! … bereits von der Temperatur belegt ist.
Beim weather.forecast_home hast du in den Entwickleroptionen/Template noch eien zweite Zeile Code rein geapckt. Da habe ich gefragt warum. Deine nachvollziehbare Antwort war:
Das sind beides Strings! Mit der ersten Zeile greifst du - sozusagen - direkt in den Sensor rein und holst da den Wert ab. Wenn der Sensor diesen Wert gar nicht hat, weil er ihn generell nicht hat oder Du Dich vielleicht nur verschrieben hast, dann gibt es einen Fehler:
Mit der zweiten Zeile sagst Du Home Assistant “Hey, frag mal den Sensor nach dem Wert und gib ihn mir”. Das macht HA dann. Weil HA das managed bekommst Du aber immer etwas zurück. Entweder den Wert, none (wenn der Sensor den Wert gar nicht hat) oder unknown / unavailiable (wenn es den Wert zwar generell gibt, er aber gerade unbekannt oder nicht verfügbar ist)
Was mache ich jetzt mit dem Sensor von Sonoff? Gibt der mit
So, da bin ich wieder. Ich bin dann mal im Urlaub. Zwar nur auf Balkonien, dafür hab ich jetzt Zeit einen ganzen Karton voller Zeug zu installieren und in HA reinzufrickeln, das sich während meiner Abwesenheit hier so angesammelt hat.
Fast richtig.
battery, humidity und voltage sind Entitäten. Das Gerät (also das Sonoff SNZB-02WD) ermittelt mit Sensoren den entsprechenden Wert und schreibt ihn in den state der Entität. Soweit ist es korrekt, ja.
Bei weather.forecast_home gibt es für diese Werte keine separaten Entitäten. Dort werden diese Werte als Attribut bereitgestellt. Soweit auch korrekt.
Ich nehme an, Du wolltest beim Sonoff außerdemtemperature hinzufügen, hast aber aus Versehen temperature_units erwischt? Für temperature stimmt das eben gesagte ebenfalls.
temperature_units ist eine Entität, die nicht (ob direkt oder indirekt) von der Hardware abhängt, z.B. einem Sensor. Diese Entität kannst Du setzen. Damit kannst Du festlegen, welche Einheit auf dem Display angezeigt werden soll.
Das erkennt man z.B. an der domain, der die Entität angehört.
Falls Du da mehr zu wissen möchtest, schreib kurz Bescheid.
Für die Version in der ersten Zeile bekommst Du immer etwas zurück, ja. states(…) ist eine Funktion von HA. Die versucht den state der angegebenen Entität auszulesen. Kann der state nicht gelesen werden, dann gibt HA Dir unknown oder unavailable zurück. Falls es einen state gibt, bekommst Du den Wert des state geliefert. D.h. die Fehlerprüfung, Wertermittlung und alles andere, was dazu gehört, übernimmt HA für Dich.
Die erste Zeile gibt Dir den state der Entität 859_sonoff_snzb_02wd_garten_temperature als Text (String) zurück. Mit einem Text kann man natürlich nicht rechnen. Versuchst Du es trotzdem, bekommst Du einen Fehler:
Es gibt einen TypeError, weil HA zu einem Text (string / str) keine Ganzzahl (integer / int) addieren kann. Damit HA mit der Temperatur tatsächlich rechnen kann, muss man den Text in eine Zahl umwandeln. Dann funktioniert das:
Das macht das | float. Das | float bedeutet: nimm das links von dem senkrechten Strich und mach eine Kommazahl daraus. Zu dem Ergebnis dieser Umrechnung addieren wir dann mit + 1 noch eins. Mal gucken. Ja, passt:
Und wenn das Ergebnis der Umrechnung mit | floatkeine Kommazahl ergibt? Mal gucken, was passiert, wenn wir eine Entität angeben, die es gar nicht gibt:
Wie erwarte meckert HA. HA sagt uns sogar, was nicht passt:
ValueError: Template error: float got invalid input ‘unknown’ when rendering template ‘{{ states(‘sensor.sonoff’) | float}}’ but no default was specified
HA hat nachgeguckt, die Entität sensor.sonoff nicht gefunden und gibt deshalb den Text unknown (unbekannt) zurück. Das ist auch richtig so. unknown ist nun offensichtlich keine Zahl, deshalb kann HA diesen Text nicht in eine Kommazahl umwandeln. Deshalb beendet HA die Abarbeitung und meldet einen Fehler. Bei dem Fehlertext gibt es aber noch einen interessanten Teil weiter hinten:
ValueError: Template error: float got invalid input ‘unknown’ when rendering template ‘{{ states(‘sensor.sonoff’) | float}}’ but no default was specified
Man kann einen Default-Wert (Standard-Wert) angeben. Genau das macht die (0) hinter float. Wenn HA versucht den Text in eine Kommazahl umzuwandeln, das aber nicht funktioniert, dann wird stattdessen der Default-Wert übergeben. Damit verhindert man, dass z.B. eine Automation, die irgendetwas berechnen soll, plötzlich mittendrin mit einem Fehler stehenbleibt, weil die Entität z.B. gerade nicht erreichbar ist. Dann ist ihr state nämlich‘unavailable', was? … genau! … nicht in eine Kommazahl umgewandelt werden kann.
Abschließend nochmal die Kurzfassung
(Achtung! Ich hab extra Leerzeichen eingefügt, damit man es besser erkennt!)
Wenn Du diesen Ausdruck jetzt verwendest, um irgendwo einen Text anzeigen zu lassen, z.B. im Template, dann kann das passieren:
Die Aussentemperatur ist {{ states('sensor.859_sonoff_snzb_02wd_garten_temperature') | float(0) }} °C
Moment, die Temperatur ist doch falsch! So kalt ist es noch gar nicht. Stimmt, aber die Ausgabe ist korrekt und logisch, weil die Entität mit diesem Namen in meinem HA nicht existiert. Es ist der Name Deiner Entität. Das ist nicht die Temperatur, das ist der Default-Wert 0. Aber immerhin ist das Template sauber durchgelaufen und hat mir keine Fehlermeldung um die Ohren gehauen.
Sowas kann man natürlich auch abfragen und entsprechend drauf reagieren, das kommt aber etwas später dran, denke ich.
Automatisierung, die den Helfer aus 2. jede volle Stunde um den aktuellen Temperaturwert von draußen erhöht, wenn die Temperatur >0 ist. Hier ist noch ein Fehler drin, weil für die GTS nur die positiven Tagesdurchschnittswerte relevant sind. Bei der Tagesdurchschnittstemperatur sind negative Werte in Ordnung. Ich weiß, wie man das löscht, brauche es aber noch für 4.
Automatisierung, die den Helfer aus 3. jede volle Stunde um 1 erhöht. Ich bin nicht sicher, ob hier auch um 1 erhöht wird, wenn bei 1. udn 2. kein Wert kommt (z.B: weil der Sensor defekt ist).
Home Assistant zählt bisher jede Stunde die Temperatur hoch und erhöht auch den Zähler.
Unter Template/Entwicklungsoptionen habe ich den Durchschnittswert gebildet:
summiert vom 01. Januar bis 31. Dezember jeden Tag um 23:05:00 Uhr die positiven Tagesdurchschnittstemperaturen (Helfer 3) auf, wird am 31. Dezember um 23:10:00 Uhr auf null zurück gesetzt
Automatisierung 1
859 Temperatur jede Stunde addieren
Summiert von 0:00:00 bis 23:00:00 Uhr jede volle Stunde die Temperatur auf
Setzt täglich um 23:10:00 den Helfer 1 auf 0 zurück
alias 859 Temperatur jede Stunde addieren zuruecksetzen
description
triggers
- trigger time
at 231000
conditions []
actions
- action input_number.set_value
target
entity_id input_number.859_tagestemperatur_summe_jede_stunde
data
value -
{{ states('input_number.859_tagestemperatur_summe_jede_stunde')float
0 }}
mode single
859 Tagesdurchschnittstemperatur groesser null jeden Tag addieren
Summiert täglich jeden Tag um 23:05:00 Uhr den Wert von Helfer 3 (wenn positiv) auf den Wert von Helfer 4, Januarwerte werden mit 0,5, Februarwerte mit 0,75 gewichtet
Bitte hier mal schauen, ob da was auffällt. Danke!
Ich hoffe, dass Automatisierung 5 funktioniert. Diese if then Sachen habe ich noch nicht oft gemacht, die Monatsbedingung musste ich googlen.
Die Rechnung habe ich vorher im Template getestet. Das funktioniert.
Was fehlt jetzt noch?
Helfer 5
859_GTS_erreicht
Schalter
input_boolean.859_gts_erreicht
Schalter, der als Bedingung für den späteren Mähvorgang dient.
Automatisierung 6, die den Helfer 5 auf ein schaltet, wenn Helfer 4 > 160 ist
Automatisierung 7, die Helfer 4 am 31.12.2025 um 23:10:00 auf 0 zurück.
Automatisierung 8, die den Helfer 4 am 31.12.2025 um 23:10:00 auf aus schaltet.
Wenn das erledigt ist, ist die GTS Bedingung vollständig.
Ich muss danach noch zwei Dinge machen:
A) das tägliche Rasenwachstum bzw. das Rasenwachstum seit dem letzte Mähen berechnen. Das müsste einfahc sein, wenn Automatisierung 5 mit der Monatsbedingung klappt.
B) die Automatisierung für den Mähroboter erstellen, der fährt, wenn:
Addierst Du das vielleicht aus versehen woanders nochmal?
Nachtrag
Was sich herauskristallisiert: Es wird langsam unübersichtlich - und damit wird es fehleranfälliger.
Die if … then … endif hast Du ja bereits gefunden. Die können wir nutzen, um ein wenig aufzuräumen. Ziel ist es eine Automation zu haben, in der all das getan wird, was bisher von den einzelnen Automationen geleistet wird.
Ich hab gestern Deine Automationen 1:1 kopiert. Die einzige Anpassung, die ich vornehmen musste, war der Name des Temperatursensors für aussen. Mich dünkt, da ist noch irgendwo ein Fehler drin:
summiert vom 01. Januar bis 31. Dezember jeden Tag um 23:05:00 Uhr die positiven Tagesdurchschnittstemperaturen (Helfer 3) auf, wird am 31. Dezember um 23:10:00 Uhr auf null zurück gesetzt
Automatisierung 5
859 Tagesdurchschnittstemperatur groesser null jeden Tag addieren
TODO: Automatisierung 6
Helfer 5 auf ein schaltet, wenn Helfer 4 > 160 ist
TODO: Automatisierung 7
Helfer 4 am 31.12.2025 um 23:10:00 auf 0 zurück.
TODO: Automatisierung 8
4 am 31.12.2025 um 23:10:00 auf aus schaltet.
Wenn man sich das alles genauer anschaut, sieht man, dass jede Stunde etwas gerechnet wird und bei einigen, wenigen Zeitpunkten zusätzlich etwas passiert. Als Tabelle niedergeschrieben springt es einem förmlich ins Gesicht:
An jedem Tag zu jeder vollen Stunde wird es berechnet. Jeweils um 23 Uhr wird am Ende jeden Tages etwas gelöscht (Lt), am letzten Tag jeden Monats etwas gelöscht (Lm) und am letzten Tag des Jahres etwas gelöscht (Lj).
Die Funktion now() hast Du ja bereits gefunden. Mit now() lässt sich ziemlich viel lustiges Zeug anstellen. Eine Übersicht darüber findet sich in der Doku unter …
Statt schnöder Theorie testen wir das natürlich im Template in Natura:
# Das einfachste ist die aktuelle Zeit abzufragen. Das beinhaltet Datum
# und Zeit. Das geht nicht nur als ein langer String an einem Stück ...
-> {{ now() }}
# ... sondern auch diverse Bestandteile einzeln:
now().day -> {{ now().day }}
now().month -> {{ now().month }}
now().year -> {{ now().year }}
now().hour -> {{ now().hour }}
now().minute -> {{ now().minute }}
now().second -> {{ now().second }}
# Man kann HA mittels timedelta() einen Zeitpunkt vor oder nach 'Jetzt'
# berechnen lassen. timedelta erlaubt als Argument weeks, days, hours,
# minutes, seconds, milliseconds und microseconds:
# Jetzt -3 Stunden
now() - timedelta(hours=3)
-> {{ now() - timedelta(hours=3) }}
# Jetzt +1 Tag
now() + timedelta(days=1)
-> {{ now() + timedelta(days=1) }}
# Jetzt -4 Wochen
now() - timedelta(weeks=4)
-> {{ now() - timedelta(weeks=4) }}
^^
# Guck mal. Das war ja im letzten Monat. Und wir können, wie wir oben
# gesehen haben, einzelne Bestandteile abfragen. Hm ... da fallen
# einem doch sofort ganz spontan haufenweise Schweinereien ein, die
# man damit anstellen kann:
Ist es 23 Uhr (Genauer: zwischen 23:00 und 23:59)?
now().hour == 23
-> {{ now().hour == 23 }}
Ist es 17:45 Uhr?
(now().hour == 17) and (now().minute == 45)
-> {{ (now().hour == 17) and (now().minute == 45) }}
Ist heute der 19.?
now().day == 19
-> {{ now().day == 19 }}
Welcher Montat ist heute?
now().month
-> {{ now().month }}
Welcher Monat ist in 14 Tagen?
( now() + timedelta(days=14) ).month
-> {{ (now()+timedelta(days=14)).month }}
Ist der Monat heute gleich dem Monat in 14 Tagen?
Anders formuliert: Ist in 14 Tagen ein anderer Monat?
now().month == ( now() + timedelta(days=14) ).month
-> {{ now().month == (now()+timedelta(days=14)).month}}
Bei Automatisierung 3 fehlt ein *. Mich wundert, dass da at 231000 und nicht at: “23:10:00” steht.
Bei Automatisierung 4 ist die entity id beim target falsch.
Bei Automatisierung 2 würde ich außerdem die Condition weglassen.
Das ist nicht ganz richtig.
Jede volle Stunde passiert das Aufaddieren der gemessenen Werte (Temperatur und Zähler):
859-1 Temperatur jede Stunde addieren Summiert von 0:00:00 bis 23:00:00 Uhr jede volle Stunde die Temperatur auf.
859-3 Anzahl Werte jede Stunde addieren Summiert von 0:00:00 bis 23:00:00 Uhr jede volle Stunde die Anzahl der Werte auf
Jede volle Stunde wird daraus die Durchschnittstemperatzr berechnet, eigentlich würde es um 23:00:00 reichen (oder um sicher zu gehen, um 23:03:00 Uhr)
Um 23:05 Uhr (also 5 Minuten später) passiert:
859-5 Tagesdurchschnittstemperatur groesser null jeden Tag addieren Summiert täglich jeden Tag um 23:05:00 Uhr den Wert von Helfer 3 (wenn positiv) auf den Wert von Helfer 4; Januarwerte werden mit 0,5, Februarwerte mit 0,75 gewichtet
Das Zurücksetzen folgende Helfer geschieht um 23:10:00 Uhr:
Helfer/Entität/Zurücksetzen
täglich:
1/input_number.859_1_tagestemperatur_summe_jede_stunde/23:10:00 jeden Tag
2/number.859_2_tagesdurchschnittstemperatur/23:10:00 jeden Tag
3/input_number.859_3_werte_summe_jede_stunde/23:10:00 jeden Tag
Nur Ende des Jahres
4/input_number.859_4_summe_tagesdurchschnittstemperaturen_groesser_null/23:10:00, 31. Dezember
5/input_boolean.859_5_gts_erreicht/23:10:00, 31. Dezember
alias 859 Temperatur jede Stunde addieren zuruecksetzen
description
triggers
- trigger time
at 231000
Eigentlich müsste der so aussehen. Keine Ahnung, wie Du das geschafft hast.
alias: 859 Temperatur jede Stunde addieren zuruecksetzen
description: ""
triggers:
- trigger: time
at: "23:10:00"
So hast Du es umgesetzt, ja. Aber warum lässt Du zwischen den Berechnungen 5 oder 10 Minuten verstreichen? Wichtig ist die korrekte Reihenfolge, in der die Berechnungen bzw. das Löschen gemacht werden! 5 oder gar 10 Minuten Pause dazwischen braucht es dafür nicht.
Yap. Sieht aus, als findest Du Dich so langsam zurecht!? Jetzt braucht es “nur noch” Routine und die eine oder andere pfiffige Idee. Die Routine musst Du Dir leider selber aneignen. Mit den pfiffigen Ideen kann ich Dir aber ein bissl weiterhelfen.
Zuerst einmal: einiges an den Automationen lässt sich vereinfachen. Fangen wir mal klein an. Bei diesen beiden Automationen …
triggers und conditions sind identisch, nur die actions sind unterschiedlich. Also kann man auch die zusammenfassen. Außerdem kann man noch ein bißchen was vereinfachen:
states('input_number.859_werte_summe_jede_stunde') | float * 0 ergibt immer 0. Statt der Berechnung kann man dann auch einfach die 0 hinschreiben.
2 Minuten Arbeit und - ZACK - aus 5 Automationen 3 gemacht.
Die 3 übriggebliebenen lassen sich ebenfalls zusammenfassen. Schau Dir doch den Ablauf der 3 Automationen mal ganz genau an. Dann sortieren wir ein wenig um, vereinfachen ein bisschen und fassen hier und da was zusammen:
# 859 ALLES in einer Automation
-- triggers --
jede Stunde
-- conditions --
-- actions --
# Jede Stunde aktuelle Temperatur aufsummieren
wenn akt_Temp > 0 dann
temp_summe = temp_summe + akt_Temp
zähler = zähler + 1
# Um 23 Uhr den Tagesdurchschnitt berechnen
# Diesen Tagesdurchschnitt zum GST addieren
# Summe und Zähler zurücksetzen für nächsten Tag
wenn 23:00
tages_durchschnitt_temp = temp_summe / zähler
wenn januar dann
gst = gst + (0,5 * tages_durchschnitt_temp)
wenn februar dann
gst = gst + (0,75 * tages_durchschnitt_temp)
wenn maerz bis dezember dann
gst = gst + tages_durchschnitt_temp
temp_summe = 0
zähler = 0
# Helfer / Merker setzen, wenn GST groß genug
wenn gst > 150
gst_erreicht = true
# Gaaanz am Ende des Jahres (23 Uhr am letzten Tag)
# alles löschen
wenn 23:00 und letzter Tag des Jahres
temp_summe = 0
zähler = 0
tages_durchschnitt_temp = 0
gst = 0
gst_erreicht = false
Das meiste von dem, was man dafür benötigt, kennst Du bereits und/oder ist in der einen oder anderen Automation zu finden. Für Wenn 23 Uhr reicht das Wenn-dann aus. Aber wenn man Wenn 23 Uhrundletzter Tag des Jahres abfragen möchte? Klick mal in Wenn-dann bei Wenn auf Baustein hinzufügen:
Da klicken wir einfach mal mal drauf. Mit Bedingung hinzufügen kann man nun beliebig viele Bedingungen hinzufügen, die alle erfüllt sein müssen, damit der Dann-Block abgearbeitet wird. Ist auch nur eine der Bedingungen nicht erfüllt, wird der Sonst-Block abgearbeitet.
Ein Hinweis am Rande: man muss nicht zwingend in beiden Blöcken (DannundSonst) Aktionen haben. Wo man welche Aktion einfügt, hängt davon ab, was und wie man abfragt bzw. was man erreichen möchte. Ein paar Beispiele sollten das verdeutlichen:
Wenn es regnet dann nimm den Regenschirm mit sonst
Wenn es nicht regnet dann lass den Regenschirm zu Hause sonst nimm den Regenschirm mit
Wenn es regnet und windig ist dann zieh die Regenjacke an sonst
Für die Abfrage letzter Tag des Jahres müssen wir ein bissl in die Trickkiste greifen. Das gibt es nicht out of the box. Mal schauen, was es so alles gibt:
now().year ergibt das aktuelle Jahr, also 2025.
now()+timedelta(days=1) addiert zu now einen Tag. Das Ergebnis ist dieser Zeitpunkt (jetzt / nun) genau 1 Tag (24 Stunden) später, also 22.10.2025, 22:30 Uhr
Hmmm … das kann man auch kombinieren ( now()+timedelta(days=1) ).year zeigt das Jahr, in welchem der Zeitpunkt jetzt + 1 Tag liegt. Das Ergebnis ist 2025. Nun … das Ergebnis ist immer 2025 - außer für den 31.12., weil der 31.12.2025 + 1 Tag der 01.01.2026 ist. D.h. die Abfrage
now().year != (now()+timedelta(days=1)).year
ergibt immer am 31.12. true, und zwar nur am 31.12.!
Sooo … mit diesen ganzen Infos kannst Du wieder ein wenig weiter basteln. Fragen? Fragen!
Mich hat das auch gewundert, aber das stand so im YAML Code in HA.
Inzwischen habe ich alles kontrolliert und korrigiert.
Und du liegst richtig, ich komme inzwischen echt klar. Tausend Dank für die Geduld und ausführlichen Erklärungen.
Ich habe mir ein Synology NAS für zuhause gekauft und eingebunden.
Das hat in der Integration die Gesamtgröße und den belegten Speicher angezeigt, aber nicht den freien. Ich habe also ein Template gemacht, was die Differenz berechnet. Hat auf Anhieb geklappt.
Danke auch für deinen Input mit dem Zusammenlegen der Automaitisierungen.
Das mit den Pausen habe ich gemacht, damit es sicher klappt. Ich brauche die Werte ja nicht sofort.
Aktuell habe ich keine Fragen. Ich setze das um, was du geschrieben hast und gehe dann daran, das tägliche Rasenwachstum zu berechnen. Ich weiß ja jetzt wie es geht.