Hallo zusammen,
Ich habe eine kleine Knobelaufgabe. O:-)
Für meine Markisensteuerung erkenne ich mit einem Windmesser die Windgeschwindigkeit und -böen. Sind die Böen zu heftig fahren die Markisen ein. Soweit so gut. Nun fahren sie aber auch automatisch aus und das würde ich gerne davon abhängig machen, dass die letzte Überschreitung der zulässigen Windböen mindestens x Sekunden zurück liegt.
Dazu habe ich bereits bei den Windböen ein userReading eingerichtet, welches nur dann aktualisiert wird, wenn der Schwellwert überschritten wird. Das funktioniert wie gewünscht. Das userReading und dessen Zeitstempel werden nur aktualisiert, wenn die maximal zulässige Geschwindigkeit überschritten wird.
Nun dachte ich, die Bedingung [Windmesser:letzteUberschreitung:sec]>300 in der Ausfahr-DOIFwürde die Markisen fahren, sofern die letzte Überschreitung mehr als 5 Minuten zurück liegt und alle anderen Bedingungen (es sind eine Menge) erfüllt sind.
Dem ist aber nicht so. Wie ich inzwischen verstanden habe liegt das daran, dass [Windmesser:letzteUberschreitung:sec] nur dann aktualisiert wird, wenn [Windmesser:letzteUberschreitung] aktualisiert wird. Genau das soll ja aber nicht passieren.
Frage 1: Wie kann ich sicherstellen, dass [Windmesser:letzteUeberschreitung:sec] neu berechnet wird, wenn in meinem DOIF andere Readings (Bedingungen) aktualisiert werden?
Frage 2: Gibt es vielleicht einen besseren Weg, das Ziel zu erreichen?
Vielen Dank für euren Input!
Du kannst die Überschreitung in der Bedingung angeben und ein wait-Attribut auf die Anweisung setzen.
z. B.
DOIF ([wind:boehen] > 100) (set bla on)
attr wait 300
Das funktioniert so leider nicht. Das DOIF wird mit weiteren Werten gefüttert:
- Aktuelle Markisenposition
- Zielposition abhängig vom Sonnenstand (mit AstroDaten berechnet)
- gemessene aktuelle Helligkeit
Die Markisen sollen immer dann fahren, wenn
- Eine gewisse Helligkeit überschritten ist UND
- Die Differenz zwischen aktueller und Zielposition einen Schwellwert überschreitet (damit sie nicht ständig fahren) UND
- Seit x Sekunden keine Böe über dem Grenzwert geweht hat
Die ersten beiden funktionieren tadellos. Nur beim letzten klemmt es. Es muss eben bei jeder Aktualisierung der anderen Werte geprüft werden, ob (3) erfüllt ist und zwar aktuell. Deswegen der Gedanke mit :sec, der aber nicht funktioniert.
Zitat von: FlyingPenguin am 08 August 2025, 08:44:46Das funktioniert so leider nicht. Das DOIF wird mit weiteren Werten gefüttert:
- Aktuelle Markisenposition
- Zielposition abhängig vom Sonnenstand (mit AstroDaten berechnet)
- gemessene aktuelle Helligkeit
Die Markisen sollen immer dann fahren, wenn
- Eine gewisse Helligkeit überschritten ist UND
- Die Differenz zwischen aktueller und Zielposition einen Schwellwert überschreitet (damit sie nicht ständig fahren) UND
- Seit x Sekunden keine Böe über dem Grenzwert geweht hat
Die ersten beiden funktionieren tadellos. Nur beim letzten klemmt es. Es muss eben bei jeder Aktualisierung der anderen Werte geprüft werden, ob (3) erfüllt ist und zwar aktuell. Deswegen der Gedanke mit :sec, der aber nicht funktioniert.
Dann packe alles, was du brauchst in die Bedingung, nur die Zeitbedingung kommt ins wait.
ZitatEs muss eben bei jeder Aktualisierung der anderen Werte geprüft werden, ob (3) erfüllt ist und zwar aktuell. Deswegen der Gedanke mit :sec, der aber nicht funktioniert.
ReadingsAge(device,reading,default)
liefert Sekunden seit der letzten Aktualisierung.
Zitat von: erwin am 08 August 2025, 09:50:24ZitatEs muss eben bei jeder Aktualisierung der anderen Werte geprüft werden, ob (3) erfüllt ist und zwar aktuell. Deswegen der Gedanke mit :sec, der aber nicht funktioniert.
ReadingsAge(device,reading,default)
liefert Sekunden seit der letzten Aktualisierung.
Das klingt genau nach dem, was ich brauche. Funktioniert aber trotzdem nicht. :'(
Hier mal das ganze DOIF:
defmod Balkonschatten DOIF ([AstroDaten:SunBlindTarget]!=[io_homecontrol_0:pct] and [Wetterstation:brightness.av]>37000 and ([AstroDaten:SunBlindTarget]==0 or abs([AstroDaten:SunBlindTarget]-[io_homecontrol_0:pct])>5) and ReadingsAge('Wetterstation','windGusts_overLimit','')>300) (set io_homecontrol_0 pct [AstroDaten:SunBlindTarget])
attr Balkonschatten checkall event
attr Balkonschatten cmdpause 30
attr Balkonschatten do always
[Wetterstation:windGusts_overLimit] wurde zum letzten Mal vor über 10 Minuten (600 Sekunden) aktualisiert, die Positionsdifferenz ist groß genug, die Helligkeit ist auch über dem Schwellwert, aber es bewegt sich nichts.
Entweder hab ich die Anforderung nicht kapiert oder Deine Formulierung ist falsch.
Warum sollte es mit dem Attribut Wait nicht funktionieren ?
Leider fehlt das List von "Wetterstation". Was steht denn dort im Reading "windGusts_overLimit" drin, doch wohl nicht immer der gleiche Wert ?
defmod Balkonschatten DOIF (
[AstroDaten:SunBlindTarget] != [io_homecontrol_0:pct] &&
[Wetterstation:brightness.av] >37000 &&
[Wetterstation:windGusts_overLimit] eq <???> &&
( [AstroDaten:SunBlindTarget] == 0 ||
abs( [AstroDaten:SunBlindTarget] - [io_homecontrol_0:pct]) > 5 ) )
(set io_homecontrol_0 pct [AstroDaten:SunBlindTarget])
attr Balkonschatten checkall event
attr Balkonschatten do always
attr Balkonschatten wait 300
Zitat von: JudgeDredd am 08 August 2025, 16:33:59Entweder hab ich die Anforderung nicht kapiert oder Deine Formulierung ist falsch.
Warum sollte es mit dem Attribut Wait nicht funktionieren ?
Leider fehlt das List von "Wetterstation". Was steht denn dort im Reading "windGusts_overLimit" drin, doch wohl nicht immer der gleiche Wert ?
Der Wert in "windGusts_overLimit" ist irrelevant. Dort wird bei jeder Überschreitung (und nur dann) die Geschwindigkeit der Windböe geschrieben. Es geht einzig um den Zeitpunkt, wann dies eingetroffen ist.
Wenn ich nicht einen riesen Denkfehler habe, dann verzögert "wait" die Ausführung des Befehls. Wenn also alle Bedingungen erfüllt sind, wartet das DOIF 300 Sekunden bis der Befehl ausgeführt wird. Das ist aber nicht die Anforderung.
Mir geht es darum sicherzustellen, dass in den letzten 300 Sekunden keine Windböe über dem Schwellwert lag. Es können auch 3 Tage sein, wenn kein Wind geht. Dennoch soll das DOIF jedes Mal bei aktualisierten anderen Werten ausgeführt werden, wenn die Böe lange genug zurück liegt. Das geht nach meinem Verständnis mit "wait" nicht, da wird nicht das Alter eines Readings geprüft, sondern einfach abgewartet.
Zur Erklärung der Werte in "Wetterstation": Dort gibt es den Messwert "windGusts", der ca. alle 30 Sekunden aktualisiert wird und die stärkste Böe in diesem Zeitraum zurück liefert. Bei vollkommener Windstille ist der Wert immer 0, meistens kommen Werte zwischen 1 und 3 m/s raus. Die Markisen fahren automatisch ein, wenn "windGusts" einen Wert von 5.6 m/s überschreitet. Dazu gibt es ein anderes DOIF namens "Windschutz". Böen haben es so an sich, dass sie kurz da sind und dann erst mal weg. Deswegen hatte ich bisher eine Hysterese umgesetzt, sprich die Markisen fahren bei einer Böe über 5,6 m/s rein und "Balkonschatten" wird erst wieder aktiv, wenn "windGusts" kleiner 3 m/s ist. Leider führt das dennoch häufig dazu, dass die Markisen ständig ein- und wieder ausfahren.
Deshalb die Anforderung nicht den Wert, sondern den Zeitstempel der Überschreitung zu verwenden. Damit sollten die Markisen einfahren und erst dann wieder ausfahren, wenn sich der Wind insgesamt beruhigt hat, also mindestens 5 Minuten keine Überschreitung mehr vorgekmmen ist. Dazu habe ich "Wetterstation" mit einem userReading namens "windGusts_overLimit" ergänzt. Dieses wird immer dann aktualisiert, wenn "windGusts" eine Böe über 5,6 m/s (oder testweise ein anderer Wert) registriert. Das funktioniert auch und das Reading hat den passenden Zeitstempel.
Was nicht funktioniert ist diesen Zeitstempel in "Balkonschatten" korrekt auszuwerten.
ZitatDer Wert in "windGusts_overLimit" ist irrelevant. Dort wird bei jeder Überschreitung (und nur dann) die Geschwindigkeit der Windböe geschrieben. Es geht einzig um den Zeitpunkt, wann dies eingetroffen ist.
Hier liegt wahrscheinlich das Problem. Du solltest in dieses Reading nur 0 (wenn Böe<Limit) oder 1 (wenn Böe>=Limit) schreiben. Zusätzlich muss für das Reading die Attribute timestamp-on-change-reading und event-on-change-reading gesetzt werden. Dann sollte readingsAge funktionieren.
ZitatDie Markisen sollen immer dann fahren, wenn
1) Eine gewisse Helligkeit überschritten ist UND
2) Die Differenz zwischen aktueller und Zielposition einen Schwellwert überschreitet (damit sie nicht ständig fahren) UND
2) Seit x Sekunden keine Böe über dem Grenzwert geweht hat
Wenn man die dritte Bedingung ändert in "keine Böe" dann sind drei Bedingungen, die erfüllt werden müssen, damit die Markise
ausfährt. Dh. sobald alle drei erfüllt sind, wird der Timer gesetzt zum Fahren, wenn nun irgend eine der drei Bedingungen sich ändert, insb. eine Windböe kommt, dann wird die gesamte Bedingung nicht mehr erfüllt werden und der Timer wird abgebrochen - das Device geht in den DOELSE-Zweig, bei erneuter Erfüllung aller drei Bedingungen beginnt das Spiel von vorne. Mit dieser Lösung wartet man ggf. unnötig 300 Sekunden, wenn die letzte Böe z. B. vor drei Tagen war, passt aber zu Überschrift: "DOIF nur ausführen, wenn Messwert mindestens x Sekunden zurück liegt"
Du kannst natürlich auch den letzten Zeitpunkt der Böe abfragen. Dann darf diese aber nicht triggern, also mit [?böe:state:sec] > 300. Das entspricht übrigens einer readingsAge-Abfrage. Dann hast du aber das Problem (ohne do always), wenn die anderen Bedingung wahr werden und die letzte Böe vor weniger als 300 Sekunden war, dann passiert nichts und später auch nicht mehr, weil die letzte Böe wegen der Zeitabfrage nicht triggern darf.
Edit: Es wird allerdings dann funktionieren, wenn die ersten beiden Bedingungen wiederholend triggern.
Ich würde die erste Lösung nehmen. do always sollte man rausnehmen, damit nicht ständig unnötig geschaltet wird.