Hauptmenü

Sonnenstand berechnen

Begonnen von Loredo, 18 Mai 2013, 14:41:38

Vorheriges Thema - Nächstes Thema

Loredo

Hi,

ich würde gerne berechnen wo in etwa sich die Sonne gerade befindet, um davon abhängig meine Rollläden und die Markise zu steuern.
Ich stelle mir einen Wert ost, süd-ost, süd, süd-west, west vor. Kann ich das irgendwie bereits über die Funktionen des Moduls SUNRISE_EL ableiten oder muss ich mir das komplett selbst in Perl schreiben?


Gruß
Julian
Hat meine Arbeit dir geholfen? ⟹ https://paypal.me/pools/c/8gDLrIWrG9

Maintainer:
FHEM-Docker Image, https://github.com/fhem, Astro(Co-Maintainer), ENIGMA2, GEOFANCY, GUEST, HP1000, Installer, LaMetric2, MSG, msgConfig, npmjs, PET, PHTV, Pushover, RESIDENTS, ROOMMATE, search, THINKINGCLEANER

Dietmar63

Nimm die Uhrzeit : 12:00 ist Süd...
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

Loredo

Das ist mir zu ungenau und stimmt so auch nicht (z.B. wegen der Sommerzeit)
Hat meine Arbeit dir geholfen? ⟹ https://paypal.me/pools/c/8gDLrIWrG9

Maintainer:
FHEM-Docker Image, https://github.com/fhem, Astro(Co-Maintainer), ENIGMA2, GEOFANCY, GUEST, HP1000, Installer, LaMetric2, MSG, msgConfig, npmjs, PET, PHTV, Pushover, RESIDENTS, ROOMMATE, search, THINKINGCLEANER

Dietmar63

Die Sommerzeit lässt sich leicht einrechnen: letzter Parameter von localtime!

Genauer geht es meiner Meinung nach nicht. Und etwas fertiges kenne ich nicht.
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

Loredo

Ich denke eher an sowas:


define WeatherStation.SolarAzimuthAngle dummy

define *{sunrise("NAUTIC",0,"03:00","08:00")} {

my ($sunrise_h, $sunrise_m, $sunrise_s) = split /:/, sunrise_abs("NAUTIC");
my ($sunset_h, $sunset_m, $sunset_s) = split /:/, sunset_abs("NAUTIC");
my $sunrise_rel=($sunrise_h * 60 * 60) + ($sunrise_m * 60) + $sunrise_s;
my $sunset_rel=($sunset_h * 60 * 60) + ($sunset_m * 60) + $sunset_s;

my $slotlength_se=int(($sunset_rel-$sunrise_rel)/8*1);
my $se_hours=int( ($slotlength_se/(60*60))%24 );
my $se_minutes=int( ( ($slotlength_se-$se_hours*(60*60)) /60)%60);
my $se_seconds=int( ($slotlength_se-$se_hours*(60*60)-$se_minutes*60)%60 );
my $time_se=$se_hours.":".$se_minutes.":".$se_seconds;

my $slotlength_s=int(($sunset_rel-$sunrise_rel)/8*3);
my $s_hours=int( ($slotlength_s/(60*60))%24 );
my $s_minutes=int( ( ($slotlength_s-$s_hours*(60*60)) /60)%60);
my $s_seconds=int( ($slotlength_s-$s_hours*(60*60)-$s_minutes*60)%60 );
my $time_s=$s_hours.":".$s_minutes.":".$s_seconds;

my $slotlength_sw=int(($sunset_rel-$sunrise_rel)/8*5);
my $sw_hours=int( ($slotlength_sw/(60*60))%24 );
my $sw_minutes=int( ( ($slotlength_sw-$sw_hours*(60*60)) /60)%60);
my $sw_seconds=int( ($slotlength_sw-$sw_hours*(60*60)-$sw_minutes*60)%60 );
my $time_sw=$sw_hours.":".$sw_minutes.":".$sw_seconds;

my $slotlength_w=int(($sunset_rel-$sunrise_rel)/8*7);
my $w_hours=int( ($slotlength_w/(60*60))%24 );
my $w_minutes=int( ( ($slotlength_w-$w_hours*(60*60)) /60)%60);
my $w_seconds=int( ($slotlength_w-$w_hours*(60*60)-$w_minutes*60)%60 );
my $time_w=$w_hours.":".$w_minutes.":".$w_seconds;

fhem "set WeatherStation.SolarAzimuthAngle east";
fhem "define WeatherStation.SolarAzimuthAngle.se at +$time_se set WeatherStation.SolarAzimuthAngle south-east";
fhem "define WeatherStation.SolarAzimuthAngle.s at +$time_s set WeatherStation.SolarAzimuthAngle south";
fhem "define WeatherStation.SolarAzimuthAngle.sw at +$time_sw set WeatherStation.SolarAzimuthAngle south-west";
fhem "define WeatherStation.SolarAzimuthAngle.w at +$time_w set WeatherStation.SolarAzimuthAngle west";

}

define WeatherStation.SolarAzimuthAngle.night at *{sunset("NAUTIC",0,"16:00","23:00")} { set WeatherStation.SolarAzimuthAngle night }


Der Code tut nur noch nicht, weil ich immer "Unknown command my, try help" bekomme.
Hat meine Arbeit dir geholfen? ⟹ https://paypal.me/pools/c/8gDLrIWrG9

Maintainer:
FHEM-Docker Image, https://github.com/fhem, Astro(Co-Maintainer), ENIGMA2, GEOFANCY, GUEST, HP1000, Installer, LaMetric2, MSG, msgConfig, npmjs, PET, PHTV, Pushover, RESIDENTS, ROOMMATE, search, THINKINGCLEANER

MisterEltako

Also wenn du zunächst in die Datei FHEM.cfg

define WeatherStation.SolarAzimuthAngle dummy
define WeatherStation dummy

define Testroutine notify WeatherStation {Testroutine()}



und in 99_Utils.pm:

sub
Testroutine()
{

my ($sunrise_h, $sunrise_m, $sunrise_s) = split /:/, sunrise_abs("NAUTIC");
my ($sunset_h, $sunset_m, $sunset_s) = split /:/, sunset_abs("NAUTIC");
my $sunrise_rel=($sunrise_h * 60 * 60) + ($sunrise_m * 60) + $sunrise_s;
my $sunset_rel=($sunset_h * 60 * 60) + ($sunset_m * 60) + $sunset_s;

my $slotlength_se=int(($sunset_rel-$sunrise_rel)/8*1);
my $se_hours=int( ($slotlength_se/(60*60))%24 );
my $se_minutes=int( ( ($slotlength_se-$se_hours*(60*60)) /60)%60);
my $se_seconds=int( ($slotlength_se-$se_hours*(60*60)-$se_minutes*60)%60 );
my $time_se=$se_hours.":".$se_minutes.":".$se_seconds;

my $slotlength_s=int(($sunset_rel-$sunrise_rel)/8*3);
my $s_hours=int( ($slotlength_s/(60*60))%24 );
my $s_minutes=int( ( ($slotlength_s-$s_hours*(60*60)) /60)%60);
my $s_seconds=int( ($slotlength_s-$s_hours*(60*60)-$s_minutes*60)%60 );
my $time_s=$s_hours.":".$s_minutes.":".$s_seconds;

my $slotlength_sw=int(($sunset_rel-$sunrise_rel)/8*5);
my $sw_hours=int( ($slotlength_sw/(60*60))%24 );
my $sw_minutes=int( ( ($slotlength_sw-$sw_hours*(60*60)) /60)%60);
my $sw_seconds=int( ($slotlength_sw-$sw_hours*(60*60)-$sw_minutes*60)%60 );
my $time_sw=$sw_hours.":".$sw_minutes.":".$sw_seconds;

my $slotlength_w=int(($sunset_rel-$sunrise_rel)/8*7);
my $w_hours=int( ($slotlength_w/(60*60))%24 );
my $w_minutes=int( ( ($slotlength_w-$w_hours*(60*60)) /60)%60);
my $w_seconds=int( ($slotlength_w-$w_hours*(60*60)-$w_minutes*60)%60 );
my $time_w=$w_hours.":".$w_minutes.":".$w_seconds;

fhem "set WeatherStation.SolarAzimuthAngle east";
fhem "define WeatherStation.SolarAzimuthAngle.se at +$time_se set WeatherStation.SolarAzimuthAngle south-east";
fhem "define WeatherStation.SolarAzimuthAngle.s at +$time_s set WeatherStation.SolarAzimuthAngle south";
fhem "define WeatherStation.SolarAzimuthAngle.sw at +$time_sw set WeatherStation.SolarAzimuthAngle south-west";
fhem "define WeatherStation.SolarAzimuthAngle.w at +$time_w set WeatherStation.SolarAzimuthAngle west";

}


... einträgst. Läuft dein Code zunächst über trigger WeatherStation oder Betätigen des Dummy's. Ob er allerdings das anzeigt, was du willst musst du selbst entscheiden.... ;o)

MfG, MisterEltako
HMLAN-Konfigurations-Adapter, HM-Funkjalousieaktor/HM-Dimmaktor/HM-Schaltaktor f. Markenschalter, Jalousie-/Schaltaktor von Eltako, FT4 v. Eltako, TCM310

Puschel74

Hallo,

Leerzeilen im Code sind auch eher kontraproduktiv.

Grüße
Zotac BI323 als Server mit DBLog
CUNO für FHT80B, 3 HM-Lan per vCCU, RasPi mit CUL433 für Somfy-Rollo (F2F), RasPi mit I2C(LM75) (F2F), RasPi für Panstamp+Vegetronix +SONOS(F2F)
Ich beantworte keine Supportanfragen per PM! Bitte im Forum suchen oder einen Beitrag erstellen.

Loredo

Danke, ob es nun wirklich funktioniert sehe ich morgen früh, es sieht aber ganz so aus.

Hier nochmal zusammengefasst:

99_MyUtils.pm

sub
SolarAzimuthAngle()
{
my ($sunset_h, $sunset_m, $sunset_s) = split /:/, sunset_rel("CIVIL");
my $sunshine=($sunset_h * 60 * 60) + ($sunset_m * 60) + $sunset_s;

my $slotlength_se=int($sunshine/8*1);
my $se_hours=int( ($slotlength_se/(60*60))%24 );
my $se_minutes=int( ( ($slotlength_se-$se_hours*(60*60)) /60)%60);
my $se_seconds=int( ($slotlength_se-$se_hours*(60*60)-$se_minutes*60)%60 );
if ($se_hours < 10) {$se_hours="0".$se_hours}
if ($se_minutes < 10) {$se_minutes="0".$se_minutes}
if ($se_seconds < 10) {$se_seconds="0".$se_seconds}
my $time_se=$se_hours.":".$se_minutes.":".$se_seconds;

my $slotlength_s=int($sunshine/8*3);
my $s_hours=int( ($slotlength_s/(60*60))%24 );
my $s_minutes=int( ( ($slotlength_s-$s_hours*(60*60)) /60)%60);
my $s_seconds=int( ($slotlength_s-$s_hours*(60*60)-$s_minutes*60)%60 );
if ($s_hours < 10) {$s_hours="0".$s_hours}
if ($s_minutes < 10) {$s_minutes="0".$s_minutes}
if ($s_seconds < 10) {$s_seconds="0".$s_seconds}
my $time_s=$s_hours.":".$s_minutes.":".$s_seconds;

my $slotlength_sw=int($sunshine/8*5);
my $sw_hours=int( ($slotlength_sw/(60*60))%24 );
my $sw_minutes=int( ( ($slotlength_sw-$sw_hours*(60*60)) /60)%60);
my $sw_seconds=int( ($slotlength_sw-$sw_hours*(60*60)-$sw_minutes*60)%60 );
if ($sw_hours < 10) {$sw_hours="0".$sw_hours}
if ($sw_minutes < 10) {$sw_minutes="0".$sw_minutes}
if ($sw_seconds < 10) {$sw_seconds="0".$sw_seconds}
my $time_sw=$sw_hours.":".$sw_minutes.":".$sw_seconds;

my $slotlength_w=int($sunshine/8*7);
my $w_hours=int( ($slotlength_w/(60*60))%24 );
my $w_minutes=int( ( ($slotlength_w-$w_hours*(60*60)) /60)%60);
my $w_seconds=int( ($slotlength_w-$w_hours*(60*60)-$w_minutes*60)%60 );
if ($w_hours < 10) {$w_hours="0".$w_hours}
if ($w_minutes < 10) {$w_minutes="0".$w_minutes}
if ($w_seconds < 10) {$w_seconds="0".$w_seconds}
my $time_w=$w_hours.":".$w_minutes.":".$w_seconds;

if ( defined($defs{"WeatherStation.SolarAzimuthAngle.se"}) ) { fhem("delete WeatherStation.SolarAzimuthAngle.se"); }
if ( defined($defs{"WeatherStation.SolarAzimuthAngle.s"}) ) { fhem("delete WeatherStation.SolarAzimuthAngle.s"); }
if ( defined($defs{"WeatherStation.SolarAzimuthAngle.sw"}) ) { fhem("delete WeatherStation.SolarAzimuthAngle.sw"); }
if ( defined($defs{"WeatherStation.SolarAzimuthAngle.w"}) ) { fhem("delete WeatherStation.SolarAzimuthAngle.w"); }

fhem "set WeatherStation.SolarAzimuthAngle east";
fhem "define WeatherStation.SolarAzimuthAngle.se at +$time_se set WeatherStation.SolarAzimuthAngle southeast";
fhem "define WeatherStation.SolarAzimuthAngle.s at +$time_s set WeatherStation.SolarAzimuthAngle south";
fhem "define WeatherStation.SolarAzimuthAngle.sw at +$time_sw set WeatherStation.SolarAzimuthAngle southwest";
fhem "define WeatherStation.SolarAzimuthAngle.w at +$time_w set WeatherStation.SolarAzimuthAngle west";

}


fhem.cfg

define WeatherStation.SolarAzimuthAngle dummy
attr WeatherStation.SolarAzimuthAngle alias Solar azimuth angle
attr WeatherStation.SolarAzimuthAngle group Weather
attr WeatherStation.SolarAzimuthAngle room Apartment
attr WeatherStation.SolarAzimuthAngle setList state:east,southeast,south,southwest,west,night

define WeatherStation.SolarAzimuthAngle.morning at *{sunrise("CIVIL",0,"03:00","08:00")} {SolarAzimuthAngle()}
define WeatherStation.SolarAzimuthAngle.night at *{sunset("CIVIL",0,"16:00","23:00")} set WeatherStation.SolarAzimuthAngle night
Hat meine Arbeit dir geholfen? ⟹ https://paypal.me/pools/c/8gDLrIWrG9

Maintainer:
FHEM-Docker Image, https://github.com/fhem, Astro(Co-Maintainer), ENIGMA2, GEOFANCY, GUEST, HP1000, Installer, LaMetric2, MSG, msgConfig, npmjs, PET, PHTV, Pushover, RESIDENTS, ROOMMATE, search, THINKINGCLEANER

crissiloop

Hallo Loredo,

kannst du deinen Code vielleicht kurz etwas erläutern?
Denn dein erster Entwurf ist ja noch mit Sunset und Sunrise und der 2. dann nur noch mit Sunset.

Es wäre hilfreich, um dein Vorgehen zu verstehen.

Ich würde nämlich meine Beschattungssteuerung etwas verfeinern und das Hochfahren der Rollläden abhängig vom Sonnenstand erledigen lassen. Im Moment passiert das noch über fixe Zeiten.

Gruß
Christian
FHEM 5.5 auf Cubietruck

1x HMLAN, 1x HMUSB, 12x HM-LC-Bl1 PBU-FM, 5x HM-LC-Sw1-Pl, 1x HM-LC-Sw1-FM, 2x HM-LC-Sw2-FM, 2x HM-SEC-RHS, 3x HM-SEC-SD, 8x HM-SEC-SC, 3x HM-RC-4-2, 1x HM-RC-8, 1x HM-Sec-SFA-SM, Jeelink, 7x Technoline TX 29 DTH-IT

Loredo

Hi Christian,

im Grunde kein Hexenwerk. Ich möchte wohl das gleiche wie du machen, nämlich die Beschattung anhand des Sonneneinfalls steuern ;-)
Ganz zufrieden bin ich noch nicht, hauptsächlich wegen der täglichen Berechnung. Geht was schief stimmt den ganzen Tag der Wert nicht, weil man es nicht nachberechnet kriegt. Die Nutzung der absoluten Werte aus sunset_abs sollte genau das bringen, es tat aber irgendwie nicht.
Deshalb wird momentan davon ausgegangen, dass sunset_rel() zum Zeitpunkt des Sonnenaufgangs die gesamte Dauer zwischen Auf- und Untergang für den aktuellen Tag liefert. Zuvor hatte ich das aus der Differenz zwischen sunrise_abs() und sunset_abs() berechnet. Theoretisch hätte ich gedacht, dass man die Berechnung dann beliebig oft für den aktuellen Tag durchführen kann und immer zum gleichen Ergebnis kommt. Dem war aber irgendwie nicht so, leider.

Also Grundsätzlich:
Ich definiere zwei Notifys. Der eine wird bei Sonnenaufgang (ich setze derzeit auf CIVIL, NAUTIC war doch etwas zu früh) ausgeführt und stößt das Berechnungsscript an. Das zweite Notify setzt ganz einfach den Wert auf "night" wenn die Sonne untergegangen ist.

Das Berechnungsscript SolarAzimuthAngle() startet mit der Berechnung der Sonnenscheindauer für den aktuellen Tag. Diese Zeitspanne kann man sich bildhaft als einen Halbkreis vorstellen, der auf einem Horizont von unten links nach unten rechts verläuft. Diesen Halbkreis entlang wandert die Sonne im laufe des Tages. Ich definiere ganz links als Osten und ganz rechts als Westen. Der obere Kreisschluss ist natürlich Süden und rechts und links Mittig davon liegen entsprechend Südosten und Südwesten. Das geht am einfachsten zu verstehen wenn man es sich einmal aufmalt.
http://cl.ly/image/0J1V0R2C1n27

Das Script setzt zunächst direkt die Position "Osten" und berechnet dann zu welcher Uhrzeit ein Wechsel auf die anderen Positionen stattfindet.

Auf den Halbkreis bezogen: Man erhält also 4 gleich große Abschnitte. Allerdings ist es für den Wechsel der Anzeige natürlich ungünstig nur immer dann zu wechseln, wenn die Sonne direkt auf der jeweiligen Position ist. Sinnvoller erscheint es mir wenn der Wechsel bereits etwas früher passiert und man beispielsweise auch etwas davor und nach der Position "Süd" bereits "Süd" angezeigt bekommt. Deshalb kann man den Wert für die Sonnendauer nicht einfach vierteln. Ich habe mich dafür entschieden für die Verschiebung der Position den Wert in 8 gleichgroße Teile aufzuteilen und nach 1/8 von Ost auf Süd-Ost zu wechseln. Entsprechend dann nach 3/8 auf Süd, nach 5/8 auf Süd-West und schließlich nach 7/8 auf West.

Zum Schluss werden anhand der berechneten Zeiten ganz einfache einmalige at-Jobs angelegt, die dann entsprechend den Wert für den Sonnenstand anpassen.

Falls jemand einen Vorschlag hat wie man die Berechnung verbessern kann, immer her damit ;-)


Gruß
Julian
Hat meine Arbeit dir geholfen? ⟹ https://paypal.me/pools/c/8gDLrIWrG9

Maintainer:
FHEM-Docker Image, https://github.com/fhem, Astro(Co-Maintainer), ENIGMA2, GEOFANCY, GUEST, HP1000, Installer, LaMetric2, MSG, msgConfig, npmjs, PET, PHTV, Pushover, RESIDENTS, ROOMMATE, search, THINKINGCLEANER

Dietmar63

Hallo Loredo,

ich habe mir mal die Mühe gemacht deinen Code umzubauen, dass er jederzeit gestartet werden kann:
Die Idee es mit sunset und sunrise zu machen war gar nicht schlecht!

Ich habe Teststatements drin gelassen, sunrise/sunset habe ich bei meinen ersten Tests als Konstante vorgegeben. Diese Zeilen musst du dann nur noch löschen. Zur Erzeugung der Zeiten nutze ich Perlfunktionen, die das Ergebnis einfacher liefern.  Da der Aubau der Zeitstrings immer gleich ist, habe ich eine Funktion geschrieben, die für jede Berechnung aufgerufen werden kann.


sub
SolarAzimuthAngle()
{
  #my ($sunris_h, $sunris_m, $sunris_s) = split /:/, sunrise_abs ("CIVIL");
  my ($sunris_h, $sunris_m, $sunris_s) = split /:/, "04:30:04";
  #my ($sunset_h, $sunset_m, $sunset_s) = split /:/, sunset_abs("CIVIL");
  my ($sunset_h, $sunset_m, $sunset_s) = split /:/, "20:28:03";
  my $sunshine=(($sunset_h - $sunris_h) * 60 * 60) + (($sunset_m - $sunris_m) * 60) + ($sunset_s - $sunris_s);
  Log 3, "sunshine------------>$sunshine";

  my ($now)  = time();
  my ($sec,$min,$hour)  = localtime($now);

  my $sec_Sunrise_civil = $now - ($hour-$sunris_h)*60*60 - ($min-$sunris_m)*60 - ($sec-$sunris_s);
  Log 3, "sec_Sunrise_civil------------>" . strftime("%d.%m.%Y  %H:%M:%S",localtime($sec_Sunrise_civil));

  my $time_se = get_Time($sec_Sunrise_civil+int($sunshine/8*1));
  Log 3, "time_se------------>$time_se";
  my $time_s  = get_Time($sec_Sunrise_civil+int($sunshine/8*3));
  Log 3, "time_s------------>$time_s";
  my $time_sw = get_Time($sec_Sunrise_civil+int($sunshine/8*5));
  Log 3, "time_sw------------>$time_sw";
  my $time_w  = get_Time($sec_Sunrise_civil+int($sunshine/8*7));
  Log 3, "time_w------------>$time_w";
}

sub
get_Time() {
  my ($tim) = @_;
  my ($sec,$min,$hour)  = localtime($tim);
  my $zeit = strftime("%H:%M:%S",localtime($tim));
  #Log 3, "zeit------------>$zeit";
  return $zeit;
}

ohne Teststatements:

sub
SolarAzimuthAngle()
{
  my ($sunris_h, $sunris_m, $sunris_s) = split /:/, sunrise_abs ("CIVIL");
  my ($sunset_h, $sunset_m, $sunset_s) = split /:/, sunset_abs  ("CIVIL");
  my $sunshine=(($sunset_h - $sunris_h) * 60 * 60) + (($sunset_m - $sunris_m) * 60) + ($sunset_s - $sunris_s);

  my ($now)  = time();
  my ($sec,$min,$hour)  = localtime($now);

  my $sec_Sunrise_civil = $now - ($hour-$sunris_h)*60*60 - ($min-$sunris_m)*60 - ($sec-$sunris_s);

  my $time_o  = get_Time($sec_Sunrise_civil+int($sunshine/8*0));
  my $time_se = get_Time($sec_Sunrise_civil+int($sunshine/8*1));
  my $time_s  = get_Time($sec_Sunrise_civil+int($sunshine/8*3));
  my $time_sw = get_Time($sec_Sunrise_civil+int($sunshine/8*5));
  my $time_w  = get_Time($sec_Sunrise_civil+int($sunshine/8*7));
}

sub
get_Time() {
  my ($tim) = @_;
  my ($sec,$min,$hour)  = localtime($tim);
  my $zeit = strftime("%H:%M:%S",localtime($tim));
  return $zeit;
}
Gruß Dietmar
FB7390, CUL, 2 FHT, FS20
modules: 98_WOL.pm, 98_Heating_Control.pm,   98_WeekdayTimer.pm, 98_RandomTimer.pm, 59_Twilight.pm

crissiloop

Hallo,
nach vielem Lesen und Googlen bin ich auf ein Perl-Script zur Berechnung des Sonnenstandes gestoßen. http://ww3.cad.de/cgi-bin/ubb/postings.cgi?action=printpost&forum=Lisp&number=145&topic=000485.cgi&ReplyNum=000013&TopicSubject=sonnenstandsberechnung

Vielleicht kann man ja damit etwas anfangen.

Gruß
Christian
FHEM 5.5 auf Cubietruck

1x HMLAN, 1x HMUSB, 12x HM-LC-Bl1 PBU-FM, 5x HM-LC-Sw1-Pl, 1x HM-LC-Sw1-FM, 2x HM-LC-Sw2-FM, 2x HM-SEC-RHS, 3x HM-SEC-SD, 8x HM-SEC-SC, 3x HM-RC-4-2, 1x HM-RC-8, 1x HM-Sec-SFA-SM, Jeelink, 7x Technoline TX 29 DTH-IT

Loredo

Hi,

ich habe jetzt nochmal die Zeit gefunden etwas damit herum zu experimentieren und stelle fest, dass es nicht so genau funktioniert wie gedacht. Es ist schwer bzw. unmöglich allein von der Zeit zwischen Sonnenauf- und Untergang auf die dazugehörige Himmelsrichtung zu schließen. Wenn man sich http://www.sunearthtools.com/dp/tools/pos_sun.php?lang=de oder http://cgi.stadtklima-stuttgart.de/mirror/sonne.exe ansieht versteht man auch schneller warum.

Dafür kann ich jetzt beziffern, was ich eigentlich gerne haben wollen würde. Nämlich eine Funktion (am besten in 99_SUNRISE_el.pm eingebaut), die man mit der Gradzahl des Sonnenstandes (Azimuth) füttert und welche dann die dazugehörige Uhrzeit zurück liefert, zu der die Sonne an dieser Stelle stehen wird. Also im Grunde ähnlich wie die bereits vorhandenen Funktionen, nur dass man eben damit die Himmelsrichtung angeben kann und entsprechende Schaltvorgänge abhängig davon wann der Sonnenstand erreicht ist mittels AT definieren kann.

Beispiele:
define WeatherStation.SunPos dummy
define at_SunPos.e at *{sunpos(0,75)} set WeatherStation.SunPos east
define at_SunPos.se at *{sunpos(0,105)} set WeatherStation.SunPos southeast
define at_SunPos.s at *{sunpos(0,150)} set WeatherStation.SunPos south
define at_SunPos.sw at *{sunpos(0,210)} set WeatherStation.SunPos southwest
define at_SunPos.w at *{sunpos(0,255)} set WeatherStation.SunPos west
define at_SunPos.night at *{sunpos(0,285)} set WeatherStation.SunPos night

Damit hätte ich dann genau das, was ich haben möchte. Ich hab aber keine Idee wie ich da ansetzen könnte, nachdem das mit der Uhrzeit für Sonnenauf-/untergang ja nichts ist :-/

Die Stuttgarter Seite oben liefert indirekt das, was ich haben wollen würde schon so halb. Dort gibt es den Wert "Himmelsrichtung bei Sonnenaufgang" und die Uhrzeit für den Sonnenaufgang. Jetzt müsste man nur wissen, wie die das dort berechnen und die Himmelsrichtung dynamisch änderbar haben, so dass sich daraus dann eine veränderte Uhrzeit ergibt.
Hat meine Arbeit dir geholfen? ⟹ https://paypal.me/pools/c/8gDLrIWrG9

Maintainer:
FHEM-Docker Image, https://github.com/fhem, Astro(Co-Maintainer), ENIGMA2, GEOFANCY, GUEST, HP1000, Installer, LaMetric2, MSG, msgConfig, npmjs, PET, PHTV, Pushover, RESIDENTS, ROOMMATE, search, THINKINGCLEANER

Loredo

Ich habe jetzt mal auf Grundlage von http://www.ip-symcon.de/forum/threads/14925-Sonnenstand-berechnen-(Azimut-amp-Elevation) ein entsprechendes Modul zusammengesucht (geschrieben will ich nicht sagen ;-)).

# $Id$
##############################################
#
# Sun position computing
#
# based / modified from 98_average.pm (C) by Rudolf Koenig
# based / modified from 98_dewpoint.pm (C) by Willi Herzig
# with contribution from http://www.ip-symcon.de/forum/threads/14925-Sonnenstand-berechnen-(Azimut-amp-Elevation)
#
# Copyright (C) 2013 Julian Pawlowski, julian.pawlowski AT gmail DOT com
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#
# The GNU General Public License may also be found at http://www.gnu.org/licenses/gpl-2.0.html .
#
package main;
use strict;
use warnings;
use Math::Trig;

##########################
sub
sunpos_Initialize($)
{
  my ($hash) = @_;
  $hash->{DefFn}   = "sunpos_Define";
  $hash->{NotifyFn} = "sunpos_Notify";
  $hash->{NotifyOrderPrefix} = "10-";   # Want to be called before the rest
  $hash->{AttrList} = "disable:0,1";
}


##########################
sub
sunpos_Define($$)
{
  my ($hash, $def) = @_;
  my @a = split("[ \t][ \t]*", $def);

  return "wrong syntax: define <name> sunpos devicename"
      if(@a < 3);

  my $name = $a[0];
  my $devname = $a[2];

  $hash->{STATE} = "active";
  return undef;
}

##########################
sub
sunpos_Notify($$)
{
  my ($hash, $dev) = @_;
  my $hashName = $hash->{NAME};

  return "" if(AttrVal($hashName, "disable", undef));

  my $devName = $dev->{NAME};
  my $devReadings = $dev->{READINGS};

  my $tn = TimeNow();
  my ($dSeconds,$dMinutes,$dHours,$iDay,$iMonth,$iYear,$wday,$yday,$isdst) = localtime(time);
  $iMonth++;
  $iYear += 1900;

  ############################
  # If set in global, use longitude/latitude
  # from global, otherwise set Frankfurt/Germany as
  # default
  my $dLongitude = AttrVal("global", "longitude", "8.686");
  my $dLatitude  = AttrVal("global", "latitude", "50.112");
  Log 5, "Compute sunpos for latitude $dLatitude , longitude $dLongitude";

  my $pi=3.14159265358979323846;
  my $twopi=(2*$pi);
  my $rad=($pi/180);
  my $dEarthMeanRadius=6371.01;    # In km
  my $dAstronomicalUnit=149597890;    # In km

  # Calculate difference in days between the current Julian Day
  # and JD 2451545.0, which is noon 1 January 2000 Universal Time

  # Calculate time of the day in UT decimal hours
  my $dDecimalHours=$dHours + ($dMinutes + $dSeconds / 60.0 ) / 60.0;

  # Calculate current Julian Day
  my $iYfrom2000=$iYear;#expects now as YY ;
  my $iA=(14 - ($iMonth)) / 12;
  my $iM=($iMonth) + 12 * $iA -3;
  my $liAux3=(153 * $iM + 2)/5;
  my $liAux4=365 * ($iYfrom2000 - $iA);
  my $liAux5=( $iYfrom2000 - $iA)/4;
  my $dElapsedJulianDays=($iDay + $liAux3 + $liAux4 + $liAux5 + 59)+ -0.5 + $dDecimalHours/24.0;

  # Calculate ecliptic coordinates (ecliptic longitude and obliquity of the
  # ecliptic in radians but without limiting the angle to be less than 2*Pi
  # (i.e., the result may be greater than 2*Pi)

  my $dOmega=2.1429 - 0.0010394594 * $dElapsedJulianDays;
  my $dMeanLongitude=4.8950630 + 0.017202791698 * $dElapsedJulianDays; # Radians
  my $dMeanAnomaly=6.2400600 + 0.0172019699 * $dElapsedJulianDays;
  my $dEclipticLongitude=$dMeanLongitude + 0.03341607 * sin( $dMeanAnomaly ) + 0.00034894 * sin( 2 * $dMeanAnomaly ) -0.0001134 -0.0000203 * sin($dOmega);
  my $dEclipticObliquity=0.4090928 - 6.2140e-9 * $dElapsedJulianDays +0.0000396 * cos($dOmega);

  # Calculate celestial coordinates ( right ascension and declination ) in radians
  # but without limiting the angle to be less than 2*Pi (i.e., the result may be
  # greater than 2*Pi)

  my $dSin_EclipticLongitude=sin( $dEclipticLongitude );
  my $dY1=cos( $dEclipticObliquity ) * $dSin_EclipticLongitude;
  my $dX1=cos( $dEclipticLongitude );
  my $dRightAscension=atan2( $dY1,$dX1 );
  if ( $dRightAscension < 0.0 ) { $dRightAscension=$dRightAscension + $twopi };
  my $dDeclination=asin( sin( $dEclipticObliquity )* $dSin_EclipticLongitude );

  # Calculate local coordinates ( azimuth and zenith angle ) in degrees
  my $dGreenwichMeanSiderealTime=6.6974243242 + 0.0657098283 * $dElapsedJulianDays + $dDecimalHours;

  my $dLocalMeanSiderealTime=($dGreenwichMeanSiderealTime*15 + $dLongitude)* $rad;
  my $dHourAngle=$dLocalMeanSiderealTime - $dRightAscension;
  my $dLatitudeInRadians=$dLatitude * $rad;
  my $dCos_Latitude=cos( $dLatitudeInRadians );
  my $dSin_Latitude=sin( $dLatitudeInRadians );
  my $dCos_HourAngle=cos( $dHourAngle );
  my $dZenithAngle=(acos( $dCos_Latitude * $dCos_HourAngle * cos($dDeclination) + sin( $dDeclination )* $dSin_Latitude));
  my $dY=-sin( $dHourAngle );
  my $dX=tan( $dDeclination )* $dCos_Latitude - $dSin_Latitude * $dCos_HourAngle;
  my $dAzimuth=atan2( $dY, $dX );
  if ( $dAzimuth < 0.0 ) {$dAzimuth=$dAzimuth + $twopi};
  $dAzimuth=$dAzimuth / $rad;
  # Parallax Correction
  my $dParallax=($dEarthMeanRadius / $dAstronomicalUnit) * sin( $dZenithAngle);
  $dZenithAngle=($dZenithAngle + $dParallax) / $rad;
  my $dElevation=90 - $dZenithAngle;

  # set readings
  $devReadings->{sunpos_azimuth}{VAL} = $dAzimuth;
  $devReadings->{sunpos_azimuth}{TIME} = $tn;
  $devReadings->{sunpos_elevation}{VAL} = $dElevation;
  $devReadings->{sunpos_elevation}{TIME} = $tn;

  return undef;
}

1;


=pod
=begin html

<a name="sunpos"></a>
<h3>sunpos</h3>
<ul>

  Compute current sun position (azimuth + elevation)

  <br>

  <a name="sunposdefine"></a>
  <b>Define</b>
  <ul>
    <code>define &lt;name&gt; sunpos &lt;devicename&gt;</code><br>
    <br>
    <ul>
      This module calculates the current sun azimuth and elevation and adds it as reading value to the given device name.
    </ul>
    <br>

    Example:<PRE>
    define WeatherStation.sunpos sunpos WeatherStation
    </PRE>
  </ul>

  <a name="sunposset"></a>
  <b>Set</b> <ul>N/A</ul><br>

  <a name="sunposget"></a>
  <b>Get</b> <ul>N/A</ul><br>

  <a name="sunposattr"></a>
  <b>Attributes</b>
  <ul>
    <li><a href="#disable">disable</a></li>
  </ul>

  <a name="sunposevents"></a>
  <b>Generated events:</b>
  <ul>
    <li>sunpos_azimuth: $dAzimuth</li>
    <li>sunpos_elevation: $dElevation</li>
  </ul>
</ul>


=end html
=cut


Grundsätzlich scheint es zumindest Werte zu liefern, wenn ich das Modul jetzt an mein Wetterstations-Objekt anbinde:

define WeatherStation.sunpos sunpos WeatherStation

Allerdings scheinen die Werte nicht ganz richtig zu sein, der Azimuth beispielsweise weicht (wie auch jemand in dem Posting dort bemängelt) um ca. 20 Grad ab, was natürlich viel zu viel ist.


sunpos_azimuth 298.143747535321 2013-06-09 18:31:54
sunpos_elevation 5.98709151204278 2013-06-09 18:31:54

(dies sind Werte für München)

Ich habe mich noch nicht genau auf die Fehlersuche gemacht. Aber es scheint zumindest mal ein Anfang zu sein.
Hat meine Arbeit dir geholfen? ⟹ https://paypal.me/pools/c/8gDLrIWrG9

Maintainer:
FHEM-Docker Image, https://github.com/fhem, Astro(Co-Maintainer), ENIGMA2, GEOFANCY, GUEST, HP1000, Installer, LaMetric2, MSG, msgConfig, npmjs, PET, PHTV, Pushover, RESIDENTS, ROOMMATE, search, THINKINGCLEANER

Loredo

Okay, scheint wohl zum einen an der lokalen Zeit und zum anderen an den Sekunden gelegen zu haben.
Der folgende Code generiert jetzt hinreichend gleich die selben Zahlen wie z.B. unter sunearthtools.com zu finden:


# $Id$
##############################################
#
# Sun position computing
#
# based / modified from 98_average.pm (C) by Rudolf Koenig
# based / modified from 98_dewpoint.pm (C) by Willi Herzig
# with contribution from http://www.ip-symcon.de/forum/threads/14925-Sonnenstand-berechnen-(Azimut-amp-Elevation)
#
# Copyright (C) 2013 Julian Pawlowski, julian.pawlowski AT gmail DOT com
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#
# The GNU General Public License may also be found at http://www.gnu.org/licenses/gpl-2.0.html .
#
package main;
use strict;
use warnings;
use Math::Trig;

##########################
sub
sunpos_Initialize($)
{
  my ($hash) = @_;
  $hash->{DefFn}   = "sunpos_Define";
  $hash->{NotifyFn} = "sunpos_Notify";
  $hash->{NotifyOrderPrefix} = "10-";   # Want to be called before the rest
  $hash->{AttrList} = "disable:0,1";
}


##########################
sub
sunpos_Define($$)
{
  my ($hash, $def) = @_;
  my @a = split("[ \t][ \t]*", $def);

  return "wrong syntax: define <name> sunpos devicename"
      if(@a < 3);

  my $name = $a[0];
  my $devname = $a[2];

  $hash->{STATE} = "active";
  return undef;
}

##########################
sub
sunpos_Notify($$)
{
  my ($hash, $dev) = @_;
  my $hashName = $hash->{NAME};

  return "" if(AttrVal($hashName, "disable", undef));

  my $devName = $dev->{NAME};
  my $devReadings = $dev->{READINGS};

  my $tn = TimeNow();
  my ($dSeconds,$dMinutes,$dHours,$iDay,$iMonth,$iYear,$wday,$yday,$isdst) = gmtime(time);
  $iMonth++;
  $iYear += 100;
  $dSeconds = 0;

  ############################
  # If set in global, use longitude/latitude
  # from global, otherwise set Frankfurt/Germany as
  # default
  my $dLongitude = AttrVal("global", "longitude", "8.686");
  my $dLatitude  = AttrVal("global", "latitude", "50.112");
  Log 5, "Compute sunpos for latitude $dLatitude , longitude $dLongitude";

  my $pi=3.14159265358979323846;
  my $twopi=(2*$pi);
  my $rad=($pi/180);
  my $dEarthMeanRadius=6371.01;    # In km
  my $dAstronomicalUnit=149597890;    # In km

  # Calculate difference in days between the current Julian Day
  # and JD 2451545.0, which is noon 1 January 2000 Universal Time

  # Calculate time of the day in UT decimal hours
  my $dDecimalHours=$dHours + ($dMinutes + $dSeconds / 60.0 ) / 60.0;

  # Calculate current Julian Day
  my $iYfrom2000=$iYear;#expects now as YY ;
  my $iA=(14 - ($iMonth)) / 12;
  my $iM=($iMonth) + 12 * $iA -3;
  my $liAux3=(153 * $iM + 2)/5;
  my $liAux4=365 * ($iYfrom2000 - $iA);
  my $liAux5=( $iYfrom2000 - $iA)/4;
  my $dElapsedJulianDays=($iDay + $liAux3 + $liAux4 + $liAux5 + 59)+ -0.5 + $dDecimalHours/24.0;

  # Calculate ecliptic coordinates (ecliptic longitude and obliquity of the
  # ecliptic in radians but without limiting the angle to be less than 2*Pi
  # (i.e., the result may be greater than 2*Pi)

  my $dOmega=2.1429 - 0.0010394594 * $dElapsedJulianDays;
  my $dMeanLongitude=4.8950630 + 0.017202791698 * $dElapsedJulianDays; # Radians
  my $dMeanAnomaly=6.2400600 + 0.0172019699 * $dElapsedJulianDays;
  my $dEclipticLongitude=$dMeanLongitude + 0.03341607 * sin( $dMeanAnomaly ) + 0.00034894 * sin( 2 * $dMeanAnomaly ) -0.0001134 -0.0000203 * sin($dOmega);
  my $dEclipticObliquity=0.4090928 - 6.2140e-9 * $dElapsedJulianDays +0.0000396 * cos($dOmega);

  # Calculate celestial coordinates ( right ascension and declination ) in radians
  # but without limiting the angle to be less than 2*Pi (i.e., the result may be
  # greater than 2*Pi)

  my $dSin_EclipticLongitude=sin( $dEclipticLongitude );
  my $dY1=cos( $dEclipticObliquity ) * $dSin_EclipticLongitude;
  my $dX1=cos( $dEclipticLongitude );
  my $dRightAscension=atan2( $dY1,$dX1 );
  if ( $dRightAscension < 0.0 ) { $dRightAscension=$dRightAscension + $twopi };
  my $dDeclination=asin( sin( $dEclipticObliquity )* $dSin_EclipticLongitude );

  # Calculate local coordinates ( azimuth and zenith angle ) in degrees
  my $dGreenwichMeanSiderealTime=6.6974243242 + 0.0657098283 * $dElapsedJulianDays + $dDecimalHours;

  my $dLocalMeanSiderealTime=($dGreenwichMeanSiderealTime*15 + $dLongitude)* $rad;
  my $dHourAngle=$dLocalMeanSiderealTime - $dRightAscension;
  my $dLatitudeInRadians=$dLatitude * $rad;
  my $dCos_Latitude=cos( $dLatitudeInRadians );
  my $dSin_Latitude=sin( $dLatitudeInRadians );
  my $dCos_HourAngle=cos( $dHourAngle );
  my $dZenithAngle=(acos( $dCos_Latitude * $dCos_HourAngle * cos($dDeclination) + sin( $dDeclination )* $dSin_Latitude));
  my $dY=-sin( $dHourAngle );
  my $dX=tan( $dDeclination )* $dCos_Latitude - $dSin_Latitude * $dCos_HourAngle;
  my $dAzimuth=atan2( $dY, $dX );
  if ( $dAzimuth < 0.0 ) {$dAzimuth=$dAzimuth + $twopi};
  $dAzimuth=$dAzimuth / $rad;
  # Parallax Correction
  my $dParallax=($dEarthMeanRadius / $dAstronomicalUnit) * sin( $dZenithAngle);
  $dZenithAngle=($dZenithAngle + $dParallax) / $rad;
  my $dElevation=90 - $dZenithAngle;

  # set readings
  $devReadings->{sunpos_azimuth}{VAL} = $dAzimuth;
  $devReadings->{sunpos_azimuth}{TIME} = $tn;
  $devReadings->{sunpos_elevation}{VAL} = $dElevation;
  $devReadings->{sunpos_elevation}{TIME} = $tn;

  return undef;
}

1;


=pod
=begin html

<a name="sunpos"></a>
<h3>sunpos</h3>
<ul>

  Compute current sun position (azimuth + elevation)

  <br>

  <a name="sunposdefine"></a>
  <b>Define</b>
  <ul>
    <code>define &lt;name&gt; sunpos &lt;devicename&gt;</code><br>
    <br>
    <ul>
      This module calculates the current sun azimuth and elevation and adds it as reading value to the given device name.
    </ul>
    <br>

    Example:<PRE>
    define WeatherStation.sunpos sunpos WeatherStation
    </PRE>
  </ul>

  <a name="sunposset"></a>
  <b>Set</b> <ul>N/A</ul><br>

  <a name="sunposget"></a>
  <b>Get</b> <ul>N/A</ul><br>

  <a name="sunposattr"></a>
  <b>Attributes</b>
  <ul>
    <li><a href="#disable">disable</a></li>
  </ul>

  <a name="sunposevents"></a>
  <b>Generated events:</b>
  <ul>
    <li>sunpos_azimuth: $dAzimuth</li>
    <li>sunpos_elevation: $dElevation</li>
  </ul>
</ul>


=end html
=cut


Mag das wer mit ins SVN aufnehmen?


Der Vollständigkeit halber liefere ich hier auch noch wie ich nun bei mir den Dummy WeatherStation.SunPos mit einem lesbaren Richtungswert aktualisiere, um daran dann meine Rollladensteuerung zu koppeln:

1. Modul von oben als 98_sunpos.pm im FHEM Ordner speichern und FHEM neu starten bzw rereadcfg ausführen.
2. Den folgenden Code in fhem.cfg einfügen:


define WeatherStation.SunPos dummy
attr WeatherStation.SunPos alias Solar Position
attr WeatherStation.SunPos group Weather
attr WeatherStation.SunPos room Weather

define WeatherStation.SunPos.mod sunpos WeatherStation
attr WeatherStation.SunPos.mod room Weather

define n_WeatherStation notify WeatherStation {\
my $azimuth=ReadingsVal("WeatherStation","sunpos_azimuth",0);;\
\
if ($azimuth < 22.5) {\
fhem "set WeatherStation.SunPos north";;\
} elsif ($azimuth < 45) {\
fhem "set WeatherStation.SunPos north-northeast";;\
} elsif ($azimuth < 67.5) {\
fhem "set WeatherStation.SunPos northeast";;\
} elsif ($azimuth < 90) {\
fhem "set WeatherStation.SunPos east";;\
} elsif ($azimuth < 112.5) {\
fhem "set WeatherStation.SunPos east-southeast";;\
} elsif ($azimuth < 135) {\
fhem "set WeatherStation.SunPos southeast";;\
} elsif ($azimuth < 157.5) {\
fhem "set WeatherStation.SunPos south-southeast";;\
} elsif ($azimuth < 180) {\
fhem "set WeatherStation.SunPos south";;\
} elsif ($azimuth < 202.5) {\
fhem "set WeatherStation.SunPos south-southwest";;\
} elsif ($azimuth < 225) {\
fhem "set WeatherStation.SunPos southwest";;\
} elsif ($azimuth < 247.5) {\
fhem "set WeatherStation.SunPos west-southwest";;\
} elsif ($azimuth < 270) {\
fhem "set WeatherStation.SunPos west";;\
} elsif ($azimuth < 292.5) {\
fhem "set WeatherStation.SunPos west-northwest";;\
} elsif ($azimuth < 315) {\
fhem "set WeatherStation.SunPos northwest";;\
} elsif ($azimuth < 337.5) {\
fhem "set WeatherStation.SunPos north-northwest";;\
} elsif ($azimuth < 361) {\
fhem "set WeatherStation.SunPos north";;\
}\
\
}


Das Objekt "WeatherStation" ist dabei ein HM-WDS100-C6-O.
Hat meine Arbeit dir geholfen? ⟹ https://paypal.me/pools/c/8gDLrIWrG9

Maintainer:
FHEM-Docker Image, https://github.com/fhem, Astro(Co-Maintainer), ENIGMA2, GEOFANCY, GUEST, HP1000, Installer, LaMetric2, MSG, msgConfig, npmjs, PET, PHTV, Pushover, RESIDENTS, ROOMMATE, search, THINKINGCLEANER