Merge pull request 'Weather backend: NWS active alerts + nearest-METAR wind, cached (Refs #237)' (#263) from feat/237-weather-api into main
This commit was merged in pull request #263.
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
"""Weather context for the map (server-26#237): NWS alerts + nearest-METAR wind.
|
||||
|
||||
Public-domain US Government data, cached server-side in app/internal/weather.py;
|
||||
no licence gate (unlike 511NY / outage providers).
|
||||
"""
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Query
|
||||
|
||||
from app.internal import weather
|
||||
|
||||
router = APIRouter(prefix="/weather", tags=["weather"])
|
||||
|
||||
|
||||
@router.get("/alerts")
|
||||
async def get_alerts(
|
||||
south: Optional[float] = Query(None, ge=-90, le=90),
|
||||
west: Optional[float] = Query(None, ge=-180, le=180),
|
||||
north: Optional[float] = Query(None, ge=-90, le=90),
|
||||
east: Optional[float] = Query(None, ge=-180, le=180),
|
||||
):
|
||||
"""Active NWS alerts with polygons, optionally filtered to those intersecting a bbox.
|
||||
|
||||
``zone_only`` holds alerts whose zones could not be resolved to a polygon; it
|
||||
is never bbox-filtered (there is no shape to test) and never dropped.
|
||||
"""
|
||||
box = (south, west, north, east)
|
||||
if any(v is not None for v in box) and any(v is None for v in box):
|
||||
raise HTTPException(400, "give all of south, west, north, east or none")
|
||||
if south is not None and (south > north or west > east):
|
||||
raise HTTPException(400, "bbox must satisfy south<=north and west<=east")
|
||||
feed = await weather.alerts.get()
|
||||
items = feed.alerts
|
||||
if south is not None:
|
||||
items = [a for a in items if weather.intersects(a.get("bbox"), south, west, north, east)]
|
||||
return {
|
||||
"alerts": items,
|
||||
"zone_only": feed.zone_only,
|
||||
"fetched_at": feed.fetched_at,
|
||||
"error": feed.error,
|
||||
"credit": weather.CREDIT,
|
||||
}
|
||||
|
||||
|
||||
@router.get("/wind")
|
||||
async def get_wind(
|
||||
lat: float = Query(..., ge=-90, le=90),
|
||||
lon: float = Query(..., ge=-180, le=180),
|
||||
):
|
||||
"""Wind from the nearest METAR station, or ``available: false`` with a reason."""
|
||||
return await weather.nearest_wind(lat, lon)
|
||||
Reference in New Issue
Block a user