MILITAERFLUGVERKEHR (adsb.lol /v2/mil): - ~254 Militaerflugzeuge weltweit in Echtzeit (rot) - Callsign-Labels bei Zoom (RCH=USAF, GAF=Luftwaffe etc.) - Klick zeigt: Callsign, Registration, Typ, Hoehe, Squawk - 20s Refresh SEEKABEL (TeleGeography): - Untersee-Glasfaserkabel als cyan-Linien auf dem Globus - ~500+ internationale Kabelverbindungen - Geopolitisch relevant (Sabotage, Abhoerung) INFRASTRUKTUR (OpenStreetMap Overpass): - 348 Kernkraftwerke weltweit (gelb mit Orange-Rand) - Militaerflughaefen (rot) - Labels bei Zoom (<500km) - 24h Cache (statische Daten) ISS TRACKER (Open-Notify API): - Echtzeit-Position der ISS (roter Punkt, 420km Hoehe) - 5s Refresh, prominentes Label - Klick zeigt Details Backend: data_military.py, data_infra.py (2 neue Dateien) Frontend: military.js, cables.js, infra.js, iss.js (4 neue Dateien)
50 Zeilen
1.7 KiB
Python
50 Zeilen
1.7 KiB
Python
"""Militaerflugverkehr: adsb.lol /v2/mil Endpoint."""
|
|
import asyncio, logging, time, httpx
|
|
from fastapi import APIRouter
|
|
|
|
logger = logging.getLogger("globe.military")
|
|
router = APIRouter()
|
|
_cache = {"data": None, "ts": 0}
|
|
_task = None
|
|
|
|
async def _fetch():
|
|
now = time.time()
|
|
if _cache["data"] and now - _cache["ts"] < 15:
|
|
return _cache["data"]
|
|
try:
|
|
async with httpx.AsyncClient(timeout=15) as client:
|
|
r = await client.get("https://api.adsb.lol/v2/mil")
|
|
r.raise_for_status()
|
|
ac = []
|
|
for a in r.json().get("ac", []):
|
|
if a.get("lat") and a.get("lon"):
|
|
ac.append({
|
|
"hex": a.get("hex",""), "flight": (a.get("flight") or "").strip(),
|
|
"reg": a.get("r",""), "type": a.get("t",""),
|
|
"lat": a["lat"], "lon": a["lon"],
|
|
"alt_baro": a.get("alt_baro"), "gs": a.get("gs"),
|
|
"track": a.get("track"), "squawk": a.get("squawk",""),
|
|
"dbFlags": a.get("dbFlags", 0),
|
|
})
|
|
_cache["data"] = {"ac": ac, "total": len(ac)}
|
|
_cache["ts"] = time.time()
|
|
logger.info(f"Military: {len(ac)} Flugzeuge")
|
|
except Exception as e:
|
|
logger.warning(f"Military: {e}")
|
|
return _cache["data"] or {"ac": [], "total": 0}
|
|
|
|
async def _loop():
|
|
await asyncio.sleep(5)
|
|
while True:
|
|
await _fetch()
|
|
await asyncio.sleep(20)
|
|
|
|
def start_mil_collector():
|
|
global _task
|
|
if _task is None or _task.done():
|
|
_task = asyncio.create_task(_loop())
|
|
|
|
@router.get("/military")
|
|
async def get_military():
|
|
return await _fetch()
|