40 lines
1.3 KiB
Python
40 lines
1.3 KiB
Python
"""Bounded vessel snapshot APIs for viewport-first consumers."""
|
|
|
|
from typing import Optional
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.api.v1.visualization import _parse_bbox, build_vessel_snapshot_response
|
|
from app.db.session import get_db
|
|
from app.services.vessel_ais_aggregation import MAX_SNAPSHOT_LIMIT
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/snapshot")
|
|
async def get_vessel_snapshot(
|
|
bbox: Optional[str] = Query(None, description="Viewport bbox as lon_min,lat_min,lon_max,lat_max"),
|
|
zoom: int = Query(..., ge=1, le=20, description="Current map zoom level"),
|
|
type: Optional[str] = Query(
|
|
None,
|
|
description="Comma-separated vessel types: cargo,tanker,passenger,fishing,military,other",
|
|
),
|
|
limit: int = Query(1000, ge=1, le=MAX_SNAPSHOT_LIMIT),
|
|
since_minutes: int = Query(60, ge=1, le=1440),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
if not bbox:
|
|
raise HTTPException(status_code=400, detail="bbox is required")
|
|
parsed_bbox = _parse_bbox(bbox)
|
|
if parsed_bbox is None:
|
|
raise HTTPException(status_code=400, detail="bbox is required")
|
|
return await build_vessel_snapshot_response(
|
|
db,
|
|
bbox=parsed_bbox,
|
|
zoom=zoom,
|
|
type_filter=type,
|
|
limit=limit,
|
|
since_minutes=since_minutes,
|
|
)
|