zurück zur Startseite

zurück zur Übersicht der Heimautomatisierung

19. Die eigenen perl-Funktionen (Stand 07.09.2018)

FHEM ist ein offenes System und erlaubt somit auch eigene Funktionen (Utilities) zu schreiben. Am Beispiel des Rollladens, gesteuert abhängig von Temperatur, Helligkeit und Anwesenheit, versuche ich das zu erklären.

Wichtig ist, dass man eine Datei namens „99_myUtils" an der richtigen Stelle mit dem richtigen Inhalt ablegt. Am einfachsten geht das so:

Hat man das alles erledigt, so muss man noch einen FHEM-Befehl eingeben:

reload 99_myUtils.pm

Dies muss immer nach einer Änderung in „99_myUtils" gemacht werden.

Hier nochmals die Anforderungen:

  1. Wenn es nachts draußen richtig kalt ist (weniger als -10°C), dann soll der Rollladen immer zu 90% geschlossen sein.
  2. Wenn es Nacht ist, niemand zu Hause ist und wärmer als 5°C, dann soll der Rollladen zu 100% geschlossen sein.
  3. Wenn es Nacht ist, niemand zu Hause ist und weniger als 5°C, dann soll der Rollladen zu 90% geschlossen sein.
  4. Wenn wir schlafen und es draußen nicht richtig kalt ist, dann soll der Rollladen offen bleiben.
  5. Wenn es draußen richtig heiß ist (mehr als 32°C), dann soll der Rollladen immer zu 50% geschlossen sein.
  6. Wenn es drinnen wärmer als 24°C ist, es draußen noch wärmer ist und die Sonne hoch genug steht (mehr als 58°), dann soll der Rollladen 30% geschlossen sein.
  7. Wenn es drinnen wärmer als 24°C ist, es draußen noch wärmer ist und die Sonne deutlich herein scheint (hängt von Azimut und Fensterrichtung ab), dann soll der Rollladen 50% geschlossen sein.

Dann wollen wir mal loslegen - und vor allem sauber dokumentieren, was wir machen, denn perl ist eine mächtige, aber keineswegs selbst-dokumentierende Programmiersprache. Weiterhin empfehle ich einen Editor zu verwenden, der die Syntax (farbig) hervorhebt, das erleichtert das Arbeiten schon einmal.

#######################################################
# Automatische Rollladensteuerung
# Jürgen A. Reimann                    Stand 05.07.2015
#######################################################
sub shuttercontrol ($$) {
  my ($slider, $shutter) = @_;
  my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
  my $oldpos = 0;
  my $newpos = 100;

#######################################################
# $slider ist die aktuelle Position des Rollladens
# $shutter sagt, um welchen Rollladen es sich handelt
# Nur wenn sich die Position ändert, soll der Aktor
# angesteuert werden, um den Funkverkehr zu minimieren.
#######################################################
  $oldpos = $slider;

#######################################################
# Berechnen des Sonnenstands
# Der Tag im Jahr ist durch $yday bestimmt
#######################################################
# Konstante zur Umrechnung von Bogenmaß in Grad
  my $konstante = 0.01745;
# Deklination (Grad)
  my $deklin = -23.45*cos($konstante*360*($yday+10)/365);
# Zeitgleichung (Minuten)
  my $zeitgleichung = 60*(-0.171*sin(0.0337*$yday+0.465)-0.1299*sin(0.01787*$yday-0.168));
# Stundenwinkel (Grad)
  my $stundenwinkel = 15*($hour+$min/60-(15.0-AttrVal("global","longitude",0))/15.0-12+$zeitgleichung/60);
# x-Höhe (Sinuswert) und Höhe (Grad)
  my $xhoehe = ($konstante*AttrVal("global","latitude",0))*sin($konstante*$deklin)+cos($konstante*AttrVal("global","latitude",0))*cos($konstante*$deklin)*cos($konstante*$stundenwinkel);
  my $hoehe = asin($xhoehe)/$konstante;
# y-Azimut (Cosinuswert) und Azimut (Grad)
  my $yazimut = -(sin($konstante*AttrVal("global","latitude",0))*sin($konstante*$hoehe)-sin($konstante*$deklin))/(cos($konstante*AttrVal("global","latitude",0))*sin(acos(sin($konstante*$hoehe))));
  my $azimut = acos($yazimut)/$konstante;

##############################################################
# Hier die Anforderungen:
# WENN es nachts draußen richtig kalt ist (weniger als -10°C),
#    DANN soll der Rollladen immer zu 90% geschlossen sein.
# WENN es Nacht ist, niemand zu Hause ist und wärmer als 5°C,
#    DANN soll der Rollladen zu 100% geschlossen sein.
# WENN es Nacht ist, niemand zu Hause ist und weniger als 5°C,
#    DANN soll der Rollladen zu 90% geschlossen sein.
# WENN wir schlafen und es draußen nicht richtig kalt ist,
#    DANN soll der Rollladen offen bleiben.
# WENN es draußen richtig heiß ist (mehr als 32°C),
#    DANN soll der Rollladen immer zu 50% geschlossen sein.
# WENN es drinnen wärmer als 24°C ist, es draußen noch wärmer
#  ist und die Sonne hoch genug steht (mehr als 58°),
#    DANN soll der Rollladen 30% geschlossen sein.
# WENN es drinnen wärmer als 24°C ist, es draußen noch wärmer
#  ist und die Sonne deutlich herein scheint (hängt von Azimut
#  und Fensterrichtung ab),
#    DANN soll der Rollladen 50% geschlossen sein.
##############################################################

# Außentemperatur:
# ReadingsVal("tr_aussensensor", "temperature",0)
# Nacht:
# ($azimut<90)||($azimut>270)&&($hoehe<5)
# Wir:
# Value("menschen")
# Innentemperatur:
# ReadingsVal("or_raumsensor", "temperature",0)
# Fensterrichtung:
# 1 bedeutet die Sonne scheint herein

  my $fenster = 0;
  if ($shutter eq "or_blind_lin"
      && ($azimut > 120 || $azimut < 240)) {
    $fenster = 1; # Südfenster im Orientzimmer
  }

  if ((($azimut<90)||($azimut>270)&&($hoehe<5))
      && ReadingsVal("tr_aussensensor", "temperature",0)<-10) {
    $newpos = 90;
  } elsif ((($azimut<90)||($azimut>270)&&($hoehe<5))
      && (Value("menschen") eq "gone")
      && ReadingsVal("tr_aussensensor", "temperature",0)>5) {
    $newpos = 100;
  } elsif ((($azimut<90)||($azimut>270)&&($hoehe<5))
      && (Value("menschen") eq "gone")
      && ReadingsVal("tr_aussensensor", "temperature",0)<5) {
    $newpos = 90;
  } elsif (Value("menschen") eq "asleep" || Value("menschen") eq "gotosleep") {
    $newpos = 0;
  } elsif (ReadingsVal("tr_aussensensor", "temperature",0)>32) {
    $newpos = 50;
  } elsif (ReadingsVal("or_raumsensor", "temperature",0)>24
      && ReadingsVal("tr_aussensensor", "temperature",0)>25
      && $hoehe>58) {
    $newpos = 30;
  } elsif (ReadingsVal("or_raumsensor", "temperature",0)>24
      && ReadingsVal("tr_aussensensor", "temperature",0)>25
      && $fenster==1) {
    $newpos = 50;
  }

###############################################################
# Wenn keine bedingung erfüllt war, dann bleibt der Defaultwert
# von $newpos unverändert auf 100 --> Rollladen ganz nach oben.
###############################################################

###############################################################
# Jetzt noch die Aktion ausführen, wenn sich etwas geändert hat
###############################################################
   if ($newpos != $oldpos) {
     fhem("set $shutter $newpos")
   }
########
# fertig
########
}
################################################################
# Ende von shuttercontrol
################################################################

Mit einem guten Editor sieht das dann in etwa wie folgt aus und ist dann besser verständlich. Ich habe hier aber darauf verzichtet, die Farben in html-Code alle zu editieren. Andererseits möchte ich hier möglichst weitgehend kopierbaren Text und keine Bildschirmfotos von Texten.

Ist noch nicht vollständig getestet!

weiter zu: 20. Die Anwesenheit