Moin,
ich stehe zzt. vor einem Problem, das ich offenbar nicht selbst lösen kann:
Ich habe einen Notify, der auf bestimmte Ereignisse triggert, die in regelmäßigen Abständen von einem Modul ausgelöst werden. Der Notify benachrichtigt mich dann über diese Events. Da jedoch das Modul jede Stunde aktualisiert (u.A. für meine Plots), bekomme ich ggf. am Tag 24 Emails mit der selben Meldung - das ist eindeutig zu viel.
Ich suche also eine Möglichkeit, dass die Events zwar wie gewohnt ausgelöst werden, jedoch ich nur einmal pro Tag eine Nachricht / Email darüber bekomme.
Eigentlich möchte ich das definieren eines zusätzlichen Dummys zum puffern vermeiden, da ich mehrere Module definiert habe, die auslösen und ich dann ja für jedes Modul auch einen Dummy benötige - dann spame ich mir mein FHEM zu. :)
Konkret geht es um meine neuen Pflanzensensoren. Das Modul produziert Events auf die ich reagieren möchte, wenn Werte unter oder Überschritten werden.
Ich bin über alle Anregungen dankbar.
Hi,
Ich löse solche Aufgaben immer mit einem DOIF. Du kannst fast den gleichen Event Trigger nehmen wie beim notify. Da DOIF im Standardverhalten in dem Status stehen bleibt, bekommst Du genau eine Mail. Einmal am Tag muss lediglich das DOIF "zurückgesetzt" werden, das kann er aber "selbst".
Beispiele als Anregung
Schalte früh das Radio an wenn das erste Mal das Licht angeschaltet wird.
defmod di_GutenMorgen2 DOIF ([05:45-11:00] and ["LichtBWaSw_02:on"]) (set Sonos_Bad GroupMute 0)
Starte den Staubsauger wenn ich außer Haus bin, halte ihn eventuell an wenn ich unverhofft wiederkomme damit er nicht nervt, setze den Vorgang 23:00 zurückdefmod di_MyRobot DOIF (["AlleAnwesend:absent"]) (set MyRobot start) DOELSEIF (["AlleAnwesend:present"] and [MyRobot] eq "Cleaning") (set MyRobot pause) DOELSEIF ([23:00]) (set MyRobot charge, set di_MyRobot2 initialize)
Gruß Otto
War Otto wieder schneller. :)
Ich würde mir userreadings in dem Notify anlegen und die mit den Werten füllen. Sobald der Wert dort erscheint, kann man dann über ein AT inkl. IF einmal am Tag darauf reagieren. In dem AT würde ich dann auch gleich die Werte der Readings zurücksetzen.
Oder noch einfacher: Im notify zuletzt sich selbst
attr <notifyname> disable 1
setzen und über ein AT um 0:00 wieder auf 0 setzen
DOIF ([mein Trigger]) (set mail bla..) DOELSEIF ([00:00])
Ich würde einfach prüfen, ob der ReadingsTimestamp von "state" des notify bereits das heutige Datum enthält. Wenn ja, wurde das notify heute bereits ausgeführt.
Ich habe es jetzt mal mit einem Doif probiert - doch noch klappt es nicht endgültig. Das Ding ist zunächst echt verwirrend!
So sieht's jetzt aus:
define Di_FlowerSensor DOIF (["Pflanzensensor.*:minFertility.low"]) \
{$dv = AttrVal($DEVICE,'alias',$DEVICE)} {DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ('.$dv.') hat zu wenig Fruchtbarkeit! Gebe etwas Dünger zum Wasser!', '')} \
DOELSEIF (["Pflanzensensor.*:maxFertility.high"]) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ($DEVICE) hat zu viel Fruchtbarkeit! Der Boden ist zu stark gedüngt!', '')}) \
DOELSEIF (["Pflanzensensor.*:minLux.low"]) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ($DEVICE) hat zu wenig Sonneneinstrahlung! Stelle sie ins Licht!', '')}) \
DOELSEIF (["Pflanzensensor.*:maxLux.high"]) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ($DEVICE) hat zu viel Sonneneinstrahlung! Stelle sie in den Schatten!', '')}) \
DOELSEIF (["Pflanzensensor.*:minMoisture.low"]) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ($DEVICE) hat zu wenig Wasser! Gieße die Pflanze!', '')}) \
DOELSEIF (["Pflanzensensor.*:maxMoisture.high"]) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ($DEVICE) hat zu viel Wasser! Entferne etwas Wasser!', '')}) \
DOELSEIF (["Pflanzensensor.*:minTemperature.low"]) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ($DEVICE) ist zu kalt! Stelle sie an einen wärmeren Ort!', '')}) \
DOELSEIF (["Pflanzensensor.*:maxTemperature.high"]) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ($DEVICE) ist zu warm! Stelle sie an einen kälteren Ort!', '')})
attr Di_FlowerSensor do always
Die 1. Bedingung ist zzt. meine Baustelle: Ich möchte nicht den Devicenamen, sondern Alias ausgegeben haben - klappt aber nicht, weil ich die Bedingung falsch definiere. Do Always nehme ich zum Schluss raus und ergänze den "AT-Teil".
So sieht der Zugrundeliegende Notify aus (zum Vergleich):
define Notify_FlowerSensor notify Pflanzensensor.*:(minFertility|minLux|minMoisture|minTemperature|maxFertility|maxLux|maxMoisture|maxTemperature).(low|high) {\
my $alert;;\
my $device;;\
$device = AttrVal("$NAME","alias", "$NAME");;\
if ($EVTPART1 eq "low") {\
$alert = "Die Pflanze (".$device.") hat zu wenig Fruchtbarkeit! Gebe etwas Dünger zum Wasser!" if ($EVTPART0 eq "minFertility");;\
$alert = "Die Pflanze (".$device.") hat zu wenig Sonneneinstrahlung! Stelle sie ins Licht!" if ($EVTPART0 eq "minLux");;\
$alert = "Die Pflanze (".$device.") hat zu wenig Wasser! Gieße die Pflanze!" if ($EVTPART0 eq "minMoisture");;\
$alert = "Die Pflanze (".$device.") ist zu kalt! Stelle sie an einen wärmeren Ort!" if ($EVTPART0 eq "minTemperature");;\
} elsif ($EVTPART1 eq "high") {\
$alert = "Die Pflanze (".$device.") hat zu viel Fruchtbarkeit! Der Boden ist zu stark gedüngt!" if ($EVTPART0 eq "maxFertility");;\
$alert = "Die Pflanze (".$device.") hat zu viel Sonneneinstrahlung! Stelle sie in den Schatten!" if ($EVTPART0 eq "maxLux");;\
$alert = "Die Pflanze (".$device.") hat zu viel Wasser! Entferne etwas Wasser!" if ($EVTPART0 eq "maxMoisture");;\
$alert = "Die Pflanze (".$device.") ist zu warm! Stelle sie an einen kälteren Ort!" if ($EVTPART0 eq "maxTemperature");;\
}\
if ($alert) {DebianMail('<Email>', 'Smarthome: Pflanzenstand', $alert, '')};;\
Log 3, "$device: Pflanzenwarnung: $alert" if ($alert);;\
}
attr Notify_FlowerSensor comment Notify zum Überwachen der Pflanzensensoren.
attr Notify_FlowerSensor disable 1
Im if habe ich nun, anders als im Notify für jede Möglichkeit einen eigenen Schleifenteil gewählt.
Ok, nun klappt es. Was haltet ihr von dem Doif? Ist der ok, oder optimierungswürdig - ist mein erster ;)
define Di_FlowerSensor DOIF (["Pflanzensensor.*:minFertility.low"]) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu wenig Fruchtbarkeit! Gebe etwas Dünger zum Wasser!', '')}) \
DOELSEIF (["Pflanzensensor.*:maxFertility.high"]) \
({DebianMail('<Email>', 'Smarthome Fuhrmann: Pflanzenstand', 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu viel Fruchtbarkeit! Der Boden ist zu stark gedüngt!', '')}) \
DOELSEIF (["Pflanzensensor.*:minLux.low"]) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu wenig Sonneneinstrahlung! Stelle sie ins Licht!', '')}) \
DOELSEIF (["Pflanzensensor.*:maxLux.high"]) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu viel Sonneneinstrahlung! Stelle sie in den Schatten!', '')}) \
DOELSEIF (["Pflanzensensor.*:minMoisture.low"]) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu wenig Wasser! Gieße die Pflanze!', '')}) \
DOELSEIF (["Pflanzensensor.*:maxMoisture.high"]) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu viel Wasser! Entferne etwas Wasser!', '')}) \
DOELSEIF (["Pflanzensensor.*:minTemperature.low"]) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') ist zu kalt! Stelle sie an einen wärmeren Ort!', '')}) \
DOELSEIF (["Pflanzensensor.*:maxTemperature.high"]) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') ist zu warm! Stelle sie an einen kälteren Ort!', '')}) \
DOELSEIF ([00:00])
attr Di_FlowerSensor comment Doif zum Überwachen der Pflanzensensoren.
Zitat von: rubbertail am 02 September 2017, 11:51:01
attr <notifyname> disable 1
grundsätzlich eine schöne Lösung!
Besser ist noch
set <notifyname> inactive
und im at dann
set <notifyname> active
das vermeidet das rote Fragezeichen.
gb#
Hm, so richtig klappt der neue DOIF auch noch nicht. Ich bekomme weiterhin mehrere Emails pro Tag über das selbe Ereignis.
Mit dem DOIF überwache ich zzt. 4 Pflanzensensoren auf Temperatur, Feuchtigkeit, Düngewert und Lichteinstrahlung.
Meine Absicht: Ich möchte jede erzeugte Meldung nur einmal pro Tag bekommen, auch wenn die Sensoren alle 2 Stunden die Umgebung checken. Das hatte mit dem Notify nicht geklappt. Der hat mir alle 2 Stunden eine Email geschickt (etwa, wenn bei Pflanzensensor 1 zu weinig Wasser gemessen wurde).
Der DOIF schickt nicht mehr so oft Emails raus, doch auch dort gibt es Doppelungen. So hat er mir z.B. für Pflanze 3 heute bereits 3 Emails geschickt, dass ich sie düngen möge (um 11:36, 13:38 und 17:42 Uhr).
Aber was mache ich da noch falsch?
Zitat von: Grinsekatze am 03 September 2017, 18:26:32
Hm, so richtig klappt der neue DOIF auch noch nicht. Ich bekomme weiterhin mehrere Emails pro Tag über das selbe Ereignis.
Mit dem DOIF überwache ich zzt. 4 Pflanzensensoren auf Temperatur, Feuchtigkeit, Düngewert und Lichteinstrahlung.
Meine Absicht: Ich möchte jede erzeugte Meldung nur einmal pro Tag bekommen, auch wenn die Sensoren alle 2 Stunden die Umgebung checken. Das hatte mit dem Notify nicht geklappt. Der hat mir alle 2 Stunden eine Email geschickt (etwa, wenn bei Pflanzensensor 1 zu weinig Wasser gemessen wurde).
Der DOIF schickt nicht mehr so oft Emails raus, doch auch dort gibt es Doppelungen. So hat er mir z.B. für Pflanze 3 heute bereits 3 Emails geschickt, dass ich sie düngen möge (um 11:36, 13:38 und 17:42 Uhr).
Aber was mache ich da noch falsch?
DOIF - ohne do always-Attribut - schaltet nach Zustandswechsel. Jeder DO-Zweig stellt einen eigenen Zustand dar.
Wenn die Nachrichten im Wechsel kommen, wechselt auch der DO-Zweig und eine Nachricht wird wiederholt.
Soll eine Nachricht nicht wiederholt werden, musst du pro Nachricht ein DOIF definieren mit DOELSE([00:00)] am Ende, damit der Zustand um Mitternacht wechselt.
Hm, das habe ich befürchtet.
Das bedeutet dann, dass ich pro Sensor (zzt. sind 4 im Einsatz, weitere 6 liegen bereit) mind. 8 DOIFs benötige, um auf High und Low für Temperatur, Wasser, Lichteinstrahlung und Dünger zu reagieren.
Das wollte ich eigentlich vermeiden und einen generischen Schreiben, der egal wie viele Sensoren in Betrieb sind, alle abdeckt. Das macht die Erweiterbarkeit leichter und den Code übersichtlicher.´
Danke
Zitat von: betateilchen am 02 September 2017, 15:44:25
Ich würde einfach prüfen, ob der ReadingsTimestamp von "state" des notify bereits das heutige Datum enthält. Wenn ja, wurde das notify heute bereits ausgeführt.
Damit wäre es pro device ein notify.
Oder du setzt bei jedem device einen "Marker" (userattr), wenn die Meldung raus ist und prüfst in einem generischen notify, ob der Marker exisitert => Senden nur, wenn nicht bzw. auf 0. Einmal am Tag dann alle userattr auf "0" setzen, löschen oä.
Als "Gerüst" kannst du dich daran orientieren: https://forum.fhem.de/index.php/topic,36504.msg287778.html#msg287778
Gruß, Beta-User
Zitat von: Beta-User am 06 September 2017, 11:49:35
Oder du setzt bei jedem device einen "Marker" (userattr),
Ich würde dafür aber eher ein Reading empfehlen (s.a. Commandref setreading (https://fhem.de/commandref_DE.html#setreading))
Beim Setzen von Attributen wird eine strukturelle Änderung der Konfiguration festgestellt (rotes Fragezeichen), die mit einem
save gespeichert werden müsste. Das ist beim Setzen von Readings nicht der Fall. Auch die Readings überstehen ggf. einen Neustart von FHEM, da diese im Statefile gesichert werden.
Daher auch mein Hinweis bereits weiter oben (https://forum.fhem.de/index.php/topic,76123.msg680096.html#msg680096) in diesem Thread
Zitat von: Beta-User am 06 September 2017, 11:49:35
Als "Gerüst" kannst du dich daran orientieren
Ziemlich viel Gerüst für die kleine Aufgabe hier ;)
Gruß Benni.
setreading : guter Hinweis.
Zitat von: Benni am 06 September 2017, 13:11:49
Ziemlich viel Gerüst für die kleine Aufgabe hier ;)
...ist mein persönlicher "Steinbruch", wenn ich codeblöcke für solche Aufgaben suche ::) , aber zugegebenermaßen: Da ist deutlich mehr Funktionalität drin, als hier benötigt. Trotzdem an der Stelle nochmal: Danke für den Code!
Soll pro Pflanze oder pro Nachricht pro Tag nur eine Nachricht kommen?
Pro Pflanze geht einfach:
define Di_FlowerSensor DOIF (["Pflanzensensor.*:minFertility.low"] and [?SELF.cmd] == 8) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu wenig Fruchtbarkeit! Gebe etwas Dünger zum Wasser!', '')}) \
DOELSEIF (["Pflanzensensor.*:maxFertility.high"] and [?SELF:cmd] == 8) \
({DebianMail('<Email>', 'Smarthome Fuhrmann: Pflanzenstand', 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu viel Fruchtbarkeit! Der Boden ist zu stark gedüngt!', '')}) \
DOELSEIF (["Pflanzensensor.*:minLux.low"] and [?SELF:cmd] == 8) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu wenig Sonneneinstrahlung! Stelle sie ins Licht!', '')}) \
DOELSEIF (["Pflanzensensor.*:maxLux.high"] and [?SELF:cmd] == 8) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu viel Sonneneinstrahlung! Stelle sie in den Schatten!', '')}) \
DOELSEIF (["Pflanzensensor.*:minMoisture.low"] and [?SELF:cmd] == 8) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu wenig Wasser! Gieße die Pflanze!', '')}) \
DOELSEIF (["Pflanzensensor.*:maxMoisture.high"] and [?SELF:cmd] == 8) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu viel Wasser! Entferne etwas Wasser!', '')}) \
DOELSEIF (["Pflanzensensor.*:minTemperature.low"] and [?SELF:cmd] == 8) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') ist zu kalt! Stelle sie an einen wärmeren Ort!', '')}) \
DOELSEIF (["Pflanzensensor.*:maxTemperature.high"] and [?SELF:cmd] == 8) \
({DebianMail('<Email>', 'Smarthome: Pflanzenstand', 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') ist zu warm! Stelle sie an einen kälteren Ort!', '')}) \
DOELSEIF ([00:00])
attr Di_FlowerSensor comment Doif zum Überwachen der Pflanzensensoren.
Pro Meldung könntest du ein Flag/Userreading setzen und auswerten. Ist halt etwas mehr Schreibarbeit.
Es soll pro Pflanze nur jeweils eine Meldung pro DOIF-Zweig kommen. Wenn Also Pflanze 1 z.B. mehr Wasser und mehr Dünger benötigt, dann soll beides per Nachricht mitgeteilt werden - aber eben nur 1x pro Tag. Wenn aber Pflanze 2 auch mehr Wasser benötigt und etwa mehr Licht, dann soll das auch am selben Tag mitgeteilt werden (aber eben auch nur 1x pro Tag).
Ich hatte zunächst auch überlegt, ob ich es mit UserReadings im DOIF löse. Etwa per z.B. für Dünger (zu weinig) setreading Di_FlowerSensor "Fertility_".$DEVICE "low"
die benötigten Readings erstellen und dann deie DOIF-Bedingungen um einen Timestamp-Check der benötigten UserReadings ergänzen. Doch da kam ich erstmal nicht weiter mit dem Timestamp-Vergleich. :D
Ich pobiere mal deinen Vorschlag aus, Danke.
Zitat von: Grinsekatze am 07 September 2017, 23:56:21Doch da kam ich erstmal nicht weiter mit dem Timestamp-Vergleich.
"Billig-Variante": auf "true" oder "gesendet" setzen und [0:00] alles resetten.
So richtig funktioniert die Lösung von Per nicht.
Ich bekomme seit Donnerstag keine Nachrichten mehr.
Dafür habe ich diese Meldungen im Log gefunden (für alle cmd des DOIF):
2017.09.08 06:00:45 1: PERL WARNING: Argument "" isn't numeric in numeric eq (==) at (eval 415940) line 1.
2017.09.08 06:00:45 3: eval: Di_FlowerSensor: warning in condition c03
Was bewirkt [?SELF:cmd] == 8 eigentlich?
So, ich habe meinen DOIF mal angepasst - und wieder komme ich nicht weiter. Langsam fühle ich mich wie ein Grundschüler. :/
define Di_FlowerSensor DOIF (["Pflanzensensor.*:minFertility.low"] and [?SELF:alarm.$DEVICE.Fertility] ne "low") \
({DebianMail('<E-Mail>', 'Smarthome: Pflanzenzustand: '.AttrVal("$DEVICE","alias","$DEVICE"), 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu wenig Fruchtbarkeit! Gebe etwas Dünger zum Wasser!', '')},\
(setreading $SELF alarm$DEVICEFertility low)) \
DOELSEIF (["Pflanzensensor.*:maxFertility.high"] and [?SELF:alarm.$DEVICE.Fertility] ne "high") \
({DebianMail('<E-Mail>', 'Smarthome: Pflanzenzustand: '.AttrVal("$DEVICE","alias","$DEVICE"), 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu viel Fruchtbarkeit! Der Boden ist zu stark gedüngt!', '')},\
(setreading $SELF alarm$DEVICEFertility high)) \
DOELSEIF (["Pflanzensensor.*:minLux.low"] and [?SELF:alarm.$DEVICE.Lux] ne "low") \
({DebianMail('<E-Mail>', 'Smarthome: Pflanzenzustand: '.AttrVal("$DEVICE","alias","$DEVICE"), 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu wenig Sonneneinstrahlung! Stelle sie ins Licht!', '')},\
(setreading $SELF alarm$DEVICELux low)) \
DOELSEIF (["Pflanzensensor.*:maxLux.high"] and [?SELF:alarm.$DEVICE.Lux] ne "high") \
({DebianMail('<E-Mail>', 'Smarthome: Pflanzenzustand: '.AttrVal("$DEVICE","alias","$DEVICE"), 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu viel Sonneneinstrahlung! Stelle sie in den Schatten!', '')},\
(setreading $SELF alarm$DEVICELux high)) \
DOELSEIF (["Pflanzensensor.*:minMoisture.low"] and [?SELF:alarm.$DEVICE.Moisture] ne "low") \
({DebianMail('<E-Mail>', 'Smarthome: Pflanzenzustand: '.AttrVal("$DEVICE","alias","$DEVICE"), 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu wenig Wasser! Gieße die Pflanze!', '')},\
(setreading $SELF alarm$DEVICEMoisture low)) \
DOELSEIF (["Pflanzensensor.*:maxMoisture.high"] and [?SELF:alarm.$DEVICE.Moisture] ne "high") \
({DebianMail('<E-Mail>', 'Smarthome: Pflanzenzustand: '.AttrVal("$DEVICE","alias","$DEVICE"), 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') hat zu viel Wasser! Entferne etwas Wasser!', '')},\
(setreading $SELF alarm$DEVICEMoisture high)) \
DOELSEIF (["Pflanzensensor.*:minTemperature.low"] and [?SELF:alarm.$DEVICE.Temperature] ne "low") \
({DebianMail('<E-Mail>', 'Smarthome: Pflanzenzustand: '.AttrVal("$DEVICE","alias","$DEVICE"), 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') ist zu kalt! Stelle sie an einen wärmeren Ort!', '')},\
(setreading $SELF alarm$DEVICETemperature low)) \
DOELSEIF (["Pflanzensensor.*:maxTemperature.high"] and [?SELF:alarm.$DEVICE.Temperature] ne "high") \
({DebianMail('<E-Mail>', 'Smarthome: Pflanzenzustand: '.AttrVal("$DEVICE","alias","$DEVICE"), 'Die Pflanze ('.AttrVal("$DEVICE","alias","$DEVICE").') ist zu warm! Stelle sie an einen kälteren Ort!', '')},\
(setreading $SELF alarm$DEVICETemperature high)) \
DOELSEIF ([00:00]) \
((setreading $SELF alarm*Fertility ok),\
(setreading $SELF alarm$DEVICELux ok),\
(setreading $SELF alarm$DEVICEMoisture ok),\
(setreading $SELF alarm$DEVICETemperature ok))
attr Di_FlowerSensor comment Doif zum Überwachen der Pflanzensensoren.
attr Di_FlowerSensor icon helper_doif
Wie man schön erkennen kann habe ich nun für jeden Sensor max. 4 Readings (alarm[Device][Fertility|Lux|Moisture|Temperature]) die drei Werte annehmen können: "low" (dann wird die Low-Warnung getrigert) "high" und "ok" (ist dann wird gar nichts getriggert).
Ich habe jedoch ein Problem beim reseten der Readings: Wenn ich im Reading $DEVICE verwende, dann wird (logischer weise) nur der Reading vom letzten auslösenden Device benutzt. * wird nicht angenommen. Gibt es eine Möglichkeit für die Reading-Angabe bei setreading einen RegEx zu verwenden (und ja, welchen)?
Ich habe früher mit diversen Sprachen gearbeitet. Doch hier ist die Syntax manchmal echt ekelig, etwa ein alarm$DEVICETemperature würde mir viel besser als alarm.$DEVICE.Temperature gefallen (aber dann auch hinterher ohne die Punkte im Namen).
Zitat von: Grinsekatze am 09 September 2017, 11:45:52
Ich habe früher mit diversen Sprachen gearbeitet. Doch hier ist die Syntax manchmal echt ekelig,
Dann vielleicht doch lieber mit notify und etwas Perl ;D
*duckundweg*
und vor allem nicht so einen kompletten Roman in das DEF eines devices schreiben...
ZitatIch habe früher mit diversen Sprachen gearbeitet. Doch hier ist die Syntax manchmal echt ekelig,
Dann nimm ein einfaches notify, da kannst Du mit purem perl arbeiten. Das ist wenigstens verständlich.
Ich wollte es gerade schreiben. Wo wir wieder bei DOIF wären und wie einfach es doch sein soll.
Aber egal. Warum zum Teufel wird nicht Udo sein Vorschlag von Seite 1 verwendet. Es ist das einfachste. Wenn man dann etwas weiter denkt macht man folgendes.
Man triggert auf alle Pflanzen und Events die man braucht. Man bastellt mit Perl ReadingAge Abfrage auf ein Reading im Notify. Am Ende setzt man das Reading für das Notify, es sollte aus Device und Event bestehen. Also readingname Pflanze1humidity value High. Das Reading ist zum unterscheiden der Devices und Events aber vor allem für den Timestamp. Das sind nicht Mal 8 Zeilen Perlcode.
Nur eine Anmerkung am Rande:
Einige wenige solcher eleganter und ausgetesteter Varianten im Wiki (Udo: keep cool) oder von mir aus angepinnt bei Automatisierung, dann würde sich vielleicht der eine oder andere überlegen, ob er das mit notify/perl nicht einfach ausprobiert.
So sind viele "Verluste" an "höhere" Module zu "beklagen" :'( ... und ich bin nicht der einzige, der sich einigermaßen frustriert von diesem Irrweg DOIF abgekehrt habt.
Wenn ich heute Abend dazu kommen kann ich versuchen ein Beispiel zu erstellen.
Zitat von: CoolTux am 09 September 2017, 12:19:41Man triggert auf alle Pflanzen und Events die man braucht. Man bastellt mit Perl ReadingAge Abfrage auf ein Reading im Notify. Am Ende setzt man das Reading für das Notify, es sollte aus Device und Event bestehen. Also readingname Pflanze1humidity value High. Das Reading ist zum unterscheiden der Devices und Events aber vor allem für den Timestamp. Das sind nicht Mal 8 Zeilen Perlcode.
Das habe ich im Groben auch überlegt. Aber da ich nun schon ein DOIF gebaut habe, wollte ich zunächst testen, ob ich es damit auch umgesetzt bekomme.
Ich habe hier noch eine aktuellere Version des DOIF. Dort habe ich zum Schluss dann notgedrungener Weise deletereading verwendet und bei den Meldungen auch ein Log 3 Eintrag erstellt. Aber alleine, dass ich ewig den gleichen Code für jeden DOIF-Zweig angeben muss und es nicht zentral definieren und dann darauf zugreifen kann (ok, ginge per myUtlis) stört mich ja schon am DOIF. Ich finde die alten Notifys erheblich verständlicher - und oft auch kürzer.
Gut, ich habe meinen ursprünglichen Notify einmal erweitert:
define Notify_FlowerSensor notify Pflanzensensor.*:(minFertility|minLux|minMoisture|minTemperature|maxFertility|maxLux|maxMoisture|maxTemperature).(low|high) {\
my $alert;;\
my $device;;\
my $reading;;\
$device = AttrVal("$NAME","alias","$NAME");;\
$reading = "Fertility" if ($EVTPART0 =~ /Fertility$/);;\
$reading = "Lux" if ($EVTPART0 =~ /Lux$/);;\
$reading = "Moisture" if ($EVTPART0 =~ /Moisture$/);;\
$reading = "Temperature" if ($EVTPART0 =~ /Temperature$/);;\
if ({ReadingsAge($SELF,$reading,0)} >= 86400) {\
if ($EVTPART1 eq "low") {\
$alert = "Die Pflanze (".$device.") hat zu wenig Fruchtbarkeit! Gebe etwas Dünger zum Wasser!" if ($EVTPART0 eq "minFertility");;\
$alert = "Die Pflanze (".$device.") hat zu wenig Sonneneinstrahlung! Stelle sie ins Licht!" if ($EVTPART0 eq "minLux");;\
$alert = "Die Pflanze (".$device.") hat zu wenig Wasser! Gieße die Pflanze!" if ($EVTPART0 eq "minMoisture");;\
$alert = "Die Pflanze (".$device.") ist zu kalt! Stelle sie an einen wärmeren Ort!" if ($EVTPART0 eq "minTemperature");;\
} elsif ($EVTPART1 eq "high") {\
$alert = "Die Pflanze (".$device.") hat zu viel Fruchtbarkeit! Der Boden ist zu stark gedüngt!" if ($EVTPART0 eq "maxFertility");;\
$alert = "Die Pflanze (".$device.") hat zu viel Sonneneinstrahlung! Stelle sie in den Schatten!" if ($EVTPART0 eq "maxLux");;\
$alert = "Die Pflanze (".$device.") hat zu viel Wasser! Entferne etwas Wasser!" if ($EVTPART0 eq "maxMoisture");;\
$alert = "Die Pflanze (".$device.") ist zu warm! Stelle sie an einen kälteren Ort!" if ($EVTPART0 eq "maxTemperature");;\
}\
setreading $SELF $NAME.$reading $EVTPART1
if ($alert) {DebianMail('<E-Mail>', 'Smarthome: Pflanzenstand', $alert, '')};;\
Log 3, "$device: Pflanzenwarnung: $alert" if ($alert);;\
}\
}
attr Notify_FlowerSensor comment Notify zum Überwachen der Pflanzensensoren.
In meinen Augen viel zu viel Code. Alles wichtige kommt doch mit dem EVENT das musst Du doch nicht noch mal abfragen.
Alleine Deine RegEx geht viel viel kürzer.
define Notify_FlowerSensor notify Pflanzensensor.*:(min.*|max.*)
RegEx sind nicht gerade meine Stärke. Danke für den Tipp.
Edit:
Wobei ich jetzt nicht wirklich noch mehr Einsparpotential sehe.
$device benötige ich fürs Alias. Sonst kann hier im Haus niemand was mit der Meldung anfangen, weil sie dann nicht wissen, welche Pflanze gemeint ist.
$reading benötige ich, um die Anzahl der Readings gering zu halten. Sonst hätte ich pro Sensor 8 Readings. Jetzt sind es nur max. 4, da ich statt z.B. minTemperature und maxTemperature nur temperature verwende.
$alarm wird für die richtige Meldung benötigt.
Sonst werden ja nur die Bedingungen geprüft (Reading alt genug).
Ich versuche mich mal heute Abend.
Grüße
Zitat von: Grinsekatze am 09 September 2017, 14:34:32
Das habe ich im Groben auch überlegt. Aber da ich nun schon ein DOIF gebaut habe, wollte ich zunächst testen, ob ich es damit auch umgesetzt bekomme.
Ich habe hier noch eine aktuellere Version des DOIF. Dort habe ich zum Schluss dann notgedrungener Weise deletereading verwendet und bei den Meldungen auch ein Log 3 Eintrag erstellt. Aber alleine, dass ich ewig den gleichen Code für jeden DOIF-Zweig angeben muss und es nicht zentral definieren und dann darauf zugreifen kann (ok, ginge per myUtlis) stört mich ja schon am DOIF. Ich finde die alten Notifys erheblich verständlicher - und oft auch kürzer.
Gut, ich habe meinen ursprünglichen Notify einmal erweitert:
define Notify_FlowerSensor notify Pflanzensensor.*:(minFertility|minLux|minMoisture|minTemperature|maxFertility|maxLux|maxMoisture|maxTemperature).(low|high) {\
my $alert;;\
my $device;;\
my $reading;;\
$device = AttrVal("$NAME","alias","$NAME");;\
$reading = "Fertility" if ($EVTPART0 =~ /Fertility$/);;\
$reading = "Lux" if ($EVTPART0 =~ /Lux$/);;\
$reading = "Moisture" if ($EVTPART0 =~ /Moisture$/);;\
$reading = "Temperature" if ($EVTPART0 =~ /Temperature$/);;\
if ({ReadingsAge($SELF,$reading,0)} >= 86400) {\
if ($EVTPART1 eq "low") {\
$alert = "Die Pflanze (".$device.") hat zu wenig Fruchtbarkeit! Gebe etwas Dünger zum Wasser!" if ($EVTPART0 eq "minFertility");;\
$alert = "Die Pflanze (".$device.") hat zu wenig Sonneneinstrahlung! Stelle sie ins Licht!" if ($EVTPART0 eq "minLux");;\
$alert = "Die Pflanze (".$device.") hat zu wenig Wasser! Gieße die Pflanze!" if ($EVTPART0 eq "minMoisture");;\
$alert = "Die Pflanze (".$device.") ist zu kalt! Stelle sie an einen wärmeren Ort!" if ($EVTPART0 eq "minTemperature");;\
} elsif ($EVTPART1 eq "high") {\
$alert = "Die Pflanze (".$device.") hat zu viel Fruchtbarkeit! Der Boden ist zu stark gedüngt!" if ($EVTPART0 eq "maxFertility");;\
$alert = "Die Pflanze (".$device.") hat zu viel Sonneneinstrahlung! Stelle sie in den Schatten!" if ($EVTPART0 eq "maxLux");;\
$alert = "Die Pflanze (".$device.") hat zu viel Wasser! Entferne etwas Wasser!" if ($EVTPART0 eq "maxMoisture");;\
$alert = "Die Pflanze (".$device.") ist zu warm! Stelle sie an einen kälteren Ort!" if ($EVTPART0 eq "maxTemperature");;\
}\
setreading $SELF $NAME.$reading $EVTPART1
if ($alert) {DebianMail('<E-Mail>', 'Smarthome: Pflanzenstand', $alert, '')};;\
Log 3, "$device: Pflanzenwarnung: $alert" if ($alert);;\
}\
}
attr Notify_FlowerSensor comment Notify zum Überwachen der Pflanzensensoren.
Und du bist sicher, dass der Code funktioniert? M. W. kennt notify kein $SELF.
Es ist die Frage, wie ausführlich man etwas programmieren will, alles was länger als 20-30 Perl-Zeilen ist, sollte man in eigene Routinen in myUtils auslagern, egal, ob mit notify oder DOIF.
Für mich hätte auch ein Dreizeiler für alle Devices gereicht z. B.:
[quote](["^Pflanzensensor:(low|high)$"] and [?$SELF:A_$DEVICE] ne "alert")
({DebianMail('yourname@gmail.com', 'FHEM - $EVENT warning from device: $DEVICE')}, setreading $SELF A_$DEVICE alert)
DOELSEIF ([00:00]) (deletereading $SELF A_.*)[/quote]
Alles Frage dessen, was man haben will.
Hier mal Vorab eine ganz einfache Lösung für das immer Melden. Das nur einmal täglich mache ich nachher
define Notify_FlowerSensor notify Pflanzensensor.*:(min.*|max.*) {DebianMail('<E-Mail>', 'Smarthome: Pflanzenstand', $NAME meldet $EVTPART0 ist $EVTPART1, '')}
Wie gesagt das ist die gaaaanz einfache Variante. Das mit dem nur einmal täglich kommt später
define Notify_FlowerSensor notify Pflanzensensor.*:(min.*|max.*) {
DebianMail('<E-Mail>', 'Smarthome: Pflanzenstand', $NAME meldet $EVTPART0 ist $EVTPART1, '') if( ReadingsAge("Notify_FlowerSensor","$EVTPART0",90000) > 86400 );
fhem("setreading Notify_FlowerSensor $EVTPART0 $EVTPART1");
}
Das wäre nun mit Meldung nur einmal am Tag. Ich gebe zu es ist nicht das was Du hast mit Deiner ganz genauen Meldung. Aber sowas würde ich dann wenn wirklich nur in einer 99_myUtils machen.
Das funktioniert so aber nicht, weil das nicht "einmal pro Tag" bedeutet, sondern "mindestens im Abstand von 86400 Sekunden".
Angenommen, am Montagabend um 23:50 wäre der erste Event des Tages, am Dienstag um 00:05 wäre der erste Event des Folgetages. Dann würde aus Deinem notify heraus KEINE Benachrichtigung verschickt werden, obwohl die Anforderung "einmal pro Tag" zu 100% erfüllt wäre.
So gesehen gebe ich Dir Recht. Ich habe mich da an den Code gehalten der bereits von Grinsekatze vorgegeben war.
Wenn man sich Wort wörtlich an das einmal täglich hält dann muss man es noch etwas erweitern.
Ich würde nicht mit ReadingsAge() arbeiten, sondern per regexp prüfen, ob im ReadingsTimestamp() das heutige Datum steht.
define test_notify notify notifyRegexp { todayTest($year,$month,$mday) }
in der 99_myUtils:
sub todayTest {
my ($year,$month,$mday) = @_;
my $today = sprintf('%04d-%02d-%02d', $year,$month,$mday);
unless(ReadingsTimestamp('device','reading','') =~ $today) {
# macheIrgendwas, wenn das notify heute noch nicht ausgeführt wurde
# mache es in purem perl!
}
return;
}
An die Funktion todayTest können natürlich noch weitere Parameter ($EVENT usw) im Aufruf übergeben werden, die man dann innerhalb der Funktion verwenden kann.
Danke Udo für Deine Hilfe.
Grüße
Und wenn Rudi mitmacht, kann man sowas künftig noch weiter vereinfachen :)
https://forum.fhem.de/index.php/topic,76444.0.html
Ich find ja Dein "wohlwollend" immer so knuffig. ;D
@Damian: Nein, es klappt noch nicht richtig. Die Readings werden angelegt (nachdem ich den Code angepasst hatte) - der Notify erkennt $SELF:
{fhem "setreading $SELF $NAME$reading $EVTPART1"};;\
Aber mit der Timestamp-Bedingung klappt's noch nicht:
Sie wird ignoriert und zzt. bekomme ich wieder alle 2 Stunden alle Meldungen. Ebenfalls erhalte ich regelmäßig ein Fehler imLog:
Zitat2017.09.10 08:45:20 1: PERL WARNING: Odd number of elements in anonymous hash at (eval 504251) line 12.
2017.09.10 08:45:20 3: eval: my $EVTPART1='low';my $SELF='Notify_FlowerSensor';my $EVTPART0='minLux';my $NAME='Pflanzensensor03Wohnzimmer';my $EVENT='minLux low';my $TYPE='XiaomiFlowerSens';{
my $alert;
my $device;
my $reading;
$device = AttrVal("$NAME","alias","$NAME");
$reading = "Fertility" if ($EVTPART0 =~ /Fertility$/);
$reading = "Lux" if ($EVTPART0 =~ /Lux$/);
$reading = "Moisture" if ($EVTPART0 =~ /Moisture$/);
$reading = "Temperature" if ($EVTPART0 =~ /Temperature$/);
# my $tmpfx = $NAME.$reading;
# if ({ReadingsAge($SELF,$tmpfx,0)} gt 86400) {
my $tmpfx2 = {ReadingsAge("Notify_FlowerSensor","Pflanzensensor01WohnzimmerLux",0)};
if ( $tmpfx2 >= 86400) {
if ($EVTPART1 eq "low") {
$alert = "Die Pflanze (".$device.") hat zu wenig Fruchtbarkeit! Gebe etwas Dünger zum Wasser!" if ($EVTPART0 eq "minFertility");
$alert = "Die Pflanze (".$device.") hat zu wenig Sonneneinstrahlung! Stelle sie ins Licht!" if ($EVTPART0 eq "minLux");
$alert = "Die Pflanze (".$device.") hat zu wenig Wasser! Gieße die Pflanze!" if ($EVTPART0 eq "minMoisture");
$alert = "Die Pflanze (".$device.") ist zu kalt! Stelle sie an einen wärmeren Ort!" if ($EVTPART0 eq "minTemperature");
} elsif ($EVTPART1 eq "high") {
$alert = "Die Pflanze (".$device.") hat zu viel Fruchtbarkeit! Der Boden ist zu stark gedüngt!" if ($EVTPART0 eq "maxFertility");
$alert = "Die Pflanze (".$device.") hat zu viel Sonneneinstrahlung! Stelle sie in den Schatten!" if ($EVTPART0 eq "maxLux");
$alert = "Die Pflanze (".$device.") hat zu viel Wasser! Entferne etwas Wasser!" if ($EVTPART0 eq "maxMoisture");
$alert = "Die Pflanze (".$device.") ist zu warm! Stelle sie an einen kälteren Ort!" if ($EVTPART0 eq "maxTemperature");
}
{fhem "setreading $SELF $NAME$reading $EVTPART1"};
if ($alert) {DebianMail('<E-Mail>', 'Smarthome: Pflanzenwarnung '.$device, $alert, '')};
Log 3, "Pflanzenwarnung: $device: $alert" if ($alert);
}
}
$tmpfx2 ist zum testen drin.
@CoolTux: Erweitere die Bedingung mal um ".(low|high)"
Denn das Modul löst auch Events aus mit "ok". Bei deiner einfachen Lösung bekommt Man sonst auch regelmäßige Infos, dass alles ok ist.
Auch würde ich bei der erweiterten Version dem setreading noch einen $NAME für das Reading spendieren. Sonst überschreiben sich ggf. Werte, wenn mehr als 1 Sensor im Einsatz ist.
Danke
So, ich habe meinen Versuch noch einmal überarbeitet:
define Notify_FlowerSensor notify Pflanzensensor.*:(min.*|max.*).(low|high) {\
my $message;;\
my $device = AttrVal("$NAME","alias","$NAME");;\
my $reading;;\
$reading = "Fertility" if ($EVTPART0 =~ /Fertility$/);;\
$reading = "Lux" if ($EVTPART0 =~ /Lux$/);;\
$reading = "Moisture" if ($EVTPART0 =~ /Moisture$/);;\
$reading = "Temperature" if ($EVTPART0 =~ /Temperature$/);;\
my ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime(time);;\
my $today = sprintf('%04d-%02d-%02d', $year,$month,$mday);;\
unless(ReadingsTimestamp($SELF,$NAME.$reading,'') =~ $today) {\
if ($EVTPART1 eq "low") {\
$message = "Die Pflanze (".$device.") hat zu wenig Fruchtbarkeit! Gebe etwas Dünger zum Wasser!" if ($EVTPART0 eq "minFertility");;\
$message = "Die Pflanze (".$device.") hat zu wenig Sonneneinstrahlung! Stelle sie ins Licht!" if ($EVTPART0 eq "minLux");;\
$message = "Die Pflanze (".$device.") hat zu wenig Wasser! Gieße die Pflanze!" if ($EVTPART0 eq "minMoisture");;\
$message = "Die Pflanze (".$device.") ist zu kalt! Stelle sie an einen wärmeren Ort!" if ($EVTPART0 eq "minTemperature");;\
} elsif ($EVTPART1 eq "high") {\
$message = "Die Pflanze (".$device.") hat zu viel Fruchtbarkeit! Der Boden ist zu stark gedüngt!" if ($EVTPART0 eq "maxFertility");;\
$message = "Die Pflanze (".$device.") hat zu viel Sonneneinstrahlung! Stelle sie in den Schatten!" if ($EVTPART0 eq "maxLux");;\
$message = "Die Pflanze (".$device.") hat zu viel Wasser! Entferne etwas Wasser!" if ($EVTPART0 eq "maxMoisture");;\
$message = "Die Pflanze (".$device.") ist zu warm! Stelle sie an einen kälteren Ort!" if ($EVTPART0 eq "maxTemperature");;\
}\
{fhem "setreading $SELF $NAME$reading $EVTPART1"};;\
if ($message) {DebianMail('<E-Mail>', 'Smarthome: Pflanzenwarnung '.$device, $message, '')};;\
Log 3, "Pflanzenwarnung: $device: $message" if ($message);;\
}\
}
attr Notify_FlowerSensor comment Notify zum Überwachen der Pflanzensensoren.
Wobei ich mir bei der unless-Schleife noch unsicher bin: Denn jedes Mal, wenn ich die Config speichere, erhalte ich auch die Emails - was ja erst morgen der Fall sein sollte. Vermutlich habe dort noch einen Fehler:
ReadingsTimestamp($SELF,$NAME.$reading,'')
$NAME$reading (ohne Punkt) funktioniert auch nicht. Da bekomme ich einen Fehler im Log.
Ich werde jetzt mal im Abgleich mit euren Entwürfen gucken, wo ich meinen kürzen kann und ggf. in die myUtils auslagern kann.
Vielen Dank.
Stimmt das mit dem Name wollte ich noch einbauen.
Versuche mal
$NAME${reading}
Grüße
Zitat von: CoolTux am 10 September 2017, 13:06:46
Stimmt das mit dem Name wollte ich noch einbauen.
Versuche mal
$NAME${reading}
Grüße
Nö, klappt nicht:
Zitatsyntax error at (eval 518036) line 11, near "$NAME${reading}"
Hab dann mal ein $NAME{$reading} probiert. Aber dann meckerts wieder:
ZitatGlobal symbol "%NAME" requires explicit package name
Jetzt versuche ich mal
unless(ReadingsTimestamp($SELF,"$NAME$reading",'') =~ /^$today/) {\
Aber momentan bekomme ich noch einen Fehler:
Zitat2017.09.10 13:18:01 1: Timeout for XiaomiFlowerSens_BlockingRun reached, terminated process 21087
2017.09.10 13:18:01 3: (Pflanzensensor01Wohnzimmer) Sub XiaomiFlowerSens_BlockingAborted - The BlockingCall Process terminated unexpectedly. Timedout
${NAME}${reading}
Aber so sollte es gehen. Dachte eines reicht
Auch da bekomme ich die Blocking Fehlermeldung. ::)
Ja habe ich bei mir auch kurz getestet. Ich muss das mal auf meinem Testsystem sauber anschauen. Da habe ich ja noch das was ich oben geschrieben habe.
Also jetzt bin ich sprachlos
Internals:
CFGFN
DEF Pflanze.*:(min.*|max.*) {
fhem("set dummy1 $NAME meldet $EVTPART0 ist $EVTPART1") if( ReadingsAge("notifyTestDummy","$EVTPART0",90000) > 86400 );
fhem("setreading notifyTestDummy $NAME$EVTPART0 $EVTPART1");
}
NAME notifyTestDummy
NR 15
NTFY_ORDER 50-notifyTestDummy
REGEXP Pflanze.*:(min.*|max.*)
STATE 2017-09-09 18:52:53
TYPE notify
READINGS:
2017-09-09 18:52:53 PflanzeWohnzimmermaxTemp high
2017-09-09 18:45:00 maxTemp high
2017-09-09 18:46:00 minHum low
2017-09-09 18:52:36 state active
Attributes:
room Test
$NAME$EVTPART0 klappt super
So geht's mir zzt auch.
Denn selbst ein ReadingsTimestamp($SELF,$NAME.$reading,'')
klappt. Um zu prüfen, ob die Bedingung stimmt habe ich zzt. eine Log 3 Ausgabe mit genau dieser Angabe. Und das klappt auch.
Weiter unten in meinem Code (beim setreading) klappt das ja auch schon länger. Nu bei der unless-Schleife klappt es nicht als Bedingung. :(
Diese wird entweder im Log mit einem Fehler ausgegeben (wenn ich falschen Code verwende beim testen) oder der unless-Teil wird ausgeführt, obwohl die zu prüfenden Readings von heute sind und auf heute geprüft werden.
Und du solltest es wirklich auslagern in meine myUtils. Ist besser.
Zitat von: CoolTux am 10 September 2017, 14:10:11
Und du solltest es wirklich auslagern in meine myUtils. Ist besser.
Werde ich, doch vorher möchte ich es zum Laufen bekommen.
Zitat von: CoolTux am 10 September 2017, 13:51:45
Also jetzt bin ich sprachlos
$NAME$EVTPART0 klappt super
Ich wäre sprachlos, wenn das NICHT funktionieren würde. Das ist doch allersimpelstes perl, das man sich vorstellen kann. Vielleicht mal ein perl Grundlagenbuch lesen?
Zitat von: betateilchen am 10 September 2017, 14:30:30
Ich wäre sprachlos, wenn das NICHT funktionieren würde. Das ist doch allersimpelstes perl, das man sich vorstellen kann. Vielleicht mal ein perl Grundlagenbuch lesen?
Das bezog sich auf die Aussage von Grinsekatze das er Probleme damit hatte. Und da ich vor Monaten ähnliche Probleme hatte aber nicht mit zwei Variablen sondern mit einer String Variablen Kombination mein schneller Schuss zu ${var} das kannte ich noch von Andre.
Daher also meine Verblüffung das es nun doch einfach so geht wie ich es auch gedacht hätte.
Zitat von: betateilchen am 10 September 2017, 14:30:30
Ich wäre sprachlos, wenn das NICHT funktionieren würde. Das ist doch allersimpelstes perl, das man sich vorstellen kann. Vielleicht mal ein perl Grundlagenbuch lesen?
Das dachte ich auch. Darum habe ich es ja so gemacht. Aber dennoch, ich bekomme dann eine Fehlermeldung im Log:
unless(ReadingsTimestamp($SELF,$NAME$reading,'') =~ $today) {\
Produziert einen Fehler im Log:
Zitat2017.09.10 14:44:38 1: PERL WARNING: Scalar found where operator expected at (eval 1775) line 11, near "$NAME$reading"
2017.09.10 14:44:38 3: eval: my $SELF='Notify_FlowerSensor';my $EVTPART1='low';my $NAME='Pflanzensensor02Wohnzimmer';my $EVENT='minTemperature low';my $EVTPART0='minTemperature';my $TYPE='XiaomiFlowerSens';{
my $message;
my $device = AttrVal($NAME,"alias",$NAME);
my $reading;
$reading = "Fertility" if ($EVTPART0 =~ /Fertility$/);
$reading = "Lux" if ($EVTPART0 =~ /Lux$/);
$reading = "Moisture" if ($EVTPART0 =~ /Moisture$/);
$reading = "Temperature" if ($EVTPART0 =~ /Temperature$/);
my ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime(time);
my $today = sprintf('%04d-%02d-%02d', $year,$month,$mday);
unless(ReadingsTimestamp($SELF,$NAME$reading,'') =~ $today) {
if ($EVTPART1 eq "low") {
$message = "Die Pflanze (".$device.") hat zu wenig Fruchtbarkeit! Gebe etwas Dünger zum Wasser!" if ($EVTPART0 eq "minFertility");
$message = "Die Pflanze (".$device.") hat zu wenig Sonneneinstrahlung! Stelle sie ins Licht!" if ($EVTPART0 eq "minLux");
$message = "Die Pflanze (".$device.") hat zu wenig Wasser! Gieße die Pflanze!" if ($EVTPART0 eq "minMoisture");
$message = "Die Pflanze (".$device.") ist zu kalt! Stelle sie an einen wärmeren Ort!" if ($EVTPART0 eq "minTemperature");
} elsif ($EVTPART1 eq "high") {
$message = "Die Pflanze (".$device.") hat zu viel Fruchtbarkeit! Der Boden ist zu stark gedüngt!" if ($EVTPART0 eq "maxFertility");
$message = "Die Pflanze (".$device.") hat zu viel Sonneneinstrahlung! Stelle sie in den Schatten!" if ($EVTPART0 eq "maxLux");
$message = "Die Pflanze (".$device.") hat zu viel Wasser! Entferne etwas Wasser!" if ($EVTPART0 eq "maxMoisture");
$message = "Die Pflanze (".$device.") ist zu warm! Stelle sie an einen kälteren Ort!" if ($EVTPART0 eq "maxTemperature");
}
# {fhem "setreading $SELF $NAME$reading $EVTPART1"};
if ($message) {DebianMail('<EMAIL>', 'Smarthome: Pflanzenwarnung '.$device, $message, '')};
Log 3, "Pflanzenwarnung: $device: $message" if ($message);
}
}
2017.09.10 14:44:38 1: ERROR evaluating my $SELF='Notify_FlowerSensor';my $EVTPART1='low';my $NAME='Pflanzensensor02Wohnzimmer';my $EVENT='minTemperature low';my $EVTPART0='minTemperature';my $TYPE='XiaomiFlowerSens';{
my $message;
my $device = AttrVal($NAME,"alias",$NAME);
my $reading;
$reading = "Fertility" if ($EVTPART0 =~ /Fertility$/);
$reading = "Lux" if ($EVTPART0 =~ /Lux$/);
$reading = "Moisture" if ($EVTPART0 =~ /Moisture$/);
$reading = "Temperature" if ($EVTPART0 =~ /Temperature$/);
my ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime(time);
my $today = sprintf('%04d-%02d-%02d', $year,$month,$mday);
unless(ReadingsTimestamp($SELF,$NAME$reading,'') =~ $today) {
if ($EVTPART1 eq "low") {
$message = "Die Pflanze (".$device.") hat zu wenig Fruchtbarkeit! Gebe etwas Dünger zum Wasser!" if ($EVTPART0 eq "minFertility");
$message = "Die Pflanze (".$device.") hat zu wenig Sonneneinstrahlung! Stelle sie ins Licht!" if ($EVTPART0 eq "minLux");
$message = "Die Pflanze (".$device.") hat zu wenig Wasser! Gieße die Pflanze!" if ($EVTPART0 eq "minMoisture");
$message = "Die Pflanze (".$device.") ist zu kalt! Stelle sie an einen wärmeren Ort!" if ($EVTPART0 eq "minTemperature");
} elsif ($EVTPART1 eq "high") {
$message = "Die Pflanze (".$device.") hat zu viel Fruchtbarkeit! Der Boden ist zu stark gedüngt!" if ($EVTPART0 eq "maxFertility");
$message = "Die Pflanze (".$device.") hat zu viel Sonneneinstrahlung! Stelle sie in den Schatten!" if ($EVTPART0 eq "maxLux");
$message = "Die Pflanze (".$device.") hat zu viel Wasser! Entferne etwas Wasser!" if ($EVTPART0 eq "maxMoisture");
$message = "Die Pflanze (".$device.") ist zu warm! Stelle sie an einen kälteren Ort!" if ($EVTPART0 eq "maxTemperature");
}
# {fhem "setreading $SELF $NAME$reading $EVTPART1"};
if ($message) {DebianMail('<EMAIL>', 'Smarthome: Pflanzenwarnung '.$device, $message, '')};
Log 3, "Pflanzenwarnung: $device: $message" if ($message);
}
}: syntax error at (eval 1775) line 11, near "$NAME$reading"
syntax error at (eval 1775) line 17, near "} elsif"
Global symbol "$message" requires explicit package name at (eval 1775) line 18.
Global symbol "$device" requires explicit package name at (eval 1775) line 18.
Global symbol "$message" requires explicit package name at (eval 1775) line 19.
Global symbol "$device" requires explicit package name at (eval 1775) line 19.
Global symbol "$message" requires explicit package name at (eval 1775) line 20.
Global symbol "$device" requires explicit package name at (eval 1775) line 20.
Global symbol "$message" requires explicit package name at (eval 1775) line 21.
Global symbol "$device" requires explicit package name at (eval 1775) line 21.
syntax error at (eval 1775) line 22, near ";
}"
(eval 1775) has too many errors.
2017.09.10 14:44:38 3: Notify_FlowerSensor return value: syntax error at (eval 1775) line 11, near "$NAME$reading"
syntax error at (eval 1775) line 17, near "} elsif"
Global symbol "$message" requires explicit package name at (eval 1775) line 18.
Global symbol "$device" requires explicit package name at (eval 1775) line 18.
Global symbol "$message" requires explicit package name at (eval 1775) line 19.
Global symbol "$device" requires explicit package name at (eval 1775) line 19.
Global symbol "$message" requires explicit package name at (eval 1775) line 20.
Global symbol "$device" requires explicit package name at (eval 1775) line 20.
Global symbol "$message" requires explicit package name at (eval 1775) line 21.
Global symbol "$device" requires explicit package name at (eval 1775) line 21.
syntax error at (eval 1775) line 22, near ";
}"
(eval 1775) has too many errors.
Hm, ich glaub ich habe meinen Fehler gefunden: $today enthält nicht das tatsächliche heutige Datum. Also ist die Bedingung ja immer wahr und es werden immer mails geschickt.
Gib doch mal { $today } in der FHEM Kommandozeile ein
Vorsicht! Das funktioniert erst ab dem morgigen Update!
So, nun scheint es endlich zu funktionieren. Ich habe in all dem hin und her total übersehen den Monat und das Jahr anzugleichen. Nun sollte es aber funktionieren - ich kann also ans Auslagern gehen :)
define Notify_FlowerSensor notify Pflanzensensor.*:(min.*|max.*).(low|high) {\
my $message;;\
my $device = AttrVal($NAME,"alias",$NAME);;\
my $reading;;\
$reading = "Fertility" if ($EVTPART0 =~ /Fertility$/);;\
$reading = "Lux" if ($EVTPART0 =~ /Lux$/);;\
$reading = "Moisture" if ($EVTPART0 =~ /Moisture$/);;\
$reading = "Temperature" if ($EVTPART0 =~ /Temperature$/);;\
my ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime(time);;\
my $today = sprintf('%04d-%02d-%02d', $year+=1900,$month+=1,$mday);;\
unless(ReadingsTimestamp($SELF,"$NAME$reading","") =~ /^$today/) {\
if ($EVTPART1 eq "low") {\
$message = "Die Pflanze (".$device.") hat zu wenig Fruchtbarkeit! Gebe etwas Dünger zum Wasser!" if ($EVTPART0 eq "minFertility");;\
$message = "Die Pflanze (".$device.") hat zu wenig Sonneneinstrahlung! Stelle sie ins Licht!" if ($EVTPART0 eq "minLux");;\
$message = "Die Pflanze (".$device.") hat zu wenig Wasser! Gieße die Pflanze!" if ($EVTPART0 eq "minMoisture");;\
$message = "Die Pflanze (".$device.") ist zu kalt! Stelle sie an einen wärmeren Ort!" if ($EVTPART0 eq "minTemperature");;\
} elsif ($EVTPART1 eq "high") {\
$message = "Die Pflanze (".$device.") hat zu viel Fruchtbarkeit! Der Boden ist zu stark gedüngt!" if ($EVTPART0 eq "maxFertility");;\
$message = "Die Pflanze (".$device.") hat zu viel Sonneneinstrahlung! Stelle sie in den Schatten!" if ($EVTPART0 eq "maxLux");;\
$message = "Die Pflanze (".$device.") hat zu viel Wasser! Entferne etwas Wasser!" if ($EVTPART0 eq "maxMoisture");;\
$message = "Die Pflanze (".$device.") ist zu warm! Stelle sie an einen kälteren Ort!" if ($EVTPART0 eq "maxTemperature");;\
}\
{fhem "setreading $SELF $NAME$reading $EVTPART1"};;\
if ($message) {DebianMail('<EMAIL>', 'Smarthome: Pflanzenwarnung '.$device, $message, '')};;\
Log 3, "Pflanzenwarnung: $device: $message" if ($message);;\
}\
}
attr Notify_FlowerSensor comment Notify zum Überwachen der Pflanzensensoren.
Vielen Dank noch mal an eure aktive Unterstützung.
Wobei, eine Frage habe ich nun noch:
Mir ist im Log aufgefgallen, dass jedes Mal, wenn der Notify nichts macht, nachdem er getriggert wurde (also etwa immer, wenn der unless-Teil false ist) bekomme ich diese Einräge:
2017.09.10 19:21:20 3: Notify_FlowerSensor return value: 1
Kann ich das irgendwie unterdrücken, sodass es mir nicht das Log voll spamt?
Zitat von: Grinsekatze am 10 September 2017, 19:51:08
Kann ich das irgendwie unterdrücken, sodass es mir nicht das Log voll spamt?
ja, mit einem return am Ende.
Wie ich schon sagte: simpelste perl Grundlagen...