FHEM Forum

FHEM => Codeschnipsel => Thema gestartet von: d.schoen am 03 November 2016, 13:36:01

Titel: Stoßlüften - Meldung zum Schutz vor Auskühlen
Beitrag von: d.schoen am 03 November 2016, 13:36:01
Hallo zusammen,

ich habe mir für unsere Wohnung ein kleines DOIF Konstrukt erstellt, das mir eine Telegram Nachricht sendet, wenn es sinnvoll ist das Fenster nach dem Stoßlüften wieder zu schließen.
Ich möchte damit den optimalen Zeitpunkt ausgeben, so dass die Fenster nur so lange offen bleiben, wie auch wirklich ein Luftaustausch stattfindet.

Dazu untersuche ich die Änderung der Luftfeuchtigkeit eines Homematic Thermostats (bei mir HM-TC-IT-WM-W-EU).

Schritt 1: Überwachen der Änderung der Luftfeuchtigkeit

Um die Änderung der Luftfeuchtigkeit zu überwachen lege ich mir zuerst ein UserReading an, das die Ableitung der Luftfeuchtigkeit speichert:
attr Thermostat_Chan_Climate userReadings humdiff:humidity.* differential { ReadingsVal("Thermostat_Chan_Climate", "humidity", 0);; }

Somit bekommt mein Climate-Channel des Thermostats ein Reading humdiff, das folgende Werte annehmen kann:

Basierend auf diesem Wert kann ich nun feststellen, wenn ein Lüftvorgang beginnt (starker Abfall der Luftfeuchtigkeit)
humdiff < -0.01
und wann ein Lüftvorgang wieder beendet werden sollte (Luftfeuchtigkeit nimmt nicht weiter ab)
humdiff > -0.002


Schritt 2: Anlegen eines Dummy-Devices zum Speichern des aktuellen Status
define Stosslueften dummy
Hiermit werden wir dann speichern, in welcher "Phase" des Lüftvorgangs wir gerade sind.

Schritt 3: Anlegen des DOIF
define DOIF_Stosslueften DOIF ([Thermostat_Chan_Climate:humdiff] < -0.01 and [?Stosslueften ] ne "opened") (set Stosslueften opened)
DOELSEIF ([Thermostat_Chan_Climate:humdiff] > -0.002 and [?Stosslueften] eq "opened") (set Stosslueften reducing)
DOELSEIF ([Thermostat_Chan_Climate:humdiff] > -0.002 and [?Stosslueften] eq "reducing") (set Stosslueften reduced)
DOELSEIF ([Thermostat_Chan_Climate:humdiff] > -0.002 and [?Stosslueften] eq "reduced") (set Stosslueften sent; set tgbot message @... Fenster schließen)


Was mache ich nun damit konkret?

Viel Spaß mit dem Snippet.
Titel: Antw:Stoßlüften - Meldung zum Schutz vor Auskühlen
Beitrag von: sash.sc am 05 November 2016, 15:47:19
Gehe ich recht in der Annahme, dass die Erzeugen des userReading sich immer nur auf ein Gerät bezieht ???

Gruß
Sascha
Titel: Antw:Stoßlüften - Meldung zum Schutz vor Auskühlen
Beitrag von: sash.sc am 06 November 2016, 08:44:57
Zitat von: d.schoen am 03 November 2016, 13:36:01


Um die Änderung der Luftfeuchtigkeit zu überwachen lege ich mir zuerst ein UserReading an, das die Ableitung der Luftfeuchtigkeit speichert:
[code]attr Thermostat_Chan_Climate userReadings humdiff:humidity.* differential { ReadingsVal("Thermostat_Chan_Climate", "humidity", 0);; }



Bezieht sich das "differential" nur auf HM Geräte oder lässt sich das auch auf andere Sensoren anwenden ??

Gruß
Sascha
Titel: Antw:Stoßlüften - Meldung zum Schutz vor Auskühlen
Beitrag von: jeti am 06 November 2016, 14:50:12
Die Ableitung kannst du als userReading von jedem Wert erstellen lassen!
Ist also universell und kann für jeden device und reading verwendet werden.
Titel: Antw:Stoßlüften - Meldung zum Schutz vor Auskühlen
Beitrag von: locodriver am 24 November 2016, 17:01:27
@d.schoen: danke für deine Idee. Ich habe sie noch mit der Außentemperatur und dem Fensterkontakt verknüpft, da bekomme ich die Meldung nur, wenn das Fenster noch offen ist bzw. gibt es keine Meldung, wenn aus anderen Gründen (offene Badtür) die Feuchtigkeit sinkt.

Wie hast du die Schwellwerte ermittelt - probiert oder hast du einen "fachlichen Hintergrund"? Welche Zeiträume ergeben sich bei dir in der Regel, bis die Meldung abgesetzt wird?
Ich kann dazu noch nichts sagen da ich es erst gestern umgesetzt habe  :) . Bisher hatte ich ein zweistufiges Verfahren, welches mich nach 10 bzw. 15 Minuten (unter 10 bzw. 15 °C Außentemperatur) warnt und dann in der Endkonsequenz zur "Not" noch den Rollladen schließen kann. Das hat bis jetzt auch gut funktioniert...

([BD_Regler_Climate:humdiff]<-0.01 and [?Lueften] ne "opened" and (ReadingsVal("Wetter_Borsdorf","temperature",0)<15))(set Lueften opened)
DOELSEIF
([BD_Regler_Climate:humdiff] > -0.002 and [?Lueften] eq "opened" and (ReadingsVal("Wetter_Borsdorf","temperature",0)<15)) (set Lueften reducing)
DOELSEIF
([BD_Regler_Climate:humdiff] > -0.002 and [?Lueften] eq "reducing" and (ReadingsVal("Wetter_Borsdorf","temperature",0)<15)) (set Lueften reduced)
DOELSEIF
([BD_Regler_Climate:humdiff] > -0.002 and [?Lueften] eq "reduced" and (ReadingsVal("Wetter_Borsdorf","temperature",0)<15)) ((set Lueften sent)
IF ([BD_Fenster] eq "offen" set Nachrichten message Badfenster schließen))


Noch eine Frage etwas OT: Wie bildet der interne Alghoritmus die Ableitung? Eigentlich benötige ich doch eine Funktion, die ich dann nach den bekannten Regeln ableite, das ist hier ja nicht gegeben. So sind das doch eigentlich Differenzenquotienten, die hier zwischen den einzelnen Werten gebildet werden?! Damit hängt die Genauigkeit vom zeitlichen Abstand der einzelnen Feuchtigkeitwerte ab, oder? Nicht falsch verstehen: ich will nicht bis auf die letzte signifikante Stelle einen exakten Wert (man kann es ja übertreiben), es geht mir um das Verständnis.

Danke nochmals,

Uwe
Titel: Antw:Stoßlüften - Meldung zum Schutz vor Auskühlen
Beitrag von: sash.sc am 25 November 2016, 13:10:47
Das würde ich auch gerne wissen, Info´s zum differential

Gruß
Sascha
Titel: Antw:Stoßlüften - Meldung zum Schutz vor Auskühlen
Beitrag von: d.schoen am 25 November 2016, 13:39:18
Hallo zusammen,

danke für die Ergänzungen! Mangels Fensterkontakte habe ich das bei mir nicht integriert.

Die Schwellwerte habe ich probiert - und probiere immer noch. Mittlerweile hat sich mein benutzter Code noch etwas verändert: Ich nehme einen gleitenden Durchschnitt über die Ableitungswerte. Da gibt es weniger "Ausreißer".

Bzgl. der "Ableitung": Das sind definitiv Differenzquotienten und keine Ableitung im Sinne einer Kurvendiskussion. Wie das aber intern genau berechnet wird, weiß ich leider auch nicht - aber wie du schon sagst: Das wäre Mikrooptimierung. Mir ging es bei dem Snippet eher darum, mich ohne Fensterkontakt daran erinnern zu lassen, dass das Fenster wieder geschlossen werden sollte.

Grüße
Dominik
Titel: Antw:Stoßlüften - Meldung zum Schutz vor Auskühlen
Beitrag von: locodriver am 28 November 2016, 15:34:04
@Dominik:
Danke für die Ergänzungen, kannst du bitte die Änderung mit dem gleitenden Mittelwert noch posten?

Danke

Uwe.
Titel: Antw:Stoßlüften - Meldung zum Schutz vor Auskühlen
Beitrag von: d.schoen am 28 November 2016, 16:18:27
Klar, gerne.

Ich nutze dazu ein weiteres Userreading:
humdiff_avg:humidity.* {movingAverage("Device","humdiff",600)}

Der letzte Wert ist die Dauer (in Sekunden) über die der Mittelwert gebildet wird. Damit kann/muss man ein bisschen spielen um einen für sich passenden Mittelwert zu bekommen.

Zudem brauchts die Methode movingAverage in der myUtils (irgendwo hier aus dem Forum geklaut):

###############################################################################
#
#  Moving average
#
#  Aufruf: movingAverage(devicename,readingname,zeitspanne in s)
#
###############################################################################

sub movingAverage($$$){
   my ($name,$reading,$avtime) = @_;
   my $hash = $defs{$name};
   my @new = my ($val,$time) = ($hash->{READINGS}{$reading}{VAL},$hash->{READINGS}{$reading}{TIME});
   my ($cyear, $cmonth, $cday, $chour, $cmin, $csec) = $time =~ /(\d+)-(\d+)-(\d+)\s(\d+):(\d+):(\d+)/;
   my $ctime = $csec+60*$cmin+3600*$chour;
   my $num;
   my $arr;
   #-- initialize if requested
   if( ($avtime eq "-1") ){
     $hash->{READINGS}{$reading}{"history"}=undef;
   }
   #-- test for existence
   if( !$hash->{READINGS}{$reading}{"history"}){
      #Log 1,"ARRAY CREATED";
      push(@{$hash->{READINGS}{$reading}{"history"}},\@new);
      $num = 1;
      $arr=\@{$hash->{READINGS}{$reading}{"history"}};
   } else {
      $num = int(@{$hash->{READINGS}{$reading}{"history"}});
      $arr=\@{$hash->{READINGS}{$reading}{"history"}};
      my $starttime = $arr->[0][1];
      my ($syear, $smonth, $sday, $shour, $smin, $ssec) = $starttime =~ /(\d+)-(\d+)-(\d+)\s(\d+):(\d+):(\d+)/;
      my $stime = $ssec+60*$smin+3600*$shour;
      #-- correct for daybreak
      $stime-=86400
        if( $stime > $ctime);
      if( ($num < 25)&&( ($ctime-$stime)<$avtime) ){
        #Log 1,"ARRAY has $num elements, adding another one";
        push(@{$hash->{READINGS}{$reading}{"history"}},\@new);
      }else{
        shift(@{$hash->{READINGS}{$reading}{"history"}});
        push(@{$hash->{READINGS}{$reading}{"history"}},\@new);
      }
    }
    #-- output and average
    my $average = 0;
    for(my $i=0;$i<$num;$i++){
      $average+=$arr->[$i][0];
      Log 4,"[$name moving average] Value = ".$arr->[$i][0]." Time = ".$arr->[$i][1];
    }
    $average=sprintf( "%5.3f", $average/$num);
    #--average
    Log 4,"[$name moving average] calculated over $num values is $average"; 
    return $average;
}
Titel: Antw:Stoßlüften - Meldung zum Schutz vor Auskühlen
Beitrag von: locodriver am 30 November 2016, 15:23:00
Danke ... Werde ich auch mal testen  ;)

Uwe
Titel: Antw:Stoßlüften - Meldung zum Schutz vor Auskühlen
Beitrag von: TheRisen am 06 Januar 2017, 00:41:40
Falls es noch interessiert, ich habe bei mir das ganze über den Taupunkt geregelt. Dadurch stelle ich sicher, dass die Taupunkttemperatur im Raum immer kleiner ist als die Temperatur an der Innenseite des Fensters. So können die Fenster nicht von innen beschlagen.
Sowohl die Wettervorhersage als auch der Sensor im Bad bekommen den Taupunkt als Reading:

define dew_inside dewpoint dewpoint HM_Feuchte_Bad temperature humidity dewpoint
attr dew_inside max_timediff 600
define dew_outside dewpoint dewpoint Wetter temperature humidity dewp
attr dew_outside max_timediff 600


Ein Dummy berechnet die Temperatur innen an der Glasscheibe, 0,13 ist der Wärmeübergangskoeffizient und 1,2 ein typischer Wert für etwas ältere Fenster mit Doppelverglasung.

define dy_Fenster_Bad_Innen dummy
define nt_Temp_Bad notify (Wetter:temperature|HM_Feuchte_Bad:dewpoint) {fhem("set dy_Fenster_Bad_Innen ".(ReadingsVal("HM_Feuchte_Bad","temperature","0")-ReadingsVal("Wetter","temperature","0")*(-1,2*0,13)+ReadingsVal("HM_Feuchte_Bad","temperature","0")))}


Ein DOIF vergleicht den Tauounkt des Raumes mit der Temperatur am Fenster und gibt darüber Nachrichten ans Handy

define lueften_bad DOIF ([HM_Feuchte_Bad:dewpoint]<[dy_Fenster_Bad_Innen] and [HM_Fenster_Bad] eq "open" and [HM_Fenster_Bad:state:sec] > 480)(set pushoverjay msg "Bad" "Fenster im Bad kann geschlossen werden.\nTemperatur [HM_Feuchte_Bad:temperature] °C")\
DOELSEIF([HM_Feuchte_Bad:dewpoint]<[dy_Fenster_Bad_Innen] and [HM_Fenster_Bad] eq "closed")\
DOELSEIF([HM_Feuchte_Bad:dewpoint]>[dy_Fenster_Bad_Innen] and [HM_Fenster_Bad] eq "open")\
DOELSEIF([HM_Feuchte_Bad:dewpoint]>[dy_Fenster_Bad_Innen] and [HM_Fenster_Bad] eq "closed")(set pushoverjay msg "Bad" "Bitte Fenster öffnen.\nTaupunkt [HM_Feuchte_Bad:dewpoint] °C muss gesenkt werden")
attr lueften_bad alias Fenster Bad
attr lueften_bad devStateIcon cmd_1:fts_window_roof_open_2@red cmd_2:fts_window_roof@green cmd_3:fts_window_roof_open_2@green cmd_4:fts_window_roof@red
attr lueften_bad room Bad