99_SUNRISE_EL.pm 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  1. ##############################################
  2. # $Id: 99_SUNRISE_EL.pm 16632 2018-04-17 19:00:21Z rudolfkoenig $
  3. # This code is derived from DateTime::Event::Sunrise, version 0.0501.
  4. # Simplified and removed further package # dependency (DateTime,
  5. # Params::Validate, etc). For comments see the original code.
  6. #
  7. package main;
  8. use strict;
  9. use warnings;
  10. use Math::Trig;
  11. sub sr($$$$$$);
  12. sub sunrise_rel(@);
  13. sub sunset_rel(@);
  14. sub sunrise_abs(@);
  15. sub sunset_abs(@);
  16. sub isday(@);
  17. sub sunrise_coord($$$);
  18. sub SUNRISE_Initialize($);
  19. # See perldoc DateTime::Event::Sunrise for details
  20. my $long;
  21. my $lat;
  22. my $tz = ""; # will be overwritten
  23. my $defaultaltit = "-6"; # Civil twilight
  24. my $RADEG = ( 180 / 3.1415926 );
  25. my $DEGRAD = ( 3.1415926 / 180 );
  26. my $INV360 = ( 1.0 / 360.0 );
  27. my %alti = (REAL => 0, CIVIL => -6, NAUTIC => -12, ASTRONOMIC => -16); # or HORIZON <number>
  28. sub
  29. SUNRISE_EL_Initialize($)
  30. {
  31. my ($hash) = @_;
  32. }
  33. ##########################
  34. # Compute the _next_ event
  35. # rise: 1: event is sunrise (else sunset)
  36. # isrel: 1: relative times
  37. # seconds: second offset to event
  38. # daycheck: if set, then return 1 if the sun is visible, 0 else
  39. sub
  40. sr($$$$$$)
  41. {
  42. my ($rise, $seconds, $isrel, $daycheck, $min, $max) = @_;
  43. sr_alt(time(), $rise, $isrel, $daycheck, 1, $defaultaltit,$seconds,$min,$max);
  44. }
  45. sub
  46. sr_alt($$$$$$$$$)
  47. {
  48. my $nt=shift;
  49. my $rise=shift;
  50. my $isrel=shift;
  51. my $daycheck=shift;
  52. my $nextDay=shift;
  53. my $altit = defined($_[0]) ? $_[0] : "";
  54. if(exists $alti{uc($altit)}) {
  55. $altit=$alti{uc($altit)};
  56. shift;
  57. } elsif($altit =~ /HORIZON=([\-\+]*[0-9\.]+)/i) {
  58. $altit=$1;
  59. shift;
  60. } else {
  61. $altit=-6; #default
  62. }
  63. my($seconds, $min, $max)=@_;
  64. my $needrise = ($rise || $daycheck) ? 1 : 0;
  65. my $needset = (!$rise || $daycheck) ? 1 : 0;
  66. $seconds = 0 if(!$seconds);
  67. ############################
  68. # If set in global, use longitude/latitude
  69. # from global, otherwise set Frankfurt/Germany as
  70. # default
  71. $long = AttrVal("global", "longitude", "8.686");
  72. $lat = AttrVal("global", "latitude", "50.112");
  73. Log3 undef, 5, "Compute sunrise/sunset for latitude $lat , longitude $long";
  74. #my $nt = time;
  75. my @lt = localtime($nt);
  76. my $gmtoff = _calctz($nt,@lt); # in hour
  77. my ($rt,$st) = _sr_alt($altit,$needrise,$needset,
  78. $lt[5]+1900,$lt[4]+1,$lt[3], $gmtoff);
  79. my $sst = ($rise ? $rt : $st) + ($seconds/3600);
  80. my $nh = $lt[2] + $lt[1]/60 + $lt[0]/3600; # Current hour since midnight
  81. if($daycheck) {
  82. if(defined($min) && defined($max)) { #Forum #43742
  83. $min = hms2h($min); $max = hms2h($max);
  84. if($min < $max) {
  85. $rt = $min if($rt < $min);
  86. $st = $max if($st > $max);
  87. } else {
  88. $rt = $max if($rt > $max);
  89. $st = $min if($st < $min);
  90. }
  91. }
  92. return 1 if($rt <= $nh && $nh <= $st);
  93. return 0;
  94. }
  95. $sst = hms2h($min) if(defined($min) && (hms2h($min) > $sst));
  96. $sst = hms2h($max) if(defined($max) && (hms2h($max) < $sst));
  97. my $diff = 0;
  98. if (($data{AT_RECOMPUTE} || # compute it for tommorow
  99. int(($nh-$sst)*3600) >= 0) && $nextDay) { # if called a subsec earlier
  100. $nt += 86400;
  101. @lt = localtime($nt);
  102. my $ngmtoff = _calctz($nt,@lt); # in hour
  103. $diff = 24;
  104. ($rt,$st) = _sr_alt($altit,$needrise,$needset,
  105. $lt[5]+1900,$lt[4]+1,$lt[3], $ngmtoff);
  106. $sst = ($rise ? $rt : $st) + ($seconds/3600);
  107. $sst = hms2h($min) if(defined($min) && (hms2h($min) > $sst));
  108. $sst = hms2h($max) if(defined($max) && (hms2h($max) < $sst));
  109. }
  110. $sst += $diff if($isrel);
  111. $sst -= $nh if($isrel == 1);
  112. return h2hms_fmt($sst);
  113. }
  114. sub
  115. _sr_alt($$$$$$$)
  116. {
  117. my ($altit,$needrise, $needset, $y, $m, $dy, $offset) = @_;
  118. my $d = _days_since_2000_Jan_0($y,$m,$dy) + 0.5 - $long / 360.0;
  119. my ( $tmp_rise_1, $tmp_set_1 ) =
  120. _sunrise_sunset( $d, $long, $lat, $altit, 15.04107 );
  121. my ($tmp_rise_2, $tmp_rise_3) = (0,0);
  122. if($needrise) {
  123. $tmp_rise_2 = 9; $tmp_rise_3 = 0;
  124. until ( _equal( $tmp_rise_2, $tmp_rise_3, 8 ) ) {
  125. my $d_sunrise_1 = $d + $tmp_rise_1 / 24.0;
  126. ( $tmp_rise_2, undef ) =
  127. _sunrise_sunset( $d_sunrise_1, $long, $lat, $altit, 15.04107 );
  128. $tmp_rise_1 = $tmp_rise_3;
  129. my $d_sunrise_2 = $d + $tmp_rise_2 / 24.0;
  130. ( $tmp_rise_3, undef ) =
  131. _sunrise_sunset( $d_sunrise_2, $long, $lat, $altit, 15.04107 );
  132. }
  133. }
  134. my ($tmp_set_2, $tmp_set_3) = (0,0);
  135. if($needset) {
  136. $tmp_set_2 = 9; $tmp_set_3 = 0;
  137. until ( _equal( $tmp_set_2, $tmp_set_3, 8 ) ) {
  138. my $d_sunset_1 = $d + $tmp_set_1 / 24.0;
  139. ( undef, $tmp_set_2 ) =
  140. _sunrise_sunset( $d_sunset_1, $long, $lat, $altit, 15.04107 );
  141. $tmp_set_1 = $tmp_set_3;
  142. my $d_sunset_2 = $d + $tmp_set_2 / 24.0;
  143. ( undef, $tmp_set_3 ) =
  144. _sunrise_sunset( $d_sunset_2, $long, $lat, $altit, 15.04107 );
  145. }
  146. }
  147. return $tmp_rise_3+$offset, $tmp_set_3+$offset;
  148. }
  149. sub
  150. _sunrise_sunset($$$$$)
  151. {
  152. my ( $d, $lon, $lat, $altit, $h ) = @_;
  153. my $sidtime = _revolution( _GMST0($d) + 180.0 + $lon );
  154. # Compute Sun's RA + Decl + distance at this moment
  155. my ( $sRA, $sdec, $sr ) = _sun_RA_dec($d);
  156. # Compute time when Sun is at south - in hours UT
  157. my $tsouth = 12.0 - _rev180( $sidtime - $sRA ) / $h;
  158. # Compute the diurnal arc that the Sun traverses to reach
  159. # the specified altitude altit:
  160. my $cost =
  161. ( sind($altit) - sind($lat) * sind($sdec) ) /
  162. ( cosd($lat) * cosd($sdec) );
  163. my $t;
  164. if ( $cost >= 1.0 ) {
  165. $t = 0.0; # Sun always below altit
  166. }
  167. elsif ( $cost <= -1.0 ) {
  168. $t = 12.0; # Sun always above altit
  169. }
  170. else {
  171. $t = acosd($cost) / 15.0; # The diurnal arc, hours
  172. }
  173. # Store rise and set times - in hours UT
  174. my $hour_rise_ut = $tsouth - $t;
  175. my $hour_set_ut = $tsouth + $t;
  176. return ( $hour_rise_ut, $hour_set_ut );
  177. }
  178. sub
  179. _GMST0($)
  180. {
  181. my ($d) = @_;
  182. my $sidtim0 =
  183. _revolution( ( 180.0 + 356.0470 + 282.9404 ) +
  184. ( 0.9856002585 + 4.70935E-5 ) * $d );
  185. return $sidtim0;
  186. }
  187. sub
  188. _sunpos($)
  189. {
  190. my ($d) = @_;
  191. my $Mean_anomaly_of_sun = _revolution( 356.0470 + 0.9856002585 * $d );
  192. my $Mean_longitude_of_perihelion = 282.9404 + 4.70935E-5 * $d;
  193. my $Eccentricity_of_Earth_orbit = 0.016709 - 1.151E-9 * $d;
  194. # Compute true longitude and radius vector
  195. my $Eccentric_anomaly =
  196. $Mean_anomaly_of_sun + $Eccentricity_of_Earth_orbit * $RADEG *
  197. sind($Mean_anomaly_of_sun) *
  198. ( 1.0 + $Eccentricity_of_Earth_orbit * cosd($Mean_anomaly_of_sun) );
  199. my $x = cosd($Eccentric_anomaly) - $Eccentricity_of_Earth_orbit;
  200. my $y =
  201. sqrt( 1.0 - $Eccentricity_of_Earth_orbit * $Eccentricity_of_Earth_orbit )
  202. * sind($Eccentric_anomaly);
  203. my $Solar_distance = sqrt( $x * $x + $y * $y ); # Solar distance
  204. my $True_anomaly = atan2d( $y, $x ); # True anomaly
  205. my $True_solar_longitude =
  206. $True_anomaly + $Mean_longitude_of_perihelion; # True solar longitude
  207. if ( $True_solar_longitude >= 360.0 ) {
  208. $True_solar_longitude -= 360.0; # Make it 0..360 degrees
  209. }
  210. return ( $Solar_distance, $True_solar_longitude );
  211. }
  212. # Sun's Right Ascension (RA), Declination (dec) and distance (r)
  213. sub
  214. _sun_RA_dec($)
  215. {
  216. my ($d) = @_;
  217. my ( $r, $lon ) = _sunpos($d);
  218. my $x = $r * cosd($lon);
  219. my $y = $r * sind($lon);
  220. my $obl_ecl = 23.4393 - 3.563E-7 * $d;
  221. my $z = $y * sind($obl_ecl);
  222. $y = $y * cosd($obl_ecl);
  223. my $RA = atan2d( $y, $x );
  224. my $dec = atan2d( $z, sqrt( $x * $x + $y * $y ) );
  225. return ( $RA, $dec, $r );
  226. }
  227. sub
  228. _days_since_2000_Jan_0($$$)
  229. {
  230. my ($y, $m, $d) = @_;
  231. my @mn = (31,28,31,30,31,30,31,31,30,31,30,31);
  232. my $ms = 0;
  233. for(my $i = 0; $i < $m-1; $i++) {
  234. $ms += $mn[$i];
  235. }
  236. my $x = ($y-2000)*365.25 + $ms + $d;
  237. $x++ if($m > 2 && ($y%4) == 0);
  238. return int($x);
  239. }
  240. sub sind($) { sin( ( $_[0] ) * $DEGRAD ); }
  241. sub cosd($) { cos( ( $_[0] ) * $DEGRAD ); }
  242. sub tand($) { tan( ( $_[0] ) * $DEGRAD ); }
  243. sub atand($) { ( $RADEG * atan( $_[0] ) ); }
  244. sub asind($) { ( $RADEG * asin( $_[0] ) ); }
  245. sub acosd($) { ( $RADEG * acos( $_[0] ) ); }
  246. sub atan2d($$) { ( $RADEG * atan2( $_[0], $_[1] ) ); }
  247. sub
  248. _revolution($)
  249. {
  250. my $x = $_[0];
  251. return ( $x - 360.0 * int( $x * $INV360 ) );
  252. }
  253. sub
  254. _rev180($)
  255. {
  256. my ($x) = @_;
  257. return ( $x - 360.0 * int( $x * $INV360 + 0.5 ) );
  258. }
  259. sub
  260. _equal($$$)
  261. {
  262. my ( $A, $B, $dp ) = @_;
  263. return sprintf( "%.${dp}g", $A ) eq sprintf( "%.${dp}g", $B );
  264. }
  265. sub
  266. _calctz($@)
  267. {
  268. my ($nt,@lt) = @_;
  269. my $off = $lt[2]*3600+$lt[1]*60+$lt[0];
  270. $off = 12*3600-$off;
  271. $nt += $off; # This is noon, localtime
  272. my @gt = gmtime($nt);
  273. return (12-$gt[2]);
  274. }
  275. sub
  276. hms2h($)
  277. {
  278. my $in = shift;
  279. my @a = split(":", $in);
  280. return 0 if(int(@a) < 2 || $in !~ m/^[\d:]*$/);
  281. return $a[0]+$a[1]/60 + ($a[2] ? $a[2]/3600 : 0);
  282. }
  283. sub
  284. h2hms($)
  285. {
  286. my ($in) = @_;
  287. my ($h,$m,$s);
  288. $h = int($in);
  289. $m = int(60*($in-$h));
  290. $s = int(3600*($in-$h)-60*$m);
  291. return ($h, $m, $s);
  292. }
  293. sub
  294. h2hms_fmt($)
  295. {
  296. my ($in) = @_;
  297. my ($h,$m,$s) = h2hms($in);
  298. return sprintf("%02d:%02d:%02d", $h, $m, $s);
  299. }
  300. sub
  301. sr_noon($)
  302. {
  303. my ($date) = @_;
  304. my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($date);
  305. return $date - $hour*3600 - $min*60 - $sec + 12*3600;
  306. }
  307. sub sunrise_coord($$$) { ($long, $lat, $tz) = @_; return undef; }
  308. sub sunrise_rel(@) { return sr_alt(time(),1,1,0,1,shift,shift,shift,shift); }
  309. sub sunset_rel (@) { return sr_alt(time(),0,1,0,1,shift,shift,shift,shift); }
  310. sub sunrise_abs(@) { return sr_alt(time(),1,0,0,0,shift,shift,shift,shift); }
  311. sub sunset_abs (@) { return sr_alt(time(),0,0,0,0,shift,shift,shift,shift); }
  312. sub sunrise (@) { return sr_alt(time(),1,2,0,1,shift,shift,shift,shift); }
  313. sub sunset (@) { return sr_alt(time(),0,2,0,1,shift,shift,shift,shift); }
  314. sub isday (@) { return sr_alt(time(),1,0,1,1,shift,shift,shift,shift); }
  315. sub sunrise_abs_dat(@) {
  316. return sr_alt(sr_noon(shift),1,0,0,0,shift,shift,shift,shift);
  317. }
  318. sub sunset_abs_dat (@) {
  319. return sr_alt(sr_noon(shift),0,0,0,0,shift,shift,shift,shift);
  320. }
  321. 1;
  322. =pod
  323. =item helper
  324. =item summary perl functions to compute the sun position
  325. =item summary_DE perl Funktionen f&uuml;r die Sonnenstandsberechnung
  326. =begin html
  327. <a name="SUNRISE_EL"></a>
  328. <h3>SUNRISE_EL</h3>
  329. <ul>
  330. This module is used to define the functions<pre>
  331. sunrise, sunset,
  332. sunrise_rel, sunset_rel
  333. sunrise_abs, sunset_abs
  334. isday</pre>
  335. perl functions, to be used in <a href="#at">at</a> or FS20 on-till commands.
  336. <br>
  337. First you should set the longitude and latitude global attributes to the
  338. exact longitude and latitude values (see e.g. maps.google.com for the exact
  339. values, which should be in the form of a floating point value). The default
  340. value is Frankfurt am Main, Germany.
  341. <br><br>
  342. The default altitude ($defaultaltit in SUNRISE_EL.pm) defines the
  343. sunrise/sunset for Civil twilight (i.e. one can no longer read outside
  344. without artificial illumination), which differs from sunrise/sunset times
  345. found on different websites. See perldoc "DateTime::Event::Sunrise" for
  346. alternatives. <br><br>
  347. sunrise() and sunset() return the absolute time of the next sunrise/sunset,
  348. adding 24 hours if the next event is tomorrow, to use it in the timespec of
  349. an at device or for the on-till command for FS20 devices.<br>
  350. sunrise_rel() and sunset_rel() return the relative time to the next
  351. sunrise/sunset. <br>
  352. sunrise_abs() and sunset_abs() return the absolute time of the corresponding
  353. event today (no 24 hours added).<br>
  354. sunrise_abs_dat() and sunset_abs_dat() return the absolute time of the
  355. corresponding event to a given date(no 24 hours added).<br>
  356. All functions take up to three arguments:<br>
  357. <ul>
  358. <li>The first specifies an offset (in seconds), which will be added to the
  359. event.</li>
  360. <li>The second and third specify min and max values (format: "HH:MM").</li>
  361. </ul>
  362. <br>
  363. isday() can be used in some notify or at commands to check if the sun is up
  364. or down. isday() ignores the seconds parameter, but respects min and max.
  365. If min < max, than the day starts not before min, and ends not after max.
  366. If min > max, than the day starts not after max, and ends not before min.
  367. <br><br>
  368. Optionally, for all functions you can set first argument which defines a
  369. horizon value which then is used instead of the $defaultaltit in
  370. SUNRISE_EL.pm.<br> Possible values are: "REAL", "CIVIL", "NAUTIC",
  371. "ASTRONOMIC" or a positive or negative number preceded by "HORIZON="<br> REAL
  372. is 0, CIVIL is -6, NAUTIC is -12, ASTRONOMIC is -18 degrees above
  373. horizon.<br><br>
  374. Examples:<br>
  375. <ul>
  376. <PRE>
  377. # When sun is 6 degrees below horizon - same as sunrise();
  378. sunrise("CIVIL");
  379. # When sun is 3 degrees below horizon (between real and civil sunset)
  380. sunset("HORIZON=-3");
  381. # When sun is 1 degree above horizon
  382. sunset("HORIZON=1");
  383. # Switch lamp1 on at real sunset, not before 18:00 and not after 21:00
  384. define a15 at *{sunset("REAL",0,"18:00","21:00")} set lamp1 on
  385. </PRE>
  386. </ul>
  387. The functions sunrise_abs_dat()/sunset_abs_dat() need as a very first
  388. parameter the date(format epoch: time()) for which the events should be
  389. calculated.
  390. <br><br>
  391. Examples:
  392. <br>
  393. <ul>
  394. <PRE>
  395. # to calculate the sunrise of today + 7 days
  396. my $date = time() + 7*86400;
  397. sunrise_abs_dat($date);
  398. # to calculate the sunrise of today + 7 days 6 degrees below horizon
  399. my $date = time() + 7*86400;
  400. sunrise_abs_dat($date, "CIVIL");
  401. </ul>
  402. </PRE>
  403. <b>Define</b> <ul>N/A</ul><br>
  404. <b>Set</b> <ul>N/A</ul><br>
  405. <b>Get</b> <ul>N/A</ul><br>
  406. <b>Attributes</b><br>
  407. <ul>
  408. <a name="latitude"></a>
  409. <li>latitude<br>
  410. If set, this latitude is used to calculate sunset/sunrise<br>
  411. Notation need to be in decimal format (for example Berlin = 52.666)
  412. As default Frankfurt/Main, Germany (50.112) is used.
  413. </li><br>
  414. <a name="longitude"></a>
  415. <li>longitude<br>
  416. If set, this longitude is used to calculate sunset/sunrise<br>
  417. Notation need to be in decimal format (for example Berlin = 13.400)
  418. As default Frankfurt/Main, Germany (8.686) is used.
  419. </li><br>
  420. <a name="altitude"></a>
  421. <li>altitude<br>
  422. Used by other modules.
  423. </li><br>
  424. Note: these are global attributes, e.g.<br>
  425. <ul>
  426. attr global latitude 50.112<br>
  427. attr global longitude 8.686<br>
  428. </ul>
  429. </ul><br>
  430. </ul>
  431. =end html
  432. =begin html_DE
  433. <a name="SUNRISE_EL"></a>
  434. <h3>SUNRISE_EL</h3>
  435. <ul>
  436. <p>
  437. <strong>SUNRISE_EL</strong> definiert eine Reihe von Perl-Subroutinen (<abbr>z.B.</abbr> zur Nutzung mit <a href="#at">at</a>):
  438. </p>
  439. <ul>
  440. <li><code>sunrise()</code> - absolute Zeit des n&auml;chsten
  441. Sonnenaufgangs (+ 24 h, wenn am n&auml;chsten Tag)</li>
  442. <li><code>sunset()</code> - absolute Zeit des n&auml;chsten
  443. Sonnenuntergangs (+ 24 h, wenn am n&auml;chsten Tag)</li>
  444. <li><code>sunrise_rel()</code> - relative Zeit des n&auml;chsten
  445. Sonnenaufgangs</li>
  446. <li><code>sunset_rel()</code> - relative Zeit des n&auml;chsten
  447. Sonnenuntergangs</li>
  448. <li><code>sunrise_abs()</code> - absolute Zeit des n&auml;chsten
  449. Sonnenaufgangs (ohne Stundenzuschlag)</li>
  450. <li><code>sunset_abs()</code> - absolute Zeit des n&auml;chsten
  451. Sonnenuntergangs (ohne Stundenzuschlag)</li>
  452. <li><code>sunrise_abs_dat()</code> - absolute Zeit des n&auml;chsten
  453. Sonnenaufgangs an einem bestimmten Tag</li>
  454. <li><code>sunset_abs_dat()</code> - absolute Zeit des n&auml;chsten
  455. Sonnenuntergangs an einem bestimmten Tag</li>
  456. <li><code>isday()</code> - Tag oder Nacht</li>
  457. </ul>
  458. <h4>Breite, L&auml;nge und H&ouml;henwinkel</h4>
  459. <p>
  460. Bevor du <strong>SUNRISE_EL</strong> verwendest, solltest du im <a href="#global">global-Device</a> die
  461. Werte f&uuml;r <span>latitude</span> (geographische Breite) und <span>longitude</span> (geographische L&auml;nge) entsprechend
  462. deines Standorts setzen.
  463. </p>
  464. <div>
  465. <h4>Exkurs: <span>latitude</span> &amp; <span>longitude</span> ermitteln</h4>
  466. <p>
  467. Deine geopgragischen Koordinaten kannst du <abbr>z.B.</abbr> mit <a href="https://maps.google.com">Google Maps</a> bestimmen.
  468. Dazu setzt du einen Punkt auf der Karte und findest dann im unteren Bereich der Karte die Angabe f&uuml;r beide Werte.
  469. Der erste Wert ist die geographische Breite (<span>latitude</span>); der zweite Wert die geographische L&auml;nge
  470. (<span>longitude</span>).
  471. </p>
  472. <p>
  473. Der <span>Default</span>-Wert ist 50.112, 8.686 (<a href="https://goo.gl/maps/vkyedDL1DJp">Frankfurt am Main</a>).
  474. </p>
  475. </div>
  476. <p>
  477. <strong>SUNRISE_EL</strong> geht von einem H&ouml;henwinkel der Sonne bezogen zum Horizont, <var>h</var>, von -6&deg; aus. Dieser Wert bedeutet,
  478. dass die Sonne 6&deg; <strong>unter</strong> dem Horizont steht und Lesen im Freien ohne k&uuml;nstliche Beleuchtung nicht
  479. mehr m&ouml;glich ist (<span>civil twilight</span>, b&uuml;rgerliche D&auml;mmerung).
  480. <strong>SUNRISE_EL</strong> speichert diesen Wert in <var><code>$defaultaltit</code></var>.
  481. </p>
  482. <p>
  483. Siehe auch <a href="http://search.cpan.org/~jforget/DateTime-Event-Sunrise-0.0505/lib/DateTime/Event/Sunrise.pm">perldoc DateTime::Event::Sunrise</a> f&uuml;r
  484. weitere Hinweise.
  485. </p>
  486. <h4>Befehlsreferenz</h4>
  487. <h5>Parameter</h5>
  488. <p>
  489. Jede der folgenden Funktionen akzeptiert bis zu vier (<abbr>bzw.</abbr> f&uuml;nf) Parameter in der angegebenen Reihenfolge:
  490. </p>
  491. <dl>
  492. <dt>
  493. <var>unix timestamp</var>
  494. </dt>
  495. <dd>
  496. <p>
  497. <strong>Ausschlie&szlig;lich</strong> <code>sunrise_abs_dat()</code> &amp; <code>sunset_abs_dat()</code>
  498. erwarten als ersten Parameter einen Unix-Timestamp (Unix-Epoche) in Sekunden, der ein Datum spezifiziert. Andere Subroutinen
  499. erwarten diesen Parameter nicht!
  500. </p>
  501. </dd>
  502. <dt>
  503. <var>altitude</var>
  504. </dt>
  505. <dd>
  506. <p>
  507. Eine der folgenden Zeichenketten, die unterschiedliche H&ouml;henwinkel <var>h</var> definieren und den Wert
  508. von <code><var>$defaultaltit</var></code> ver&auml;ndern.
  509. </p>
  510. <p>
  511. Erlaubte Werte sind:
  512. </p>
  513. <ul>
  514. <li>
  515. <code><var>REAL</var></code>, <var>h</var> = 0&deg;,
  516. </li>
  517. <li>
  518. <code><var>CIVIL</var></code>, <var>h</var> = -6&deg;,
  519. </li>
  520. <li>
  521. <code><var>NAUTIC</var></code>, <var>h</var> = -12&deg;,
  522. </li>
  523. <li>
  524. <code><var>ASTRONOMIC</var></code>, <var>h</var> = -18&deg;,
  525. </li>
  526. <li>
  527. oder <code><var>HORIZON=</var></code>, gefolgt von einer positiven oder negativen Zahl ohn Gradzeichen, die einen H&ouml;henwinkel
  528. angibt.
  529. </li>
  530. </ul>
  531. </dd>
  532. <dt>
  533. <var>offset</var>
  534. </dt>
  535. <dd>
  536. <p>
  537. <span>Offset</span> in Sekunden, der zu dem R&uuml;ckgabewert der Funktion addiert wird.
  538. </p>
  539. <p>
  540. <code>isday()</code>
  541. ignoriert diesen Wert.
  542. </p>
  543. </dd>
  544. <dt>
  545. <var>min</var>
  546. </dt>
  547. <dd>
  548. <p>
  549. Einen Zeitstempel im Format <var>hh:mm</var>, vor dem keine Aktion ausgef&uuml;hrt werden soll.
  550. </p>
  551. <p>
  552. <code>isday()</code> wird <var>(int) 0</var> zur&uuml;ckliefern, wenn <var>min</var> gesetzt
  553. und der aktuelle Zeitstempel kleiner ist.
  554. </p>
  555. </dd>
  556. <dt>
  557. <var>max</var>
  558. </dt>
  559. <dd>
  560. <p>
  561. Einen Zeitstempel im Format <var>hh:mm</var>, nach dem keine Aktion ausgef&uuml;hrt werden soll.
  562. </p>
  563. <p>
  564. <code>isday()</code> wird <var>(int) 0</var> zur&uuml;ckliefern, wenn <var>max</var> gesetzt
  565. und der aktuelle Zeitstempel gr&ouml;&szlig;er ist.
  566. </p>
  567. </dd>
  568. </dl>
  569. <h5>Subroutinen</h5>
  570. <dl>
  571. <dt>
  572. <p><code>sunrise(), sunset()</code></p>
  573. </dt>
  574. <dd>
  575. liefern den absoluten Wert des n&auml;chsten Sonnenauf- <abbr>bzw.</abbr> -untergangs zur&uuml;ck, wobei 24 Stunden zu
  576. diesem Wert addiert werden,
  577. wenn der Zeitpunkt am n&auml;chsten Tag sein wird, im Format <var>hh:mm:ss</var>.
  578. </dd>
  579. <dt>
  580. <p><code>sunrise_rel(), sunset_rel()</code></p>
  581. </dt>
  582. <dd>
  583. liefern die relative Zeit bis zum n&auml;chsten Sonnenauf- <abbr>bzw.</abbr> -untergang im Format
  584. <var>hh:mm:ss</var>.
  585. </dd>
  586. <dt>
  587. <p><code>sunrise_abs(), sunset_abs()</code></p>
  588. </dt>
  589. <dd>
  590. liefern den n&auml;chsten absoluten Zeitpunkt des n&auml;chsten Sonnenauf- <abbr>bzw.</abbr> -untergangs
  591. <strong>ohne</strong> 24 Stunden
  592. zu addieren im Format <var>hh:mm:ss</var>.
  593. </dd>
  594. <dt>
  595. <p><code>sunrise_abs_dat(), sunset_abs()_dat</code></p>
  596. </dt>
  597. <dd>
  598. liefern den n&auml;chsten absoluten Zeitpunkt des n&auml;chsten Sonnenauf- <abbr>bzw.</abbr> -untergangs
  599. <strong>ohne</strong> 24 Stunden zu addieren im Format <var>hh:mm:ss</var> zu einem als ersten Parameter angegebenen Datum.
  600. </dd>
  601. <dt>
  602. <p><code>isday()</code></p>
  603. </dt>
  604. <dd>
  605. liefert <var>(int) 1</var> wenn Tag ist, <var>(int) 0</var> wenn Nacht ist.
  606. </dd>
  607. </dl>
  608. <h5>Beispiele</h5>
  609. <dl>
  610. <dt>
  611. <p>
  612. <code>sunrise("CIVIL");</code>
  613. </p>
  614. </dt>
  615. <dd>
  616. <p>
  617. Zeitpunkt des Sonnenaufgangs bei einem H&ouml;henwinkel der Sonne von -6&deg; unter dem Horizont (identisch zu <code>sunrise()</code>).
  618. </p>
  619. </dd>
  620. <dt>
  621. <p>
  622. <code>sunset("HORIZON=-3");</code>
  623. </p>
  624. </dt>
  625. <dd>
  626. <p>
  627. Zeitpunkt des Sonnenuntergangs bei einem H&ouml;henwinkel der Sonne von 3&deg; unter dem Horizont
  628. (zwischen <code><var>REAL</var></code> und <code><var>CIVIL</var></code>).
  629. </p>
  630. </dd>
  631. <dt>
  632. <p>
  633. <code>sunset("HORIZON=1");</code>
  634. </p>
  635. </dt>
  636. <dd>
  637. <p>
  638. Zeitpunkt des Sonnenaufgangs bei einem H&ouml;henwinkel der Sonne von 1&deg; &uuml;ber dem Horizont.
  639. </p>
  640. </dd>
  641. <dt>
  642. <p>
  643. <code>defmod a15 at *{sunset("REAL",0,"18:00","21:00")} set lamp1 on</code>
  644. </p>
  645. </dt>
  646. <dd>
  647. <p>
  648. Schalte <var>lamp1</var> an, sobald die Sonne unter den Horizont sinkt (<var>h &le; 0</var>), jedoch nicht vor 18:00 und nicht nach 21:00.
  649. </p>
  650. </dd>
  651. <dt>
  652. <p>
  653. <code>
  654. my $date = time() + 7*86400;<br />
  655. sunrise_abs_dat($date);
  656. </code>
  657. </p>
  658. </dt>
  659. <dd>
  660. <p>
  661. Berechne den Sonnenaufgang von heute + sieben Tage.
  662. </p>
  663. </dd>
  664. <dt>
  665. <p>
  666. <code>
  667. my $date = time() + 7*86400;<br />
  668. sunrise_abs_dat($date, "CIVIL");
  669. </code>
  670. </p>
  671. </dt>
  672. <dd>
  673. <p>
  674. Berechne den Sonnenaufgang von heute + sieben Tage mit einem H&ouml;henwinkel <var>h = -6&deg;</var>.
  675. </p>
  676. </dd>
  677. </dl>
  678. <h4>Define</h4>
  679. <blockquote>
  680. <strong>SUNRISE_EL</strong> kann nicht explizit als <span>Device</span> definiert werden,
  681. sondern bietet die oben genannten Subroutinen.
  682. </blockquote>
  683. <h4>Set</h4>
  684. <blockquote>
  685. <strong>SUNRISE_EL</strong> unterst&uuml;tzt <var>set</var> nicht.
  686. </blockquote>
  687. <h4>Get</h4>
  688. <blockquote>
  689. <strong>SUNRISE_EL</strong> unterst&uuml;tzt <var>get</var> nicht.
  690. </blockquote>
  691. <h4>Attribute</h4>
  692. <p>
  693. Diese Attribute m&uuml;ssen im <span><a href="#global">global</a>-Device</span> gesetzt werden!
  694. </p>
  695. <dl>
  696. <dt>
  697. <p>
  698. <var>latitude</var>
  699. </p>
  700. </dt>
  701. <dd>
  702. <blockquote>
  703. Geographische Breite in Dezimalgrad in Form eines <code>float</code>, <abbr>z.B</abbr> <code><var>49.872471</var></code>.
  704. </blockquote>
  705. <blockquote>
  706. <span>Default</span>-Wert ist <code><var>50.112</var></code>.
  707. </blockquote>
  708. </dd>
  709. <dt>
  710. <p>
  711. <var>longitude</var>
  712. </p>
  713. </dt>
  714. <dd>
  715. <blockquote>
  716. Geographische L&auml;nge in Dezimalgrad in Form eines <code>float</code>, <abbr>z.B</abbr> <code><var>8.650991</var></code>.
  717. </blockquote>
  718. <blockquote>
  719. <span>Default</span>-Wert ist <code><var>8.686</var></code>.
  720. </blockquote>
  721. </dd>
  722. <dt>
  723. <p>
  724. <var>altitude</var>
  725. </p>
  726. </dt>
  727. <dd>
  728. <blockquote>
  729. H&ouml;henwinkel <var>h</var> der Sonne bezogen auf den Horizont in Grad in Form einer Zahl ohne Gradzeichen.
  730. </blockquote>
  731. <blockquote>
  732. <span>Default</span>-Wert ist <code><var>-6</var></code>.
  733. </blockquote>
  734. </dd>
  735. </dl>
  736. </ul>
  737. =end html_DE
  738. =cut