-
Notifications
You must be signed in to change notification settings - Fork 0
Service Weather
Port 8004:8000 · services/weather_service/ ·
real METAR/TAF in, the session's ATIS out. Health: /api/v1/weather/health. See
architecture.
Fetches real METAR/TAF and generates the ATIS the whole session keys off: every other component that needs current conditions — or the runway in use — asks this service, not aviationweather.gov directly.
| Relations | Modules |
|---|---|
| Called by | Controller HMI (ATIS/weather panel, proxied) · Orchestrator (weather context fetched before forwarding to the DEL agent) |
| Calls | aviationweather.gov (external, METAR/TAF) · PostgreSQL (ATIS history) |
Try it standalone: http://localhost:8004/docs · health GET /api/v1/weather/health.
Two thin layers sit around one real upstream API. core/metar_taf_fetcher.py is a small,
key-less client with a 10 s timeout that hits /api/data/metar and /api/data/taf on
aviationweather.gov; api/routes.py exposes both as pass-through endpoints
(/metar/{icao}, /metar/{icao}/raw, /taf/{icao}, /taf/{icao}/raw) that reshape the JSON —
or hand back the raw string — without ever touching the database.
The real work happens one layer up, in core/atis_generator.py. ATISGenerator.generate()
fetches the current METAR for the requested ICAO and parses wind direction/speed/gust,
visibility, cloud layers and QNH out of the raw fields (parsing that used to live in a separate
helper module; now it's inline here, and duplicated — lightly — in routes.py's own /metar
handler). From wind alone it picks the runway: _select_runway_from_wind scores every runway
heading against the wind and keeps whichever is closest to a pure headwind. Once a runway is
chosen it picks an approach type — ILS first, then VOR, then RNAV — from a small hard-coded
AIRPORT_DATA table covering eleven Spanish airports (LEST, LEBL, LEMD, LECO, LEVX, LEGE, LEPA,
LEVC, LEAL, LEZL, LEMG); anything else falls back to a generic two-runway default. QNH drives a
five-step lookup for transition level — FL65 when pressure is high, stepping up to FL90 as QNH
drops below 978 hPa — and an in-memory counter per ICAO hands out a sequential ATIS letter with
its phonetic name ("information ALFA"), wrapping back to A after Z. ATC can override the
auto-picked runway, approach, QFE and remarks through query params on GET /atis/{icao}; a
preview=true flag runs the same generation without saving to PostgreSQL or advancing the letter —
the HMI's own /atis/generate proxy exposes that same flag to the ATC-facing form.
flowchart LR
AWX["aviationweather.gov"] --> FETCH["fetch METAR/TAF"]
FETCH --> PARSE["parse wind, vis, clouds, QNH"]
PARSE --> RWY["runway by max headwind"]
RWY --> APP["approach type + transition level"]
APP --> TXT["ATIS text + sequential letter"]
TXT --> DB[("PostgreSQL history")]
TXT --> HMI["HMI weather panel"]
TXT --> ORCH["orchestrator DEL context"]
Every non-preview call persists through ATISRepository into the atis_broadcasts table;
/atis/{icao}/latest and /atis/{icao}/history read it back. That's the only weather data this
service stores — raw METAR and TAF are fetched fresh on every call and never written to the
database.
The quiet load-bearing output here isn't the METAR, it's the runway. Because
_select_runway_from_wind runs before anything else in generate(), whichever runway wins the
headwind score becomes the arrival_runway/departure_runway baked into that ATIS broadcast, and
everything downstream reads it off the text instead of recomputing it: the DEL agent's clearance
readback names that runway, the ATIS the HMI panel and pilot agents quote is the same one, and it
holds until ATC overrides it or a fresh letter is generated. Get the runway decision wrong and the
whole session's clearances point at the wrong end of the airport.
One honest caveat: this decision doesn't reach every corner of the sim. The Arrival Simulator is currently hard-coded to LEST runway 17 geometry — spawn point, ~166° heading, the E3 vacate exit — regardless of which runway the ATIS actually selected from the wind. Only the controller-facing clearance text follows the weather; the simulated arrival traffic itself does not.
| Path | Role |
|---|---|
main.py |
FastAPI entrypoint; creates DB tables on startup |
api/routes.py |
Health, ATIS, METAR, TAF endpoints |
core/metar_taf_fetcher.py |
Thin client over aviationweather.gov (/api/data/metar, /api/data/taf) |
core/atis_generator.py |
Parses METAR, picks runway/approach/transition level, builds ATIS text |
core/database/models.py |
ATISModel → atis_broadcasts table |
core/database/repositories/atis.py |
ATIS CRUD (create, get_latest_by_icao, get_all_by_icao, ...) |
core/database/connection.py |
SQLAlchemy engine/session; check_connection backs the health check |
models/schemas.py |
Pydantic request/response schemas |
architecture · controller_hmi · orchestrator · arrival_simulator · index
Getting Started
Help
Modules
- System-Overview
- Agents
- Shared
- X-Plane
- Service-Arrival-Simulator
- Service-Asr
- Service-Controller-Hmi
- Service-Flight-Plan
- Service-Orchestrator
- Service-Weather
Internals