Hallo lb Gemeinde:
Ich habe es bis jetzt geschafft, meine 10 Rollläden halbwegs komfortabel über mein Tablett zu steuern. (Raspberry PI)
Auch kann ich schon über 1Wire die Außentemperatur (T_schatten) und die Temp. in meinem sonnenbeschienen Kasterl (T_Sonne) messen.
Die Differenz der beiden Temp. ergibt ein Maß für die Sonneneinstrahlung und sollte ein Steuerkriterium für meine Rollläden werden.
Die 2 Temp. werden auch schon brav in meinem File mitgeloggt und als Plot angezeigt.
Nur wie subtrahiere ich die 2 Temp. zu T_diff?
Ich habe schon alle möglichen Code-Schnipsel versucht, aber leider bin ich scheinbar für Perl zu blöd.
zB.:{fhem ("set T_diff" +(Value("T_Sonne")-Value("T_Schatten")))} zeigt keine Wirkung.
T_diff ist als dummy definiert.
Als nächstes muss ich:
T_diff=T_Sonne-T_Schatten
T_diff im Loggfile speichern
T_diff im Plot anzeigen
und dann noch die Abfragen, sinngemäß:
Wenn T_diff 20 Minuten lang > 20 Grad C, dann R_alle=AB
Wenn T_diff 60 Minuten lang < 19 Grad C, dann R_alle=AUF
Könnte mir bitte wer einen Schubser in die richtige Richtung oder einen dazu passenden Link posten?
Ich schaffe es alleine nicht.
mfd
Stefan
Schreib doch eine sub in die 99_myUtils, so in der Form my $temp1 = ReadingsVal("Sensor1","temperature",0);
my $temp2 = ReadingsVal("Sensor2","temperature",0);
und dann substahierst du einfach mit my $diff = ($temp1 - $temp2);
und fhem "set T_diff $diff";
fertig.
VG
Frank
oder.
{fhem ("set T_diff" . Value("T_Sonne")-Value("T_Schatten"))}
oder mit einem DOIF
define di_diff DOIF (([T_Sonne]-[T_Schatten]) > 20)(set R_alle AB)DOELSEIF(([T_Sonne]-[T_Schatten]) < 19)(set R_alle AUF)
attr di_diff cmdState alle auf|alle ab
attr di_diff stateFormat {(Value('T_Sonne')-Value('T_Schatten')).' °C<br>'.ReadingsVal('di_diff','state','???')}
attr di_diff wait 1200:3600
Grüße
igami
Danke für die Antworten.
Ich habe mal diese Lösung versucht:
Zitat von: igami am 24 Mai 2015, 17:31:03
oder mit einem DOIF
define di_diff DOIF (([T_Sonne]-[T_Schatten]) > 20)(set R_alle AB)DOELSEIF(([T_Sonne]-[T_Schatten]) < 19)(set R_alle AUF)
attr di_diff cmdState alle auf|alle ab
attr di_diff stateFormat {(Value('T_Sonne')-Value('T_Schatten')).' °C<br>'.ReadingsVal('di_diff','state','???')}
attr di_diff wait 1200:3600
Grüße
igami
Leider führt das zu folgenden Logeintrag:
2015.05.26 12:33:13 1: PERL WARNING: Argument "T: 14.25" isn't numeric in subtraction (-) at (eval 323) line 1, <$fh> line 176.
2015.05.26 12:33:13 1: PERL WARNING: Argument "T: 14.437" isn't numeric in subtraction (-) at (eval 323) line 1, <$fh> line 176.
Scheinbar erkennt er die "a4.437" nicht als Zahl.
Auch ist der Logeintrag folgend:
2015-05-26_12:34:11 T_Sonne temperature: 14.375
2015-05-26_12:34:12 T_Schatten temperature: 14.25
Da steht nicht: "T: 14.437" Wie kommt er auf diesen Text?
Ich habe den Logeintrag folgendermaßen erzeugt:
define T_Sonne GPIO4 10-000802b577a4
attr T_Sonne group temp
attr T_Sonne icon weather_sun
attr T_Sonne model DS1820
attr T_Sonne pollingInterval 3000
attr T_Sonne stateFormat {sprintf "%.1f °C", ReadingsVal($name, "temperature", 0)}
(auch irgendwo abgeschrieben)
Ich taumle von einem Fehler zum Nächsten.
Kann man den Text in eine Zahl umwandeln?
mfg
Vermutung an:
Vielleicht wird mindestens eine ganze Zahl erwartet.
Deine aktuellen Werte liefern aber 0,125 zurück.
Anderer Ansatz:
Bei der Subtraktion wird u.U. das "T:" mit einbezogen, was selbstverständlich für eine Berechnung nonsens ist.
Zumindest verstehe ich die Fehlermeldung so.
Müsste man schauen, wie man das "ausgeblendet bekommt.
Da die Stellen hinter dem Komma eher uninteressant sind, die DS1820 haben eh eine 0,5 Genauigkeit, würde ich die Werte erstmal auf ganze Zahlen runden lassen und erst diese Verarbeiten.
Versuchs mal so:
define di_temp_diff DOIF
attr di_temp_diff state {([T_Sonne:temperature:d])-([T_Schatten:temperature:d])}
Unter di_temp_diff state wird die Temperatur-Differenz gespeichert. Ein Dummy brauchst du dafür nicht.
Die Auswertung erfolgt z.B. wiederum mit einem DOIF:
define di_action DOIF ([di_temp_diff] > 20) (set R_alle AB)
DOELSEIF ([di_temp_diff] < 19) (set R_alle AUF)
attr di_action wait 1200:3600
attr di_action do always
Gruss
flurin
Zitat von: Stromschiene am 26 Mai 2015, 12:40:05
Auch ist der Logeintrag folgend:
2015-05-26_12:34:11 T_Sonne temperature: 14.375
2015-05-26_12:34:12 T_Schatten temperature: 14.25
Da steht nicht: "T: 14.437" Wie kommt er auf diesen Text?
Was steht im STATE von T_Sonne? Vielleicht T: 14.437? Dann müsste noch das Reading angegeben werden als [T_Sonne:temperature] und ReadingsVal('T_Sonne', 'temperature', 0).
Zitat von: flurin am 26 Mai 2015, 14:42:42
Versuchs mal so:
Da braucht man ja zwei DOIF für :P
Grüße
igami
Zitat von: igami am 26 Mai 2015, 17:11:07
Da braucht man ja zwei DOIF für :P
Wie hast du diese Vorgabe gelöst?
Zitat
Als nächstes muss ich:
T_diff=T_Sonne-T_Schatten
T_diff im Loggfile speichern
T_diff im Plot anzeigen
Bei meinem Vorschlag kommt lediglich noch FileLog + SVG dazu:
define FileLog_di_temp_diff FileLog ./log/di_temp_diff-%Y.log di_temp_diff
attr FileLog_di_temp_diff logtype text
Zitat von: flurin am 26 Mai 2015, 19:27:02
Wie hast du diese Vorgabe gelöst?
garnicht, hab ich überlesen.
Verändern wir also das DOIF zu
define di_diff DOIF
(([T_Sonne]-[T_Schatten]) > 20)
(
set R_alle AB,
setreading di_diff difference {([T_Sonne]-[T_Schatten])}
)
DOELSEIF(([T_Sonne]-[T_Schatten]) < 19)
(
set R_alle AUF,
setreading di_diff difference {([T_Sonne]-[T_Schatten])}
)
attr di_diff cmdState alle auf|alle ab
attr di_diff stateFormat {ReadingsVal($name, 'difference', 0).' °C<br>'.ReadingsVal('di_diff','state','???')}
attr di_diff wait 1200:3600
nun wird im DOIF noch das Reading difference angelegt, welches geplottet werden kann.
Grüße
igami
@igami
Die Berechnung [T_Sonne]-[T_Schatten] wird 4 mal ausgeführt. In höheren Sprachen würde man dafür eine Variable verwenden.
Was ist der Sinn und Zweck, alles mit einem DOIF zu lösen?
Gruss
flurin
Zitat von: flurin am 27 Mai 2015, 09:11:58
Die Berechnung [T_Sonne]-[T_Schatten] wird 4 mal ausgeführt. In höheren Sprachen würde man dafür eine Variable verwenden.
Was ist der Sinn und Zweck, alles mit einem DOIF zu lösen?
Das habe ich mir heute morgen auf dem Weg zur Arbeit auch gedacht ;)
Nur ein DOIF um das ganze schlank zu halten. Warum sollte ich einen Dummy umgehen wollen und dafür ein DOIF einsetzten?
define di_diff DOIF
([di_diff:difference] >20)
(set R_alle AB)
DOELSEIF([di_diff:difference] < 19)
(set R_alle AUF)
DOELSEIF([T_Sonne] or [T_Schatten])
(setreading di_diff difference {([T_Sonne:temperature]-[T_Schatten:temperature])})
attr di_diff cmdState alle auf|alle ab|difference
attr di_diff stateFormat difference °C
attr di_diff wait 1200:3600:0
Nun wird es nur noch einmal berechnet.
Zitat von: igami am 27 Mai 2015, 13:21:19
Das habe ich mir heute morgen auf dem Weg zur Arbeit auch gedacht ;)
Nur ein DOIF um das ganze schlank zu halten. Warum sollte ich einen Dummy umgehen wollen und dafür ein DOIF einsetzten?
schlank? Ansichtssache.
Mit dem Dummy hätte es noch ein notify oder DOIF gebraucht, mit dem "di_temp_diff" DOIF wird der Dummy überflüssig.
Mit meiner letzten Version funktioniert es auch noch nicht.
Edit: aber so:
define di_diff DOIF
([T_Sonne] or [T_Schatten])
(sleep 0.001; setreading di_diff difference {([T_Sonne]-([T_Schatten]))})
DOELSEIF([di_diff:?difference] and [di_diff:difference] > 20)
(set R_alle AB)
DOELSEIF([di_diff:?difference] and [di_diff:difference] < 19)
(set R_alle AUF)
attr di_diff cmdState difference|alle auf|alle ab
attr di_diff stateFormat difference °C
attr di_diff wait 0:1200:3600:0
Danke für die zahlreiche Anteilnahme!
Ich habe den Code von flurin verwendet, und er funkt fast perfekt (THX!).
define T_diff DOIF
attr T_diff state {([T_Sonne:temperature:d])-([T_Schatten:temperature:d])}
attr T_diff group temp
# OG Alle (außer Kinderzimmer)
define T_diff_OG DOIF ([T_diff] > 9) (set R_OG_Alle AB) DOELSEIF ([T_diff] < 6) (set R_OG_Alle AUF)
attr T_diff_OG wait 600:60
attr T_diff_OG do always
Nur leider wird das DOIF mehrmals, alle 10/1 Minute ausgeführt. Ich möchte aber die Rollläden wg. der Luftzirkulation nicht ganz schließen. Werden sie mehrmals geschlossen, so sind sie später ganz zu und der Luftpolster zwischen Scheibe und Rollladen heizt sich unnötig auf.
Lasse ich "attr T_diff_OG do always" weg, so wird das DOIF kein einziges mal, auch wenn sich T_diff ändert, nicht ausgelöst.
Es sollte aber einmal ausgelöst, auf die 2 Bedingung (>6) warten, um dann von vorne zu beginnen.
Einen kleinen Schubbs noch bitte! (:=))
mfg
Stefan
Zitat von: Stromschiene am 03 Juni 2015, 16:59:29
Nur leider wird das DOIF mehrmals, alle 10/1 Minute ausgeführt. Ich möchte aber die Rollläden wg. der Luftzirkulation nicht ganz schließen. Werden sie mehrmals geschlossen, so sind sie später ganz zu und der Luftpolster zwischen Scheibe und Rollladen heizt sich unnötig auf.
T_diff so ergänzen:
attr T_diff event-on-change-reading state
Damit wird nur bei einer Temperaturänderung getriggert.
Danke, kann es aber frühestens am Montag ausprobieren.
mfg
Stefan
Leider, nein.
Egal wie/wo ich "attr T_diff event-on-change-reading state" einfüge, geschieht nichts, oder immer.
1. Es sollte ja nur einmal das DOIF > 20 ausgeführt werden. (wird ja erkannt)
2. Dann warten und nix tun.
3. Bis < 19 ausgeführt wird. (wird auch erkannt)
4. Und wieder warten bis Punkt 1. erfüllt wird.
Grundbedingung: Diese Werten müssen eine gewisse Mindestzeit konstant anliegen. (wait: funktioniert)
Gibt es noch andere einfache Möglichkeiten?
mfg
Zitat von: Stromschiene am 08 Juni 2015, 10:53:42
Leider, nein.
Egal wie/wo ich "attr T_diff event-on-change-reading state" einfüge, geschieht nichts, oder immer.
Ich habe kurz sinngemäss diese Lösung erfolgreich getestet:
define di_temp_diff DOIF
attr di_temp_diff state {([local_weather:temperature:d]-[temp_living:temperature:d])}
ohne "attr di_temp_diff event-on-change-reading state"
define di_diff DOIF ([di_temp_diff] > 5) ({Log(3, "set R_alle AB")})
DOELSEIF ([di_temp_diff] < 4) ({Log(3,"set R_alle AUF")})
attr di_diff wait 5:5
ohne "attr di_diff do always"
Bemerkung: je nach di_temp_diff kann zuerst DOELSEIF ausgeführt werden und dann DOIF.
Leider nein.
Ich habe Deinen Code umkopiert und angepasst.
define T_diff DOIF
attr T_diff group temp
attr T_diff state {([T_Sonne:temperature:d])-([T_Schatten:temperature:d])}
define T_diff_EG DOIF ([T_diff] > 9) ({Log(3, "set Kueche AB")}) DOELSEIF ([T_diff] < 5.8) ({Log(3,"set Kueche AUF")})
attr T_diff_EG wait 60:60
(Kueche ist derzeit mein Probefenster)
Einfach keine Reaktion, keine Fehlermeldung.
T_diff arbeitet korrekt.
lt. Referenz sollte doch DOIF schon von Haus aus die Auslösereihenfolge beachten.
Vielleicht höhrt DOIF auf das falsche Ereignis?? (oder kein Ereignis??)
Oder liefert der Zahlensprung in T_diff keine Triggersignal?
Ich kenne mich da leider nicht aus.
.. und warum bei Dir und nicht bei mir??
-> Ratlos
mfg
Hallo Stromschiene
Könntest du folgende Lists posten:
list T_diff
list T_diff_EG
PS: am besten Code einfügen verwenden.
Bitteschön:
Internals:
NAME T_diff
NR 93
NTFY_ORDER 50-T_diff
STATE 12.563
TYPE DOIF
Readings:
2015-06-08 14:14:49 state 12.563
Devices:
Helper:
last_timer 0
sleeptimer -1
Itimer:
State:
device T_Sonne T_Schatten
Attributes:
group temp
state {([T_Sonne:temperature:d])-([T_Schatten:temperature:d])}
Internals:
DEF ([T_diff] > 9) ({Log(3, "set Kueche AB")}) DOELSEIF ([T_diff] < 5.8) ({Log(3,"set Kueche AUF")})
NAME T_diff_EG
NR 109
NTFY_ORDER 50-T_diff_EG
STATE cmd_1
TYPE DOIF
Readings:
2015-06-08 11:03:39 cmd_event T_diff
2015-06-08 11:03:39 cmd_nr 1
2015-06-08 14:16:48 e_T_diff_STATE 12.812
2015-06-08 11:03:39 state cmd_1
2015-06-08 13:02:13 wait_timer no timer
Condition:
0 InternalDoIf('T_diff','STATE','') > 9
1 InternalDoIf('T_diff','STATE','') < 5.8
Devices:
0 T_diff
1 T_diff
all T_diff
Do:
0 {Log(3, "set Kueche AB")}
1 {Log(3,"set Kueche AUF")}
Helper:
last_timer 0
sleeptimer -1
Internals:
0 T_diff:STATE
1 T_diff:STATE
all T_diff:STATE
Itimer:
Readings:
State:
Trigger:
Attributes:
wait 60:60
mfg
Abgesehen von den zusätzlichen Klammern (kann man weglassen):
{([T_Sonne:temperature:d])-([T_Schatten:temperature:d])}
fällt mir nichts auf.
cmd_1 wurde ausgeführt, demzufolge müsste in fhem-2015-06.log ein Eintrag vorhanden sein.
Evtl. Version prüfen:
version DOIF
# $Id: 98_DOIF.pm 8432 2015-04-13 19:34:11Z damian-s $
zusätzlich "shutdown restart" ausführen.
Edit:
cmd_1 oder cmd_2 werden nur ausgeführt, wenn die Bedingung sich ändert.
Ändert sich T_diff aber bleibt die Bedingung beispielsweise > 9, dann passiert nichts.
Zum Testen, kannst du das DOIF initialisieren (DEF und modify T_diff_EG klicken)
Version ist gleich.
Im Log ist ein set Kueche ab eingetragen. Wurde aber nicht ausgeführt.
Werde das morgen weiter verfolgen.
THX
mfg
Da scheint etwas mit dem "set" Befehl nicht zu stimmen.
"set Kueche AB" steht richtig im Log, wird aber ignoriert. Und steht auch nur ein mal dort.
"set Kueche AB", in der Commandline eingegeben, funktioniert.
mfg
Zitat von: Stromschiene am 08 Juni 2015, 18:54:10
Da scheint etwas mit dem "set" Befehl nicht zu stimmen.
"set Kueche AB" steht richtig im Log, wird aber ignoriert. Und steht auch nur ein mal dort.
"set Kueche AB", in der Commandline eingegeben, funktioniert.
mfg
Bei meiner Testversion wird der Befehl nur protokolliert nicht ausgeführt.
define di_diff DOIF ([di_temp_diff] > 5) ({Log(3, "set R_alle AB")})
DOELSEIF ([di_temp_diff] < 4) ({Log(3,"set R_alle AUF")})
attr di_diff wait 5:5
Um es mit dem Gerät zu testen, muss es so definiert werden:
define di_diff DOIF ([di_temp_diff] > 5) (set R_alle AB)
DOELSEIF ([di_temp_diff] < 4) (set R_alle AUF)
attr di_diff wait 5:5
Ich verfolge den Thread jetz schon die ganze Zeit, wiso macht ihr euch das Leben so schwer? Pack den Kram in eine sub und schreib das Ergebnis in ein dummy oder wo auch immer zurück und fertig. Da brauch ich kein DOIF oder DOELSEIF oder was auch immer. Values über ReadingsVal auslesen, einer Variablen zuweisen, berexhnen und zurückschreiben, sub über ein at triggern, hat den Vorteil das Berechnungsinterval selbst festlegen zu können.
VG
Frank
Zitat von: franky08 am 09 Juni 2015, 00:23:01
Ich verfolge den Thread jetz schon die ganze Zeit, wiso macht ihr euch das Leben so schwer? Pack den Kram in eine sub und schreib das Ergebnis in ein dummy oder wo auch immer zurück und fertig. Da brauch ich kein DOIF oder DOELSEIF oder was auch immer. Values über ReadingsVal auslesen, einer Variablen zuweisen, berexhnen und zurückschreiben, sub über ein at triggern, hat den Vorteil das Berechnungsinterval selbst festlegen zu können.
VG
Frank
Das ist wohl nicht das Problem! Wozu eine Perl-Funktion, wenn ich es mit einem simplen DOIF lösen kann?
define di_temp_diff DOIF
attr di_temp_diff state {([local_weather:temperature:d]-[temp_living:temperature:d])}
Die Differenz wird bei jeder Temperaturänderung (egal welche Temperatur sich ändert) berechnet, da brauche ich kein "at" mit einem Berechnungsintervall, um eine Perl-Funktion auszuführen. Ein Dummy ist auch überflüssig.
Aber wie sieht deine
konkrete Lösung mit einer Perl-Funktion aus? und wie löst du die
ganze Aufgabe mit den Wartezeiten?
Gruss
flurin
Flurin, Herzlichen Dank, jetzt läuft's:
Für unser Mitleser der funktionierende Code lautet jetzt:
define T_diff DOIF
attr T_diff state {([T_Sonne:temperature:d])-([T_Schatten:temperature:d])}
define T_diff_OG DOIF ([T_diff] > 9) (set R_OG_Alle AB) DOELSEIF ([T_diff] < 4) (set R_OG_Alle AUF)
attr T_diff_OG wait 600:1200
Damit ich auch weis wie's geht, was beutet:
"state {([T_Sonne:temperature:d" genau?
... und wo kann man das nachlesen?
Eine Zusatzfrage hätte ich noch:
Ich möchte die DOIF Anweisung nur ausführen, wenn das Dummy "R_OG_Alle" (alle Rollläden im Obergeschoß)
auf "AUTOM"(Automatisch) stehen.
Bevor ich mich da lange ärgere, kannst Du mir bitte das auch noch zeigen?
Du bist Spitze. Ich weis zwar nicht wer Du bist, und wo Du wohnst,
aber wenn wir uns mal in diesem oder im nächsten Leben treffen,
möchte ich Dich auf ein Bier einladen. (:=))
Danke!
Servus, aus Wien
Hallo Stromschiene
Wow! so viel Lob erhalte ich selten. Danke.
In Wien war ich auch schon, eine sehr schöne Stadt.
Zitat
Damit ich auch weis wie's geht, was beutet:
"state {([T_Sonne:temperature:d" genau?
... und wo kann man das nachlesen?
Commandref:
DOIF > Anpassung des Status mit Hilfe des Attributes state
und
DOIF >Filtern nach Zahlen"
Zitat
Ich möchte die DOIF Anweisung nur ausführen, wenn das Dummy "R_OG_Alle" (alle Rollläden im Obergeschoß)
auf "AUTOM"(Automatisch) stehen.
define T_diff_OG DOIF ([T_diff] > 9 and [?R_OG_Alle] eq "AUTOM") (set R_OG_Alle AB)
DOELSEIF ([T_diff] < 4 and [?R_OG_Alle] eq "AUTOM") (set R_OG_Alle AUF)
attr T_diff_OG wait 600:1200
Gruss
flurin
Leider gibt es weiter Probleme:
DOIF - Zeilen die nachweislich mal funktioniert haben, funktionieren ohne ersichtlichen Grund nicht mehr.
Zum Experimentieren habe ich sie mit C&P kopiert, die Originalzeile ausge# und an der Kopie weiter gearbeitet.
Danach die # wieder ausgetauscht, also das funktionierende Original wieder aktiviert, und AUS, keine Reaktion mehr. Auch nach einem Reboot nicht.
Werden an anderer Stelle Daten weggespeichert, die dann die Funktion ver(be)hindern?
Muss (kann) ich mehr als einen Reset machen?
Oder wo kann der Fehler liegen?
mfg