SATELLITEN (CelesTrak TLE): - Raumstationen (ISS), GPS, Galileo, Wetter, Erdbeobachtung, Starlink - Echtzeit-Positionsberechnung aus Kepler-Elementen (2s Update) - Orbitbahnen als leuchtende Linien (Stationen, GPS, Galileo) - Farbkodiert nach Gruppe (rot=Station, orange=GPS, blau=Galileo) NATURKATASTROPHEN (NASA EONET): - Waldbraende, Vulkane, Stuerme, Fluten, Erdrutsche, Eis - Farbige Punkte mit Emoji-Labels - Klick zeigt Details und Quellen VISUAL MODES: - STD: Standard-Ansicht - NVG: Nachtsicht (gruener Monochrom-Filter) - FLIR: Thermal-Ansicht (invertiert, Infrarot-Look) - CRT: Retro-Monitor (Scanlines, Vignette) 4 neue Dateien: satellites.js, disasters.js, visualmodes.js, data_satellites.py, data_disasters.py
70 Zeilen
2.7 KiB
Python
70 Zeilen
2.7 KiB
Python
"""Satelliten-Daten: CelesTrak TLE Orbital Elements."""
|
|
import logging
|
|
import time
|
|
|
|
import httpx
|
|
from fastapi import APIRouter
|
|
|
|
logger = logging.getLogger("globe.satellites")
|
|
router = APIRouter()
|
|
|
|
_cache: dict = {"data": None, "ts": 0}
|
|
|
|
# Wichtigste Satellitengruppen (nicht alle 14.000)
|
|
_GROUPS = [
|
|
("stations", "Raumstationen (ISS etc.)"),
|
|
("gps-ops", "GPS Navigationssatelliten"),
|
|
("galileo", "Galileo Navigation"),
|
|
("weather", "Wettersatelliten"),
|
|
("resource", "Erdbeobachtung"),
|
|
("starlink", "Starlink (Auswahl)"),
|
|
("active", None), # Fallback: alle aktiven, wird gefiltert
|
|
]
|
|
|
|
|
|
@router.get("/satellites")
|
|
async def get_satellites():
|
|
now = time.time()
|
|
if _cache["data"] and now - _cache["ts"] < 3600: # 1h Cache
|
|
return _cache["data"]
|
|
|
|
all_sats = []
|
|
try:
|
|
async with httpx.AsyncClient(timeout=15) as client:
|
|
for group, label in _GROUPS:
|
|
if group == "active":
|
|
continue # Zu gross, skip
|
|
url = f"https://celestrak.org/NORAD/elements/gp.php?GROUP={group}&FORMAT=json"
|
|
try:
|
|
r = await client.get(url)
|
|
if r.status_code == 200:
|
|
sats = r.json()
|
|
# Starlink: nur 200 nehmen (sind tausende)
|
|
if group == "starlink":
|
|
sats = sats[:200]
|
|
for s in sats:
|
|
all_sats.append({
|
|
"name": s.get("OBJECT_NAME", "?"),
|
|
"id": s.get("NORAD_CAT_ID"),
|
|
"group": group,
|
|
"epoch": s.get("EPOCH"),
|
|
"meanMotion": s.get("MEAN_MOTION"),
|
|
"eccentricity": s.get("ECCENTRICITY"),
|
|
"inclination": s.get("INCLINATION"),
|
|
"raOfAscNode": s.get("RA_OF_ASC_NODE"),
|
|
"argOfPericenter": s.get("ARG_OF_PERICENTER"),
|
|
"meanAnomaly": s.get("MEAN_ANOMALY"),
|
|
"bstar": s.get("BSTAR"),
|
|
"meanMotionDot": s.get("MEAN_MOTION_DOT"),
|
|
})
|
|
except Exception as e:
|
|
logger.warning(f"CelesTrak {group}: {e}")
|
|
except Exception as e:
|
|
logger.warning(f"CelesTrak Fehler: {e}")
|
|
return _cache["data"] or {"satellites": [], "total": 0}
|
|
|
|
_cache["data"] = {"satellites": all_sats, "total": len(all_sats)}
|
|
_cache["ts"] = time.time()
|
|
logger.info(f"Satellites: {len(all_sats)} geladen")
|
|
return _cache["data"]
|