event-on-... Vermeidung mehrfacher Log-Einträge

Begonnen von Gast45, 01 November 2019, 17:27:39

Vorheriges Thema - Nächstes Thema

Gast45

Hallo zusammen,

diese Geschichte ist vielleicht nur ein Nischen-Thema, aber vielleicht gibt es ja doch mehrere, die es interessiert, oder vielleicht hat auch jemand mit den bisher bestehenden Möglichkeiten eine Lösung gefunden?

Hier die gegebene Situation:
Ich habe Temperatursensoren die unmittelbar nacheinander (innerhalb von ms) Werte für Temperatur und Luftfeuchtigkeit übermitteln. Zusätzlich berechne ich noch Taupunkt und absolute Feuchte.
Im Log hätte ich gerne eine kompakte Darstellung in der Form: "T: 12.3 H: 12.3 D: 12.3 A: 12.3" (natürlich Phantasiewerte).
Das habe ich auch soweit erreicht mit folgender prinzipieller Verfahrensweise:


  • Mittels event-on-change lösen nur Änderungen der Temperatur und der Luftfeuchte ein Event aus
  • Aufgrund dierer beiden möglichen Events wird die Routine "dewpoint" aufgerufen
  • Nach Durchlauf wird das Reading "dewpoint" aktualisiert
  • Auf event-on-update wird über den "dewpoint" ein userReading "mystate" gebildet, dass die oben gezeigte Darstellung "T: 12.3 H:......" bildet
  • Mittels event-on-change lösen nur Änderungen an mystate letztlich einen Eintrag im Log aus

Soweit so gut....., zumindest, wenn sich nur ein Wert ändert oder die Änderungen so minimal sind, dass sich "mystate" am Ende nicht ändert.
(Anmerkung: Sensor sendet mit zwei Nachkommastellen; "mystate" arbeitet mit einer Nachkommastelle, das "glättet" etwas)

Hier mein "Problem":
Wenn sich sowohl Temperatur, als auch Leuftfeutigkeit so ändern, dass jede einzelne Änderung für sich auch zu einer Veränderung des userReadings "mystate" führt, dann erscheinen natürlich (scheinbar gleichzeitig) zwei Zeilen im Log. Natürlich ist nur die Letzte der beiden wirklich interessant.

Hier mein "Wunsch":
Wäre es denkbar oder ist es vielleicht sogar möglich, Events eine einstellbare Zeit zu verzögern und durch neue Events zu überschreiben?
In meinem Fall würde ich mir das so vorstellen:

  • Geänderter Temperaturwert ändert am Ende das userReadings "mystate" und somit entsteht ein Event
  • Das Event wird zurückgehalten, vielleicht nach einer User definierbaren Zeit, z.B. 2 Sekunden
  • Der nahezu zeitgleich  übermittelte Luftfeuchtewert ändert auch das userReading "mystate" und somit entsteht erneut ein Event
  • Da dieses neue Event innerhalb der (hier) 2 Sekunden entsteht, wird der erste verworfen, der zweite nach witeren 2 Sekunden durchgeführt, und es kommt nur ein Eintrag ins Log

Als Syntax könnte ich mir vorstellen:
attr <device> event-on-change-reading <reading>[:<Verzögerung>][,<reading>[:<Verzögerung>]]

Ist soetwas überhaupt denkbar oder greift das zu tief in die grundsätzliche Philosophie des Codes ein? Gibt es überhaupt noch Leute, die das für relevant halten? Im Prinzip ist es ja ein rein "optisches Problem". Soweit ich sehe, funktioniert das plotten der Werte auch so. Es würde halt etwas Speicherplatz im Log sparen.
Meist liegt der Fehler vor der Tastatur

frober

#1
Commandref lesen, genau das ist schon möglich.

Jedoch nicht als Zeit, sondern als Größe der Veränderung.
Raspi 3b mit Raspbian Bullseye und relativ aktuellem Fhem,  FS20, LGW, PCA301, Zigbee, MQTT, MySensors mit RS485(CAN-Receiver) und RFM69, etc.,
einiges umgesetzt, vieles in Planung, smile

********************************************
...man wächst mit der Herausforderung...

Gast45

Ja, soweit war ich schon. Aber das hilft ja nicht. Es geht ja hier darum, dass sich teilweise zwei Werte ändern und Events auslösen.
Zudem viel wichtiger, je höher das Delta zum vorherigen Wert einer Größe, umso wahrscheinlicher ist auch, dass sich der zweite Wert auch verändert und damit steigt die Wahrscheinlichkeit für doppelte Einträger nur noch mehr. :)
Meist liegt der Fehler vor der Tastatur

Pfriemler

Eine Verzögerung der Eventbehandlung löst Dein Problem aber nicht. Es wird nur zeitlich verschoben - wenn Du unterschiedliche Verzögerungen angibst, werden bei gleichzeitiger Änderung beider Werte die Log-Einträge entsprechend zeitlich geändert.
event-min-interval löst das Problem auch nicht - hier würde ja gerade der zweite aktuellere und damit interessantere Wert unterdrückt werden.
Als Krücke würde ich auf die Änderung von dewpoint reagieren und mit einem DOIF zeitverzögert (z.B. 5s) den Wert z.B. per setreading in ein drittes Reading schreiben, welches dann geloggt wird. Eine erneute kurzfristige Änderung von dewpoint würde das DOIF nur retriggern, bevor die eigentliche Aktion ausgeführt wird. Muss man natürlich entsprechend einstellen.
Geht sicher noch eleganter...
"Änd're nie in fhem.cfg, denn das tut hier allen weh!" *** Wheezy@Raspi(3), HMWLAN+HMUART, CUL868(SlowRF) für FHT+KS+FS20, miniCUL433, Rademacher DuoFern *** "... kaum macht man es richtig, funktioniert es ..."

Gast45

ZitatEine Verzögerung der Eventbehandlung löst Dein Problem aber nicht. Es wird nur zeitlich verschoben - wenn Du unterschiedliche Verzögerungen angibst, werden bei gleichzeitiger Änderung beider Werte die Log-Einträge entsprechend zeitlich geändert.
Darum war meine Idee, dass ein neues Event innerhalb der Verzögerungszeit den vorherigen Event überschreibt. Der erste also ausfällt.

Zitatevent-min-interval löst das Problem auch nicht - hier würde ja gerade der zweite aktuellere und damit interessantere Wert unterdrückt werden.
genau :)

ZitatAls Krücke würde ich auf die Änderung von dewpoint reagieren und mit einem DOIF zeitverzögert (z.B. 5s) den Wert z.B. per setreading in ein drittes Reading schreiben, welches dann geloggt wird. Eine erneute kurzfristige Änderung von dewpoint würde das DOIF nur retriggern, bevor die eigentliche Aktion ausgeführt wird. Muss man natürlich entsprechend einstellen.
Mein userReading "mystate" wird von dewpoint getriggert, aber da kann man keine Zeiten angeben. DOIF muss ich mir morgen mal ansehen, danke dafür. Aber würde das DOIF dann nicht auch zweimal durchlaufen? Mh, wie gesagt.... morgen :)
Meist liegt der Fehler vor der Tastatur

Gast45

DOIF ist ja eine Wissenschaft für sich und ich tu mich auch noch schwer das vernünftig umzusetzen.

Dennoch glaube ich eine Lösung zu haben. Statt mein userReading "mystate" direkt zu loggen, habe ich jetzt ein DOIF gebastelt, das vom Reading "dewpoint" im Device "Sensor" getriggert wird und dann nach 2 Sekunden (wait) den Inhalt meines userReadings "mystate" (das ja inzwischen den endgültigen Stand haben sollte) in ein weiteres userReading "test" kopiert:

(["Sensor:dewpoint"])(setreading Sensor test [Sensor:mystate])

Und dieses "test" logge ich dann mittels event-on-change.


Ich werde aber den Eindruck nicht los, dass ich DOIF so nicht richtig nutze, obwohl es scheinbar klappt. Was müsste ich den machen, wenn mein DOIF das userReading "mystate" im Format "T: 12.3 H: 12.3 D: 12.3 A: 12.3" direkt bauen soll? Irgendwie werde ich aus den Anleitungen noch nicht schlau :(

Meist liegt der Fehler vor der Tastatur

Gast45

Oje, überall ist die Syntax eine andere.

Syntax bei "attr <device> userReading"

mystate:dewpoint.* {"T: ".ReadingsNum("Sensor","temperature",0,1)." H: ".ReadingsNum("Sensor","humidity",0,1)." D: ".ReadingsVal("Sensor","dewpoint",0)." A: ".ReadingsVal("Sensor","absFeuchte",0)}

Syntax bei "DOIF"
(setreading  Sensor mystate T: [Sensor:temperature:d:sprintf("%.1f",$1)] H: [Sensor:humidity:d:sprintf("%.1f",$1)] D: [Sensor:dewpoint] A: [Sensor:absFeuchte])


Also mir fällt es schwer da durchzusteigen. Ich brauche immer mehrere Tage und am Ende schnell irgendwo notieren, damit man es später nochmal hinbekommt. Aber Verstehen ist was anderes :)
Meist liegt der Fehler vor der Tastatur

Damian

Das sollte doch nicht so kompliziert sein ;)

define werte DOIF

attr werte state T: [Sensor:temperature:d1] H: [Sensor:humidity:d1] D: [Sensor:dewpoint:d1] A: [Sensor:absFeuchte:d1]
attr werte event-on-change state


Loggen kannst du auf werte.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Pfriemler

Hm .. ich gestehe, dass ich Damians Vorschlag in Bezug auf die Fragestellung nicht ganz durchblicke: Das DOIF "werte" ist dann eigentlich nur ein Formatierungstool. Das Hilfs-DOIF sollte hingegen eigentlich ein Reading in einem anderen Gerät aktualisieren - von der Funktion her ist es dann eher ein zeitverzögertes userReading.

ungeprüft dahingeworfen (sorry):
Diese Funktion ersetzt nebenbei das userReading myState im Sensor (also dort löschen).

define di_Sensor_myState DOIF ([Sensor:dewpoint]) (setreading Sensor myState [Sensor:temperature:d1] H: [Sensor:humidity:d1] D: [Sensor:dewpoint:d1] A: [Sensor:absFeuchte:d1])
attr di_Sensor_myState wait 5
attr di_Sensor_myState do resetwait


Das sollte bei jedem von Sensor:dewpoint ausgelösten Event das Reading myState im Sensor entsprechend neu setzen , und zwar 5 Sekunden nach der Änderung, sofern in diesen 5 Sekunden nicht ein weiteres Event Sensor:dewpoint erzeugt wird, welches die Wartezeit zurücksetzt.

Bitte auf mich einprügeln, wenn ich falsch liege...
"Änd're nie in fhem.cfg, denn das tut hier allen weh!" *** Wheezy@Raspi(3), HMWLAN+HMUART, CUL868(SlowRF) für FHT+KS+FS20, miniCUL433, Rademacher DuoFern *** "... kaum macht man es richtig, funktioniert es ..."

Gast45

Zunächst danke an euch beide :)

Ich nehme für mich mit:

1. Das Runden hätte ich auch leichter haben können ;)

2. An der Lösung von Pfriemler war ich schon nah dran. Ich muss mal lesen, inwieweit mir ,,do resetwait" im Vergleich zu meinen ,,do always" Vorteile bringt

3. Ebenfalls muss ich mal lesen, was der Unterschied zwischen den Triggern (["Sensor:dewpoint"]) und ([Sensor:dewpoint]) ist. Ich habe mit Anführungszeichen gewählt und scheint ja zu funktionieren. Soviel wieder zu der Syntax-Verwirrung :)
Meist liegt der Fehler vor der Tastatur

Damian

#10
Du schreibst:

ZitatIch habe Temperatursensoren die unmittelbar nacheinander (innerhalb von ms) Werte für Temperatur und Luftfeuchtigkeit übermitteln. Zusätzlich berechne ich noch Taupunkt und absolute Feuchte.

Wenn Temperatur und Feuchte vom gleichen Sensor kommen, dann sind sie normalerweise innerhalb eines Eventblocks, genauso wie dewpoint-Berechnung. So sieht es bei mir aus:
Zitat
2019-11-03 15:21:47.654 CUL_WS Aussensensor T: 12.9  H: 81.8
2019-11-03 15:21:47.654 CUL_WS Aussensensor temperature: 12.9
2019-11-03 15:21:47.654 CUL_WS Aussensensor humidity: 81.8
2019-11-03 15:21:47.654 CUL_WS Aussensensor dewpoint: 9.9


DOIF arbeitet hier anders als notify. Für DOIF ist das ein Trigger und nicht vier, daher wird in meinem Beispiel nur einmal der Status geändert und nicht vier mal. Sollten die Events nicht innerhalb eines Blocks liegen (was ich mir kaum vorstellen kann, da du den gleichen Sensor definiert hast), dann kannst du nur auf das letzte Event reagieren, also in meinem Beispiel:

attr werte state T: [?Sensor:temperature:d1] H: [?Sensor:humidity:d1] D: [Sensor:dewpoint:d1] A: [?Sensor:absFeuchte:d1]

In beiden Fällen sollten irgendwelche Verzögerungen hier nicht erforderlich sein.

Loggen darfst du natürlich nur noch auf den Status des DOIFs.


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

Gast45

#11
Hi Damian,

Die Werte kommen vom gleichen Sensor, aber es liegen tatsächlich einige ms dazwischen. Ich spiele gerade mit BME280-Sensoren, die mittels ESP-01 die Werte über WLAN bringen (ESPeasy).

Ich habe noch nicht geprüft, ob die Werte wirklich immer in der gleichen Reihenfolge kommen. Wenn das so ist, dann ist das sicher die beste Lösung. Wollte mich bisher allerdings nicht darauf verlassen. Obwohl wir hier von einem Computerprogramm reden, das gewöhnlich nichts zufällig macht ;)

Zumindest war ich jetzt mal ,,gezwungen" meine ersten Schritte mit DOIF zu machen....

Und wieder was neues: wieso jetzt ,,?Sensor"?  ;D
Meist liegt der Fehler vor der Tastatur

Gast45

Und mir fällt ein:

Ich wollte nur Änderungen im Log. Deshalb habe ich event-on-change gemacht. Da ich aber nicht weiß, ob sich Temperatur und/oder Luftfeuchtigkeit ändern, muss ich schon auf beide reagieren.
Meist liegt der Fehler vor der Tastatur

Damian

Zitat von: Gast45 am 03 November 2019, 15:44:15
Hi Damian,

Die Werte kommen vom gleichen Sensor, aber es liegen tatsächlich einige ms dazwischen. Ich spiele gerade mit BME280-Sensoren, die mittels ESP-01 die Werte über WLAN bringen (ESPeasy).

Ich habe noch nicht geprüft, ob die Werte wirklich immer in der gleichen Reihenfolge kommen. Wenn das so ist, dann ist das sicher die beste Lösung. Wollte mich bisher allerdings nicht darauf verlassen. Obwohl wir hier von einem Computerprogramm reden, das gewöhnlich nichts zufällig macht ;)

Zumindest war ich jetzt mal ,,gezwungen" meine ersten Schritte mit DOIF zu machen....

Und wieder was neues: wieso jetzt ,,?Sensor"?  ;D

OK, dann musst du Events bzgl. der Reihenfolge mal untersuchen. Sollten sie sich "überholen", dann wird die Lösung mit do resetwait vom Pfriemler die beste sein.

PS: Bedeutung von d1, ?Sensor, do resetwait sowie der Unterschied zwischen (["Sensor:dewpoint"]) und ([Sensor:dewpoint]) ist in der Commandref zu DOIF beschrieben.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF