Hauptmenü

DOIF Zeitberechnung Syntax

Begonnen von errazzor, 26 Oktober 2015, 00:36:12

Vorheriges Thema - Nächstes Thema

errazzor

Hallo,

ich möchte innerhalb eines DOIF ein State (Zeitstempel) auslesen und wenn dieser mehr als 600 Sekunden zurück liegt, soll Aktion X ausgeführt werden.
Allerdings verzweifle ich an der Syntax:


define DOIF_TEST1 DOIF ([Anwesenheit.Dummy] eq "off" and {(time-time_str2num(ReadingsTimestamp("Anwesenheit.Dummy","state",0) > 600))}) (set Test.Dummy on)


Funktioniert nicht, weil laut Logfile:


2015.10.26 00:31:25 1: PERL WARNING: Argument "2015-10-26 00:31:25" isn't numeric in numeric gt (>) at (eval 67324) line 1.
2015.10.26 00:31:25 1: PERL WARNING: Use of uninitialized value in subtraction (-) at (eval 67324) line 1.
2015.10.26 00:31:25 1: PERL WARNING: Odd number of elements in anonymous hash at (eval 67324) line 1.


Ich vermute mal die Klammern stimmen einfach nicht, kann mir jemand weiterhelfen?

Sirel

Hallo Errazzor,
mit Readingstimestamp wird auch das aktuelle Datum zurückgegeben. Damit kann dann das DOIF nichts mehr anfangen (Zeile 1 im Log).
Habe damit auch schon rumexperimentiert, aber keine Lösung für das Problem gefunden.

Max

igami

Warum nutzt du nicht einfach das wait Attribut und spendierst dann noch ein DOELSE?
Pi3 mit fhem.cfg + DbLog/logProxy
Komm vorbei zum FHEM Treffen im Kreis Gütersloh! Das nächste Mal im April 2020.

MAINTAINER: archetype, LuftdatenInfo, monitoring, msgDialog, Nmap, powerMap
ToDo: AVScene, FluxLED

errazzor

#3
Also das mit dem ReadingsTimestamp funktioniert ja soweit, zumindest wenn ich ich den gleichen Befehl in der FHEM Kommandozeile ausführe.

Mit o.g. Befehl bekomme ich die Anzahl Sekunden zurück, welche seit dem Timestamp vergangen sind.
Nur die Verschachtelung in der DOIF-Schleife bekomme ich nicht hin.

Die Fehlermeldung im Log kommt nur, weil die Verschachtelung (Klammern) nicht korrekt ist und FHEM den Befehl somit nicht richtig ausführt.
Aber ich habe bisher nicht herausgefunden, wie die Klammern aussehen müssen, es ist zum wahnsinnig werden.

@igami: Verstehe leider nicht was Du meinst, kannst Du etwas genauer werden?

Sonst jemand noch eine Idee, wie das oben genannte DOIF richtig aussehen müsste?

CoolTux

Mal ab von Deinem Problem. Schreib uns bitte einmal was genau Dein Ziel ist.

Ich sehe in Deinem DOIF kein wirklichen Sinn.


define DOIF_TEST1 DOIF ([Anwesenheit.Dummy] eq "off" and {(time-time_str2num(ReadingsTimestamp("Anwesenheit.Dummy","state",0) > 600))}) (set Test.Dummy on)


Triggert Anwesenheit.Dummy auf off und der Timestamp vom Status Anwenheit ist älter wie +600 dann schalte einen anderen Dummy on???

Mach mal so


define DOIF_TEST1 DOIF ([Anwesenheit.Dummy] eq "off" ) (set Test.Dummy on) DOELSE ()
attr DOIF_TEST1 wait 600


Sollte glaube gehen
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

errazzor

#5
Die DOIF-Abfrage ist nur zu Testzwecken verkürzt und gibt in der o.g. Form tatsächlich keinen Sinn, hier geht es mir nur im die Funktion.

Im Echtbetrieb sind da noch mehr Bedingungen drin, sodaß es Sinn ergibt.

Das Ziel ist das setzen eines Alarm-Dummys auf on, wenn zwei Bewohner abwesend sind und ein Türkontakt geöffnet wird - allerdings nur, wenn der Status des zuletzt gegangenen Bewohners mindestens vor 10 Minuten auf "abwesend" gesetzt wurde und wenn sich kein Bewohner in den nächsten 2 Minuten wieder anmeldet.

Und für das "mindestens seit 10 Minuten abwesend" brauche ich eben den Zeitstempel des Dummys um diesen mit der aktuellen Uhrzeit zu vergleichen.

Daher reicht ein reines wait leider nicht.

Hier mal zur Verdeutlichung mein ( noch nicht funktionierendes) komplettes DOIF:


define DOIF_EG_Alarm_on DOIF ([Anwesenheit.Dummy1] eq "off" and [Anwesenheit.Dummy2] eq "off" and [Status.EG] eq "on" and (time-time_str2num(ReadingsTimestamp("Anwesenheit.Dummy1","state",0) > 600))) (set Alarm.Status.EG on)
attr DOIF_EG_Alarm_on wait 120


--> Wenn Bewohner1 und Bewohner2 "absent" sind und Status.EG (Fenster/Tür offen) auf "on" und Bewohner1 sich vor mehr als 10 Minuten abgemeldet hat, setze Alarm-Dummy auf "on".
Ausführung allerdings erst nach 120 Sekunden (Warteschleife, ob sich in der Zeit ein Bewohner anmeldet)



CoolTux


define DOIF_EG_Alarm_on DOIF ([Anwesenheit.Dummy1] eq "off" and [Anwesenheit.Dummy2] eq "off" and [?Status.EG] eq "on") (set Alarm.Status.EG on)
attr DOIF_EG_Alarm_on wait 300


Getriggert werden nur die Anwesenheitsdummy und es wird als Bedingung geschaut ob Status.EG on ist. Sollte sich innerhalb der nächsten 5 Minuten keine Änderung ergeben wird geschalten.

Davon aber mal ab kannst Du Dir mal Residents und Roommate anschauen. Das ist ein virtuelles zuHause mit Bewohnern. Residents ist das Haus und Roommate sind die Bewohner. Das Haus schaltet sich entsprechend der Schaltung aller Bewohner. Dazu gibt es dann noch fertige Scripte für Abläufe die gestartet werden sollen.

Bsp.:
Bewohner1 ist abwesend und Bewohner2 ist home. Status Residents bleibt home. Bewohner2 ist dann irgendwann auch abwesend Status Residents geht auf abwesend. Bewohner1 kommt Status Residents geht auf home Bewohner2 kommt Status Residents bleibt auf home.

Nun kannst Du ganz einfach Deine Alarmanlage schalten


define doifAlarmScharf DOIF ([Residdents] eq "absent" and [?Status.EG] eq "on") (set alarm on) DOELSE ()
attr doifAlarmScharf wait 600

Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

errazzor

#7
Ja, dein Beispiel hatte ich ja schon funktionierend am laufen, nur fehlt mir da eben die Bedingung "Bewohner seit mindestens 10 Minuten absent" - darum ging es mir hier ja.

Ich glaube ich habe es jetzt aber beim 10000. Versuch wie folgt hinbekommen:


define DOIF_EG_Alarm_TEST DOIF ([Anwesenheit.Dummy] eq "off" and ([{time}]-[{time_str2num(ReadingsTimestamp("Anwesenheit.Dummy","state",0))}] > 600)) (set Alarm.EG on)


Muss das ganze jetzt nur noch im Realbetrieb testen, aber es sieht gut aus :-)

Vielen Dank für den Hinweis auf Residents / Roommate, das schaue ich mir mal an!



AET_FHEM

#8
Wieso macht man das nicht einfach mit einem Watchdog?


define WD_EG_Alarm_TEST  Anwesenheit.Dummy:off 00:10 Anwesenheit.Dummy:on set Alarm.EG on; setstate WD_EG_Alarm_TEST defined

errazzor

Gute Frage, wie würde denn die Umsetzung mit einem Watchdog für das komplette DOIF (siehe unten) aussehen?


define DOIF_EG_Alarm_on DOIF ([Anwesenheit.Dummy1] eq "off" and [Anwesenheit.Dummy2] eq "off" and [Status.EG] eq "on" and ([{time}]-[{time_str2num(ReadingsTimestamp("Anwesenheit.Dummy1","state",0))}] > 600)) (set Alarm.Status.EG on)
attr DOIF_EG_Alarm_on wait 120

AET_FHEM

ja da müssen wir Dummy1 und Dummy2 als struktur anlegen
=> um dummy1 und Dummy2 zu verbinden und eine Meldung draus zu machen

So etwa:
define Familie structure Familie_structure Dummy2 Dummy1
attr Familie clientstate_behavior relative
attr Familie clientstate_priority present absent
attr Familie event-on-change-reading state
attr Familie group Familie
attr Familie room Haus,HomeStatus

und 

define WD_EG_Alarm_TEST  Familie:absent 00:10 Familie:present set Alarm.EG on; setstate WD_EG_Alarm_TEST defined

--> hier sagen wir wenn die Struktur (Dummy1+Dummy2) 10 minuten nicht anwesend sind dann schalte Alarm EG on
=> damit müsste es klappen

CoolTux

Zitat von: errazzor am 26 Oktober 2015, 10:35:44
Ja, dein Beispiel hatte ich ja schon funktionierend am laufen, nur fehlt mir da eben die Bedingung "Bewohner seit mindestens 10 Minuten absent" - darum ging es mir hier ja.

Dein Problem ist das Du null Ahnung hast von DOIF oder es nicht verstehst. Bitte nicht persönlich nehmen aber als Kritik.
Das Ding mit den "Bewohner seit mindestens 10 Minuten absent" ist ja das wait. Das DOIF wird nur geschalten wenn es sich nicht innerhalb der nächsten (bei mir waren es 5 Minuten glaube) ändert wait 300.
Also was stand im DOIF


([Anwesenheit.Dummy1] eq "off" and [Anwesenheit.Dummy2] eq "off" and [Status.EG] eq "on"

Sollten sich diese Zustände in den nächsten 10 Minuten nicht ändern, wird

set Alarm.Status.EG on

geschalten

wait 600 also als attribut

Und ja man kann es auch mit einem watchdog machen. Aber DOIF kann es auch, wenn man versteht wie DOIF funktioniert oder wenigstens versucht sich die commandref mal an zu schauen wo DOIF eines der mit bestens dokumentierten Module ist mit endlos vielen Beispielen.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

CoolTux

#12
Ähm könnten wir mal versuchen das ganze einfach zu halten. Es gibt bereits fertige Module die super tolle Eigenschaften haben mit denen man ein Haus/Wohnung und deren Bewohner darstellen kann. Aber nein stattdessen wird hier mit Dummy und Structure gearbeitet.
Mal so ne Frage, was willst Du dem Threadersteller sagen wenn er kommt mit Weckzeiten, Aufwachschaltungen oder Bettgehschaltungen. Wieder mit Dummy und Structure?

Bitte bitte verwendet doch die schon vorhandenen Möglichkeiten welche eine einfach nachvollziehbare Schaltung möglich machen. Die nächste Frage wäre dann wohl wie funktioniert watchdog.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

errazzor

#13
Zitat von: CoolTux am 26 Oktober 2015, 11:18:42
Dein Problem ist das Du null Ahnung hast von DOIF oder es nicht verstehst. Bitte nicht persönlich nehmen aber als Kritik.
Das Ding mit den "Bewohner seit mindestens 10 Minuten absent" ist ja das wait. Das DOIF wird nur geschalten wenn es sich nicht innerhalb der nächsten (bei mir waren es 5 Minuten glaube) ändert wait 300.
Also was stand im DOIF


([Anwesenheit.Dummy1] eq "off" and [Anwesenheit.Dummy2] eq "off" and [Status.EG] eq "on"

Sollten sich diese Zustände in den nächsten 10 Minuten nicht ändern, wird

set Alarm.Status.EG on

geschalten

wait 600 also als attribut


Tut mir leid, aber Du hast offenbar nicht verstanden, was meine Anforderung ist. Dann gleich in so einem Ton zu antworten naja, ich weiss nicht.
Natürlich habe ich bereits die Commandref bemüht, aber ich habe es bisher trotzdem nicht hinbekommen. Nicht jeder ist ein begnadeter Programmierer.

In deinem Beispiel wird einfach 10 Minuten gewartet ob sich etwas ändert - das habe ich wie bereits geschrieben auch schon hinbekommen.
Allerdings deckt es nicht meine Anforderung wie schon zu Anfang beschrieben ab:

* Es ändert sich innerhalb von 2 Minuten nichts (Bewohner meldet sich nicht an) UND der Bewohner ist seit x Minuten abwesend. Das in Verbindung mit dem "on" Status des Staus-EG-Dummys soll erst das Event auslösen.

Darum doch die ganze Geschichte mit dem Auslesen der zeit des Dummys.

Übrigens funktioniert mein oben gepostetes Beispiel doch noch nicht, irgendwas stimmt mit dem ausgelesenen Wert noch nicht.

Ich poste es gerne nochmal:


define DOIF_EG_Alarm_on DOIF ([Anwesenheit.Dummy1] eq "off" and [Anwesenheit.Dummy2] eq "off" and [Status.EG] eq "on" and ([{time}]-[{time_str2num(ReadingsTimestamp("Anwesenheit.Dummy1","state",0))}] > 600)) (set Alarm.Status.EG on)
attr DOIF_EG_Alarm_on wait 120


Hier ist doch zu sehen, ich habe ein "wait 120" - dieses sorgt dafür, dass das ganze DOIF erst nach 120 Sekunden ausgeführt wird (sprich der Status der Bewohner ändert sich nicht innerhalb dieser Zeit).

So..ändert sich der Bewohnerstatus innerhalb 120 Sekunden nicht, soll der Alarm auch nur dann auf "on" gesetzt werden, wenn der Bewohner schon seit mehr als 10 Minuten abwesend ist.

Das ist alles. Nur wie gesagt, bisher funktioniert der zeitvergleich noch nicht, der zeitvergleich ist offenbar nicht plausibel. "> 600" wird nicht korrekt umgesetzt, auch wenn der Rückgabewert beispielsweise 9130 ist. Ändere ich es in "< 600" löst der Alarm aus, obwohl der Rückgabewert wie gesagt 9130 ist. Irgendwas stimmt da noch nicht.

CoolTux

#14
Das ist mir zu hoch. Sorry aber ich verstehe Dich nicht. Tut mir leid. Ich glaube das ich alles gegeben habe um genau Deine eben noch mal beschriebende Anforderung zu erfüllen. Aber so wie es scheint habe ich Dich in der Tat nicht korrekt verstanden.


define DOIF_EG_Alarm_on DOIF ([Anwesenheit.Dummy1] eq "off" and [Anwesenheit.Dummy2] eq "off" and [?Status.EG] eq "on") (set Alarm.Status.EG on)
attr DOIF_EG_Alarm_on wait 120


Dummy1 und Dummy2 lösen das DOIF aus. Bedingung ist das Dummy1 und Dummy2 off sind und Status.EG on ist. Wird alleine diese Bedingung nicht erfüllt wird nichts gemacht. Wird die Bedingung erfüllt, wird 120 Sekunden gewartet ob sich Dummy1 oder Dummy2 nicht doch wieder mit einem on melden, melden sie sich nicht mit einem on innerhalb der nächsten 120 sekunden wird der Alarm auf on gesetzt, wenn sich doch etwas tut und Dummy1 oder 2 bekommen ein on wird nichts gemacht.

Sollte das hier jetzt nicht das sein was Du wolltest, dann habe ich Deine Anforderung falsch verstanden und dann entschuldige ich mich dafür.

Hier Beispiele aus der Comandref

define di_washer DOIF ([power:watt]<2) ({system("wmail washer finished")})
attr di_washer wait 300

Eine erneute Benachrichtigung wird erst wieder ausgelöst, wenn zwischendurch der Verbrauch über 2 Watt angestiegen war.

Anwendungsbeispiel: Rolladen um 20 Minuten zeitverzögert bei Sonne runter- bzw. hochfahren (wenn der Zustand der Sonne wechselt, wird die Verzögerungszeit zurückgesetzt):

define di_shutters DOIF ([Sun] eq "on") (set shutters down) DOELSE (set shutters up)
attr di_shutters wait 1200:1200



Zitat
Bewohner ist seit x Minuten abwesend

Ist es nicht logisch das der Bewohner 120 Sekunden abwesend ist wenn der Alarm geschalten wird, wenn zwischen dem Trigger Bewohner off und dem wait von 120 Sekunden geschalten wird?

Ich versuche Dich ernsthaft zu verstehen, also Dein Anliegen.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net