fix: SLM control no longer shows false "Unknown error" on start

Starting a measurement could pop "Error: Unknown error" in the browser
even though the device started recording fine. Two causes: the proxy's
10s timeout was shorter than a real device start over cellular, and on
an httpx timeout str(e) is empty, so the relayed detail was "" -> the
frontend's `result.detail || 'Unknown error'` rendered "Unknown error".

- Raise the control proxy timeout to 30s so a healthy start isn't cut off.
- Surface SLMM's own error detail on non-200 responses.
- Add an explicit, honest timeout message.
- Never return an empty detail (which rendered as "Unknown error").

Pairs with the SLMM-side fix that makes /start confirm promptly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-21 20:22:52 +00:00
parent c9bb25e7e1
commit c049ac8a41
+24 -9
View File
@@ -207,24 +207,39 @@ async def control_slm(unit_id: str, action: str):
return {"status": "error", "detail": f"Invalid action. Must be one of: {valid_actions}"}
try:
async with httpx.AsyncClient(timeout=10.0) as client:
# 30s: a real device start confirms over cellular in a few seconds, but
# leave headroom so a healthy start is never cut off mid-flight (which
# surfaced to users as a misleading "Unknown error").
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.post(
f"{SLMM_BASE_URL}/api/nl43/{unit_id}/{action}"
)
if response.status_code == 200:
return response.json()
else:
return {
"status": "error",
"detail": f"SLMM returned status {response.status_code}"
}
except Exception as e:
logger.error(f"Failed to control {unit_id}: {e}")
# Surface SLMM's own error detail when it provides one.
detail = f"SLMM returned status {response.status_code}"
try:
body = response.json()
if isinstance(body, dict) and body.get("detail"):
detail = body["detail"]
except Exception:
pass
return {"status": "error", "detail": detail}
except httpx.TimeoutException:
logger.error(f"Timeout controlling {unit_id} (action={action}) via SLMM")
return {
"status": "error",
"detail": str(e)
"detail": (
f"Timed out waiting for the device to {action}. "
f"The command may still have been applied — refresh to confirm."
),
}
except Exception as e:
logger.error(f"Failed to control {unit_id}: {e}")
# Never return an empty detail — it renders to users as "Unknown error".
return {"status": "error", "detail": str(e) or f"{type(e).__name__}"}
@router.get("/config/{unit_id}", response_class=HTMLResponse)
async def get_slm_config(request: Request, unit_id: str, db: Session = Depends(get_db)):