Misterhouse: Logik

0

Misterhouse – Komplexe Logiken

Rollladen Steuerung

Ich habe Rollläden, die haben keine genaue Positionierung. Um dieses Manko aufzuheben und die Rollläden zum Beispiel auf „Lüften“ zu stellen habe ich eine eigene Klasse in Perl eingeführt und ein entsprechendes PM File geschrieben.

Das PM File gibt es hier [URL]http://ralf.klueber.googlepages.com/Rollerblinds.pm
ACHTUNG: Beta ;). Ausserdem habe ich noch einen recht schwerwiegenden Fehler in der letzten Version korrigiert. Ladet euch die PM einfach noch mal runter.

Kopiert es einfach in euer Usercode Verzeichnis.

Definition der Rollladen

Die Rollladen werden nicht mehr als EIB7 Objekte in einer MHT Datei definiert. Ich habe ein eigenes PL File für die Rollläden.

# So sah die Definition in den Misterhouse eigenen MHT Files aus.
#EIB7, 1/3/2|1/3/1, Arbeiten_Rollladen, Rollladen|EG_Arbeiten|EG_Rollladen
#EIB7, 1/3/4|1/3/3, Wohnen_Rollladen, Rollladen|EG_Wohnen|EG_Rollladen
#EIB7, 1/3/6|1/3/5, Essen_Rollladen, Rollladen|EG_Wohnen|EG_Rollladen

use Rollerblinds;

# Daraus wird folgendes
$Arbeiten_Rollladen = new EIBRB_Item('1/3/2|1/3/1|10/2/1', 12);
$Wohnen_Rollladen = new EIBRB_Item('1/3/4|1/3/3|10/2/2', 27);
$Essen_Rollladen = new EIBRB_Item('1/3/6|1/3/5|10/2/3', 27);

$v_eg1 = new Voice_Cmd "Rollladen Essen [up,down,stop,0,5,10,15,20,25,30,35,40,45,50,55,60,65,67,70,75,80,85,90,95,100]";
$v_eg2 = new Voice_Cmd "Rollladen Wohnen [up,down,stop,0,5,10,15,20,25,30,35,40,45,50,55,60,65,67,70,75,80,85,90,95,100]";
$v_eg3 = new Voice_Cmd "Rollladen Arbeiten [up,down,stop,0,5,10,15,20,25,30,35,40,45,50,55,60,65,67,70,75,80,85,90,95,100]";

if ($state = said $v_eg1) { set $Essen_Rollladen $state; }
if ($state = said $v_eg2) { set $Wohnen_Rollladen $state; }
if ($state = said $v_eg3) { set $Arbeiten_Rollladen $state; }

 

 

Die ersten beiden GAs sind die MOVE bzw. STOP Adressen vom Aktor. Die dritte GA ist eine EIB6 GA für Werte zwischen 0 und 100%. Die letzte Zahl ist eine Zeitspanne die der Rollladen braucht um von der oberen Endlage in die untere Endlage zu fahren.
Damit lassen sich die Rollläden schon steuern mit

# house Rollladen Essen up
# house Rollladen Essen 50
# house Rollladen Essen down
# house Rollladen Essen 50

Wie findet man die Zeitspanne heraus? Ich fahre aus der oberen Endlage auf 50%, markiere die Position am Fensterrahmen. Dann fahre ich von der unteren Endlage in auf 50% und setze eine Markierung. Sollten die Markierung von der oberen Endlage über der Fahrt aus der unteren Endlage befinden, dann ist die Zeit zu lange. Nach ein paar wenigen Fahrten hat man die genaue Zeitspanne.
Damit lassen sich die Rollläden dann schon positionieren.
Ich freue mich auf euer Feedback.

Die eigentliche Rollladen Steuerung

Das war nun erst der erste Streich ;). Jetzt wollen wir die Rollladen ja automatisch steuern. Der Rollladen Baustein ist so noch nicht komplett. Ich bin gerade dabei den weiterzuentwickeln.

use Rollerblinds;

#EIB7, 1/3/4|1/3/3, Wohnen_Rollladen, Rollladen|EG_Wohnen|EG_Rollladen
#EIB7, 1/3/6|1/3/5, Essen_Rollladen, Rollladen|EG_Wohnen|EG_Rollladen

$Wohnen_Rollladen = new EIBRB_Item('1/3/4|1/3/3|10/2/2', 28);
$Essen_Rollladen = new EIBRB_Item('1/3/6|1/3/5|10/2/3', 28);

$Rollladen = new Group;
$EG_Rollladen = new Group;

$Rollladen -> add($Wohnen_Rollladen);
$EG_Wohnen -> add($Wohnen_Rollladen);
$EG_Rollladen -> add($Wohnen_Rollladen);
$Rollladen -> add($Essen_Rollladen);
$EG_Wohnen -> add($Essen_Rollladen);
$EG_Rollladen -> add($Essen_Rollladen);

my %poseg = (
anwesend_lueften => 67,
abwesend_lueften => 67,
anwesend_schlafen => 67,
abwesend_schlafen => 67,
abwesend_gekippt => 67,
anwesend_gekippt => 67,
abwesend_zu => 100,
anwesend_zu => 100,
abwesend_sonne => 60,
anwesend_sonne => 60,
anwesend_offen => 'up',
abwesend_offen => 'up'
);

sub rollladen_baustein {
my ($rollladen, $gekippt, $offen,
$schlafen, $raumtemp, $sonne,
%pos) = @_;

my $anwesend = $Anwesend->state() eq 'on' ? "anwesend" : "abwesend";
my $state = state $rollladen;
$state = 100 if $state eq 'down';
$state = 0 if $state eq 'up';
my $pos = $state;
my $dir = -1;
my $name = $rollladen->get_object_name();

# $state ist der aktuelle Stand des Rollladen
# $pos ist der Zielzustand
# $dir = -1, dann wird die position nur angefahren, wenn $state > $pos
# $dir = 0, dann wird die position auf jeden Fall angefahren.
# $dir = +1, dann wird die position nur angefahren, wenn $state < $pos

# nach oben auf 67% wenn gekippt
if (state_changed $gekippt eq ON) {
if (($state > $pos) &&
(time_greater_than("06:00 PM"))) {
$pos = $pos{$anwesend."_lueften"}; $dir = -1;
}
}

# 0% wenn morgens und FK offen
if (state_changed $offen eq ON) {
if (time_less_than("10:00 AM")) {
$pos = $pos{$anwesend."_offen"}; $dir = 0;
}
}

# 100% um 4h morgens am Wochenende
if (time_cron('0 4 * * 6-7')) {
$pos = 100;
$dir = +1;
}

# Die Schattensachen nur all 10 min pruefen
if (($New_Minute && !($Minute %10)) || $Startup || $Reload) {
# 40% wenn Sonne auf Fenster und hohe aussentemp
if ($sonne && $Aussentemp >= 25) {
$pos = $pos{$anwesend."_sonne"}; $dir = +1;
} else {
# $pos = 0; $dir = 0;
}

# $dir = -1, dann wird die position nur angefahren, wenn $state > $pos
# $dir = 0, dann wird die position auf jeden Fall angefahren.
# $dir = +1, dann wird die position nur angefahren, wenn $state < $pos

print_log "########## $name state:$state pos:$pos dir:$dir" if ($pos != $state);

# Haben wir die Position schon?
if ($state < $pos - 3 || $state > $pos +3) {
# Nein, na dann los
if ($dir == -1) {
if ($state > $pos + 3) {
set $rollladen $pos;
} else {
print_log "########## nicht angefahren weil dir == -1";
}
} elsif ($dir == 0) {
set $rollladen $pos;
} elsif ($dir == +1) {
if ($state < $pos) {
set $rollladen $pos;
} else {
print_log "########## nicht angefahren weil dir == +1";
}
}
}
}
}

my $Raumtemp_Wohnen = state $Kueche_Temperatur;
# Ich hab nich nicht ueberall nen RTR ;(

my $Sonne_NO = 0;
my $Sonne_NW = 0;
my $Sonne_SO = 0;
my $Sonne_SW = 0;

$Sonne_SO = ($Sonnenwinkel >= 95 && $Sonnenwinkel <= 250 && $Sonnenhoehe >=35 && $Sonnenhoehe <=90) ? 1 : 0;
$Sonne_NO = ($Sonnenwinkel >= 0 && $Sonnenwinkel <= 130 && $Sonnenhoehe >=35 && $Sonnenhoehe <=90) ? 1 : 0;

rollladen_baustein($Essen_Rollladen, $FK_Essen_oben, $FK_Essen_unten,
0, $Raumtemp_Wohnen, $Sonne_SO, %poseg);
rollladen_baustein($Wohnen_Rollladen, $FK_Wohnen_oben, $FK_Wohnen_unten,
0, $Raumtemp_Wohnen, $Sonne_NO, %poseg);

# Zeitgesteuerte Aktionen

# Unter der Woche 6:30
if (time_cron('30 6 * * 1-5')) {
set $EG_Rollladen UP;
print_log "rollladen.pl EG_Rollladen UP";
}
# Wochenende 8:30
if (time_cron('30 8 * * 6-7')) {
set $EG_Rollladen UP;
print_log "rollladen.pl EG_Rollladen UP";
}
# jeden Abend mit Sonnenuntergang runter
if (time_now($Time_Sunset)) {
set $EG_Rollladen DOWN;
set $Eltern_Rollladen DOWN;
}

$v_eg1 = new Voice_Cmd "Rollladen Essen [up,down,stop,0,5,10,15,20,25,30,35,40,45,50,55,60,65,67,70,75,80,85,90,95,100]";
$v_eg2 = new Voice_Cmd "Rollladen Wohnen [up,down,stop,0,5,10,15,20,25,30,35,40,45,50,55,60,65,67,70,75,80,85,90,95,100]";
if ($state = said $v_eg1) { set $Essen_Rollladen $state; }
if ($state = said $v_eg2) { set $Wohnen_Rollladen $state; }

 

 

Den Sonnenstand brauchen wir damit auch

# QUELLE: http://www.jgiesen.de/SME/tk/index.htm
#tageszahl = (monat-1)*30 + datum + 0.5 ^M
#deklin = -23.45*cos(K*360*(tageszahl+10)/365) ^M
#zeitdiff = stunde + minute/60 - (15.0-long)/15.0 - 12 ^M
#x = sin(K*lat)*sin(K*deklin) + cos(K*lat)*cos(K*deklin)*Math.cos(K*15*zeitdiff)^M
#Ergebnis für den Höhenwinkel der Sonne in Grad: ^M
#hoehe = x/K + 0.25*x*x*x/K (Die ARCSIN-Funktion wird durch ein Polynom approximiert)^M

use vars ('$Sonnenhoehe', '$Sonnenwinkel');

if (($New_Minute && ($Minute % 10) == 9) || $Reread || $Startup) {
my $tageszahl = ($Month - 1) * 30 + $Mday + 0.5;
my $K = 0.01745;
my $deklin = -23.45 * cos( $K * 360 * ($tageszahl + 10) / 365);
my $zeitdiff = $Hour + $Minute / 60 - (15 - $config_parms{longitude}) / 15 - 12;
my $x = sin($K * $config_parms{latitude}) * sin($K * $deklin) +
cos($K * $config_parms{latitude}) * cos($K * $deklin) * cos($K*15*$zeitdiff);
$Sonnenhoehe = $x/$K + 0.25*$x*$x*$x/$K;
my $y = -(sin($K * $config_parms{latitude}) *$x - sin($K * $deklin)) /
(cos($K * $config_parms{latitude}) * sin(atan2( sqrt(1 - $x * $x), $x)));
$Sonnenwinkel = atan2( sqrt(1- $y * $y), $y) / $K;
$Sonnenwinkel = 360 - $Sonnenwinkel if ($Hour > 12);

print_log "########## Sonnenhoehe:$Sonnenhoehe Sonnenwinkel:$Sonnenwinkel";
}