mirror of
https://github.com/zvx-echo6/meshai.git
synced 2026-06-11 17:34:44 +02:00
feat(env): USGS stream gauges, TomTom traffic, 511 road conditions
This commit is contained in:
parent
ab7392c518
commit
f8bf7e5057
16 changed files with 2542 additions and 1183 deletions
|
|
@ -1,108 +1,140 @@
|
|||
"""Environmental data API routes."""
|
||||
|
||||
from fastapi import APIRouter, Request
|
||||
|
||||
router = APIRouter(tags=["environment"])
|
||||
|
||||
|
||||
@router.get("/env/status")
|
||||
async def get_env_status(request: Request):
|
||||
"""Get environmental feeds status."""
|
||||
env_store = getattr(request.app.state, "env_store", None)
|
||||
|
||||
if not env_store:
|
||||
return {"enabled": False, "feeds": []}
|
||||
|
||||
return {
|
||||
"enabled": True,
|
||||
"feeds": env_store.get_source_health(),
|
||||
}
|
||||
|
||||
|
||||
@router.get("/env/active")
|
||||
async def get_active_env(request: Request):
|
||||
"""Get active environmental events."""
|
||||
env_store = getattr(request.app.state, "env_store", None)
|
||||
|
||||
if not env_store:
|
||||
return []
|
||||
|
||||
return env_store.get_active()
|
||||
|
||||
|
||||
@router.get("/env/swpc")
|
||||
async def get_swpc_data(request: Request):
|
||||
"""Get SWPC space weather data."""
|
||||
env_store = getattr(request.app.state, "env_store", None)
|
||||
|
||||
if not env_store:
|
||||
return {"enabled": False}
|
||||
|
||||
status = env_store.get_swpc_status()
|
||||
if not status:
|
||||
return {"enabled": False}
|
||||
|
||||
return {
|
||||
"enabled": True,
|
||||
**status,
|
||||
}
|
||||
|
||||
|
||||
@router.get("/env/propagation")
|
||||
async def get_rf_propagation(request: Request):
|
||||
"""Get combined HF + UHF propagation data for dashboard."""
|
||||
env_store = getattr(request.app.state, "env_store", None)
|
||||
|
||||
if not env_store:
|
||||
return {"hf": {}, "uhf_ducting": {}}
|
||||
|
||||
return env_store.get_rf_propagation()
|
||||
|
||||
|
||||
@router.get("/env/ducting")
|
||||
async def get_ducting_data(request: Request):
|
||||
"""Get tropospheric ducting assessment."""
|
||||
env_store = getattr(request.app.state, "env_store", None)
|
||||
|
||||
if not env_store:
|
||||
return {"enabled": False}
|
||||
|
||||
status = env_store.get_ducting_status()
|
||||
if not status:
|
||||
return {"enabled": False}
|
||||
|
||||
return {
|
||||
"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"),
|
||||
}
|
||||
"""Environmental data API routes."""
|
||||
|
||||
from fastapi import APIRouter, Request
|
||||
|
||||
router = APIRouter(tags=["environment"])
|
||||
|
||||
|
||||
@router.get("/env/status")
|
||||
async def get_env_status(request: Request):
|
||||
"""Get environmental feeds status."""
|
||||
env_store = getattr(request.app.state, "env_store", None)
|
||||
|
||||
if not env_store:
|
||||
return {"enabled": False, "feeds": []}
|
||||
|
||||
return {
|
||||
"enabled": True,
|
||||
"feeds": env_store.get_source_health(),
|
||||
}
|
||||
|
||||
|
||||
@router.get("/env/active")
|
||||
async def get_active_env(request: Request):
|
||||
"""Get active environmental events."""
|
||||
env_store = getattr(request.app.state, "env_store", None)
|
||||
|
||||
if not env_store:
|
||||
return []
|
||||
|
||||
return env_store.get_active()
|
||||
|
||||
|
||||
@router.get("/env/swpc")
|
||||
async def get_swpc_data(request: Request):
|
||||
"""Get SWPC space weather data."""
|
||||
env_store = getattr(request.app.state, "env_store", None)
|
||||
|
||||
if not env_store:
|
||||
return {"enabled": False}
|
||||
|
||||
status = env_store.get_swpc_status()
|
||||
if not status:
|
||||
return {"enabled": False}
|
||||
|
||||
return {
|
||||
"enabled": True,
|
||||
**status,
|
||||
}
|
||||
|
||||
|
||||
@router.get("/env/propagation")
|
||||
async def get_rf_propagation(request: Request):
|
||||
"""Get combined HF + UHF propagation data for dashboard."""
|
||||
env_store = getattr(request.app.state, "env_store", None)
|
||||
|
||||
if not env_store:
|
||||
return {"hf": {}, "uhf_ducting": {}}
|
||||
|
||||
return env_store.get_rf_propagation()
|
||||
|
||||
|
||||
@router.get("/env/ducting")
|
||||
async def get_ducting_data(request: Request):
|
||||
"""Get tropospheric ducting assessment."""
|
||||
env_store = getattr(request.app.state, "env_store", None)
|
||||
|
||||
if not env_store:
|
||||
return {"enabled": False}
|
||||
|
||||
status = env_store.get_ducting_status()
|
||||
if not status:
|
||||
return {"enabled": False}
|
||||
|
||||
return {
|
||||
"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"),
|
||||
}
|
||||
|
||||
@router.get("/env/streams")
|
||||
async def get_streams_data(request: Request):
|
||||
"""Get USGS stream gauge readings."""
|
||||
env_store = getattr(request.app.state, "env_store", None)
|
||||
|
||||
if not env_store:
|
||||
return []
|
||||
|
||||
return env_store.get_active(source="usgs")
|
||||
|
||||
|
||||
@router.get("/env/traffic")
|
||||
async def get_traffic_data(request: Request):
|
||||
"""Get TomTom traffic flow data."""
|
||||
env_store = getattr(request.app.state, "env_store", None)
|
||||
|
||||
if not env_store:
|
||||
return []
|
||||
|
||||
return env_store.get_active(source="traffic")
|
||||
|
||||
|
||||
@router.get("/env/roads")
|
||||
async def get_roads_data(request: Request):
|
||||
"""Get 511 road conditions."""
|
||||
env_store = getattr(request.app.state, "env_store", None)
|
||||
|
||||
if not env_store:
|
||||
return []
|
||||
|
||||
return env_store.get_active(source="511")
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,17 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" class="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>MeshAI Dashboard</title>
|
||||
<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-BaC2Rd9C.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-0HCYKWnt.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>MeshAI Dashboard</title>
|
||||
<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-B6VnC_vh.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-D5w3LcwM.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue