feat(env): NIFC fire perimeters + avalanche advisories

- WFIGS ArcGIS fire perimeter polling with proximity alerts
- Avalanche.org advisory polling (seasonal, SNFAC)
- !fire and !avy commands
- Distance-based severity for fires near mesh infrastructure
- Dashboard environment page integration
- Alert engine fires on fires within 50km of mesh area

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
zvx-echo6 2026-05-12 15:22:07 -06:00
commit 2255ca5803
15 changed files with 1013 additions and 93 deletions

View file

@ -75,3 +75,34 @@ async def get_ducting_data(request: Request):
"enabled": True,
**status,
}
@router.get("/env/fires")
async def get_fires_data(request: Request):
"""Get active wildfire perimeters."""
env_store = getattr(request.app.state, "env_store", None)
if not env_store:
return []
return env_store.get_active(source="nifc")
@router.get("/env/avalanche")
async def get_avalanche_data(request: Request):
"""Get avalanche advisories."""
env_store = getattr(request.app.state, "env_store", None)
if not env_store:
return {"off_season": True, "advisories": []}
adapters = getattr(env_store, "_adapters", {})
avy_adapter = adapters.get("avalanche")
if avy_adapter and avy_adapter.is_off_season():
return {"off_season": True, "advisories": []}
return {
"off_season": False,
"advisories": env_store.get_active(source="avalanche"),
}

View file

@ -8,8 +8,8 @@
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
<script type="module" crossorigin src="/assets/index-Hvb4qZ75.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-B5wp_1Dg.css">
<script type="module" crossorigin src="/assets/index-BaC2Rd9C.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-0HCYKWnt.css">
</head>
<body>
<div id="root"></div>