Hallo,
nachdem ich erfolgreich KNXD mit einem fremden Bussystem ans Laufen gebracht habe, stelle ich meine Plugins auf den Wiregate Syntax um.
Hier ist jetzt eine Abwandlung des Schaltuhr-Plugins, welches aber ohne eine Cycle-Zeit von 20 Sekunden auskommt.
Das Plugin wird immer nur zu den Schaltzeiten aufgerufen und behandelt einen Feiertag als Sonntag. Sonnenauf- und Untergangszeiten sind ebenfalls möglich.
Nach dem gleichen Prinzip habe ich auch andere Plugins mit täglich festgelegten Aktionszeiten angepasst. Ich denke dass dadurch weniger Ressourcen verbraucht werden, was z.B. bei ARM-Systemen von Vorteil ist.
Gruß
Carsten
nachdem ich erfolgreich KNXD mit einem fremden Bussystem ans Laufen gebracht habe, stelle ich meine Plugins auf den Wiregate Syntax um.
Hier ist jetzt eine Abwandlung des Schaltuhr-Plugins, welches aber ohne eine Cycle-Zeit von 20 Sekunden auskommt.
Das Plugin wird immer nur zu den Schaltzeiten aufgerufen und behandelt einen Feiertag als Sonntag. Sonnenauf- und Untergangszeiten sind ebenfalls möglich.
Nach dem gleichen Prinzip habe ich auch andere Plugins mit täglich festgelegten Aktionszeiten angepasst. Ich denke dass dadurch weniger Ressourcen verbraucht werden, was z.B. bei ARM-Systemen von Vorteil ist.
Code:
# Wochenzeitschaltuhr zum Senden von GA's
# - Berücksichtigung von Sonnenaufgang und Sonnenuntergang
# - Feiertag wird als Sonntag behandelt (Feiertage je
# nach Bundesland im Unterprogramm anpassen)
# - Berücksichtigung von Wechsel auf Sommer- oder Winterzeit
#
# Version 0.1 21.05.2013
# Copyright: derwolff2010 (https://knx-user-forum.de/members/derwolff2010.html)
# License: GPL (v2)
# Inspiriert durch die Plugins von swiss, zeitlerw, Fry
my @Schaltzeiten;
#Einstellungen---------------------------------------------------------------------------
# Die Standortdaten
# Die Koordinaten des Hauses. Sehr einfach über http://www.getlatlon.com/ zu ermitteln.
my ($lat, $lon, $elev) = (
0.0, # Breitengrad in Grad
0.0 );# 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=-6; # Bürgerliche Dämmerung
#Pro Schaltpunkt den unten stehenden Eintrag kopieren und anpassen.
#Sollen Schaltzeiten astronomisch geschaltet werden, so muss bei astro 'a' für Sonnenaufgang
#oder 'u' für Sonnenuntergang eingetragen werden. Die Uhrzeit wird dann ignoriert.
#Feiertage werden wie Sonntage behandelt.
push @Schaltzeiten, { name => "Schaltzeit", mo => 1, di => 1, mi => 1, do => 1, fr => 1, sa => 0, so => 0,
zeit => '08:00', astro => '', ga => '0/0/0', wert => 1, dpt => 1 };
# Ende Einstellungen-----------------------------------------------------------------------
use POSIX;
use Time::Local;
use Astro::Sunrise;
# Aufrufgrund ermitteln
my $event=undef;
if (!$plugin_initflag) {
$event='restart'; } # Restart des daemons / Reboot
elsif ($plugin_info{$plugname.'_lastsaved'} > $plugin_info{$plugname.'_last'}) {
$event='modified'; } # Plugin modifiziert
elsif (%msg) { $event='bus'; } # Bustraffic
elsif ($fh) { $event='socket'; } # Netzwerktraffic
else { $event='cycle'; } # Zyklus
# Plugin-Code fuer die verschiedenen Aufrufvarianten
if($event=~/restart|modified/) {
# Erster Aufruf nach Reboot, Daemon-Restart oder Plugin-Modifikation
# Cleanup aller Variablen
for my $k (grep /^$plugname\_/, keys %plugin_info) {
delete $plugin_info{$k};
}
plugin_log($plugname,"initialisiert");
}
#Hier wird ein Array angelegt, um die Wochentagsnummer von localtime zu übersetzen
my @Wochentag = ('so', 'mo', 'di', 'mi', 'do', 'fr', 'sa');
# Sonnenaufgang und Untergang berechnen
my $sonnenaufgang = sec(sun_rise($lon,$lat,$winkel));
my $sonnenuntergang = sec(sun_set($lon,$lat,$winkel));
my $schaltzeit = 0;
my $schaltzeit_min = 86400; # 1 Tag
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = localtime(time);
$yday = $yday+1;
my $time = $hour*3600+$min*60+$sec;
# Feiertag als Sonntag behandeln
if (is_holiday()) { $wday = 0;}
# nächste Schaltzeit bestimmen
foreach my $element (@Schaltzeiten) {
#Überspringe Schaltpunkt wenn heute schon ausgeführt oder Wochentag nicht aktiv ist
if ($plugin_info{$plugname.'_'.$element->{name}}==$yday || $element->{$Wochentag[$wday]} != 1 ) {next;}
if ($element->{astro} ne '') {
if ($element->{astro} eq 'a') {$schaltzeit = $sonnenaufgang;}
else {$schaltzeit = $sonnenuntergang;}
}
else {$schaltzeit = sec($element->{zeit});}
if ($time >= $schaltzeit && $time < ($schaltzeit+60)) {
$plugin_info{$plugname.'_'.$element->{name}}=$yday;
knx_write($element->{ga},$element->{wert},$element->{dpt});
plugin_log($plugname,'Schaltpunkt: '.$element->{name}.' ausgeführt. Wert: '.$element->{wert}.' an Gruppenadresse '.$element->{ga}.' gesendet');
}
elsif ($schaltzeit > $time && $schaltzeit < $schaltzeit_min) {$schaltzeit_min = $schaltzeit;}
}
# Nächste Aufrufzeit setzen, spätestens wieder um 0 Uhr
if ($schaltzeit_min == 86400) {$schaltzeit_min=sek_bis_schaltzeit(sec('00:00'));}
else {$schaltzeit_min=sek_bis_schaltzeit($schaltzeit_min);}
$plugin_info{$plugname.'_cycle'}=$schaltzeit_min;
($sec,$min,$hour) = localtime(time + $schaltzeit_min);
$hour = sprintf "%02d",$hour;
$min = sprintf "%02d",$min;
plugin_log($plugname,"Nächster Aufruf in $schaltzeit_min Sek., $hour:$min Uhr");
return;
# Unterprogramme ---------------------------------------------------------------
sub sek_bis_schaltzeit {
# Eingangsparam.: Zeit in Sek., Ausgabeparam.: Zeit in Sek.
# Berechnet die Zeit von aktueller Zeit bis zur Schaltzeit in Sek.
my $schalt_zeit_sek = $_[0];
my $stunde = int($schalt_zeit_sek/3600);
# Aktuelle Zeit lesen
my ($sec,$min,$hour) = localtime(time);
my $time = $hour*3600+$min*60+$sec;
# Wenn akt. Zeit schon später als Schaltzeit, nächsten Tag einplanen?
if ($schalt_zeit_sek < $time) {$schalt_zeit_sek+=86400; }
my $wartezeit = $schalt_zeit_sek - $time;
($sec,$min,$hour) = localtime(time+$wartezeit);
# Überprüfung auf Wechsel von Sommer- u. Winterzeit
if ($hour<$stunde) {$wartezeit+=3600;}
elsif ($hour>$stunde) {$wartezeit-=3600;}
return ($wartezeit);
}
sub is_holiday
{
#Aufruf: is_holiday()
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = localtime(time);
$year = $year + 1900;
$yday = $yday + 1;
# Schaltjahr?
my $leapyear = ($year % 4)==0 && ($year % 100!=0 || $year % 400==0);
# Osterdatum berechnen (Algorithmus von Ron Mallen, Codefragment von Randy McLeary, beruht auf der Formel von Gauss/Lichtenberg)
my $C = int($year/100);
my $G = $year%19;
my $K = int(($C - 17)/25);
my $I = ($C - int($C/4) - int(($C - $K)/3) + 19 * $G + 15)%30;
$I = $I - int($I/28) * (1 - int($I/28) * int(29/($I + 1)) * int((21 - $G)/11));
my $L = $I - ($year + int($year/4) + $I + 2 - $C + int($C/4))%7;
my $M = 3 + int(($L + 40)/44);
my $D = $L + 28 - 31 * int($M/4);
# diesjaehriger Ostersonntag ist $year-$M-$D
# julianisches Osterdatum (Tag im Jahr) berechnen $year-$J
my @days_before_month=(0,0,31,59+$leapyear,90+$leapyear,120+$leapyear,151+$leapyear,181+$leapyear,212+$leapyear,243+$leapyear,
273+$leapyear,304+$leapyear,334+$leapyear);
my $J = $days_before_month[$M]+$D;
# Feiertagstabelle für NRW als Tageszahl im Jahr (1=1.Januar, 32=1.Februar usw.): 1.1., 1.5., 3.10., 1.11., 25./26.12.
# und die auf Ostern bezogenen Kirchenfeiertage: Karfreitag, Ostern (2x), Christi Himmelfahrt, Pfingsten (2x), Fronleichnam
my @holidays=(1,121+$leapyear,276+$leapyear,304+$leapyear,359+$leapyear,360+$leapyear,$J-2,$J,$J+39,$J+49,$J+50,$J+60);
return (grep { $_==$yday } @holidays) ? 1 : 0;
}
sub sunpos {
# Module laden
use Astro::Coord::ECI;
use Astro::Coord::ECI::Sun;
use Astro::Coord::ECI::TLE;
use Astro::Coord::ECI::Utils qw{rad2deg deg2rad};
# Aktuelle Zeit
my $time = time ();
# Die eigenen Koordinaten
my $loc = Astro::Coord::ECI->geodetic(deg2rad(shift), deg2rad(shift), shift);
# Sonne instanzieren
my $sun = Astro::Coord::ECI::Sun->universal($time);
# Sonnenstand berechnen
my ($azimut, $elevation, $range) = $loc->azel($sun);
return (rad2deg($azimut), rad2deg($elevation));
}
sub sec {
# Konvertiert HH:MM in Sekunden
my $time = $_[0];
$time =~ /(\d+):(\d+)/;
return ($1*60*60+$2*60);
}
Carsten


Ich werde es bei Gelegenheit testen. Läuft auch auf dem Wiregate oder?
Kommentar