FHEM Forum

FHEM => Anfängerfragen => Thema gestartet von: Mad-at am 28 November 2021, 17:42:49

Titel: [Gelöst] Mittelwert mehrerer Devicereadings erzeugen und weiterreichen
Beitrag von: Mad-at am 28 November 2021, 17:42:49
Hallo!

Habe gerade ein Brett vorm Kopf, vielleicht kann ja jemand helfen.
Ich möchte den Mittelwert des Temperaturreadings mehrer Temperaturdevices bilden um diesen dann über MQTT2 an meine Heizung zu senden.

Mit dem Temperaturreading eines Devices funktioniert das Ganze. Aber dann war ich "superschlau" und habe versucht den Mittelwert mit einem kanibalisierten DOIF zu errechnen. Das an sich funktioniert ebenfalls, ist aber nicht mittels RegExp fürs notify auslesbar.
Nächster Versuch: ein Dummydevice das alle Readings mittels Notify gefüttert bekommt und dann als UserReadings Wert den Mittelwert errechnet. Ein bisschen durch die Brust ins Auge, könnte aber funktionieren. Denkste. Nächstes Problem: die Readings meiner KNX Devices lassen sich entweder nicht mit notify auslesen oder nicht mit set oder setreading schreiben.


Internals:
   DEF        Temperatur_EG_Esszimmer:state:.* setreading Mitteltemperatur EGDecketemperatur $EVTPART1
   FUUID      61a39f44-f33f-db1a-e3a7-5c3673b978d4e200
   NAME       Temperatur_EG_EsszimmerDecke_toMitteltemperatur
   NOTIFYDEV  Temperatur_EG_Esszimmer
   NR         100
   NTFY_ORDER 50-Temperatur_EG_EsszimmerDecke_toMitteltemperatur
   REGEXP     Temperatur_EG_Esszimmer:state:.*
   STATE      2021-11-28 17:02:27
   TRIGGERTIME 1638115347.07679
   TYPE       notify
   Helper:
     DBLOG:
       state:
         DBLogging:
           TIME       1638115617.02407
           VALUE      active
   READINGS:
     2021-11-28 17:06:57   state           active
Attributes:


Edit: Ich sollte vielleicht erwähnen, dass es mit LaCrosse Devices sehr gut klappt. Nur spezielle bei den KNX Devices geht es nicht


Internals:
   DEF        Esszimmer:temperature:.* setreading Mitteltemperatur Esszimmertemperatur $EVTPART1
   FUUID      61a39d91-f33f-db1a-88e1-ebb9285c6a41936f
   NAME       LaCrosseEsszimmer_toMitteltemperatur
   NOTIFYDEV  Esszimmer
   NR         96
   NTFY_ORDER 50-LaCrosseEsszimmer_toMitteltemperatur
   REGEXP     Esszimmer:temperature:.*
   STATE      2021-11-28 18:00:47
   TRIGGERTIME 1638118847.61745
   TYPE       notify
   READINGS:
     2021-11-28 16:24:52   state           active
Attributes:



Ein mit dem Eventmonitor angelegtes Notify setzt gleich ganz den aktuellen Reading Wert

defmod Temperatur_EG_Esszimmer_notify_1 notify Temperatur_EG_Esszimmer:21.06 {}

Führt mich auch nicht weiter.

Also alles ein wenig wirr. Ich wäre dankbar wenn mich jemand an die Hand nehmen könnte und mich in die richtige Richtung drehen würde. Ich glaub ich seh vor lauter Bäumen keinen Wald...
Titel: Antw:Mittelwert mehrerer Devicereadings erzeugen und (mit Notify?) weiterreichen
Beitrag von: Mad-at am 28 November 2021, 19:13:54
OK, einen großen Schritt weiter - vielleicht hilft es jemand anderem
Um Werte aus KNX mit Notify an ein Dummy Device weiterzugeben braucht es folgendes Notify:


defmod Temperatur_EG_EsszimmerDecke_toMitteltemperatur notify Temperatur_EG_Esszimmer:getG1:.* setreading Mitteltemperatur EGDecketemperatur $EVTPART1
Titel: Antw:Mittelwert mehrerer Devicereadings erzeugen und (mit Notify?) weiterreichen
Beitrag von: Mad-at am 28 November 2021, 20:04:11
So, nun geht's auch mit Mittelwert im Dummy Berechnen:


Internals:
   DEF       
   FUUID      61a39d91-f33f-db1a-dbab-db8aa41977e5c757
   NAME       Mitteltemperatur
   NR         93
   STATE      21.0 °C
   TYPE       dummy
   Helper:
     DBLOG:
       EGDecketemperatur:
         DBLogging:
           TIME       1638125849.44105
           VALUE      21.08
       EGGlastastertemperatur:
         DBLogging:
           TIME       1638126048.43081
           VALUE      20.70
       Esszimmertemperatur:
         DBLogging:
           TIME       1638126081.73458
           VALUE      21.1
       Mitteltemperatur:
         DBLogging:
           TIME       1638126081.73458
           VALUE      20.96
       state:
         DBLogging:
           TIME       1638114761.22285
           VALUE      EGDecketemperatur
   OLDREADINGS:
   READINGS:
     2021-11-28 19:57:29   EGDecketemperatur 21.08
     2021-11-28 20:00:48   EGGlastastertemperatur 20.70
     2021-11-28 20:01:21   Esszimmertemperatur 21.1
     2021-11-28 20:01:21   Mitteltemperatur 20.96
Attributes:
   reading01Name Zeit
   reading01Regex localtime("time":"([\d]+))
   reading02Name Esszimmertemperatur
   reading02Regex value":([\d\.-]+)
   reading03Name EGGlastastertemperatur
   reading03Regex value":([\d\.-]+)
   reading04Name EGDecketemperatur
   reading05Name Mitteltemperatur
   reading05Regex value":([\d\.-]+)
   stateFormat {sprintf("%.1f °C", ReadingsVal("$name","Mitteltemperatur",0))}
   userReadings Mitteltemperatur { (ReadingsVal("Mitteltemperatur","Esszimmertemperatur", 0) + ReadingsVal("Mitteltemperatur","EGGlastastertemperatur", 0) + ReadingsVal("Mitteltemperatur","EGDecketemperatur", 0) )/3 }
   userattr   reading01Name reading01Regex reading02Name reading02Regex reading03Name reading03Regex reading04Name reading04Regex reading05Name reading05Regex


Device schaut so aus:

defmod Mitteltemperatur dummy
attr Mitteltemperatur userattr reading01Name reading01Regex reading02Name reading02Regex reading03Name reading03Regex reading04Name reading04Regex reading05Name reading05Regex
attr Mitteltemperatur reading01Name Zeit
attr Mitteltemperatur reading01Regex localtime("time":"([\d]+))
attr Mitteltemperatur reading02Name Esszimmertemperatur
attr Mitteltemperatur reading02Regex value":([\d\.-]+)
attr Mitteltemperatur reading03Name EGGlastastertemperatur
attr Mitteltemperatur reading03Regex value":([\d\.-]+)
attr Mitteltemperatur reading04Name EGDecketemperatur
attr Mitteltemperatur reading05Name Mitteltemperatur
attr Mitteltemperatur reading05Regex value":([\d\.-]+)
attr Mitteltemperatur stateFormat {sprintf("%.1f °C", ReadingsVal("$name","Mitteltemperatur",0))}
attr Mitteltemperatur userReadings Mitteltemperatur { (ReadingsVal("Mitteltemperatur","Esszimmertemperatur", 0) + ReadingsVal("Mitteltemperatur","EGGlastastertemperatur", 0) + ReadingsVal("Mitteltemperatur","EGDecketemperatur", 0) )/3 }


Das erzeugt, anders als das DOIF auch jedesmal ein Regexp auslesbares event dass dann mittels Notify weiterverarbeitet werden kann.
Weiterleitung mit


defmod LaCrosseToMQTT_Innentemp notify Mitteltemperatur:Mitteltemperatur:.* set Innentemp_MQTT temperature $EVTPART1

Nicht etwa setreading, sonst funktioniert es dann mit dem MQTT Publishing nicht.

Vielleicht hilfts ja wem...
Titel: Antw:[Gelöst] Mittelwert mehrerer Devicereadings erzeugen und weiterreichen
Beitrag von: Gisbert am 28 November 2021, 20:44:33
Hallo Mad-at,

schön, dass du eine Lösung gefunden hast, die funktioniert. Sie scheint mir nur reichlich kompliziert.

Ich hab mal versucht Mittelwerte (geht aber auch gut für die Suche nach Minimal- oder Maximalwerten) von verschiedenen Readings zu erhalten. Dazu habe ich eine Funktion in 99_myUtils.pm reingesetzt:
sub av_cloudCover() {
    my $avcloudCover="";
    my $avdev="";
    my $anzahl=1;
    foreach my $device (qw(Leverkusen.DarkSky Leverkusen.OpenWeatherMap)) {
        my $cloudCover = ReadingsNum($device, "cloudCover", 0);
        my $age = ReadingsAge($device, "cloudCover", 0);
        if($age <= 1800) {
            $avcloudCover=($avcloudCover*($anzahl-1)+$cloudCover)/$anzahl;
            $avdev=$device;
            $anzahl=$anzahl+1;
            }
        }
    return $avcloudCover;
}


Mit dieser Funktion kann in einem beliebigen Device ein userReadings erstellt werden:
attr <device> userReadings Mittelwert {av_cloudCover()}

Den Code müsstest du natürlich anpassen, ich glaube das Prinzip sollte klar sein. Damit keine Uraltwerte in den Mittelwert eingehen, habe ich das ReadingsAge abgefragt, musst du natürlich auch nach deinen Bedürfnissen anpassen.

Viele​ Grüße​ Gisbert​
Titel: Antw:[Gelöst] Mittelwert mehrerer Devicereadings erzeugen und weiterreichen
Beitrag von: Damian am 28 November 2021, 20:45:21
Das sieht mir alles unnötig umständlich aus.

Mit dem Zweizeiler

defmod durchschnitt DOIF ##
attr durchschnitt state [#average:"^(Esszimmer|Zimmer2|Zimmer3)":"^temperature"]


bekommst du im Status des Devices die Durchschnittstemperatur von allen angegebenen Zimmern, sobald der erste Sensor seine Temperatur sendet.

Titel: Antw:[Gelöst] Mittelwert mehrerer Devicereadings erzeugen und weiterreichen
Beitrag von: Damian am 28 November 2021, 20:55:50
Und weil ein Zweizeiler schon zu viel ist:

defmod mittelwert DOIF init {set_State([#average:"^(Esszimmer|Zimmer2|Zimmer3)":"^temperature"])}

hier erscheint der Durchschnitt im Status sogar sofort nach der Definition, bevor sich die Zimmer melden ;)
Titel: Antw:[Gelöst] Mittelwert mehrerer Devicereadings erzeugen und weiterreichen
Beitrag von: Mad-at am 29 November 2021, 14:59:24
Vielen Dank, ja Du hast recht, und so hatte ich es ursprünglich. Das ist aber so über Regex nicht abgreifbar und dadurch in Verbindung mit Notify nicht nutzbar. Leider.  :(
Titel: Antw:[Gelöst] Mittelwert mehrerer Devicereadings erzeugen und weiterreichen
Beitrag von: Mad-at am 29 November 2021, 15:05:33
Zitat von: Gisbert am 28 November 2021, 20:44:33
[...]

Oh, das ist aber auch sehr elegant! :)
Danke fürs Teilen!
Titel: Antw:[Gelöst] Mittelwert mehrerer Devicereadings erzeugen und weiterreichen
Beitrag von: Nobbynews am 29 November 2021, 15:35:02
Ich habe da mal eine vermutlich ziemlich blöde und absolut OT-Frage:
Zitat von: Gisbert am 28 November 2021, 20:44:33

    foreach my $device (qw(Leverkusen.DarkSky Leverkusen.OpenWeatherMap)) {
        my $cloudCover = ReadingsNum($device, "cloudCover", 0);
        my $age = ReadingsAge($device, "cloudCover", 0);

Gibt das nicht mindestens eine Warnung im Log, weil bei jedem Schleifendurchlauf eine neue Variable deklariert wird bzw. diese schon deklariert sind??
Titel: Antw:[Gelöst] Mittelwert mehrerer Devicereadings erzeugen und weiterreichen
Beitrag von: Damian am 29 November 2021, 17:53:54
Zitat von: Mad-at am 29 November 2021, 14:59:24
Vielen Dank, ja Du hast recht, und so hatte ich es ursprünglich. Das ist aber so über Regex nicht abgreifbar und dadurch in Verbindung mit Notify nicht nutzbar. Leider.  :(

Was ist nicht abgreifbar?

Der Durchschnitt ist mit Event, auf den kann man triggern.
Titel: Antw:[Gelöst] Mittelwert mehrerer Devicereadings erzeugen und weiterreichen
Beitrag von: Gisbert am 29 November 2021, 20:00:36
Zitat von: Nobbynews am 29 November 2021, 15:35:02
Ich habe da mal eine vermutlich ziemlich blöde und absolut OT-Frage:Gibt das nicht mindestens eine Warnung im Log, weil bei jedem Schleifendurchlauf eine neue Variable deklariert wird bzw. diese schon deklariert sind??

Wenn Damian eine gute Lösung hat, dann würde ich erst einmal darauf aufbauen, denn er weiß im Gegensatz zu mir, was er tut.
Zu deiner Frage, ich kann dir die nicht beantworten. Ich hab den Code sinnvoll aus einem anderen Code übernommen und für meine Bedürfnisse angepasst. Ich kann mir aber auf der anderen Seite nicht vorstellen, dass dieses bisschen Code Fhem schwindelig rechnet. Es werden ja wohl keine tausende an Zyklen jede 100 Millisekunden anfallen.

Viele​ Grüße​ Gisbert​
Titel: Antw:[Gelöst] Mittelwert mehrerer Devicereadings erzeugen und weiterreichen
Beitrag von: Nobbynews am 30 November 2021, 12:19:24
Zitat von: Gisbert am 29 November 2021, 20:00:36
Ich kann mir aber auf der anderen Seite nicht vorstellen, dass dieses bisschen Code Fhem schwindelig rechnet. Es werden ja wohl keine tausende an Zyklen jede 100 Millisekunden anfallen.
Das ganz sicher nicht. Und wenn es so wie gewünscht funktioniert, ist doch alles OK.