Minimum und Maximum Werte von Temperature/Feuchte-Sensoren

Begonnen von Aeroschmelz, 21 Februar 2023, 21:04:25

Vorheriges Thema - Nächstes Thema

Aeroschmelz

Hallo,

ich betreibe in jedem Raum einen Raumsensor, der die Feuchtigkeit und Temperatur über einen CUL an FHEM liefert. Für jeden Raum plotte ich beide Werte. Ich würde nun gerne innerhalb von 24 h von allen Sensoren jeweils den minimalen und maximalen Wert finden, damit alle Plots jeweils die gleichen Achsen haben. Das Problem habe ich gelöst. Ich kann mir auch über DoIF zu einem beliebigen Zeitpunkt den minimalen und maximalen Wert berechnen lassen, aber nicht über den ganzen Tag. Mit der event-aggregator Funktion scheint einiges im Argen zu liegen, das funktioniert trotz vieler Suche nicht. Ich weiß es gibt das statistics Modul und ich verwende das auch für diverse Sensoren, aber ich halte das für den Zweck für Overkill. . Jetzt wollte ich es mal mit einem DoIf versuchen, komme da leider aber auf Grund mangelhafter Perl Kenntnisse aber nicht weiter. Vielleicht kann mich ja jemand unterstützen. Folgendes habe ich mal zusammen gebastelt:


define DO_WohnungRanges DOIF [$group eq "Sensoren"] ({\
my $myminT = [#min:":^temperature":temperature:$group eq "Sensoren"];;\
my $mymaxT = [#max:":^temperature":temperature:$group eq "Sensoren"];;\
if ($myminT < ReadingsVal("DO_WohnungRanges", "minT",0)) (set_Reading(minT,$myminT));;\
if ($mymaxT > ReadingsVal("DO_WohnungRanges", "maxT",0)) (set_Reading(maxT,$mymaxT));;\
\
my $myminH = [#min:":^humidity":humidity:$group eq "Sensoren"];;\
my $mymaxH = [#max:":^humidity":humidity:$group eq "Sensoren"];;\
if ($myminH < ReadingsVal("DO_WohnungRanges", "minH",0))  (set_Reading(minT,$myminH));;\
if ($mymaxH > ReadingsVal("DO_WohnungRanges", "maxH",0)) (set_Reading(maxT,$mymaxH));;\
})\
DOELSEIF ([00:00]) (set Dummy -99)({\
set_Reading_Begin;;\
set_Reading_Update("minT",0);;\
set_Reading_Update("maxT",0);;\
set_Reading_Update("minH",0);;\
set_Reading_Update("maxH",0);;\
set_Reading_End(1);;\
})


Muss ich die Aggregations-Funktion in ein Attribut verschieben?

Danke im voraus.

Viele Grüsse
Marcus

Damian

Was soll das für eine Syntax sein:

DOIF [$group eq "Sensoren"] ({\

Wenn du in einem (DOIF) Device Max, Min für einzelne Sensoren bestimmen willst, dann ist es schon komplizierter. Da wirst du wohl nicht über den Perlmodus herum kommen. Die Aggregation kannst du dann nutzen, wenn du zu einem Zeitpunkt z. B. um Mitternacht über alle deine gesammelten Werte das Extremum zu bestimmen willst.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Aeroschmelz

#2
Hi,

ja, das war zugegebnermaßen etwas sehr frei aus der commandref unter Aggregieren von Werten interpretiert. ;-) Ich habe es aber auch schon mit [Wohnzimmer:"temperature"] probiert. Ich dachte eigentlich, dass ich mit dem Aggregieren zu einem bestimmten Zeitpunkt das Minimum/Maximum der einzelnen Sensorwerte bestimmen kann und über die IF Bedingung dann das jeweils immer neue Minimum / Maximum in die Variablen minT/maxT bzw. minH/MaxH schreiben könnte. Um Mitternacht sollten die dann auf 0 gesetzt werden. Damit sollte (nach meiner Denkweise ;-) ) zumindest zu einem beliebigen Punkt das Maximum / Minimum der Vergangenheit definiert sein und die Werte nicht aus den Y-Achsen laufen...

Alternativ gibt es ja für den gleichen Zweck noch z.B. die minNum Funktion in der 99_myUtils Datei. Da muss man aber dann alle Sensoren einzeln angeben....

Viele Grüsse
Marcus

Per

Ich habe min und max für die Außentemperaturen ermittelt und lasse die min 16 Uhr, die max 4 Uhr zurücksetzen.
Für die Anzeige stelle ich mir das komplizierter vor, denn zumindest das eingebaute Plotting ändert den Maßstab dynamisch, wenn man statt 1 Tag 1 Monat oder 1 Stunde anzeigen lässt. Da müsste man ja für jeden möglichen Zeitraum min und max ermitteln...

Damian

Zitat von: Aeroschmelz am 21 Februar 2023, 21:25:34
Hi,

ja, das war zugegebnermaßen etwas sehr frei aus der commandref unter Aggregieren von Werten interpretiert. ;-) Ich habe es aber auch schon mit [Wohnzimmer:"temperature"] probiert. Ich dachte eigentlich, dass ich mit dem Aggregieren zu einem bestimmten Zeitpunkt das Minimum/Maximum der einzelnen Sensorwerte bestimmen kann und über die IF Bedingung dann das jeweils immer neue Minimum / Maximum in die Variablen minT/maxT bzw. minH/MaxH schreiben könnte. Um Mitternacht sollten die dann auf 0 gesetzt werden. Damit sollte (nach meiner Denkweise ;-) ) zumindest zu einem beliebigen Punkt das Maximum / Minimum der Vergangenheit definiert sein und die Werte nicht aus den Y-Achsen laufen...

Alternativ gibt es ja für den gleichen Zweck noch z.B. die minNum Funktion in der 99_myUtils Datei. Da muss man aber dann alle Sensoren einzeln angeben....

Viele Grüsse
Marcus

Du brauchst erst mal einen allgemeinen Trigger über alle Sensoren. Am besten über eine RegEx zum Device. Das setzt voraus, dass deine Devices eine einheitlich Namensgebung haben. Mit $device kannst du den Namen des triggernden Devices herausfinden und daraus passende Min/Max-Readings basteln.
D. h. bei 20 Zimmern müssten dynamisch 40 Readings entstehen. Um Mitternacht kannst du über einen Aggregationsaufruf das Minimum aller Minimum-Readings und das Maximum aller Maximum-Readings bestimmen.

All das erfordert aber schon etwas abstrakte Programmierung und ist mit einem einfachen wenn-dann-DOIF im FHEM-Modus schlecht zu realisieren.


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

Damian

Übrigens, ich lasse die Temperaturverläufe mit gleicher Skalierung mit Min/Max bei mir untereinander anzeigen (siehe Anhang). Plots, wo sich so viele Linien in einem Diagramm überlagert haben, haben mir damals nicht zugesagt.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

Aeroschmelz

Zitat von: Per am 21 Februar 2023, 22:04:31
Ich habe min und max für die Außentemperaturen ermittelt und lasse die min 16 Uhr, die max 4 Uhr zurücksetzen.
Für die Anzeige stelle ich mir das komplizierter vor, denn zumindest das eingebaute Plotting ändert den Maßstab dynamisch, wenn man statt 1 Tag 1 Monat oder 1 Stunde anzeigen lässt. Da müsste man ja für jeden möglichen Zeitraum min und max ermitteln...

Hi Per, der Teil war einfach. Du schreibst in der Plot Datei folgendes:

set yrange {getRange("minH","maxH",5)}
set y2range {getRange("minT","maxT",3)}


und in der 99_myUtils.pm Datei erstellst du folgende Funktion:


sub getRange ($$$) {
        my ($minVariable,$maxVariable,$offset) = @_;

my $min = ReadingsVal("DO_WohnungRanges",$minVariable,"10");
my $max = ReadingsVal("DO_WohnungRanges",$maxVariable,"60");
my $padding = $offset;

if ($padding == 0) {
                $padding += 3;
        }

        $min -= $padding;
        $max += $padding;

        my $range = sprintf("[%d:%d]", $min, $max);

Log(3, "range = $range");
       
return $range;
}


Um den min / Max bei jedem Trigger eines Devices zu bestimmen, funktioniert das folgende DoIF:


define DO_WohnungRanges DOIF {set_Reading ("minT",[#min:":^temperature":TempMin:$group eq "Sensoren"])}\
{set_Reading ("maxT",[#max:":^temperature":TempMax:$group eq "Sensoren"])}\
{set_Reading ("minH",[#min:":^humidity":HumMin:$group eq "Sensoren"])}\
{set_Reading ("maxH",[#max:":^humidity":HumMax:$group eq "Sensoren"])}
attr DO_WohnungRanges room System


Da ergibt sich nur das Problem, das er bei jedem Trigger die aktuellen Werte bestimmt. Wenn die Werte nun in der Vergangenheit höher oder niedriger waren, passen die Achsen nicht mehr. Daher habe ich dann folgendes probiert:


attr Buero event-aggregator TempMax::none:max:86400,TempMin::none:min:86400,HumMax::none:max:86400,HumMin::none:min:86400
attr Buero userReadings TempMax:temperature.* {ReadingsVal("$name","temperature","Fehler")}, TempMin:temperature.* {ReadingsVal("$name","temperature","Fehler")}, HumMax:humidity.* {ReadingsVal("$name","humidity","Fehler")}, HumMin:humidity.* {ReadingsVal("$name","humidity","Fehler")}


Das Reading funktioniert, aber nicht der event-aggregator trotz verschiedenen Kombinationen mit "interval" und "holdTime". Im Wiki ist dazu auch vermerkt, dass die commandref hier etwas falsches beschreibt. Trotzdem sind beide Werte immer gleich, weil der event-aggregator das Reading nicht modifiziert. Dann wollte ich wieder auf das DoIf zurück und im Prinzip zum aktuellen Zeitpunkt über die Funktionen den min/max Wert bestimmen und wenn dieser größer bzw. kleiner als ein Wert in der Vergangenheit sein sollte, so wird dieser Wert als neuer Wert gesetzt. Um Mitternacht sollen die Werte resettet werden und das Spiel von vorne beginnen. Ich habe dazu auch viel im Forum und in der CommandRef gelesen, aber da komme ich mit meinen limitierten Kenntnissen nicht weiter. Im Prinzip ist der Trigger nebensächlich (Ich kann auch irgendein Temperature Device nehmen). Dann soll er von allen Devices den min und max Werten bestimmen und diesen mit einem für den Tag vorhandenen Min/Max Wert vergleichen. Wenn die Werte kleiner oder größer als diese gespeicherten Werte sind, soll er die Werte ändern, ansonsten gar nichts machen.





Aeroschmelz

Das DoIF funktioniert jetzt zusammen mit de getRange Funktion von oben und dem Set yrange. Bestimmt nicht elegant und den Trigger würde ich gerne auch noch optimieren, aber funktioniert. Set_reading aus dem WIKI gab bei mir immer eine Fehlermeldung...


defmod DO_Wohnung_Range DOIF ([Buero:"temperature"] or [Buero:"humidity"]) (\
{\
my $CurrentTempMax=0;;\
my $CurrentTempMin=0;;\
my $DayTempMax=0;;\
my $DayTempMin=0;;\
\
$DayTempMax = ReadingsVal("DO_Wohnung_Range","maxT",10);;\
$DayTempMin = ReadingsVal("DO_Wohnung_Range","minT",10);;\
$CurrentTempMax=[#max:":^temperature":temperature:$group eq "Sensoren"];;\
$CurrentTempMin=[#min:":^temperature":temperature:$group eq "Sensoren"];;\
\
if ($CurrentTempMax > $DayTempMax){ \
fhem("setreading DO_Wohnung_Range maxT ".$CurrentTempMax);;\
}\
\
if ($CurrentTempMin < $DayTempMin){ \
fhem("setreading DO_Wohnung_Range minT ".$CurrentTempMin);;\
}\
\
Log 1, "minimale Temperatur ".$CurrentTempMin." und maximale Temperatur ".$CurrentTempMax;;\
\
my $CurrentHumMax=0;;\
my $CurrentHumMin=0;;\
my $DayHumMax=0;;\
my $DayHumMin=0;;\
\
$DayHumMax = ReadingsVal("DO_Wohnung_Range","maxH",10);;\
$DayHumMin = ReadingsVal("DO_Wohnung_Range","minH",10);;\
$CurrentHumMax=[#max:":^humidity":humidity:$group eq "Sensoren"];;\
$CurrentHumMin=[#min:":^humidity":humidity:$group eq "Sensoren"];;\
\
if ($CurrentHumMax > $DayHumMax){ \
fhem("setreading DO_Wohnung_Range maxH ".$CurrentHumMax);;\
}\
\
if ($CurrentHumMin < $DayHumMin){ \
fhem("setreading DO_Wohnung_Range minH ".$CurrentHumMin);;\
}\
\
Log 1, "minimale Feuchtigkeit ".$CurrentHumMin." und maximale Feuchtigkeit ".$CurrentHumMax;;\
}\
)\
DOELSEIF([00:00]) ({\
fhem("setreading DO_Wohnung_Range maxT 0");;\
fhem("setreading DO_Wohnung_Range minT 90");;\
fhem("setreading DO_Wohnung_Range maxH 0");;\
fhem("setreading DO_Wohnung_Range minH 90");;\
})

daedalus0815

...oder auch mal so....den TEMP-Filter find ich  8) :


attr event_raedings anlegen....:
TempDiffSensor: (   ( [TEMP_OUTSIDE:temperature:d] > -20 and [TEMP_OUTSIDE:temperature:d] < 45 )  *
   ( [TEMP_OUTSIDE:temperature] )  )

   
....TempDiffSensor sind also die gefilterten Sensorwerte

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

....einmaliges anlegen via Commandline oder einmaliger Aufruf von cmd_2 des u.a. DOIF ....:

setreading TEMP_OUTSIDE Temperature_max_day -99
setreading TEMP_OUTSIDE Temperature_min_day  99

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


DOIF-Definition ("attr do always" nicht vergessen):

 
( [$SELF:TempDiffSensor]  != 0 )

( setreading $SELF temperature  [TEMP_OUTSIDE:temperature] )

(
IF ( [TEMP_OUTSIDE:Temperature] > [TEMP_OUTSIDE:Temperature_max_day]  )
( setreading TEMP_OUTSIDE  Temperature_max_day  [TEMP_OUTSIDE:Temperature] )
)
(
IF ( [TEMP_OUTSIDE:Temperature] < [TEMP_OUTSIDE:Temperature_min_day]  )
( setreading TEMP_OUTSIDE  Temperature_min_day  [TEMP_OUTSIDE:Temperature] )
)

DOELSEIF   ### Reset Min/Max zum Zeitpunkt  ... [23:59|Mo] => Wochen-Min/Max
( [23:59] )
(setreading TEMP_OUTSIDE Temperature_max_day -99)
(setreading TEMP_OUTSIDE Temperature_min_day  99)