Indirekter Zeittrigger mit UNIX Timestamp und Offset

Begonnen von xenos1984, 28 März 2024, 08:47:44

Vorheriges Thema - Nächstes Thema

xenos1984

Folgende Aufgabenstellung: Ich habe ein Device, das zwei Readings liefert, start und end. Beide sind UNIX Timestamps. Dazu habe ich noch ein weiteres Reading offset, das eine Anzahl von Sekunden enthält. Dabei kann offset auch Werte von über 24 Stunden annehmen. Gibt es eine Triggerbedingung, die innerhalb des Zeitintervalls von start - offset bis end wahr ist, und außerhalb nicht, d.h. die zu diesen beiden Zeitpunkten triggert und damit z.B. ein Gerät zu Beginn einschaltet und am Ende wieder ausschaltet?

betateilchen

#1
Zitat von: xenos1984 am 28 März 2024, 08:47:44Beide sind UNIX Timestamps.
...
die zu diesen beiden Zeitpunkten triggert und damit z.B. ein Gerät zu Beginn einschaltet und am Ende wieder ausschaltet?

Warum legst Du nicht einfach zwei at devices an, eines zum Einschalten und eines zum Ausschalten?
Ein at kann out-of-the-box mit einem Unix Timestamp als timespec umgehen.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Damian

#2
Zitat von: xenos1984 am 28 März 2024, 08:47:44Folgende Aufgabenstellung: Ich habe ein Device, das zwei Readings liefert, start und end. Beide sind UNIX Timestamps. Dazu habe ich noch ein weiteres Reading offset, das eine Anzahl von Sekunden enthält. Dabei kann offset auch Werte von über 24 Stunden annehmen. Gibt es eine Triggerbedingung, die innerhalb des Zeitintervalls von start - offset bis end wahr ist, und außerhalb nicht, d.h. die zu diesen beiden Zeitpunkten triggert und damit z.B. ein Gerät zu Beginn einschaltet und am Ende wieder ausschaltet?

Das sollte mit einem Zeitintervall realisierbar sein:

DOIF ([([start]-[offset])-[end]] and ["Trigger"]) (set bla..)
Beim Zeitintervall gibt es immer einen internen Trigger zum Start und zum Ende, wie von dir gewünscht.

Start- bzw. end-Reading musst du allerdings am besten über ein DOIF_Reading in HH:MM wandeln.

Das Ergebnis von start-offset wird immer als Zeitpunkt in der Zukunft interpretieret.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

xenos1984

Zitat von: betateilchen am 28 März 2024, 09:25:00Warum legst Du nicht einfach zwei at devices an, eines zum Einschalten und eines zum Ausschalten?
Ein at kann out-of-the-box mit einem Unix Timestamp als timespec umgehen.

Weil die (vereinfachte) Aufgabenstellung nur ein Teil eines größeren und komplexeren DOIF ist, das noch weitere Zweige hat als nur einen Zeittrigger. U.a. sind es mehrere solche Zeittrigger sowie Zustände die von anderen Readings abhängen.

Zitat von: Damian am 28 März 2024, 10:09:56Das sollte mit einem Zeitintervall realisierbar sein:

DOIF ([([start]-[offset])-[end]] and ["Trigger"]) (set bla..)

Wird damit nicht jeden Tag um die gleiche Zeit getriggert? Also wenn ich z.B. Start heute um 18:00 und Ende morgen um 12:00 hätte, würde es nicht morgen um 18:00 wieder einschalten?

Damian

ja, Zeitintervalle sind täglich . Im DOIF-Perlmodus kannst du das Zeitintervall über eine Variable abfragen.

DOIF {if ([start] and $md eq "0328") {$_mytime=1} elsif  ([end] and $md eq "0401") {$_mytime=undef}}
     {if  ([mytrigger] and defined($_mytime)) {...}}

Im DOIF-FHEM Modus muss man ein zweites DOIF definieren und über Readings beide DOIFs koppeln.

Wie ich dich kenne, wirst du Perlmodus bevorzugen :)
 
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Damian

und wenn du noch einen Zeittrigger zu Beginn und zum Ende benötigst, kannst auch gleich über den Status eines zentralen DOIFs gehen.

di_mytime DOIF ([start] and $md eq "0328") DOELSEIF ([end] and $md eq "0401")
attr cmdState on|off


und dann im Haupt-DOIF abfragen ([mytrigger] and [di_mytime] eq "on") (...)
bei einem reinen Ereignistrigger müsstest du das Intervall noch mal mit or verknüpfen, weil mytrigger dann ja false ist.

([mytrigger] and [?di_mytime] eq "on" or [di_mytime] eq "on") (...)
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

xenos1984

Danke für die Vorschläge!

Statt des "zentralen DOIF" könnte ich doch auch ein DOIF_Readings anlegen, oder? Vorausgesetzt, in DOIF_Readings ließen sich auch Zeittrigger nutzen, und nicht nur Readings.

In dem Fall nutze ich tatsächlich den DOIF-FHEM Modus, weil das DOIF dann automatisch jederzeit einen bestimmten Status hat und nur bei Statuswechsel schaltet (kein do always). Alles auf Perl-Modus umzustellen wäre etwas aufwändiger, aber natürlich auch möglich.

betateilchen

-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

xenos1984

Zitat von: betateilchen am 28 März 2024, 21:46:59Popcorn...

Nein, das ist Ausnahmsweise mal kein Popcorn-Thread, da ich genau weiß, was ich da umsetze und was ich dafür brauche. Es geht in meiner Frage nur darum, welche Triggermöglichkeiten DOIF schon von sich aus bereitstellt. Die dann zu nutzen bekomme ich schon noch hin. Ist ja nicht mein erstes DOIF, weder im FHEM-Modus noch im Perl-Modus.

Damian

Zitat von: xenos1984 am 28 März 2024, 21:45:48Danke für die Vorschläge!

Statt des "zentralen DOIF" könnte ich doch auch ein DOIF_Readings anlegen, oder? Vorausgesetzt, in DOIF_Readings ließen sich auch Zeittrigger nutzen, und nicht nur Readings.

In dem Fall nutze ich tatsächlich den DOIF-FHEM Modus, weil das DOIF dann automatisch jederzeit einen bestimmten Status hat und nur bei Statuswechsel schaltet (kein do always). Alles auf Perl-Modus umzustellen wäre etwas aufwändiger, aber natürlich auch möglich.

Ja, der DOIF-FHEM-Modus hat tatsächlich den Vorteil, dass es (ohne do always) nur einen Trigger beim Zustandswechsel abgibt. Du kannst natürlich, wenn du alles innerhalb eines DOIFs realisieren willst auch ein Reading als Zustand aber auch als Zeittrigger nutzen, z. B.

DOIF {if ([start] and $md eq "0328") {set_Reading("mytime",1,1)} elsif ([end] and $md eq "0401") {set_Reading("mytime",0,1)}
    {if  ([mytrigger] and [?$SELF:mytime,0] == 1 or [$SELF:mytime,0] == 1) {...}}

Die zweite Eins beim set_Reading erzeugt ein Event und die Null hinter mytime ist für den Fall, dass das Reading noch nicht existiert.

Noch eleganter wäre einen Zeittrigger als DOIF_Reading zu generieren, auf den man im gleichen DOIF reagieren könnte, weil man dann keine externen Events produzieren würde, allerdings habe ich bei DOIF_Readings keine Zeittrigger vorgesehen. Das hat hier aber eher einen philosophischen Charakter.

Popcorn ist auch dann gut, wenn man im falschen Film sitzt, den man nicht versteht ;)
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

xenos1984

Na gut, dann werde ich wohl bei Gelegenheit auf DOIF-Perl umstellen. Machbar ist ja fast alles, es braucht nur genug Code dafür :D Danke für die Hilfe.

Stimmt auch wieder, mit dem falschen Film ;)

Damian

Zitat von: xenos1984 am 29 März 2024, 08:13:08Na gut, dann werde ich wohl bei Gelegenheit auf DOIF-Perl umstellen. Machbar ist ja fast alles, es braucht nur genug Code dafür :D Danke für die Hilfe.

Für kleine Aufgaben ist der DOIF-FHEM-Modus oft sogar besser geeignet, wie das reine Bestimmen des Zeitintervalls über den Status des DOIF-Devices in meinem vorletzten Beispiel.

Allerdings würde ich bei mehreren Aufgaben tatsächlich den Perlmodus bevorzugen, denn beim FHEM-Modus wird standardmäßig bei einem Trigger immer nur ein Zweig ausgeführt - es gibt keine unabhängigen Ausführungsblöcke (Zweige) innerhalb eines DOIF-Devices. Und wie in meinem letzten Beispiel im Perl-Modus zu sehen, habe ich zwei Blöcke definiert, die zunächst unabhängig von einander ausgeführt werden können, was im FHEM-Modus nicht möglich wäre. In Wirklichkeit reagiert aber in dem Beispiel der zweite Block auf Events vom ersten, das macht er erst nachdem das System durch das ausgelöste Event des ersten Blocks das DOIF-Device wieder aufruft. Im FHEM-Modus würde auch das als "Selbsttriggerung" unterbunden werden.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Damian

#12
Einen Verbesserungsvorschlag habe ich noch:

DOIF init {if ($hm ge [?start] and $md ge "0328" and $hm le [?end] and $md le "0401") {set_Reading("mytime",1)} else {set_Reading("mytime",0)}}
     {if ([[start]] and $md eq "0328") {set_Reading("mytime",1,1)} elsif ([[end]] and $md eq "0401") {set_Reading("mytime",0,1)}}
     {if ([mytrigger] and [?$SELF:mytime,0] == 1 or [$SELF:mytime,0] == 1) {...}}

Ich habe einen dritten Block definiert. Durch den Namen "init" wird er insbesondere bei der Definition/Neustart ausgeführt, das ist für den korrekten Initialzustand des Zeitintervalls gedacht. Übrigens indirekte Zeittrigger brauchen eine zusätzliche eckige Klammer, damit sie als solche erkannt werden - das habe ich noch korrigiert.

Vielleicht baue ich noch irgendwann Datumsspezifikation mit Uhrzeit für Zeittrigger bzw. Zeitintervalle ein.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

xenos1984

Ja, das stimmt natürlich, dass man im Perl-Modus mehrere Dinge ausführen kann. In meinem Anwendungsfall hatte ich bisher den FHEM-Modus, weil es sich im wesentlichen um einen Zustandsautomaten handelt, der zu jedem Zeitpunkt in einem bestimmten Zustand sein soll, und der beim Zustandswechsel eine Aktion auslöst. Deshalb sind auch alle Bedingungen als Zeitintervalle oder Readings formuliert, statt als Event-Trigger oder einzelne Zeiten.

(Hintergrundinfo: Es geht um die Steuerung der Heizung, bei der ich für jeden Raum über DOIF eine Temperatur vorgebe. Das DOIF hat dabei eine Funktion der Art: "Falls x Stunden vor Rückkehr von Reise: Vorheiztemperatur. Ansonsten, falls derzeit verreist: Heizung aus / Minimaltemperatur. Ansonsten, falls Tag: Tagestemperatur. Ansonsten: Nachttemperatur." Und es ging mir um die Umsetzung des ersten Zweiges, "Vorheizen", bei dem das Intervall von x Stunden (ggf. über Mitternacht) bis zu einem bestimmten Zeitpunkt, der aus meinem Kalender kommt, definiert ist.)

An den Init-Block hatte ich auch schon gedacht :) Den habe ich bei DOIF-Perl bisher immer im Einsatz, um einen definierten Ausgangszustand festzulegen.

Damian

Naja, egal wie komplex die Aufgabenstellung sein mag, es gibt auf jeden Fall genügend Möglichkeiten sie umzusetzen. Im schlimmsten Fall muss man etwas in Perl nachhelfen.

Dennoch bleibt für mich die Prämisse, ein Problem möglichst in einem Device umzusetzen und nicht mehrere Devices zu definieren, die man in ein paar Jahren mühselig zusammensuchen muss, wenn man was ändern will.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF