diff --git a/routes/meshcore.py b/routes/meshcore.py index 57f6fca..a596f25 100644 --- a/routes/meshcore.py +++ b/routes/meshcore.py @@ -48,7 +48,11 @@ def status(): } ) c = _client() - return jsonify({"available": True, "state": c.get_state().value}) + state, message = c.get_state() + payload = {"available": True, "state": state.value} + if message: + payload["message"] = message + return jsonify(payload) @meshcore_bp.route("/connect", methods=["POST"]) diff --git a/static/js/modes/meshcore.js b/static/js/modes/meshcore.js index 769978d..3551437 100644 --- a/static/js/modes/meshcore.js +++ b/static/js/modes/meshcore.js @@ -97,7 +97,8 @@ const MeshCore = (function () { function _pollUntilConnected(attempts) { if (_connected) return; - if (attempts > 15) { + if (attempts > 45) { + // Backend retry window (5+15+45s) has elapsed — give up _updateStatusUI('error', 'Connection timed out'); return; } diff --git a/utils/meshcore.py b/utils/meshcore.py index 7eb46aa..857bb3f 100644 --- a/utils/meshcore.py +++ b/utils/meshcore.py @@ -250,6 +250,7 @@ class MeshcoreClient: def __init__(self) -> None: self._state = ConnectionState.DISCONNECTED + self._status_message: str | None = None self._config: ConnectionConfig | None = None self._event_queue: queue.Queue = queue.Queue(maxsize=500) self._nodes: dict[str, MeshcoreNode] = {} @@ -261,14 +262,15 @@ class MeshcoreClient: # -- State -- - def get_state(self) -> ConnectionState: - """Return the current connection state.""" + def get_state(self) -> tuple[ConnectionState, str | None]: + """Return the current connection state and last status message.""" with self._lock: - return self._state + return self._state, self._status_message def _set_state(self, state: ConnectionState, **extra) -> None: with self._lock: self._state = state + self._status_message = extra.get("message") # Push the status event OUTSIDE the lock (avoids deadlock; _push is queue-based) payload: dict = {"state": state.value} payload.update(extra)