Auf der Strecke
Lauffähige Beispiele für Wetter auf der Strecke (En-Route) innerhalb eines geografischen Begrenzungsrahmens (Bounding Box): Höhenwinde, PIREPs und AIRMET/SIGMET. Für Abläufe mit METAR/TAF am Flughafen siehe Am Flughafen.
| # | Frage | Verwendete Daten |
|---|---|---|
| 7 | Reiseflugwind auf FL180 nahe dem Abflug in KJFK (regionale US-Bbox)? | Höhenwinde |
| 8 | Gibt es dringende Pilotenmeldungen (UUA) entlang der Route in den letzten 3 Stunden? | PIREPs |
| 9 | Aktive AIRMET-Polygone, die die Bbox der Route schneiden? | AIRMET/SIGMET |
Voraussetzungen
x-api-key bei jeder Anfrage (Direktabonnement). Mehr erfahren →Installation
Die folgenden Skripte verwenden requests für API-Aufrufe und rich für die Terminalausgabe. Einmalig installieren:
pip install requests rich7. Reiseflugwind auf FL180 (Höhenwinde)
Frage: Welche Höhenwind-Stufe liegt nahe dem Abflug in KJFK am nächsten an FL180?
Höhenwinde sind nur für die USA verfügbar. Fragen Sie bei langen Routen regionale Bboxes entlang des US-Abschnitts ab (eine Box von Küste zu Küste ist langsam und führt oft zu 503). Im Folgenden: eine enge Box rund um New York.
import os
import requests
from rich.console import Console
from rich.table import Table
console = Console()
HEADERS = {
"X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
"X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"
# Regional box around KJFK - reliable for FB Winds (US only)
NYC_BBOX = "38,-76,42,-71"
TARGET_ALT_FT = 18_000
def fetch_winds_aloft(bbox: str, forecast: int = 12) -> dict | None:
r = requests.get(
f"{BASE}/weather/winds-aloft",
headers=HEADERS,
params={"bbox": bbox, "forecast": forecast, "level": "low"},
timeout=(10, 20),
)
if r.status_code in (404, 503):
return None
r.raise_for_status()
return r.json()
def print_cruise_wind(bbox: str, label: str, target_ft: int = TARGET_ALT_FT) -> None:
data = fetch_winds_aloft(bbox)
if not data:
console.print("[yellow]Winds aloft unavailable or no stations - retry or widen bbox.[/]")
return
if not data.get("stations"):
console.print("[yellow]No FB winds stations in this bbox.[/]")
return
station = data["stations"][0]
levels = station.get("winds") or []
if not levels:
console.print(f"[yellow]Station {station['station']} returned no wind levels.[/]")
return
best = min(levels, key=lambda w: abs(w["altitude_ft"] - target_ft))
table = Table(title=f"Cruise wind near FL{target_ft // 100} - {label}")
table.add_column("Field", style="cyan")
table.add_column("Value", justify="right")
table.add_row("Bbox", bbox)
table.add_row("Station", station["station"])
table.add_row("Level used", f"{best['altitude_ft']} ft MSL")
table.add_row("Direction", f"{best.get('wind_direction') or '-'}° true")
table.add_row("Speed", f"{best.get('wind_speed_kt') or '-'} kt")
temp = best.get("temperature_c")
table.add_row("Temperature", f"{temp} °C" if temp is not None else "not reported")
table.add_row("Valid time", data.get("valid_time") or "-")
console.print(table)
if __name__ == "__main__":
print_cruise_wind(NYC_BBOX, "KJFK departure area")Ausgabe: Tabelle mit der Windstufe, die Ihrer Zielhöhe am nächsten liegt, von der ersten Station in der Bbox.
8. Dringende PIREPs entlang der Route
Frage: Wurden in den letzten 3 Stunden in der Bbox der Route UUA-Pilotenmeldungen (dringend) abgegeben?
PIREPs sind selten — eine leere Liste ist üblich. Wenn Meldungen vorhanden sind, zeigen Sie UUA vor routinemäßigen UA-Meldungen an.
import os
import requests
from rich.console import Console
from rich.panel import Panel
console = Console()
HEADERS = {
"X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
"X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"
KJFK = (40.6413, -73.7781)
KLAX = (33.9425, -118.4081)
def route_bbox(dep, arr, pad_deg: float = 2.0) -> str:
dep_lat, dep_lon = dep
arr_lat, arr_lon = arr
return (
f"{min(dep_lat, arr_lat) - pad_deg},{min(dep_lon, arr_lon) - pad_deg},"
f"{max(dep_lat, arr_lat) + pad_deg},{max(dep_lon, arr_lon) + pad_deg}"
)
def fetch_pireps(bbox: str, hours: int = 3) -> dict:
r = requests.get(
f"{BASE}/weather/pireps",
headers=HEADERS,
params={"bbox": bbox, "hours": hours},
timeout=(10, 20),
)
r.raise_for_status()
return r.json()
def print_urgent_pireps(dep, arr) -> None:
bbox = route_bbox(dep, arr)
data = fetch_pireps(bbox, hours=3)
reports = data.get("reports") or []
urgent = [r for r in reports if r.get("report_type") == "UUA"]
routine = [r for r in reports if r.get("report_type") != "UUA"]
if not reports:
console.print(Panel(
f"No PIREPs in bbox {bbox} (last 3 h).\n"
"This is normal on quiet routes - not an error.",
title="PIREPs - none filed",
style="blue",
))
return
lines = []
for r in urgent + routine[:5]:
tag = "[red]UUA[/]" if r.get("report_type") == "UUA" else "UA"
turb = r.get("turbulence") or "-"
icing = r.get("icing") or "-"
lines.append(f"{tag} {r.get('location') or '?'} @ {r.get('altitude') or '?'} - turb: {turb}, ice: {icing}")
console.print(Panel(
"\n".join(lines),
title=f"PIREPs in route bbox ({data['total']} total, {len(urgent)} urgent)",
))
if __name__ == "__main__":
print_urgent_pireps(KJFK, KLAX)Ausgabe: Panel, das zuerst dringende PIREPs und danach bis zu fünf Routinemeldungen auflistet — oder eine eindeutige Meldung „keine abgegeben“.
9. Aktive AIRMETs auf der Route
Frage: Schneiden derzeit AIRMET-Warnungen die Bbox der Route?
Verwenden Sie type=airmet für Bulletins zu IFR, Turbulenz und Vereisung, wie sie in der Flugdienstberatung (Dispatch) genutzt werden. Zeichnen Sie observation.coords auf einer Karte ein, sofern vorhanden.
import os
import requests
from rich.console import Console
from rich.table import Table
console = Console()
HEADERS = {
"X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
"X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"
KJFK = (40.6413, -73.7781)
KLAX = (33.9425, -118.4081)
def route_bbox(dep, arr, pad_deg: float = 2.0) -> str:
dep_lat, dep_lon = dep
arr_lat, arr_lon = arr
return (
f"{min(dep_lat, arr_lat) - pad_deg},{min(dep_lon, arr_lon) - pad_deg},"
f"{max(dep_lat, arr_lat) + pad_deg},{max(dep_lon, arr_lon) + pad_deg}"
)
def fetch_airsigmets(bbox: str, advisory_type: str = "airmet") -> dict:
r = requests.get(
f"{BASE}/weather/airsigmet",
headers=HEADERS,
params={"bbox": bbox, "type": advisory_type},
timeout=(10, 25),
)
r.raise_for_status()
return r.json()
def print_route_airsigmets(dep, arr) -> None:
bbox = route_bbox(dep, arr)
data = fetch_airsigmets(bbox)
reports = data.get("reports") or []
if not reports:
console.print(f"[green]No active AIRMETs intersect bbox {bbox} - fair weather or outside advisory area.[/]")
return
table = Table(title=f"Active AIRMETs - {len(reports)} in bbox")
table.add_column("Type")
table.add_column("Valid")
table.add_column("Hazard")
table.add_column("Polygon points")
for r in reports:
obs = r.get("observation") or {}
hazard = obs.get("type") or r.get("report_type") or "-"
floor = obs.get("floor") or "-"
ceiling = obs.get("ceiling") or "-"
coords = obs.get("coords") or []
valid = f"{r.get('start_time') or '?'} → {r.get('end_time') or '?'}"
table.add_row(
r.get("report_type") or "AIRMET",
valid,
f"{hazard} ({floor}–{ceiling})",
str(len(coords)),
)
console.print(table)
console.print("[dim]Render observation.coords as map polygons; hide expired advisories past end_time.[/dim]")
if __name__ == "__main__":
print_route_airsigmets(KJFK, KLAX)Ausgabe: Tabelle der aktiven AIRMETs mit Gültigkeitszeitraum, Gefahrentyp und Anzahl der Polygoneckpunkte.
Siehe auch: METAR · TAF · Höhenwinde · PIREPs · AIRMET/SIGMET · Fehlerbehandlung · Caching & Monitoring
Am Flughafen
Integrationsbeispiele für METAR und TAF am Flughafen — Flugwetterkategorien, Dichtehöhe, Abflugvorhersagen und Ausweichflughäfen.
Fehlerbehandlung
Fehlende METAR- und TAF-Daten im Produktivbetrieb behandeln – Bedeutung von 404, Fallbacks und Verweise auf die Fehlerbehandlung der Plattform.