Wie Notify nur täglich ausführen und nicht bei jedem Trigger?

Begonnen von Grinsekatze, 02 September 2017, 11:26:10

Vorheriges Thema - Nächstes Thema

Grinsekatze

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.

Otto123

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
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

majorshark

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.
Grüße aus Dewitz

VM auf Synology DS718+ mit FHEM 5.9 auf Debian 9.5/32-Bit (stretch)
Nächster Leipziger Stammtisch:

rubbertail

#3
Oder noch einfacher: Im notify zuletzt sich selbst

attr <notifyname> disable 1

setzen und über ein AT um 0:00 wieder auf 0 setzen
FHEM auf Raspi, CUL433, CUL868, RFXTRX433e, CULCuBE
FRITZ: Fritzbox7590AX, 6xFritzDECT301, 10xFritzDECT200, FritzRepeater 6000
MAX!: Fensterkontakte
netatmo: Wetterstation & Thermostat
Milights, IT, Withings, HUE

Damian

Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

betateilchen

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.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Grinsekatze

#6
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.

Grinsekatze

#7
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.

Benni

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#

Grinsekatze

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?

Damian

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.

Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Grinsekatze

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

Beta-User

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
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

Benni

#13
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)

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 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.

Beta-User

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!
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors