index sonne und Mond rein und Sat Überflüge

This commit is contained in:
Eskimue
2026-04-02 08:45:41 +02:00
parent a3209f6131
commit c85d6a89b8
5 changed files with 470 additions and 73 deletions
+27 -1
View File
@@ -16,7 +16,33 @@
"Bash(php --version)",
"Bash(/c/Users/ich/Downloads/php/php -S localhost:8080 -t public)",
"Bash(/c/Users/ich/Downloads/php/php -m)",
"Bash(/c/Users/ich/Downloads/php/php --ini)"
"Bash(/c/Users/ich/Downloads/php/php --ini)",
"Bash(php -S localhost:8080 -t c:/Users/HP/source/repos/skyview.astronomiemuseum.de/public)",
"Bash(where php:*)",
"Bash(/e/php/php.exe -S localhost:8080 -t \"c:/Users/HP/source/repos/skyview.astronomiemuseum.de/public\")",
"Bash(/e/php/php.exe -m)",
"Read(//e/php/ext//**)",
"Bash(/e/php/php.exe --ini)",
"Bash(sed -i 's|^;extension_dir = \"ext\"|extension_dir = \"ext\"|' /e/php/php.ini)",
"Bash(sed -i 's|^;extension=pdo_mysql|extension=pdo_mysql|' /e/php/php.ini)",
"Bash(sed -i 's|^;extension=mysqli|extension=mysqli|' /e/php/php.ini)",
"Bash(taskkill //F //IM php.exe)",
"Bash(/usr/bin/python3 --version)",
"Bash(/usr/bin/python --version)",
"Read(//c/Users/HP/AppData/Local/Programs/**)",
"Bash(ls /c/Python*/python.exe)",
"Bash(/c/Users/HP/AppData/Local/Python/bin/python.exe --version)",
"Bash(/c/Users/HP/AppData/Local/Python/bin/python.exe c:/Users/HP/source/repos/skyview.astronomiemuseum.de/public/py/api.py sun_moon_rise_set 50.35 11.17 360 2026-04-01 Europe/Berlin)",
"Bash(/c/Users/HP/AppData/Local/Python/bin/python.exe -c \"from zoneinfo import ZoneInfo; ZoneInfo\\('Europe/Berlin'\\)\")",
"Bash(/c/Users/HP/AppData/Local/Python/bin/python.exe -m pip install tzdata)",
"Bash(/e/php/php.exe -r ':*)",
"Bash(/e/php/php.exe -r \"echo ini_get\\('disable_functions'\\);\")",
"Bash(/e/php/php.exe -S localhost:8080 -r \"echo ini_get\\('disable_functions'\\);\")",
"Bash(cp /tmp/debug_exec.php \"c:/Users/HP/source/repos/skyview.astronomiemuseum.de/public/debug_exec.php\")",
"Bash(/e/php/php.exe -l \"c:/Users/HP/source/repos/skyview.astronomiemuseum.de/public/index.php\")",
"Bash(/e/php/php.exe \"c:/Users/HP/source/repos/skyview.astronomiemuseum.de/public/index.php\")",
"Bash(curl -s -o /dev/null -w \"%{http_code}\" http://localhost:8080/index.php)",
"Bash(curl -s http://localhost:8080/index.php)"
]
}
}
+52
View File
@@ -828,6 +828,58 @@ footer a:hover { color: var(--gold); }
padding-right: 1rem;
}
/* Kompakte Auf-/Untergangs-Übersicht (Startseite) */
.riseset-card { display: inline-block; }
.riseset-grid {
display: grid;
grid-template-columns: auto auto auto;
column-gap: 1.2rem;
row-gap: 0.18rem;
align-items: baseline;
font-size: 0.88rem;
}
.riseset-label { color: var(--text-dim); white-space: nowrap; }
.riseset-val { font-variant-numeric: tabular-nums; white-space: nowrap; }
.riseset-main.riseset-label,
.riseset-main.riseset-val {
color: var(--gold-pale);
font-weight: 600;
font-size: 0.92rem;
}
.riseset-moon.riseset-label,
.riseset-moon.riseset-val {
color: var(--cyan);
font-weight: 600;
font-size: 0.92rem;
}
.riseset-dim.riseset-label,
.riseset-dim.riseset-val {
color: var(--text-dim);
font-size: 0.8rem;
}
.riseset-sep {
grid-column: 1 / -1;
height: 0;
border-top: 1px solid var(--border);
margin: 0.3rem 0;
}
.sat-passes-grid {
grid-template-columns: auto auto auto;
}
.sat-passes-grid small {
color: var(--text-dim);
font-size: 0.75em;
margin-left: 0.2em;
}
/* --- Aktions-Zelle (Buttons in Tabellenzeilen) ------------ */
.action-cell {
+295 -66
View File
@@ -1,58 +1,236 @@
<?php
declare(strict_types=1);
ini_set('display_errors', '1');
error_reporting(E_ALL);
session_start();
$loggedIn = isset($_SESSION['user_id']);
$defaultLocation = null;
if ($loggedIn) {
$config = require __DIR__ . '/../config/database.php';
$dsn = sprintf(
'mysql:host=%s;dbname=%s;charset=%s',
$config['host'],
$config['dbname'],
$config['charset'] ?? 'utf8mb4'
);
$pdo = new PDO(
$dsn,
$config['user'],
$config['pass'],
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]
);
$userId = (int)$_SESSION['user_id'];
$displayName = $_SESSION['display_name'] ?? '';
$username = $_SESSION['username'] ?? '';
$role = $_SESSION['role'] ?? 'user';
$stmtLocation = $pdo->prepare("
SELECT
`name`,
`latitude`,
`longitude`,
`elevation`,
`timezone`
FROM `app_user_locations`
WHERE `user_id` = :user_id
AND `is_default` = 1
LIMIT 1
");
$stmtLocation->execute([':user_id' => $userId]);
$defaultLocation = $stmtLocation->fetch();
if (!function_exists('h')) {
function h(?string $value): string { return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); }
}
if (!function_exists('risesetTime')) {
function risesetTime(array $ev, string $key): string { return (!empty($ev[$key]['found'])) ? htmlspecialchars($ev[$key]['local_time'], ENT_QUOTES, 'UTF-8') : '—'; }
}
if (!function_exists('fmtLocalTime')) {
function fmtLocalTime(string $utcIso, string $tz): string { return (new DateTime($utcIso))->setTimezone(new DateTimeZone($tz))->format('H:i'); }
}
if (!function_exists('azDir')) {
function azDir(float $az): string { $dirs = ['N','NO','O','SO','S','SW','W','NW']; return $dirs[(int)round($az / 45) % 8]; }
}
function h(?string $value): string
function idx_tleChecksum(string $line): int
{
return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
$sum = 0;
for ($i = 0; $i < 68; $i++) {
$c = $line[$i];
if (ctype_digit($c)) $sum += (int)$c;
elseif ($c === '-') $sum += 1;
}
return $sum % 10;
}
function idx_tleExp(float $val): string
{
if (abs($val) < 1e-99) return ' 00000-0';
$sign = $val >= 0 ? '+' : '-';
$abs = abs($val);
$exp = (int)floor(log10($abs)) + 1;
$mantissa = (int)round($abs / pow(10, $exp) * 1e5);
if ($mantissa >= 100000) { $mantissa = 10000; $exp++; }
return sprintf('%s%05d%s%d', $sign, $mantissa, $exp >= 0 ? '+' : '-', abs($exp));
}
function idx_tleMmDot(float $val): string
{
return sprintf('%s.%08d', $val >= 0 ? ' ' : '-', (int)round(abs($val) * 1e8));
}
function idx_tleEpoch(string $epochStr): string
{
$dt = new DateTimeImmutable($epochStr, new DateTimeZone('UTC'));
$yy = (int)$dt->format('Y') % 100;
$jan1 = new DateTimeImmutable($dt->format('Y') . '-01-01 00:00:00', new DateTimeZone('UTC'));
$day = ((float)$dt->format('U') - (float)$jan1->format('U')) / 86400.0 + 1.0;
return sprintf('%02d%012.8f', $yy, $day);
}
function idx_tleIntlDesig(?string $id): string
{
if (!$id) return str_repeat(' ', 8);
if (preg_match('/^(\d{4})-(\d+)([A-Z]*)$/i', trim($id), $m)) {
$yy = substr($m[1], 2, 2);
return substr(str_pad($yy . str_pad($m[2], 3, '0', STR_PAD_LEFT) . str_pad(strtoupper($m[3]), 3), 8), 0, 8);
}
return str_pad(substr($id, 0, 8), 8);
}
function buildTleLine1(array $sat, array $tle): string
{
$line = sprintf('1 %05d%1s %-8s %14s %10s %8s %8s %1d %4d',
(int)$sat['norad_cat_id'],
in_array($sat['classification_type'] ?? '', ['U','C','S'], true) ? $sat['classification_type'] : 'U',
idx_tleIntlDesig($sat['object_id'] ?? null),
idx_tleEpoch((string)$tle['epoch']),
idx_tleMmDot((float)($tle['mean_motion_dot'] ?? 0)),
idx_tleExp((float)($tle['mean_motion_ddot'] ?? 0)),
idx_tleExp((float)($tle['bstar'] ?? 0)),
(int)($tle['ephemeris_type'] ?? 0),
(int)($tle['element_set_no'] ?? 0)
);
$line = str_pad($line, 68);
return $line . idx_tleChecksum($line);
}
function buildTleLine2(array $sat, array $tle): string
{
$ecc = (float)($tle['eccentricity'] ?? 0);
$line = sprintf('2 %05d %8.4f %8.4f %7s %8.4f %8.4f %11.8f%5d',
(int)$sat['norad_cat_id'],
(float)($tle['inclination'] ?? 0),
(float)($tle['ra_of_asc_node'] ?? 0),
substr(sprintf('%.7f', $ecc), 2),
(float)($tle['arg_of_pericenter'] ?? 0),
(float)($tle['mean_anomaly'] ?? 0),
(float)($tle['mean_motion'] ?? 0),
(int)($tle['rev_at_epoch'] ?? 0)
);
$line = str_pad($line, 68);
return $line . idx_tleChecksum($line);
}
// Standort und astronomische Daten nur wenn eingeloggt und Standort vorhanden
$skyData = null;
$planetData = null;
$satData = null;
$pyError = null;
if ($loggedIn) {
// header.php lädt $currentLocation – wir brauchen ihn vorab
$config = require __DIR__ . '/../config/database.php';
$pdo = new PDO(
sprintf('mysql:host=%s;dbname=%s;charset=%s', $config['host'], $config['dbname'], $config['charset'] ?? 'utf8mb4'),
$config['user'],
$config['pass'],
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
);
$stmtLoc = $pdo->prepare(
'SELECT name, latitude, longitude, elevation, timezone
FROM app_user_locations WHERE user_id = ? AND is_default = 1 LIMIT 1'
);
$stmtLoc->execute([(int)$_SESSION['user_id']]);
$defaultLocation = $stmtLoc->fetch() ?: null;
if ($defaultLocation) {
$lat = (float)$defaultLocation['latitude'];
$lon = (float)$defaultLocation['longitude'];
$elev = (float)($defaultLocation['elevation'] ?? 0);
$tz = $defaultLocation['timezone'] ?? 'Europe/Berlin';
$date = date('Y-m-d');
$scriptPath = realpath(__DIR__ . '/py/api.py');
if (file_exists('/usr/bin/python3')) {
$pythonBin = '/usr/bin/python3';
} elseif (file_exists('/usr/bin/python')) {
$pythonBin = '/usr/bin/python';
} else {
$pythonBin = 'C:\\Users\\HP\\AppData\\Local\\Python\\bin\\python.exe';
}
putenv('PYTHONUTF8=1');
putenv('PYTHONIOENCODING=utf-8');
// Sonne + Mond
$args = [
$pythonBin,
escapeshellarg($scriptPath),
escapeshellarg('sun_moon_rise_set'),
escapeshellarg((string)$lat),
escapeshellarg((string)$lon),
escapeshellarg((string)$elev),
escapeshellarg($date),
escapeshellarg($tz),
];
$cmd = implode(' ', $args) . ' 2>&1';
$out = [];
exec($cmd, $out);
$raw = json_decode(implode('', $out), true);
if (is_array($raw) && ($raw['ok'] ?? false)) {
$skyData = $raw;
} else {
$pyError = $raw['error'] ?? 'Fehler beim Berechnen der Aufgangszeiten.';
}
// Planeten
$args2 = [
$pythonBin,
escapeshellarg($scriptPath),
escapeshellarg('planet_rise_set'),
escapeshellarg((string)$lat),
escapeshellarg((string)$lon),
escapeshellarg((string)$elev),
escapeshellarg($date),
escapeshellarg($tz),
];
$cmd2 = implode(' ', $args2) . ' 2>&1';
$out2 = [];
exec($cmd2, $out2);
$raw2 = json_decode(implode('', $out2), true);
if (is_array($raw2) && ($raw2['ok'] ?? false)) {
$planetData = $raw2;
} elseif ($pyError === null) {
$pyError = $raw2['error'] ?? 'Fehler beim Berechnen der Planetenzeiten.';
}
// Satelliten-Überflüge heute — Favorit zuerst, dann alle gemerkten
$stmtSat = $pdo->prepare(
'SELECT s.id, s.norad_cat_id, s.object_name, s.object_type,
s.object_id, s.classification_type,
t.epoch, t.mean_motion, t.eccentricity, t.inclination,
t.ra_of_asc_node, t.arg_of_pericenter, t.mean_anomaly,
t.ephemeris_type, t.element_set_no, t.rev_at_epoch,
t.bstar, t.mean_motion_dot, t.mean_motion_ddot,
us.is_favorite
FROM app_user_satellites us
JOIN sat_satellites s ON s.id = us.satellite_id
JOIN sat_tle_current t ON t.satellite_id = s.id
WHERE us.user_id = ?
AND t.epoch IS NOT NULL
ORDER BY us.is_favorite DESC, s.object_name ASC
LIMIT 3'
);
$stmtSat->execute([(int)$_SESSION['user_id']]);
$userSats = $stmtSat->fetchAll();
if ($userSats) {
$tzObj = new DateTimeZone($tz);
$dayStart = new DateTime('today', $tzObj);
$dayStart->setTimezone(new DateTimeZone('UTC'));
$dayEnd = new DateTime('tomorrow', $tzObj);
$dayEnd->setTimezone(new DateTimeZone('UTC'));
$satsJson = json_encode(array_map(fn($r) => [
'id' => $r['id'],
'norad_cat_id' => $r['norad_cat_id'],
'object_name' => $r['object_name'],
'tle_line1' => buildTleLine1($r, $r),
'tle_line2' => buildTleLine2($r, $r),
'is_favorite' => (bool)$r['is_favorite'],
], $userSats), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$args3 = [
$pythonBin,
escapeshellarg($scriptPath),
escapeshellarg('satellite_passes'),
escapeshellarg((string)$lat),
escapeshellarg((string)$lon),
escapeshellarg((string)$elev),
escapeshellarg($tz),
escapeshellarg($dayStart->format('Y-m-d\TH:i:s\Z')),
escapeshellarg($dayEnd->format('Y-m-d\TH:i:s\Z')),
escapeshellarg($satsJson),
];
$cmd3 = implode(' ', $args3) . ' 2>&1';
$out3 = [];
exec($cmd3, $out3);
$raw3 = json_decode(implode('', $out3), true);
if (is_array($raw3) && ($raw3['ok'] ?? false)) {
$satData = $raw3;
}
}
}
}
?>
<?php require __DIR__ . '/header.php'; ?>
@@ -70,36 +248,87 @@ function h(?string $value): string
<?php else: ?>
<p class="welcome-text">
Willkommen zurück, <strong><?= h($displayName !== '' ? $displayName : $username) ?></strong>.
<?php if (!$defaultLocation): ?>
<p class="hint">Noch kein Standort hinterlegt. <a href="settings.php">Jetzt anlegen</a></p>
<?php elseif ($pyError): ?>
<ul class="msg-error"><li><?= h($pyError) ?></li></ul>
<?php else: ?>
<p class="hint rise-set-location">
Aufgangs- und Untergangszeiten für
<strong><?= h($defaultLocation['name']) ?></strong>
&mdash; <?= h(date('d.m.Y')) ?>
</p>
<div class="grid-2">
<?php $ev = $skyData['events'] ?? []; ?>
<div class="card riseset-card">
<h2>Heute</h2>
<div class="riseset-grid">
<span class="riseset-label riseset-main">☀ Sonne</span>
<span class="riseset-val riseset-main">↑ <?= risesetTime($ev, 'sunrise') ?></span>
<span class="riseset-val riseset-main">↓ <?= risesetTime($ev, 'sunset') ?></span>
<div class="card">
<h2>Konto</h2>
<table class="data-table">
<tr><td>Benutzername</td><td><?= h($username) ?></td></tr>
<tr><td>Rolle</td><td><?= h($role) ?></td></tr>
</table>
<span class="riseset-label riseset-dim">Bürgerl.</span>
<span class="riseset-val riseset-dim"><?= risesetTime($ev, 'civil_dawn') ?></span>
<span class="riseset-val riseset-dim"><?= risesetTime($ev, 'civil_dusk') ?></span>
<span class="riseset-label riseset-dim">Nautisch</span>
<span class="riseset-val riseset-dim"><?= risesetTime($ev, 'nautical_dawn') ?></span>
<span class="riseset-val riseset-dim"><?= risesetTime($ev, 'nautical_dusk') ?></span>
<span class="riseset-label riseset-dim">Astronom.</span>
<span class="riseset-val riseset-dim"><?= risesetTime($ev, 'astro_dawn') ?></span>
<span class="riseset-val riseset-dim"><?= risesetTime($ev, 'astro_dusk') ?></span>
<span class="riseset-sep"></span><span class="riseset-sep"></span><span class="riseset-sep"></span>
<span class="riseset-label riseset-moon">☽ Mond</span>
<span class="riseset-val riseset-moon">↑ <?= risesetTime($ev, 'moonrise') ?></span>
<span class="riseset-val riseset-moon">↓ <?= risesetTime($ev, 'moonset') ?></span>
<span class="riseset-sep"></span><span class="riseset-sep"></span><span class="riseset-sep"></span>
<?php foreach (($planetData['planets'] ?? []) as $planet): ?>
<span class="riseset-label"><?= h($planet['name']) ?></span>
<span class="riseset-val">↑ <?= ($planet['rise']['found'] ?? false) ? h($planet['rise']['local_time']) : '—' ?></span>
<span class="riseset-val">↓ <?= ($planet['set']['found'] ?? false) ? h($planet['set']['local_time']) : '—' ?></span>
<?php endforeach; ?>
</div>
</div>
<div class="card">
<h2>Standard-Standort</h2>
<?php if ($defaultLocation): ?>
<table class="data-table">
<tr><td>Name</td><td><?= h($defaultLocation['name']) ?></td></tr>
<tr><td>Breitengrad</td><td><?= h((string)$defaultLocation['latitude']) ?></td></tr>
<tr><td>Längengrad</td><td><?= h((string)$defaultLocation['longitude']) ?></td></tr>
<tr><td>Höhe</td><td><?= h($defaultLocation['elevation'] !== null ? (string)$defaultLocation['elevation'] . ' m' : '—') ?></td></tr>
<tr><td>Zeitzone</td><td><?= h($defaultLocation['timezone']) ?></td></tr>
</table>
<?php if ($satData): ?>
<?php
$favName = '';
$favPasses = [];
foreach (($satData['results'] ?? []) as $sat) {
if ($sat['is_favorite']) {
$favName = $sat['name'];
$favPasses = $sat['passes'] ?? [];
break;
}
}
usort($favPasses, fn($a, $b) => strcmp($a['aos_utc'], $b['aos_utc']));
?>
<div class="card riseset-card">
<h2>☆ <?= h($favName ?: 'Favorit') ?></h2>
<?php if (empty($favPasses)): ?>
<p class="hint">Heute keine Überflüge.</p>
<?php else: ?>
<p class="hint">Noch kein Standort hinterlegt. <a href="settings.php">Jetzt anlegen</a></p>
<div class="riseset-grid sat-passes-grid">
<span class="riseset-label riseset-dim">AOS</span>
<span class="riseset-label riseset-dim">LOS</span>
<span class="riseset-label riseset-dim">Max</span>
<?php foreach ($favPasses as $p): ?>
<span class="riseset-val riseset-main"><?= fmtLocalTime($p['aos_utc'], $tz) ?> <small><?= $p['aos_az'] !== null ? azDir((float)$p['aos_az']) : '' ?></small></span>
<span class="riseset-val"><?= fmtLocalTime($p['los_utc'], $tz) ?> <small><?= $p['los_az'] !== null ? azDir((float)$p['los_az']) : '' ?></small></span>
<span class="riseset-val riseset-dim"><?= round((float)$p['peak_el']) ?>°</span>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<?php endif; ?>
<?php endif; ?>
Binary file not shown.
+91 -1
View File
@@ -151,6 +151,24 @@ def action_sun_moon_rise_set(args: list[str]) -> dict:
moon_rise = search_event(astronomy.Body.Moon, astronomy.Direction.Rise, observer, start_time, utc_end)
moon_set = search_event(astronomy.Body.Moon, astronomy.Direction.Set, observer, start_time, utc_end)
def search_altitude(direction: astronomy.Direction, altitude_deg: float) -> astronomy.Time | None:
limit_days = (utc_end - time_to_datetime(start_time)).total_seconds() / 86400.0
result = astronomy.SearchAltitude(astronomy.Body.Sun, observer, direction, start_time, limit_days, altitude_deg)
if result is None:
return None
if time_to_datetime(result) >= utc_end:
return None
return result
# Morgens: Sonne steigt auf → Direction.Rise (Höhe wird größer)
# Abends: Sonne sinkt ab → Direction.Set (Höhe wird kleiner)
astro_dawn = search_altitude(astronomy.Direction.Rise, -18.0)
nautical_dawn = search_altitude(astronomy.Direction.Rise, -12.0)
civil_dawn = search_altitude(astronomy.Direction.Rise, -6.0)
civil_dusk = search_altitude(astronomy.Direction.Set, -6.0)
nautical_dusk = search_altitude(astronomy.Direction.Set, -12.0)
astro_dusk = search_altitude(astronomy.Direction.Set, -18.0)
return {
"ok": True,
"action": "sun_moon_rise_set",
@@ -168,14 +186,81 @@ def action_sun_moon_rise_set(args: list[str]) -> dict:
"utc_end": utc_end.isoformat().replace("+00:00", "Z"),
},
"events": {
"astro_dawn": serialize_event("Astronomische Morgendämmerung", astro_dawn, tz),
"nautical_dawn": serialize_event("Nautische Morgendämmerung", nautical_dawn, tz),
"civil_dawn": serialize_event("Bürgerliche Morgendämmerung", civil_dawn, tz),
"sunrise": serialize_event("Sonnenaufgang", sun_rise, tz),
"sunset": serialize_event("Sonnenuntergang", sun_set, tz),
"civil_dusk": serialize_event("Bürgerliche Abenddämmerung", civil_dusk, tz),
"nautical_dusk": serialize_event("Nautische Abenddämmerung", nautical_dusk, tz),
"astro_dusk": serialize_event("Astronomische Abenddämmerung", astro_dusk, tz),
"moonrise": serialize_event("Mondaufgang", moon_rise, tz),
"moonset": serialize_event("Monduntergang", moon_set, tz),
},
}
PLANETS = [
("Merkur", astronomy.Body.Mercury),
("Venus", astronomy.Body.Venus),
("Mars", astronomy.Body.Mars),
("Jupiter", astronomy.Body.Jupiter),
("Saturn", astronomy.Body.Saturn),
("Uranus", astronomy.Body.Uranus),
("Neptun", astronomy.Body.Neptune),
]
def action_planet_rise_set(args: list[str]) -> dict:
if len(args) != 5:
fail(
"Aktion planet_rise_set erwartet 5 Argumente: latitude longitude elevation date timezone",
extra={"argv": args},
)
latitude = parse_float(args[0], "Latitude")
longitude = parse_float(args[1], "Longitude")
elevation = parse_float(args[2], "Elevation")
date_text = args[3]
timezone_name = args[4]
try:
datetime.strptime(date_text, "%Y-%m-%d")
except ValueError:
fail("Datum muss im Format YYYY-MM-DD uebergeben werden.", extra={"date": date_text})
try:
tz = ZoneInfo(timezone_name)
except Exception as exc:
fail("Zeitzone ist ungueltig.", extra={"details": str(exc)})
observer = astronomy.Observer(latitude, longitude, elevation)
local_start = datetime.strptime(date_text, "%Y-%m-%d").replace(tzinfo=tz)
local_end = local_start + timedelta(days=1)
utc_start = local_start.astimezone(timezone.utc)
utc_end = local_end.astimezone(timezone.utc)
start_time = dt_to_time(utc_start)
planets = []
for name, body in PLANETS:
rise = search_event(body, astronomy.Direction.Rise, observer, start_time, utc_end)
set_ = search_event(body, astronomy.Direction.Set, observer, start_time, utc_end)
planets.append({
"name": name,
"rise": serialize_event(name + "aufgang", rise, tz),
"set": serialize_event(name + "untergang", set_, tz),
})
return {
"ok": True,
"action": "planet_rise_set",
"date": date_text,
"timezone": timezone_name,
"planets": planets,
}
def classify_visibility(sun_alt_deg: float) -> dict:
if sun_alt_deg > -5:
return {"key": "day", "label": "Tag"}
@@ -1201,7 +1286,12 @@ def main() -> None:
print(json.dumps(result, ensure_ascii=False))
return
fail("Unbekannte Aktion.", extra={"action": action, "available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes"]})
if action == "planet_rise_set":
result = action_planet_rise_set(args)
print(json.dumps(result, ensure_ascii=False))
return
fail("Unbekannte Aktion.", extra={"action": action, "available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set"]})
if __name__ == "__main__":