Split webapp for Raspberry Pi deployment, remote generation API and sync
La webapp (carte + vignettes) et la génération de tuiles se déploient sur deux machines : image légère Dockerfile.webapp (FastAPI + Pillow AVIF natif + pyproj) sur Raspberry Pi, pipeline complet sur la machine de traitement. LIDAR_GENERATION_URL délègue /api/generate, /api/preview et /api/status ; /api/sync ramène les tuiles par rsync puis régénère vignettes et index localement. Token partagé optionnel (LIDAR_API_TOKEN/LIDAR_REMOTE_TOKEN). Retire du dépôt les journaux internes (.swival, audit-findings) et les données (data/, notebooks/). Doc : docs/DEPLOY_WEBAPP.md.
This commit is contained in:
@ -96,3 +96,82 @@ def test_fetch_tiles_skips_existing_and_generated(tmp_path, monkeypatch):
|
||||
result = fetch_ign.fetch_tiles(input_dir, [(1054, 6882), (1055, 6882)],
|
||||
output_dir=output_dir)
|
||||
assert result == []
|
||||
|
||||
|
||||
def _make_viz_dirs(output_dir, col, row, viz_keys, resolutions=(0.5, 0.2)):
|
||||
"""Crée les dossiers de visualisations d'une tuile (une entrée par résolution).
|
||||
|
||||
Le suffixe de résolution n'est que sur le DOSSIER : les fichiers gardent
|
||||
le basename nu (cf. _expected_output_path dans le pipeline).
|
||||
"""
|
||||
base = f"LHD_FXX_{col:04d}_{row:04d}_PTS_LAMB93_IGN69"
|
||||
for res in resolutions:
|
||||
suffix = "" if res == 0.5 else "_r" + str(res).replace('.', 'p')
|
||||
vis = output_dir / "visualisations" / (base + suffix)
|
||||
vis.mkdir(parents=True, exist_ok=True)
|
||||
for key in viz_keys:
|
||||
(vis / f"{base}_{key}.avif").write_bytes(b"x")
|
||||
|
||||
|
||||
def test_fetch_tiles_downloads_incomplete_tile(tmp_path, monkeypatch):
|
||||
"""Une tuile incomplète (visualisation manquante) est téléchargée, une complète non."""
|
||||
from pathlib import Path
|
||||
from lidar_pipeline import fetch_ign
|
||||
|
||||
input_dir = tmp_path / "input"
|
||||
input_dir.mkdir()
|
||||
output_dir = tmp_path / "output"
|
||||
_make_viz_dirs(output_dir, 1054, 6882, ["aspect"]) # slope manquant
|
||||
_make_viz_dirs(output_dir, 1055, 6882, ["aspect", "slope"]) # complète
|
||||
|
||||
calls = []
|
||||
|
||||
def fake_find_tile_url(col, row, timeout=20):
|
||||
calls.append((col, row))
|
||||
return "https://example.org/dalle.copc.laz"
|
||||
|
||||
def fake_download(url, dest, timeout=120, chunk=1024 * 1024):
|
||||
Path(dest).write_bytes(b"laz")
|
||||
return 3
|
||||
|
||||
monkeypatch.setattr(fetch_ign, "find_tile_url", fake_find_tile_url)
|
||||
monkeypatch.setattr(fetch_ign, "download_file", fake_download)
|
||||
|
||||
result = fetch_ign.fetch_tiles(input_dir, [(1054, 6882), (1055, 6882)],
|
||||
output_dir=output_dir,
|
||||
only_viz=["aspect", "slope"],
|
||||
resolutions=(0.5, 0.2))
|
||||
# Seule la tuile incomplète est retéléchargée
|
||||
assert calls == [(1054, 6882)]
|
||||
assert [p.name for p in result] == [fetch_ign.tile_filename(1054, 6882)]
|
||||
|
||||
|
||||
def test_fetch_tiles_force_downloads_complete(tmp_path, monkeypatch):
|
||||
"""force=True télécharge même une tuile complète (régénération avec --force)."""
|
||||
from pathlib import Path
|
||||
from lidar_pipeline import fetch_ign
|
||||
|
||||
input_dir = tmp_path / "input"
|
||||
input_dir.mkdir()
|
||||
output_dir = tmp_path / "output"
|
||||
_make_viz_dirs(output_dir, 1054, 6882, ["aspect", "slope"])
|
||||
|
||||
calls = []
|
||||
|
||||
def fake_find_tile_url(col, row, timeout=20):
|
||||
calls.append((col, row))
|
||||
return "https://example.org/dalle.copc.laz"
|
||||
|
||||
def fake_download(url, dest, timeout=120, chunk=1024 * 1024):
|
||||
Path(dest).write_bytes(b"laz")
|
||||
return 3
|
||||
|
||||
monkeypatch.setattr(fetch_ign, "find_tile_url", fake_find_tile_url)
|
||||
monkeypatch.setattr(fetch_ign, "download_file", fake_download)
|
||||
|
||||
result = fetch_ign.fetch_tiles(input_dir, [(1054, 6882)],
|
||||
output_dir=output_dir,
|
||||
only_viz=["aspect", "slope"],
|
||||
resolutions=(0.5, 0.2), force=True)
|
||||
assert calls == [(1054, 6882)]
|
||||
assert len(result) == 1
|
||||
|
||||
Reference in New Issue
Block a user