FHEM Forum

FHEM => Anfängerfragen => Thema gestartet von: Loredo am 18 Mai 2013, 14:41:38

Titel: Sonnenstand berechnen
Beitrag von: Loredo am 18 Mai 2013, 14:41:38
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
Titel: Aw: Sonnenstand berechnen
Beitrag von: Dietmar63 am 18 Mai 2013, 16:27:00
Nimm die Uhrzeit : 12:00 ist Süd...
Titel: Aw: Sonnenstand berechnen
Beitrag von: Loredo am 18 Mai 2013, 16:28:18
Das ist mir zu ungenau und stimmt so auch nicht (z.B. wegen der Sommerzeit)
Titel: Aw: Sonnenstand berechnen
Beitrag von: Dietmar63 am 18 Mai 2013, 16:38:42
Die Sommerzeit lässt sich leicht einrechnen: letzter Parameter von localtime!

Genauer geht es meiner Meinung nach nicht. Und etwas fertiges kenne ich nicht.
Titel: Aw: Sonnenstand berechnen
Beitrag von: Loredo am 18 Mai 2013, 17:12:59
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.
Titel: Aw: Sonnenstand berechnen
Beitrag von: MisterEltako am 18 Mai 2013, 18:08:31
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
Titel: Aw: Sonnenstand berechnen
Beitrag von: Puschel74 am 18 Mai 2013, 18:11:37
Hallo,

Leerzeilen im Code sind auch eher kontraproduktiv.

Grüße
Titel: Aw: Sonnenstand berechnen
Beitrag von: Loredo am 18 Mai 2013, 18:46:08
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
Titel: Aw: Sonnenstand berechnen
Beitrag von: crissiloop am 20 Mai 2013, 17:13:50
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
Titel: Aw: Sonnenstand berechnen
Beitrag von: Loredo am 20 Mai 2013, 18:06:38
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 (//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
Titel: Aw: Sonnenstand berechnen
Beitrag von: Dietmar63 am 20 Mai 2013, 20:31:11
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;
}
Titel: Aw: Sonnenstand berechnen
Beitrag von: crissiloop am 22 Mai 2013, 18:19:39
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 (//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
Titel: Aw: Sonnenstand berechnen
Beitrag von: Loredo am 09 Juni 2013, 13:59:08
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 (//www.sunearthtools.com/dp/tools/pos_sun.php?lang=de) oder http://cgi.stadtklima-stuttgart.de/mirror/sonne.exe (//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.
Titel: Aw: Sonnenstand berechnen
Beitrag von: Loredo am 09 Juni 2013, 18:33:43
Ich habe jetzt mal auf Grundlage von http://www.ip-symcon.de/forum/threads/14925-Sonnenstand-berechnen- (//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.
Titel: Aw: Sonnenstand berechnen
Beitrag von: Loredo am 09 Juni 2013, 19:00:40
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.
Titel: Aw: Sonnenstand berechnen
Beitrag von: Puschel74 am 09 Juni 2013, 19:43:05
Hallo,

zu
Zitat1. Modul von oben als 98_sunpos.pm im FHEM Ordner speichern und FHEM neu starten bzw rereadcfg ausführen.
müsste eigentlich auch ein
reload 98_sunpos.pm
reichen.

FHEM neu starten macht zwar das selbe aber das finde ich "etwas" übertrieben um ein Modul zu laden.

Aber ich möchte hier in keinster Weise deine Arbeit für FHEM kritisieren - also bitte nicht falsch verstehen ;-)

Aber eine Bitte hätte ich noch - könntest du das nochmal als 98_sunpos.pm hochladen - also die Datei und nicht den Code.
Danke

Grüße

P.S.: Ich werds mir geich mal runterladen und einbinden.
Titel: Aw: Sonnenstand berechnen
Beitrag von: Loredo am 09 Juni 2013, 19:46:11
Zitat von: Puschel74 schrieb am So, 09 Juni 2013 19:43
Zitat1. Modul von oben als 98_sunpos.pm im FHEM Ordner speichern und FHEM neu starten bzw rereadcfg ausführen.
müsste eigentlich auch ein
reload 98_sunpos.pm
reichen.

Ja. Ich schrieb ja auch rereadcfg geht genauso. So weit auseinander liegen die Befehle auch nicht. Letztendlich ist es nur ein Hinweis, dass man etwas in der Richtung tun muss. Bleibt jedem überlassen, wie er es ausführt :-)

Zitat von: Puschel74 schrieb am So, 09 Juni 2013 19:43Aber eine Bitte hätte ich noch - könntest du das nochmal als 98_sunpos.pm hochladen - also die Datei und nicht den Code.

Sorry, macht natürlich Sinn. Anbei!


Gruß
Julian
Titel: Aw: Sonnenstand berechnen
Beitrag von: Puschel74 am 09 Juni 2013, 19:53:47
Hallo,

danke erstmal für das PM-File ;-)

Aber bei rereadcfg denke ich an das neu einlesen der Konfig - und wenn das Modul noch nicht definiert ist bzw. das define in FHEM noch nicht programmiert ist wird auch das Modul nicht geladen (soweit mein Wissenstand).

Daher wird es da mit Sicherheit zu Nachfragen von Anfängern (wie mir) kommen.

Ein reload lädt das Modul - egal ob in FHEM schon was definiert ist um das Modul anzusprechen (glaube ich).
Aber ich kann damit auch völlig daneben liegen.

Grüße
Titel: Aw: Sonnenstand berechnen
Beitrag von: Loredo am 09 Juni 2013, 19:55:01
Mit dem reload ist man sicher auf der sicheren Seite.
IMHO impliziert ein rereadcfg aber auch ein reload aller Module.
Titel: Aw: Sonnenstand berechnen
Beitrag von: Puschel74 am 09 Juni 2013, 19:58:29
Hallo,

Zitat von: Loredo schrieb am So, 09 Juni 2013 19:55Mit dem reload ist man sicher auf der sicheren Seite.
IMHO impliziert ein rereadcfg aber auch ein reload aller Module.

Nur damit ich das auch endlich mal verstehe - danke für deine Geduld.

ALLER Module oder nur bestimmter Module?
99_xxx.pm wird, soweit ich weiß automatisch geladen.
Nur mit 98_xxx.pm kenn ich mich nicht so aus da ich meine immer unter 99_xxx.pm abspeichere und dann ein reload durchführe.

Grüße
Titel: Aw: Sonnenstand berechnen
Beitrag von: Loredo am 09 Juni 2013, 20:00:49
Zitat von: Puschel74 schrieb am So, 09 Juni 2013 19:58Nur damit ich das auch endlich mal verstehe - danke für deine Geduld.

ALLER Module oder nur bestimmter Module?
99_xxx.pm wird, soweit ich weiß automatisch geladen.
Nur mit 98_xxx.pm kenn ich mich nicht so aus da ich meine immer unter 99_xxx.pm abspeichere und dann ein reload durchführe.

Keine Ahnung. Ausprobieren würd ich sagen.
Titel: Aw: Sonnenstand berechnen
Beitrag von: Puschel74 am 09 Juni 2013, 20:01:49
Hallo,

ok. Mache ich.

Danke dir nochmal für deinen Einsatz und deine Geduld mit mir.

Grüße
Titel: Aw: Sonnenstand berechnen
Beitrag von: Dietmar63 am 09 Juni 2013, 23:58:34
readcfg liest alle Definitionen der fhem.cfg ein und lädt kein Modul neu ein.
Ein reload ersetzt den Code des Moduls im Laufzeitsystem, ist äußerst praktisch bei der Weiterentwicklung von Modulen.

Ich habe mir ein dummy gebastelt, das mit den passenden notifys die wichtigsten reloads bei mir per Knopfdruck ermöglicht:

define Befehl                 dummy
attr   Befehl                 webCmd rest:HC:99:RT:WOL:RR:PT:P1h



define BefehlUT               notify Befehl:99          {fhem ("reload 99_Utils_Ort")}
define BefehlRT               notify Befehl:RT          {fhem ("reload 98_RandomTimer")}
define BefehlHC               notify Befehl:HC          {fhem ("reload 98_Heating_Control")}

probiert es mal aus ist wirklich praktisch.

@Loredo:
wie/wann wird die sunpos_Notify Funktion aufgerufen?

In vielen Modulen wird dazu ein InternalTimer gesetzt. Mit dem folgenden Code wird sunpos_Notify alle 15 Minuten ausgeführt.
Am Besten in sunpos_Define einmal sunpos_Notify direkt aufrufen und am Ende von sunPos_notify den folgendne Code anhängen:

  my $nextTime = time() + 15*60;  
  RemoveInternalTimer($hash);
  InternalTimer($nextTime, "sunpos_Notify", $hash, 0);


Eigentlich könnte man das Modul gleich so erweitern, dass vom Modul selbst Ereignise wie
northeast, north-northeast, north ... gefeuert werden, wenn bestimmte azimuth-Werte erreicht werden:

 
  readingsBeginUpdate($hash);
  readingsBulkUpdate ($hash,  "sunpos", "north");
  readingsEndUpdate  ($hash,  defined($hash->{LOCAL} ? 0 : 1));


zu dieser Definition von sunpos:
define WeatherStation.sunpos sunpos WeatherStation
kann man dann die Ereignisse mit einem notify weiterverarbeiten:

define sunposAuswert notify WeatherStation.sunpos:.* { doAnything() }
Titel: Aw: Sonnenstand berechnen
Beitrag von: stromer-12 am 10 Juni 2013, 00:36:10
Ich hatte auch nach einer Funktion gesucht, und habe da auch was gefunden und angepasst war in javascript.
Ist sogar etwas kürzer.
Titel: Aw: Sonnenstand berechnen
Beitrag von: Loredo am 10 Juni 2013, 00:50:08
Hi Dietmar,

Zitat von: Dietmar63 schrieb am So, 09 Juni 2013 23:58wie/wann wird die sunpos_Notify Funktion aufgerufen?

In vielen Modulen wird dazu ein InternalTimer gesetzt. Mit dem folgenden Code wird sunpos_Notify alle 15 Minuten ausgeführt.
Am Besten in sunpos_Define einmal sunpos_Notify direkt aufrufen und am Ende von sunPos_notify den folgendne Code anhängen:

  my $nextTime = time() + 15*60;  
  RemoveInternalTimer($hash);
  InternalTimer($nextTime, "sunpos_Notify", $hash, 0);


Ja, beim Aufruf gibt es wirklich noch Probleme.
Momentan ist es wohl Zufall, dass sunpos_Notify aufgerufen wird. Ein Symptom scheint zu sein, dass die beiden Readings nicht nur bei dem gewollten Device (WeatherStation in meinem Fall, also das, was ich als Parameter bei der Definition mit angegeben habe), sondern auch bei anderen Devices. Vermutlich wird momentan die Funktion bei jeder Statusänderung ausgeführt und der Reading-Wert dann dem jeweiligen Device ebenfalls zugewiesen. Ich habe die anderen Module, die ich als Vorlage genommen habe, diesbezüglich leider nicht richtig verstehen können :-(

Wie löse ich das? Deine Zeilen hinzuzufügen dürfte dabei ja allein nicht ausreichend sein.

Zitat von: Dietmar63 schrieb am So, 09 Juni 2013 23:58Eigentlich könnte man das Modul gleich so erweitern, dass vom Modul selbst Ereignise wie
northeast, north-northeast, north ... gefeuert werden, wenn bestimmte azimuth-Werte erreicht werden:

 
  readingsBeginUpdate($hash);
  readingsBulkUpdate ($hash,  "sunpos", "north");
  readingsEndUpdate  ($hash,  defined($hash->{LOCAL} ? 0 : 1));


zu dieser Definition von sunpos:
define WeatherStation.sunpos sunpos WeatherStation
kann man dann die Ereignisse mit einem notify weiterverarbeiten:

define sunposAuswert notify WeatherStation.sunpos:.* { doAnything() }

die readings*Update Funktionen verstehe ich auch nicht.
Grundsätzlich ist es sicherlich eine gute Idee die Readings entweder nur dem mit dem sunpos Modul definierten Device zuzuordnen oder aber eben den Readings Wert (wie bei dem average oder dewpoint Modul) einem bestimmten Device mit zuzuordnen (so habe ich es bisher eigentlich angedacht gehabt, deshalb auch der Parameter "WeatherStation", um die neuen Readings dort zusätzlich zuzuweisen).

Ich kriege das leider nicht richtig sortiert wie so ein Modul auszusehen hat :-(
Gibt es da denn keine Doku oder ein Dummy-Modul zu? Ich finde den vorhandenen Code schwer zu lesen.


Gruß
Julian
Titel: Aw: Sonnenstand berechnen
Beitrag von: Loredo am 10 Juni 2013, 00:52:59
Zitat von: str0mer schrieb am Mo, 10 Juni 2013 00:36Ich hatte auch nach einer Funktion gesucht, und habe da auch was gefunden und angepasst war in javascript.
Ist sogar etwas kürzer.

Schön, hast es aber nicht geteilt oder als Modul verfasst :-)
Titel: Aw: Sonnenstand berechnen
Beitrag von: stromer-12 am 10 Juni 2013, 01:01:03
Ich habe es in deinen Modul eingebaut anstelle deiner Funktion.
Titel: Aw: Sonnenstand berechnen
Beitrag von: Loredo am 10 Juni 2013, 01:03:50
Zitat von: str0mer schrieb am Mo, 10 Juni 2013 01:01Ich habe es in deinen Modul eingebaut anstelle deiner Funktion.

Danke, jetzt vermischt du mein Modul mit deinem, da es den selben Namen hat. Das dürfte sicherlich einige verwirren.
Ich schaue es mir auch mal an, letztendlich sollte es aber nur ein Modul geben, was dann alles macht. Das erhöht auch die Chance, dass es ins SVN kommt und alle es einfach benutzen können ;-)
Titel: Aw: Sonnenstand berechnen
Beitrag von: stromer-12 am 10 Juni 2013, 01:07:31
Ich kann es wieder löschen.

Löschen geht nicht mehr.
Titel: Aw: Sonnenstand berechnen
Beitrag von: Dietmar63 am 10 Juni 2013, 11:28:04
ZitatJa, beim Aufruf gibt es wirklich noch Probleme.
Momentan ist es wohl Zufall, dass sunpos_Notify aufgerufen wird. Ein Symptom scheint zu sein, dass die beiden Readings nicht nur bei dem gewollten Device (WeatherStation in meinem Fall, also das, was ich als Parameter bei der Definition mit angegeben habe), sondern auch bei anderen Devices. Vermutlich wird momentan die Funktion bei jeder Statusänderung ausgeführt und der Reading-Wert dann dem jeweiligen Device ebenfalls zugewiesen. Ich habe die anderen Module, die ich als Vorlage genommen habe, diesbezüglich leider nicht richtig verstehen können :-(

Ich denke, dass es als erstes wichtig ist, dass du dir überlegst, wie dein Modul genutzt werden soll. Ich sehe da eigentlich nur eine Möglichkeit:
Dein Modul errechnet alle n Minuten den Azimuth und die Höhe der Sonne über dem Horizont für die gegebenen Koordinaten auf der Weltkugel.
Du führst drei Readings im Modul selbst ein

azimuth       (91°)
altitude      (46°)
compassPoint  north-east ...


Diese Readings werden dann ggf. alle n Minunten verändert. Ich denke alle 5 Minuten ist ein guter Wert: 24*60/360.  
Der Update der Readings führt dazu, dass alle notifys, die sich auf die Readings von sunpos beziehen, sofort feuern.  

Wenn du nichts dagegen hast sehe ich mir das Modul an und ändere es ensprechend.

Zitatdie readings*Update Funktionen verstehe ich auch nicht.
Grundsätzlich ist es sicherlich eine gute Idee die Readings entweder nur dem mit dem sunpos Modul definierten Device zuzuordnen oder aber eben den Readings Wert (wie bei dem average oder dewpoint Modul) einem bestimmten Device mit zuzuordnen (so habe ich es bisher eigentlich angedacht gehabt, deshalb auch der Parameter "WeatherStation", um die neuen Readings dort zusätzlich zuzuweisen).

Es ist mir nicht bekannt, dass eine solche Dokumentation gibt. Ich habe seit Anfang des Jahres auf der Basis von Twiglight Heating_Control entwickelt. Tobias hat mir geholfen. Inzwischen habe ich einen ganz guten Überblick. Das Problem ist manchmal, dass sich am Standard für die Modulentwicklung etwas ändert, und aufgrund der mangendend Doku nicht so klar ist.

Die Readings würde ich auch einführen.
Die Grundstruktur deines Moduls bleibt weitestgehend unangetastet - sieht schon ganz gut aus.
Titel: Aw: Sonnenstand berechnen
Beitrag von: UliM am 10 Juni 2013, 16:33:15
Hi,
mal als Frage: die Werte, die das Modul twilight liefert, reichen Dir nicht?

Siehe http://www.fhemwiki.de/wiki/Twilight_Anwendungsbeispiel (//www.fhemwiki.de/wiki/Twilight_Anwendungsbeispiel) ganz am Ende der Seite sind die Werte erklärt, die als STATE geliefert werden.
Alternativ könntest Du den Wert von "light" verwenden.

Gruß, Uli
Titel: Aw: Sonnenstand berechnen
Beitrag von: Tobias am 11 Juni 2013, 08:12:01
ich habe mir mal den Code kurz angesehen.
Klar, das der Code bei JEDEM Notify anspringt. Du musst nach  return "" if(AttrVal($hashName, "disable", undef));
noch folgendes einbauen:return "" if($dev->{NAME} !~ m/$hash->{DEVICE}/) ;
Soll heißen: führe den folgenden Code nicht aus, wenn das Notifyauslösende Device nicht deinem definiertem Device entspricht. In deinem Fall "Weatherstation", also HM-WDS100-C6-O.
Wichtig ist auch, das du im "Define" das DEVICE noch sicherst ;)
also so etwa:$hash->{DEVICE} = $devname;

Den internen Timer würde ich auch einbauen, der soll aber nur dann etwas tun wenn ein notify ausbleibt. Wird das notify vor Auslösen den Timers ausgelöst, so muss der interne Timer gelöscht, und neu angelegt werden.
Titel: Aw: Sonnenstand berechnen
Beitrag von: Loredo am 11 Juni 2013, 18:31:10
So!

Mit Dietmar63's Hilfe haben wir jetzt wohl ein fertiges Modul.
Es stellt ein komplett eigenständiges virtuelles Devices zur Verfügung, welches den Sonnenstand alle 5min berechnet und als Kompasswert bereitstellt. Zusätzlich kann man die zu Grunde liegenden Readings Azimut und Elevation einsehen.

Denke das sollte ins SVN.

INSTALLATION
Nachdem man das Modul ins FHEM Verzeichnis kopiert hat muss man lediglich
define Sonnenposition sunpos

definieren und schon gehts los. Man kann dann wie gewohnt Notifies auf dieses Device erstellen.
Voraussetzung für den korrekten Standort ist das Setzen der globalen Variablen latitude und longitude wie z.B. auch für das Wettermodul notwendig.


Gruß
Julian
Titel: Aw: Sonnenstand berechnen
Beitrag von: Dietmar63 am 11 Juni 2013, 23:01:33
Herzlichen Glückwunsch!
Wir können noch mehr davon gebrauchen
Titel: Aw: Sonnenstand berechnen
Beitrag von: Petrosilius Zwackelmann am 18 Juni 2013, 15:46:31
Super!
Danke für eure Bemühungen.

Ich habe das Modul heute in meine Beschattungssteuerung integriert und es scheint alles zu laufen.
Zunächst war ich unsicher ob das Modul auf der FritzBox läuft (Math) ... ist aber wohl kein Thema.

Die Logeinträge sind etwas ungewohnt mit den Pfeilen...
Ich nehme an das sind noch die Logeinträge welche zum testen verwendet wurden, für die SVN Version sollte das etwas ausgedünnt werden.
Was bedeutet der Wert idxf ?

2013.06.18 15:10:11 3: azimuth------------>230.44
2013.06.18 15:10:11 3: idxf----------->10.2417777777778
2013.06.18 15:10:11 3: idx------------>10
2013.06.18 15:10:11 3: Azimuth-------------->230.44
2013.06.18 15:10:11 3: Elevation------------>56.01
2013.06.18 15:10:11 3: compassPoint---------->southwest
2013.06.18 15:10:11 3: compassPointH--------->southwest

Gruß Manuel
Titel: Aw: Sonnenstand berechnen
Beitrag von: Dietmar63 am 18 Juni 2013, 15:54:45
Die log Einträge können komplett heraus genommen werden.

Idx : index
Idxf: index Fliesskomma

Test halt!
Titel: Aw: Sonnenstand berechnen
Beitrag von: Puschel74 am 18 Juni 2013, 16:07:20
Hallo,

vielen Dank für das (ein weiteres) geniale Modul.

Soeben eingebunden und läuft perfekt bis auf ...

Das hab ich im LogFile:

ZitatScalar value @compassPoints[$idx] better written as $compassPoints[$idx] at ./FHEM/98_sunpos.pm line 220.
2013.06.18 16:04:59 3: azimuth------------>244.88
2013.06.18 16:04:59 3: idxf----------->10.8835555555556
2013.06.18 16:04:59 3: idx------------>10
2013.06.18 16:04:59 3: Azimuth-------------->244.88
2013.06.18 16:04:59 3: Elevation------------>51.24
2013.06.18 16:04:59 3: compassPoint---------->southwest
2013.06.18 16:04:59 3: compassPointH--------->southwest

Hardware siehe Signatur (RasPi1).
Update von FHEM ist von gestern abend.

Grüße

Edith: Gesamten Logeintrag gepostet
Edith2: Hardware genauer angegeben
Titel: Aw: Sonnenstand berechnen
Beitrag von: Dietmar63 am 18 Juni 2013, 16:15:06
Die log-Einträge wirst du alle 5 Minuten bekommen.
Bitte selbst die Zeilen im Code löschen oder warten bis Loredo eine neue Version bereitstellt.
Titel: Aw: Sonnenstand berechnen
Beitrag von: Puschel74 am 18 Juni 2013, 16:33:46
Hallo,

ZitatDie log-Einträge wirst du alle 5 Minuten bekommen.

Das ist mir schon klar wenn das Modul alle 5 Minuten den Sonnenstand neu berechnet.
Die Logeinträge kann ich schon selbst raus nehmen ;-)
Das ist nicht das Problem.

Mir geht es um die erste Zeile:

ZitatScalar value @compassPoints[$idx] better written as $compassPoints[$idx] at ./FHEM/98_sunpos.pm line 220.

Mich stört die auch nicht - ich wollte nur Bescheid geben das neben den Logeinträgen erstmalig auch diese Meldung erscheint.

Das Modul läuft wunderbar.
Danke nochmal dafür.

Grüße
Titel: Aw: Sonnenstand berechnen
Beitrag von: Petrosilius Zwackelmann am 19 Juni 2013, 14:26:18
Ich habe ein paar Icons dazugebastelt siehe hier...

Link (http://forum.fhem.de/index.php?topic=13393.msg83002#msg83002)

Gruß Manuel
Titel: Aw: Sonnenstand berechnen
Beitrag von: Tobias am 19 Juni 2013, 20:09:35
Kommt das Modul noch in den Maintree sodass es per update ausgeliefert werden kann? incl commandref-doku?
Titel: Aw: Sonnenstand berechnen
Beitrag von: Dietmar63 am 19 Juni 2013, 20:42:17
Ja!

Aber Loredo und ich haben abgemacht, dass wir die Funktionalität in Twilight einbauen wollen.
Damit wollen wir vermeiden, dass zu viele Module entstehen.
Titel: Aw: Sonnenstand berechnen
Beitrag von: oniT am 05 Juli 2013, 19:54:54
Julian und Dietmar,

ich finde das Modul mit der Sonnenposition sehr gut. Wäre es möglich, dass das Abfrageintervall verändert werden kann? Also so zum Beispiel wie beim Wetter Modul.

Danke
Gruß,
TinoB
Titel: Aw: Sonnenstand berechnen
Beitrag von: Dietmar63 am 05 Juli 2013, 20:14:40
Möglich ist das schon.
Was versprichst du dir davon?
Titel: Aw: Sonnenstand berechnen
Beitrag von: oniT am 05 Juli 2013, 21:02:25
Hallo Dietmar,

wenn ich das Modul aktivert habe, bekomme ich recht viele Disconnects von HMLan. Das liegt zum einen daran, dass ich schon viele Abfragen an verschiedene Geräte habe (ja auch da gibt es noch Optimierungpotenzial). Aber auch daran, dass ich das Modul für die Beschattungssteuerung mit einsetzen möchte. Und da reicht meiner Meinung nach ein Abfrageintervall von 15 - 30 Minuten würde ich so schätzen.

Danke
Gruß,
TinoB
Titel: Aw: Sonnenstand berechnen
Beitrag von: Dietmar63 am 06 Juli 2013, 00:25:01
Nutzt du Twilight oder sunpos?

Ich glaube allerdings, dass dein Problem mit den disconnects so nicht wirklich gelöst werden kann.

Beschreib mal warum du glaubst, dass diese Änderung das Problem lösen sollte.



Titel: Aw: Sonnenstand berechnen
Beitrag von: Dietmar63 am 17 Juli 2013, 22:19:40
Hast du das Problem mit den diconnects gelöst?
Soll ich dich noch unterstützen?
Titel: Aw: Sonnenstand berechnen
Beitrag von: oniT am 18 Juli 2013, 22:01:47
Hallo Dietmar,

sorry, bin bisher noch nicht zum Antworten gekommen. Ja das Problem besteht immer noch. Eventuell ist ja auch die FritzBox überlastet ;-) ich melde mich bei Gelegenheit hierzu nochmals und hole diesen Thread dann wieder nach oben.

Viele Grüße,
TinoB
Titel: Aw: Sonnenstand berechnen
Beitrag von: tobias.gj am 19 Juli 2013, 10:28:29
Hi zusammen,
vielen Dank, tolles Modul!
Gruß Tobias
Titel: Aw: Sonnenstand berechnen
Beitrag von: Loredo am 22 Juli 2013, 11:25:35
Ich bin jetzt am Wochenende endlich mal selbst dazu gekommen, meine Beschattungssteuerung in Version 1 umzusetzen (V2 wird dann noch die Markise berücksichtigen, für die mir aktuell jedoch noch die Regen und Wind Steuerung fehlt).
Aber schön, dass andere vor mir schon so fleißig nach der Sonne ausrichten :D
Titel: Aw: Sonnenstand berechnen
Beitrag von: Marcus am 30 Juli 2013, 23:38:09
Ich glaube eine "+1" oder "Danke"-Funktion gibt es hier im Forum nicht, daher auf diesem Wege: vielen Dank für das Modul.

Habe es gerade eingebaut und werde die Werte mal ein wenig testen und mit der Realität abgleichen und dann später auch für meine Rolladen-Steuerung verwenden.
Titel: Antw:Sonnenstand berechnen
Beitrag von: oniT am 17 Dezember 2013, 21:10:29
Hallo Dietmar,

so, ich wollte mich hierzu ja nochmals eine Rückmeldung geben. Ich habe inzwischen meine anderen Abfragen soweit mir es möglich ist optimiert und bekomme nun keine Disconnects vom HMLan mehr.

Viele Grüße,
Tino