feat: DEM-based elevation recalculation via edit drawer button

Adds a "Recalculate from terrain map (DEM)" button to the activity edit
drawer. On click it queries an Open-Elevation-compatible API to replace
GPS altitude with SRTM terrain data, applies 5m hysteresis, and updates
the activity's elevation stats and timeseries chart in place.

- bincio/extract/dem.py: lookup_elevations() (batched HTTP POST) +
  recalculate_elevation() (subsample → DEM → interpolate → hysteresis →
  patch activity JSON, timeseries JSON, index.json)
- POST /api/activity/{id}/recalculate-elevation on both serve and edit
  servers; serve endpoint is auth-gated and triggers merge + rebuild
- --dem-url flag (also DEM_URL env var) on bincio serve and bincio edit;
  logged at startup; missing URL returns a clear 503 with setup instructions
- /api/me response gains dem_configured bool
- EditDrawer: button with loading state, shows new ↑/↓ values on success
This commit is contained in:
Davide Scaini
2026-04-20 20:45:06 +02:00
parent 872651f471
commit 1940e2409b
6 changed files with 340 additions and 1 deletions
+8
View File
@@ -24,6 +24,8 @@ console = Console()
help="Strava API client ID (enables Strava sync in the UI). Also reads STRAVA_CLIENT_ID env var.")
@click.option("--strava-client-secret", default=None, envvar="STRAVA_CLIENT_SECRET",
help="Strava API client secret. Also reads STRAVA_CLIENT_SECRET env var.")
@click.option("--dem-url", default=None, envvar="DEM_URL",
help="Base URL of an Open-Elevation-compatible API (enables 'Recalculate elevation' button).")
def edit(
data_dir: Optional[str],
port: int,
@@ -31,6 +33,7 @@ def edit(
config_path: Optional[str],
strava_client_id: Optional[str],
strava_client_secret: Optional[str],
dem_url: Optional[str],
) -> None:
"""Start a local web UI for editing activity sidecar files.
@@ -69,11 +72,16 @@ def edit(
srv.site_url = site_url
srv.strava_client_id = strava_client_id or ""
srv.strava_client_secret = strava_client_secret or ""
srv.dem_url = dem_url or ""
if strava_client_id:
console.print(f"Strava sync: [green]enabled[/green] (client {strava_client_id})")
else:
console.print("Strava sync: [yellow]disabled[/yellow] (pass --strava-client-id to enable)")
if dem_url:
console.print(f"DEM: [green]enabled[/green] ({dem_url})")
else:
console.print("DEM: [yellow]disabled[/yellow] (pass --dem-url to enable elevation recalculation)")
uvicorn.run(srv.app, host="127.0.0.1", port=port, log_level="warning")