feat(gpsjam): GPS interference hex overlay API (GPSJAM/ADS-B Exchange) #29

Merged
sirius merged 1 commit from feat/gpsjam-interference-overlay into master 2026-08-29 17:54:02 -04:00
Owner

Summary

Adds GET /api/map/gpsjam?date=YYYY-MM-DD (default yesterday UTC) — a whole-world GPS-interference hex layer sourced from gpsjam.org (John Wiseman / ADS-B Exchange).

Data source (probed, stable)

GPSJAM publishes a daily H3 resolution-4 CSV at a stable per-date URL:
https://gpsjam.org/data/{YYYY-MM-DD}-h3_4.csv (gzip, columns hex,count_good_aircraft,count_bad_aircraft). No ADS-B Exchange scraping. Attribution preserved.

Behaviour

  • Converts each hex to a GeoJSON polygon; level = low|medium|high using GPSJAM's denoise formula 100*(bad-1)/(good+bad) (0–2% / 2–10% / >10%).
  • Whole world once, 1h in-process TTL cache. No per-pan refetch.
  • Hexes with zero bad aircraft (normal background) are dropped.
  • Malformed date → 422. Missing/empty date → {error: "unavailable", href: "https://gpsjam.org/"} (200) so the frontend shows a HUD link, not an error.
  • overlay_catalog() gains a kind=geojson gpsjam stub.
  • Adds h3>=4.0 (has cp313 manylinux aarch64 wheels — Pi-safe).

Out of scope

Leaflet styling, chokepoints, VesselAPI, nav-accuracy hexbin fallback (ADS-B.lol feed has no NACp/nic fields — skipped as allowed).

Tests

9 new mocked-HTTP tests (tests/test_gpsjam.py): level thresholds, CSV→GeoJSON (drop zero-bad, malformed rows), catalog stub, API contract (FeatureCollection, 422, unavailable paths), 1h TTL single-fetch.

Full suite: 161 passed, 16 skipped (DB integration).

## Summary Adds `GET /api/map/gpsjam?date=YYYY-MM-DD` (default yesterday UTC) — a whole-world GPS-interference hex layer sourced from gpsjam.org (John Wiseman / ADS-B Exchange). ## Data source (probed, stable) GPSJAM publishes a daily H3 resolution-4 CSV at a stable per-date URL: `https://gpsjam.org/data/{YYYY-MM-DD}-h3_4.csv` (gzip, columns `hex,count_good_aircraft,count_bad_aircraft`). No ADS-B Exchange scraping. Attribution preserved. ## Behaviour - Converts each hex to a GeoJSON polygon; `level` = `low|medium|high` using GPSJAM's denoise formula `100*(bad-1)/(good+bad)` (0–2% / 2–10% / >10%). - Whole world once, 1h in-process TTL cache. No per-pan refetch. - Hexes with zero bad aircraft (normal background) are dropped. - Malformed date → 422. Missing/empty date → `{error: "unavailable", href: "https://gpsjam.org/"}` (200) so the frontend shows a HUD link, not an error. - `overlay_catalog()` gains a `kind=geojson` `gpsjam` stub. - Adds `h3>=4.0` (has cp313 manylinux aarch64 wheels — Pi-safe). ## Out of scope Leaflet styling, chokepoints, VesselAPI, nav-accuracy hexbin fallback (ADS-B.lol feed has no NACp/nic fields — skipped as allowed). ## Tests 9 new mocked-HTTP tests (`tests/test_gpsjam.py`): level thresholds, CSV→GeoJSON (drop zero-bad, malformed rows), catalog stub, API contract (FeatureCollection, 422, unavailable paths), 1h TTL single-fetch. Full suite: 161 passed, 16 skipped (DB integration).
sirius added 1 commit 2026-08-29 14:17:14 -04:00
GET /api/map/gpsjam?date=YYYY-MM-DD (default yesterday UTC) fetches the
daily gpsjam.org H3 resolution-4 CSV, converts hexes to GeoJSON polygons,
and tags each with level low|medium|high (0-2% / 2-10% / >10%) via GPSJAM's
denoise formula. Whole world once, 1h TTL, graceful unavailable fallback.

- overlay_catalog: add kind=geojson gpsjam stub
- tests: mocked-HTTP unit + API contract (9 new)
sirius merged commit 0406eb6b7b into master 2026-08-29 17:54:02 -04:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: sirius/osint-dashboard#29
No description provided.