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:
@@ -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)):
|
||||
|
||||
Reference in New Issue
Block a user