Wenn dies dein erster Besuch hier ist, lies bitte zuerst die Hilfe - Häufig gestellte Fragen durch. Du musst dich vermutlich registrieren, bevor du Beiträge verfassen kannst. Klicke oben auf 'Registrieren', um den Registrierungsprozess zu starten. Du kannst auch jetzt schon Beiträge lesen. Suche dir einfach das Forum aus, das dich am meisten interessiert.
Ankündigung
Einklappen
Keine Ankündigung bisher.
Schaltuhr - Plugin erweitert um Sonnenauf- und Untergang
Ich habe jetzt mal meine Programmierkünste bemüht, und mit meinem gefährlichen Halbwissen folgendes festgestellt:
In Zeile 90 bzw. 91:
Code:
if (knx_read($element->{ga},0,$element->{DPT}) ne $element->{Wert}) {
wird ja abgefragt, ob der Wert ungleich ist, und NUR dann eine Schalthandlung ausgeführt.
Nun ist es bei mir so, dass die Rolläden immer per 0/2/5 runtergefahren werden.
Das Hochfahren allerdings kann auch schon mal dezentral über andere GA's erfolgen.
0/2/5 ändert sich dann nicht; und die Schalthandlung am Abend wird ignoriert.
Das hätte mir auch schon mal früher auffallen können!
Für Zentralschaltungen, welche auch manuell und einzeln über andere GA's erolgen können, ist der Code somit meines Erachtens nicht geeignet.
Für meine Zwecke würde ich die Abfrage also entfernen und gegebenenfalls eine GA doppelt senden (wenn schon manuell oder über andere GA aus, dann halt nochmal per Zeitschaltuhr aus).
Noch eine Idee:
Wäre es nicht sinnvoll für jede Schaltzeit auch den Winkel einzeln vorzugeben?
Somit könnte man bestimmte Aktionen zu unterschiedlichen Sonnenständen steuern.
Hmm... Ohne diese Abfrage hast du jedes Schalttelegramm 3 mal auf dem BUS. Aber für deinen Fall wäre das erst mal egal. Ich lass mir da aber noch was einfallen.
Also arbeitet das Plugin doch ordnungsgemäss. Die fehlenden Schaltpunkte sind den Schaltaktionen auf paralellen GAs geschuldet.
Nochmal zu meiner Idee mit dem Winkel je Schaltzeit:
Für sunset/sunrise ist ja der Höhenwinkel der Sonne ausschlaggebend.
Um aber aber zum Beipiel nachmittags eine Beschattung durchzuführen, braucht man ja den Azimutwinkel.
Diesen für eine Schaltzeit zu verwenden wäre zwar toll, damit wären wir wieder bei einer fast vollständigen Beschattungslösung.
Ich glaube, da gab es schon einmal was.
Hmm... Naja.. Als Beschattungslösung war das Plugin eigentlich nie gedacht. Das war mal einfach als simple Schaltuhr geplant, die von Wolfgang (ZeitlerW) um die Astrofunktion erweitert wurde. Damit braucht man keinen Dämmerungssensor um z.B. abends die Beleuchtung einzuschalten.
Für Beschattungslösungen (inklusive Sonnennachlauf) usw... gibt es andere Plugins die das bereits machen. Ich sehe also momentan noch nicht ganz den Nutzen hinter dieser Änderung. Es steht dir aber dank GPL jederzeit frei, das Plugin nach deinen Wünschen anzupassen
Also ich habe mir mal etwas ausgedacht, damit alle Schaltbefehle nur 1 mal ausgeführt werden. Dafür werden aber alle Schaltpunkte in jedem Fall ausgeführt um das Problem der Paralell-GA's zu umgehen.
Bitte mal testen
Code:
# Plugin zum Zeit abhängigem schalten von GA's (Schaltuhr)
# Version 0.7 BETA 11.09.2012
# Copyright: swiss (https://knx-user-forum.de/members/swiss.html)
# License: GPL (v2)
# Aufbau möglichst so, dass man unterhalb der Einstellungen nichts verändern muss!
# -Erweitert um Sonnenauf / - untergang von ZeitlerW (https://knx-user-forum.de/members/zeitlerw.html)
# -Inspiriert von kleinklausi's Rolladen - Plugin
my @Schaltzeiten;
####################
###Einstellungen:###
####################
# Die Standortdaten
# Die Koordinaten des Hauses. Sehr einfach ?ber http://www.getlatlon.com/ zu ermitteln.
my ($lat, $lon) = (
51.66787081407156, # Breitengrad in Grad
13.64227294921875 # L?ngengrad in Grad
);
#Winkel für Beginn der Dämmerung
# siehe auch: http://search.cpan.org/~rkhill/Astro-Sunrise-0.91/Sunrise.pm#DESCRIPTION
my $winkel=-3;
#Pro Schaltpunkt einfach den unten stehenden Eintrag kopieren und anpassen.
#Sollen Schaltzeiten astronomisch geschaltet werden, so muss bei Astro 'a' für Sonnenaufgang
#und 'u' für Sonnenuntergang eingetragen werden. Der Stunden und Minutenwert wird dann ignoriert.
push @Schaltzeiten, { name => "test", montag => 1, dienstag => 1, mittwoch => 1, donnerstag => 1, freitag => 1, samstag => 0, sonntag => 0, Stunden => 21, Minuten => 10, Wert => 1, DPT => 1, ga => '1/0/0', KW => '', Monat => '', Astro => '' };
push @Schaltzeiten, { name => "test1", montag => 1, dienstag => 1, mittwoch => 1, donnerstag => 1, freitag => 1, samstag => 0, sonntag => 0, Stunden => 21, Minuten => 11, Wert => 0, DPT => 1, ga => '1/0/0', KW => '', Monat => '', Astro => '' };
push @Schaltzeiten, { name => "test2", montag => 1, dienstag => 1, mittwoch => 1, donnerstag => 1, freitag => 1, samstag => 0, sonntag => 0, Stunden => 21, Minuten => 10, Wert => 1, DPT => 1, ga => '1/0/25', KW => '', Monat => '', Astro => '' };
push @Schaltzeiten, { name => "test3", montag => 1, dienstag => 1, mittwoch => 1, donnerstag => 1, freitag => 1, samstag => 0, sonntag => 0, Stunden => 21, Minuten => 12, Wert => 0, DPT => 1, ga => '1/0/25', KW => '', Monat => '', Astro => '' };
######################
##ENDE Einstellungen##
######################
use POSIX;
use Time::Local;
# Wir brauchen auch Sonnenstandsberechnung
use Astro::Sunrise;
# Eigenen Aufruf-Zyklus auf 20sek. setzen
$plugin_info{$plugname.'_cycle'} = 20;
#Hier wird ein Array angelegt, um die Wochentagsnummer von localtime zu übersetzen
my @Wochentag = ('sonntag', 'montag', 'dienstag', 'mittwoch', 'donnerstag', 'freitag', 'samstag');
my @sunrise=split(/:/,sun_rise($lon,$lat,$winkel));
my @sunset=split(/:/,sun_set($lon,$lat,$winkel));
my $sec; #Sekunde
my $min; # Minute
my $hour; #Stunde
my $mday; #Monatstag
my $mon; #Monatsnummer
my $year; #Jahr
my $wday; #Wochentag 0-6
my $yday; #Tag ab 01.01.xxxx
my $isdst;
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year += 1900;
$mon += 1;
my $kw = getWeekNumber($year, $mon, $mday);
if(($plugin_info{$plugname.'_time'}+60) <= $plugin_info{$plugname.'_last'}){
foreach my $element (@Schaltzeiten) {
if ($element->{Astro} ne '') {
if ($element->{Astro} eq 'a') {
$element->{Stunden}=$sunrise[0];
$element->{Minuten}=$sunrise[1];
} elsif ($element->{Astro} eq 'u') {
$element->{Stunden}=$sunset[0];
$element->{Minuten}=$sunset[1];
}
}
if ($element->{$Wochentag[$wday]} == 1 && $element->{Stunden} == $hour && $element->{Minuten} == $min && $element->{KW} ne '') {
$plugin_info{$plugname.'_time'} = time();
if ($element->{KW} == $kw) {
knx_write($element->{ga},$element->{Wert},$element->{DPT});
next;
} else {
next;
}
} elsif ($element->{$Wochentag[$wday]} == 1 && $element->{Stunden} == $hour && $element->{Minuten} == $min && $element->{Monat} ne '') {
$plugin_info{$plugname.'_time'} = time();
if ($element->{Monat} == $mon) {
knx_write($element->{ga},$element->{Wert},$element->{DPT});
next;
} else {
next;
}
} elsif ($element->{$Wochentag[$wday]} == 1 && $element->{Stunden} == $hour && $element->{Minuten} == $min && $element->{KW} eq '' && $element->{Monat} eq '') {
$plugin_info{$plugname.'_time'} = time();
knx_write($element->{ga},$element->{Wert},$element->{DPT});
next;
}
next;
}
}else{
return;
}
sub getWeekNumber {
my ($year, $month, $day) = @_;
my $weekNumber = checkWeekNumber($year, $month, $day);
# wenn Wochennummer gleich 0, dann ist das aktuelle Datum
# in der Woche vor dem 4. Januar
# also in der letzten Woche des letzten Jahres
if ($weekNumber eq 0)
{
# Wochennummer des letzten Woche des letzten Jahres suchen
$weekNumber = checkWeekNumber(($year - 1), 12, 31);
# wenn die Wochennummer gr??er als 52 ist
# dann prüfen ob diese Wochennummer korrekt ist oder
# sie bereits die erste Woche des aktuellen Jahres ist
if ($weekNumber gt 52)
{
$weekNumber = checkWeekNumber($year, 1, 1);
# wenn der 1. Januar des aktuellen Jahres in der Woche 0 liegt
# dann ist es die Woche 53
if ($weekNumber eq 0)
{
$weekNumber = 53;
}
}
}
# wenn die Wochennummer grösser als 52 ist
# dann prüfen ob diese Wochennummer korrekt ist oder
# sie bereits die erste Woche des nächsten Jahres ist
elsif ($weekNumber gt 52)
{
$weekNumber = checkWeekNumber(($year + 1), 1, 1);
# wenn der 1. Januar des nächsten Jahres in der Woche 0 liegt
# dann ist es die Woche 53
if ($weekNumber eq 0)
{
$weekNumber = 53;
}
}
return ($weekNumber);
}
sub checkWeekNumber {
my ($year, $month, $day) = @_;
# 4. Januar als erste Woche erstellen
my $firstDateTime = timelocal(0, 0, 12, 4, 0, $year);
# Wochentag des 4. Januar ermitteln
my $dayOfWeek = (localtime($firstDateTime))[6];
$dayOfWeek = abs((($dayOfWeek + 6) % 7));
# geh zu Wochenanfang (Montag) zurück
$firstDateTime -= ($dayOfWeek * 3600 * 24);
# aktuelles Datum erstellen
my $currentDateTime = timelocal(0, 0, 14, $day, ($month - 1),$year);
# Differenz in Tagen berechnen
my $diffInDay = ($currentDateTime - $firstDateTime) / 3600 / 24;
# Anzahl der Wochen zwischen aktuellem Datum und 4. Januar berechnen
my $weekNumber = floor($diffInDay / 7) + 1;
return ($weekNumber);
}
die Version scheint zu funktionieren. Da die aktuelle SVN Version nicht funktioniert (sunrise und sunset sind nicht definiert) schlage ich vor, du lädtst sie hoch.
Eine Bitte hätte ich noch:
#und 'u' f�r Sonnenuntergang eingetragen werden. Der Stunden und Minutenwert wird dann ignoriert.
Ich meine, ich hätte es schonmal vorgeschlagen: Könnten die Stunden einfach drauf addiert werden auf den Astro-Wert?
Dann könnte man z.B. die Außenbeleuchtung 1h nach Sonnenuntergang anschalten.
Ja das klingt nach einer guten Lösung. Mal sehen ob ich morgen dazu komme. Dann stelle ich die Erweiterung hier nochmal zum testen ein und wenn es so klapt, wird es in's SVN übertragen
Super!
Wo wir gerade beim Wünsch dir Was sind:
Log-Einträge beim Schalten wären super! (vllt. gibt's die mittlerweile, ich hatte bis heute die ältere Version installiert)
Ich habe die aktuelle Version mal ergänzt. Leider kann ich selbst es nicht testen, da bei mir Astro nicht funktioniert. (Hat damit zutun das ipk 100 seltsame Fragen Stellt -.-) egal.
Also bitte mal testen damit ich weiss ob es so funktioniert
Code:
# Plugin zum Zeit abhängigem schalten von GA's (Schaltuhr)
# Version 0.8 BETA 03.10.2012
# Copyright: swiss (https://knx-user-forum.de/members/swiss.html)
# License: GPL (v2)
# Aufbau möglichst so, dass man unterhalb der Einstellungen nichts verändern muss!
# -Erweitert um Sonnenauf / - untergang von ZeitlerW (https://knx-user-forum.de/members/zeitlerw.html)
# -Inspiriert von kleinklausi's Rolladen - Plugin
my @Schaltzeiten;
####################
###Einstellungen:###
####################
# Die Standortdaten
# Die Koordinaten des Hauses. Sehr einfach ?ber http://www.getlatlon.com/ zu ermitteln.
my ($lat, $lon) = (
51.66787081407156, # Breitengrad in Grad
13.64227294921875 # L?ngengrad in Grad
);
#Winkel für Beginn der Dämmerung
# siehe auch: http://search.cpan.org/~rkhill/Astro-Sunrise-0.91/Sunrise.pm#DESCRIPTION
my $winkel=-3;
#Pro Schaltpunkt einfach den unten stehenden Eintrag kopieren und anpassen.
#Sollen Schaltzeiten astronomisch geschaltet werden, so muss bei Astro 'a' für Sonnenaufgang
#und 'u' für Sonnenuntergang eingetragen werden. Der Stunden und Minutenwert wird dann ignoriert.
push @Schaltzeiten, { name => "test", montag => 1, dienstag => 1, mittwoch => 1, donnerstag => 1, freitag => 1, samstag => 0, sonntag => 0, Stunden => 21, Minuten => 10, Wert => 1, DPT => 1, ga => '1/0/0', KW => '', Monat => '', Astro => '' };
push @Schaltzeiten, { name => "test1", montag => 1, dienstag => 1, mittwoch => 1, donnerstag => 1, freitag => 1, samstag => 0, sonntag => 0, Stunden => 21, Minuten => 11, Wert => 0, DPT => 1, ga => '1/0/0', KW => '', Monat => '', Astro => '' };
push @Schaltzeiten, { name => "test2", montag => 1, dienstag => 1, mittwoch => 1, donnerstag => 1, freitag => 1, samstag => 0, sonntag => 0, Stunden => 21, Minuten => 10, Wert => 1, DPT => 1, ga => '1/0/25', KW => '', Monat => '', Astro => '' };
push @Schaltzeiten, { name => "test3", montag => 1, dienstag => 1, mittwoch => 1, donnerstag => 1, freitag => 1, samstag => 0, sonntag => 0, Stunden => 21, Minuten => 12, Wert => 0, DPT => 1, ga => '1/0/25', KW => '', Monat => '', Astro => '' };
######################
##ENDE Einstellungen##
######################
use POSIX;
use Time::Local;
# Wir brauchen auch Sonnenstandsberechnung
use Astro::Sunrise;
# Eigenen Aufruf-Zyklus auf 20sek. setzen
$plugin_info{$plugname.'_cycle'} = 20;
#Hier wird ein Array angelegt, um die Wochentagsnummer von localtime zu übersetzen
my @Wochentag = ('sonntag', 'montag', 'dienstag', 'mittwoch', 'donnerstag', 'freitag', 'samstag');
my @sunrise=split(/:/,sun_rise($lon,$lat,$winkel));
my @sunset=split(/:/,sun_set($lon,$lat,$winkel));
my $sec; #Sekunde
my $min; # Minute
my $hour; #Stunde
my $mday; #Monatstag
my $mon; #Monatsnummer
my $year; #Jahr
my $wday; #Wochentag 0-6
my $yday; #Tag ab 01.01.xxxx
my $isdst;
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year += 1900;
$mon += 1;
my $kw = getWeekNumber($year, $mon, $mday);
if(($plugin_info{$plugname.'_time'}+60) <= $plugin_info{$plugname.'_last'}){
foreach my $element (@Schaltzeiten) {
if ($element->{Astro} ne '') {
if ($element->{Stunden} ne '' or $element->{Minuten} ne '') {
if ($element->{Astro} eq 'a') {
$element->{Stunden}+=$sunrise[0];
$element->{Minuten}+=$sunrise[1];
} elsif ($element->{Astro} eq 'u') {
$element->{Stunden}+=$sunset[0];
$element->{Minuten}+=$sunset[1];
}
}else{
if ($element->{Astro} eq 'a') {
$element->{Stunden}=$sunrise[0];
$element->{Minuten}=$sunrise[1];
} elsif ($element->{Astro} eq 'u') {
$element->{Stunden}=$sunset[0];
$element->{Minuten}=$sunset[1];
}
}
}
if ($element->{$Wochentag[$wday]} == 1 && $element->{Stunden} == $hour && $element->{Minuten} == $min && $element->{KW} ne '') {
$plugin_info{$plugname.'_time'} = time();
if ($element->{KW} == $kw) {
knx_write($element->{ga},$element->{Wert},$element->{DPT});
plugin_log($plugname,'Schaltpunkt: ' . $element->{name} . ' ausgeführt. Wert: ' . $element->{Wert} . ' an Gruppenadresse ' . $element->{ga} . ' gesendet');
next;
} else {
next;
}
} elsif ($element->{$Wochentag[$wday]} == 1 && $element->{Stunden} == $hour && $element->{Minuten} == $min && $element->{Monat} ne '') {
$plugin_info{$plugname.'_time'} = time();
if ($element->{Monat} == $mon) {
knx_write($element->{ga},$element->{Wert},$element->{DPT});
plugin_log($plugname,'Schaltpunkt: ' . $element->{name} . ' ausgeführt. Wert: ' . $element->{Wert} . ' an Gruppenadresse ' . $element->{ga} . ' gesendet');
next;
} else {
next;
}
} elsif ($element->{$Wochentag[$wday]} == 1 && $element->{Stunden} == $hour && $element->{Minuten} == $min && $element->{KW} eq '' && $element->{Monat} eq '') {
$plugin_info{$plugname.'_time'} = time();
knx_write($element->{ga},$element->{Wert},$element->{DPT});
plugin_log($plugname,'Schaltpunkt: ' . $element->{name} . ' ausgeführt. Wert: ' . $element->{Wert} . ' an Gruppenadresse ' . $element->{ga} . ' gesendet');
next;
}
next;
}
}else{
return;
}
sub getWeekNumber {
my ($year, $month, $day) = @_;
my $weekNumber = checkWeekNumber($year, $month, $day);
# wenn Wochennummer gleich 0, dann ist das aktuelle Datum
# in der Woche vor dem 4. Januar
# also in der letzten Woche des letzten Jahres
if ($weekNumber eq 0)
{
# Wochennummer des letzten Woche des letzten Jahres suchen
$weekNumber = checkWeekNumber(($year - 1), 12, 31);
# wenn die Wochennummer gr??er als 52 ist
# dann prüfen ob diese Wochennummer korrekt ist oder
# sie bereits die erste Woche des aktuellen Jahres ist
if ($weekNumber gt 52)
{
$weekNumber = checkWeekNumber($year, 1, 1);
# wenn der 1. Januar des aktuellen Jahres in der Woche 0 liegt
# dann ist es die Woche 53
if ($weekNumber eq 0)
{
$weekNumber = 53;
}
}
}
# wenn die Wochennummer grösser als 52 ist
# dann prüfen ob diese Wochennummer korrekt ist oder
# sie bereits die erste Woche des nächsten Jahres ist
elsif ($weekNumber gt 52)
{
$weekNumber = checkWeekNumber(($year + 1), 1, 1);
# wenn der 1. Januar des nächsten Jahres in der Woche 0 liegt
# dann ist es die Woche 53
if ($weekNumber eq 0)
{
$weekNumber = 53;
}
}
return ($weekNumber);
}
sub checkWeekNumber {
my ($year, $month, $day) = @_;
# 4. Januar als erste Woche erstellen
my $firstDateTime = timelocal(0, 0, 12, 4, 0, $year);
# Wochentag des 4. Januar ermitteln
my $dayOfWeek = (localtime($firstDateTime))[6];
$dayOfWeek = abs((($dayOfWeek + 6) % 7));
# geh zu Wochenanfang (Montag) zurück
$firstDateTime -= ($dayOfWeek * 3600 * 24);
# aktuelles Datum erstellen
my $currentDateTime = timelocal(0, 0, 14, $day, ($month - 1),$year);
# Differenz in Tagen berechnen
my $diffInDay = ($currentDateTime - $firstDateTime) / 3600 / 24;
# Anzahl der Wochen zwischen aktuellem Datum und 4. Januar berechnen
my $weekNumber = floor($diffInDay / 7) + 1;
return ($weekNumber);
}
EDIT: BUG mit der Klammer in der Zeile 92 behoben.
Wir verarbeiten personenbezogene Daten über die Nutzer unserer Website mithilfe von Cookies und anderen Technologien, um unsere Dienste bereitzustellen. Weitere Informationen findest Du in unserer Datenschutzerklärung.
Indem Du unten auf "ICH stimme zu" klickst, stimmst Du unserer Datenschutzerklärung und unseren persönlichen Datenverarbeitungs- und Cookie-Praktiken zu, wie darin beschrieben. Du erkennst außerdem an, dass dieses Forum möglicherweise außerhalb Deines Landes gehostet wird und bist damit einverstanden, dass Deine Daten in dem Land, in dem dieses Forum gehostet wird, gesammelt, gespeichert und verarbeitet werden.
Kommentar