dashboard — bouton live (viser natif demo.py) + PLY (fallback viser_ply)

live button:
- POST /jobs/{id}/live
- Probe le port natif (worker viser_port_base + job_id) via nc
- 200 + viser_url si demo.py encore alive (necessite le patch keep-alive)
- 410 + fallback message si ferme

PLY button:
- POST /jobs/{id}/view (existant)
- Lance viser_ply.py standalone sur port VIEWER_PORT_BASE+id

Permet de choisir entre viser natif (PointCloudViewer de lingbot-map avec
camera frustums, filtre confiance interactif, animation) et viewer basic
XYZ+RGB uniquement.
This commit is contained in:
Flag
2026-04-22 19:48:43 +00:00
parent 2bc24b2cc4
commit fa996f62d6
2 changed files with 27 additions and 1 deletions

View File

@@ -375,6 +375,31 @@ async def view_job(job_id: int):
return {"url": f"http://{worker['host']}:{port}"} return {"url": f"http://{worker['host']}:{port}"}
@app.post("/jobs/{job_id}/live")
async def live_job(job_id: int):
"""Return the URL of demo.py's native viser (PointCloudViewer with camera frustums,
confidence filtering, animation) if it's still listening. Otherwise 404 so the UI falls
back to /view (viser_ply.py standalone)."""
with closing(db()) as conn:
row = conn.execute(
"SELECT viser_url, worker_host FROM jobs WHERE id=? AND status='done'",
(job_id,),
).fetchone()
if not row or not row["viser_url"]:
raise HTTPException(404, "viser natif jamais démarré")
worker = _worker_by_host(row["worker_host"]) or WORKERS[0]
native_port = worker["viser_port_base"] + job_id
proc = await asyncio.create_subprocess_exec(
"ssh", "-o", "BatchMode=yes", "-o", "ConnectTimeout=3", worker["ssh_alias"],
f"nc -z -w2 127.0.0.1 {native_port}",
stdout=asyncio.subprocess.DEVNULL, stderr=asyncio.subprocess.DEVNULL,
)
await proc.wait()
if proc.returncode != 0:
raise HTTPException(410, "viser natif fermé — utilise le bouton PLY")
return {"url": row["viser_url"]}
@app.post("/stitches/{stitch_id}/view") @app.post("/stitches/{stitch_id}/view")
async def view_stitch(stitch_id: int): async def view_stitch(stitch_id: int):
with closing(db()) as conn: with closing(db()) as conn:

View File

@@ -23,7 +23,8 @@
<span class="prog-wrap"><span class="prog-fill" style="width:{{ j.progress }}%"></span><span class="prog-text">{{ j.progress }}%</span></span> <span class="prog-wrap"><span class="prog-fill" style="width:{{ j.progress }}%"></span><span class="prog-text">{{ j.progress }}%</span></span>
{% endif %} {% endif %}
{% if j.status == 'done' and j.ply_path %} {% if j.status == 'done' and j.ply_path %}
<button class="ext viewer-btn" data-view-url="jobs/{{ j.id }}/view">viser</button> <button class="ext viewer-btn" data-view-url="jobs/{{ j.id }}/live" title="viser natif de demo.py (camera frustums, filtre confiance) — si encore alive">live</button>
<button class="ext viewer-btn" data-view-url="jobs/{{ j.id }}/view" title="viser_ply.py standalone — toujours dispo">PLY</button>
{% endif %} {% endif %}
</span> </span>
<span class="dur">{{ j._duration }}</span> <span class="dur">{{ j._duration }}</span>