Hallo,
um mich mit dem ungemein mächtigen DOIF vertraut zu machen habe ich versucht einen counter in Abhängigkeit von einem Schalter hoch und runterzählen zu lassen.
Bevor die Frage kommt, das ist jetzt nur um mich erst mal mit Fhem allgemein, mit dem Syntax und den einzelnen Modulen vertraut zu machen.
Also ich habe einen dummy Schalter namens "Schalter" erstellt, mit den webCmd ON:OFF.
dann einen dummy namens "count", der den aktuellen zählwert enthält.
dann ein DOIF namens di_count_UPDN, welches dann die arbeit macht :-)
hier die RAW Definition von dem DOIF:
Zitat
defmod di_count_UPDN DOIF ([Schalter] eq "on" && [count] < 1)\
(\
set count {([count]+1)};;\
set BadHeizung_Clima ValvePosition [count];;\
) DOELSE ([Schalter] eq "off" && [count] > 0)\
(\
set count {([count]-1)};;\
)\
attr di_count_UPDN do resetwait
attr di_count_UPDN repeatcmd 0.2
attr di_count_UPDN repeatsame 100
attr di_count_UPDN room counter
setstate di_count_UPDN initialized
setstate di_count_UPDN 2019-05-17 12:10:18 cmd 0
setstate di_count_UPDN 2019-05-17 12:10:18 mode enabled
setstate di_count_UPDN 2019-05-17 12:10:18 state initialized
das Problem ist fogendes:
Wenn count = 0 und ich schalte den Schalter auf ON, dann wird hochgezählt...super.
Wenn aber count > 0 ist und ich den Schalter auf OFF schalte, dann wird count immer nur um 1 verringert??
Das verstehe ich nicht so ganz. Warum wird denn da nicht, genau wie anders herum, heruntergezählt ??
Verstehe ich da noch etwas an dem DOELSE falsch ?
Ich hab das ganze mit zwei DOIF's , eins für UP und eins für DOWN mit den gleichen einstellungen versucht, da funtioniert es. NUr wenn ich beides in ein DOIF machen will, dann funktioniert es nicht.
Hier noch die RAW von den beiden DOIF's für UP und DN getrennt:
UP:
Zitat
defmod di_count_UP DOIF ([Schalter] eq "on" && [count] < 1)\
(\
set count {([count]+1)};;\
set BadHeizung_Clima ValvePosition [count];;\
)\
attr di_count_UP do resetwait
attr di_count_UP repeatcmd 0.2
attr di_count_UP repeatsame 100
attr di_count_UP room counter
setstate di_count_UP 2019-05-17 11:35:33 Device count
setstate di_count_UP 2019-05-17 11:34:24 cmd 1
setstate di_count_UP 2019-05-17 11:34:24 cmd_event count
setstate di_count_UP 2019-05-17 11:34:24 cmd_nr 1
setstate di_count_UP 2019-05-17 11:35:04 e_Schalter_STATE off
setstate di_count_UP 2019-05-17 11:35:33 e_count_STATE 0
setstate di_count_UP 2019-05-17 11:49:06 last_cmd cmd_1
setstate di_count_UP 2019-05-17 11:49:06 mode disabled
setstate di_count_UP 2019-05-17 11:49:06 state disabled
setstate di_count_UP 2019-05-17 11:34:24 wait_timer no timer
DN:
Zitat
defmod di_count_DN DOIF ([Schalter] eq "off" && [count] > 9)\
(\
set count {([count]-1)};;\
)
attr di_count_DN do resetwait
attr di_count_DN repeatcmd 0.2
attr di_count_DN repeatsame 100
attr di_count_DN room counter
setstate di_count_DN disabled
setstate di_count_DN 2019-05-17 11:35:04 Device Schalter
setstate di_count_DN 2019-05-17 11:35:33 cmd 1
setstate di_count_DN 2019-05-17 11:35:33 cmd_event Schalter
setstate di_count_DN 2019-05-17 11:35:33 cmd_nr 1
setstate di_count_DN 2019-05-17 11:35:04 e_Schalter_STATE off
setstate di_count_DN 2019-05-17 11:34:24 e_count_STATE 100
setstate di_count_DN 2019-05-17 11:48:55 last_cmd cmd_1
setstate di_count_DN 2019-05-17 11:48:55 mode disabled
setstate di_count_DN 2019-05-17 11:48:55 state disabled
setstate di_count_DN 2019-05-17 11:35:34 wait_timer no timer
Ich wäre euch für eine kurze Hilfe dankbar, jeder hat ja mal angefangen und ich stehe leider noch ganz am Anfang :-)
Matthias
Dein DOELSE ist eher ein DOELESEIF ;)
Solche Aufgaben kann man besser im DOIF-Perl-Modus lösen. Dort kannst du mit echten Instanzvariablen arbeiten, deren Zugriffe wesentlich performanter sind als über Dummys (hier: count).
Hallo,
danke für die Antwort.
Ich muss ja irgendwo anfangen, und da wollte ich nicht gleich auch noch mit pearl anfangen und es geht mir ja auch darum erst mal das DOIF zu verstehen.
Eigentlich hieß das auch DOELSEIF, da hatte ich wohl gerade etwas ausprobiert, als ich den Code hier reinkopiert hatte.
Auf jeden fall geht es auch damit nicht.
Ich verstehe nicht warum der das nur einmal macht und nicht genauso wie im DOIF ([Schalter] eq "on" && [count] < 1)?
Das komische ist ja, das er auch in der DOELSEIF ankommt. Sieht man , das dann immer "cmd_2" kommt.
Aber warum zählt er denn nich von 100 bis 0, sondern bei jedem klick auf Schalter immer nur um 1 herunter ??
Matthias
repeatcmd 0.2:0.2
repeatsame 100:100
Ahh, super...funktioniert.
Schön wäre noch zu wissen wo sowas steht?
Entweder habe ich es überlesen oder es steht wirklich nirgends (glaube ich nicht, denn die Erklärungen sind eigentlich recht gut.), das man das so machen muss.
Matthias
Im CommandRef
ZitatWiederholungen der Ausführung von Kommandos werden pro Befehlsfolge über das Attribut "repeatcmd" definiert. Syntax:
attr <DOIF-modul> repeatcmd <Sekunden für Befehlsfolge des ersten DO-Falls>:<Sekunden für Befehlsfolge des zweiten DO-Falls>:...
ZitatMit dem Attribut repeatsame <maximale Anzahl von cmd_1>:<maximale Anzahl von cmd_2>:... wird die maximale Anzahl hintereinander folgenden Ausführungen festgelegt.
Jetzt warte ich auf eine andere Frage ;) Ich vermute, das funktioniert immer noch nicht ganz, wie Du es möchtest...
Danke, ach so ist das gemeint...naja, wenn man das erst mal verstanden hat, dann gehts.
Ich glaube du wartest auf die Frage was passiert, wenn count nicht auf 100 steht, wenn man den Schalter auf OFF stellt um herunter zu zählen...
und du hast Recht...ist mir auch schon aufgefallen.
Der zählt ja dann in den Minus bereich herein.
in DOESEIF steht zwar "DOELSEIF ([Schalter] eq "off" && [count] > 0)", aber das hat ja damit nichts zu tun.
Man müsste also irgendwie eine Abbruch Abfrage für das repeatCmd haben.... keine Ahnung, aber das kostet mich sicher wieder eine Nach :-)
Matthias
ZitatIch glaube du wartest auf die Frage was passiert, wenn count nicht auf 100 steht, wenn man den Schalter auf OFF stellt um herunter zu zählen...
und du hast Recht...ist mir auch schon aufgefallen.
Der zählt ja dann in den Minus bereich herein.
Ganz genau ;) Und über 100 kann er auch gehen
Die Bedingungen werden nicht bei jeder Iteration wieder bewertet, sondern die Befehle einfach wiederholt. Bis ein Trigger kommt. Da standardmässig ein DOIF sich selbst nicht triggert, bleibt nur [Schalter], um ein Zustandswechsel zu produzieren. [count] hat keinen Einfluss mehr.
Ich würde es so machen:
defmod di_count_UPDN DOIF ([Schalter] eq "on" and [count] < 100)\
(set count {([count]+1)})\
DOELSEIF ([Schalter] eq "off" and [count] > 0)\
(set count {([count]-1)})\
attr di_count_UPDN do resetwait
attr di_count_UPDN room counter
attr di_count_UPDN selftrigger wait
attr di_count_UPDN wait 0.2:0.2
Hallo,
irgendwie scheint es das noch nicht zu sein.
Ich hab die definition so geändert, aber er zählt immer noch "drüber":
Zitat
defmod di_count_UPDN DOIF ([Schalter] eq "on" && [count] < 1 && [count] < 99)\
(\
set count {([count]+1)};;\
# set BadHeizung_Clima ValvePosition [count];;\
) DOELSEIF ([Schalter] eq "off" && [count] > 0)\
(\
set count {([count]-1)};;\
)\
attr di_count_UPDN do resetwait
attr di_count_UPDN repeatcmd 0.2:0.2
attr di_count_UPDN repeatsame 100:100
attr di_count_UPDN room counter
attr di_count_UPDN selftrigger wait
attr di_count_UPDN wait 0.2:0.2
hmm....
Matthias
repeatsame und repeatcmd weg
Und "[count] < 1 && [count] < 99" ist falsch. Es muss nur "<100" (oder "< 99") sein, sonst zählt er nicht mehr hoch
Das hattest du aber selbst so geschrieben...sorry.
Ausserdem zählt er so nicht, wenn ich das beides rausnehme:
Zitat
defmod di_count_UPDN DOIF ([Schalter] eq "on" and [count] < 100)\
(set count {([count]+1)})\
DOELSEIF ([Schalter] eq "off" and [count] > 0)\
(set count {([count]-1)})\
attr di_count_UPDN do resetwait
attr di_count_UPDN room counter
attr di_count_UPDN selftrigger wait
komisch
Die Skriptsprache von FHEM ist keine universelle Programmiersprache und hat keine konsistente Syntax. Das bedeutet: Es ist ein vollkommen verfehlter Ansatz, damit komplexere Programmlogik (und das beginnt schon bei diesem "Zähler"...) realisieren zu wollen. So etwas sollte immer in Perl realisiert werden - wie man übrigens auch an den Tipps ablesen kann, DOIF im Perl-Modus zu verwenden...
Also, konstruktiver Vorschlag: Perl lernen und dann so etwas wie "Zähler" realisieren.
LG
pah
Hallo,
danke für den Hinweis, das mach ich auch.
Wie oben geschrieben, das war nur mal ein Versuch um das DOIF erst mal zu verstehen und ein bisschen zu probieren.
Irgendwo muss man ja anfangen :-)
Pearl kommt natürlich auch noch zum Einsatz, wobei es da etwas schwieriger wird, damit FHEM nicht blockiert wird.
Das hatte ich schon mal bei was anderem probiert und kenne ich auch aus C#. Da muss man auch immer aufpassen, das einem die HUI nicht einfriert.
Matthias
In FHEM sind 0,2 Sekunden schon recht knapp. Welche praktische Anwendung könnte diese Aufgabe haben? Evtl. sanftes Ein- oder Ausschalten einer Lampe über einen Dimmer. Das allerdings über FHEM zu realisieren, ist keine gute Idee, denn man produziert sehr viel Traffic, der je nach Aktor (z. B. bei HM) schnell zu einer Blockade (ein-Prozent-Regel) führt. Die Lösung für solche Aufgaben sollte, ja muss im Aktor (hier Dimmer) selbst bereits realisiert sein. Allein ein simples Blicken ist besser im Aktor aufgehoben, als es in FHEM nachzubilden.
Ich würde mich eher an den Beispielen in der Commandref zu DOIF orientieren, die ja einen sinnvollen praktischen Hintergrund haben. Und wie gesagt, wenn du Programmiererfahrung hast, dann schau dir Perl (nicht Pearl) genauer an, denn das wirst du in FHEM überall brauchen.
Zitat von: mroschk am 18 Mai 2019, 00:43:01
Das hattest du aber selbst so geschrieben...sorry.
Ausserdem zählt er so nicht, wenn ich das beides rausnehme:
komisch
Naja... für die nicht funktionierende Lösung ja. Aber dann habe ich geschrieben:
defmod di_count_UPDN DOIF ([Schalter] eq "on" and [count] < 100)\
(set count {([count]+1)})\
DOELSEIF ([Schalter] eq "off" and [count] > 0)\
(set count {([count]-1)})\
attr di_count_UPDN do resetwait
attr di_count_UPDN room counter
attr di_count_UPDN selftrigger wait
attr di_count_UPDN wait 0.2:0.2
Also... so wie es hier steht. Nur das, und genau das (cf. wait Attribute) und es sollte funktionieren. Wenn Du improvisierst... kann ich die Ergebnisse nicht garantieren...
Und da Du verstehen möchtest, die Erklärung:
mit "selftrigger wait" triggert [count] auch. Das heisst, jedes Mal wenn [count] sich ändert, wird die Bedingung wieder getestet. Deswegen brauchst Du nur noch die Grenzen in der Bedingungen
Mit "wait 0.2:0.2" sind die Befehle jedes Mal 0.2 Sek verzögert
Somit die Logik: "wenn [count] oder [Schalter] sich ändert, prüfe die Bedingungen, warte 0.2s und führe entspr. einen Befehl aus.. was dazu führt, [count] neu zu kalkulieren... was wieder zum Anfang bringt, da [count] triggert.
Deswegen braucht man jetzt weder repeatcmd noch repeatsame: wird durch Triggern von [count] ersetzt
Für die konkrete Anwendung davon, bin ich davon ausgegangen, dass es nur zum Testen war, und das Du zukünftig z.B. eher 60s oder so haben wirst. Sonst siehe Anmerkung von Damian. Wegen 'Perl Modus' kann ich nicht wirklich helfen, da ich in der DOIF-Perl Syntax noch keine Zeit investiert habe. Ich schaffe bisher alles was ich brauche mit "normalem" DOIF-Modus
Hallo,
ja genau, funktioniert super!
Danke dir/euch für die Hilfe !
Wieder was gelernt :-)
Jetzt werd ich mal schauen wie ich das mit Pearl hinbekomme :-)
Matthias
Hier ein Beispiel wie man diese Aufgabe in DOIF-Perl-Mode umsetzen kann:
define di_count DOIF
subs { # Deklaration von Funktionen
sub count_inc { #Funktion zum hochzählen
if ($_count < 10) {
$_count++; # zähle Instanzvariable $_count eins hoch
set_Reading("count",$_count,1); # setze Reading count
set_Exec("timer",1,"count_inc"); # Funktion ruft sich selbst auf in einer Sekunde
}
}
sub count_dec { #Funktion zum runterzählen
if ($_count > 0) {
$_count--;
set_Reading("count",$_count,1);
set_Exec("timer",1,"count_dec")
}
}
}
## BLock reagiert auf Trigger von Schalter und ruft ggf. Funktion count_inc auf
{if ([Schalter] eq "on" and $_count < 100) {count_inc()}}
## BLock reagiert auf Trigger von Schalter und ruft ggf. Funktion count_dec auf
{if ([Schalter] eq "off" and $_count > 0) {count_dec()}}
Im Reading count von di_count kann man sehen, was passiert.
An diesem Beispiel sieht man, wie man im DOIF-Perl-Mode:
- Trigger-Blöcke definiert
- eigene Funktionen programmiert
- eigene Funktionen sich über Timer selbst aufrufen können
- Device-Variablen (Instanzvariablen) nutzt ($_count)
- Perl nutzt, Angaben in eckigen Klammern stellen hier einer Erweiterung der Perl-Syntax um Trigger dar, diese gibt es im reinen Perl so natürlich nicht
- ohne FHEM-Befehle auskommt, der FHEM-Parser wird zur Laufzeit gar nicht in Anspruch genommen
- ohne Attribute auskommt
Hallo,
wow, was für eine SUPER Erklärung mit Kommentaren !!
Das werd ich vielleicht nachher noch ausprobieren.
Ich danke dir sehr !!
Matthias
Moin,
müsste es hier
sub count_inc { #Funktion zum hochzählen
if ($_count < 10) {
$_count++; # zähle Instanzvariable $_count eins hoch
nicht auch <100 heißen?
LG
Andreas
OT
Könnte man das nicht so auch als 'Eieruhr' nutzen?
ja egal, sind doch nur Testwerte.
aber Eieruhr klingt gut :-)
Matthias
10 war Absicht, sonst muss man zu lange warten, bis man beim höchsten Wert ankommt. Es sind auch nicht 0.2 Sekunden ;)
Hallo,
im Umzugsstress hatte ich kurz zeit das DOIF mit Pearl zu testen.
Was genau soll denn diese Zeile machen?
set_Reading("count",$_count,1); # setze Reading count
ich hab mal noch ein fhem"set count $_count" in das DOIF aufgenommen, damit wird das state von dem dummy namens "count" gesetzt.
Soll die das Reading ( also state ) von dem dummy "count" setzen ? Falls ja, dann funktioniert das nicht.
Zweite Frage: Woher kommt denn $_count ? Das wird ja nirgends definiert.
Dank euch für die Hilfe.
Matthias
ZitatPearl
::)
Freundlicher Hinweis: Bei Pearl handelt es sich um eine
ANDERE Programmiersprache als die für FHEM verwendete Sprache
Perlpah
Zitat von: mroschk am 20 Mai 2019, 10:32:06
Hallo,
im Umzugsstress hatte ich kurz zeit das DOIF mit Pearl zu testen.
Was genau soll denn diese Zeile machen?
set_Reading("count",$_count,1); # setze Reading count
ich hab mal noch ein fhem"set count $_count" in das DOIF aufgenommen, damit wird das state von dem dummy namens "count" gesetzt.
Soll die das Reading ( also state ) von dem dummy "count" setzen ? Falls ja, dann funktioniert das nicht.
Zweite Frage: Woher kommt denn $_count ? Das wird ja nirgends definiert.
Dank euch für die Hilfe.
Matthias
Ich zitiere mal:
ZitatIm Reading count von di_count kann man sehen, was passiert.
Zum Thema Instanzvariablen im DOIF-Perl-Mode und dass man sie nicht definieren muss, kann man hier nachlesen: https://fhem.de/commandref_DE.html#DOIF_Device-Variablen
oh, ich muss besser lesen...SORRY !!
Danke nochmal
Matthias
Nebenbei:
Bei meinem Beispiel kommt man auch mit einem Ereignisblock aus, da der Trigger der selbe ist.
Statt:
## BLock reagiert auf Trigger von Schalter und ruft ggf. Funktion count_inc auf
{if ([Schalter] eq "on" and $_count < 100) {count_inc()}}
## BLock reagiert auf Trigger von Schalter und ruft ggf. Funktion count_dec auf
{if ([Schalter] eq "off" and $_count > 0) {count_dec()}}
lässt sich auch definieren:
{if ([Schalter] eq "on" and $_count < 100) {count_inc()} elsif ([Schalter] eq "off" and $_count > 0) {count_dec()}}
Hallo,
ahh, ok...probier ich, wenn ich meinen Raspi wieder in Stellung gebracht habe :-)
Matthias
Zitat von: mroschk am 18 Mai 2019, 09:03:07
Das hatte ich schon mal bei was anderem probiert und kenne ich auch aus C#. Da muss man auch immer aufpassen, das einem die HUI nicht einfriert.
oha.... wie kommst du zu dieser annahme??