fix: disable buggy library auto-reconnect, handle reconnection ourselves

meshcore 2.3.0's ConnectionManager has a bug: when auto-reconnect creates
a new TCP connection, the old connection's connection_lost callback fires,
triggering another reconnect cycle. Since each success resets the attempt
counter, this loops forever (~1 TCP connection/second).

Disabled library auto_reconnect and added reconnection logic to
_on_disconnected() with 3 attempts and increasing backoff (5/10/15s).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
MarekWo
2026-03-23 21:31:45 +01:00
parent dfc3b1403a
commit 1684f9f3ff

View File

@@ -149,14 +149,19 @@ class DeviceManager:
self.mc = await MeshCore.create_tcp(
host=self.config.MC_TCP_HOST,
port=self.config.MC_TCP_PORT,
auto_reconnect=self.config.MC_AUTO_RECONNECT,
# Disable library auto-reconnect — it has a bug where old
# connection's close callback triggers infinite reconnect loop.
# We handle reconnection ourselves in _on_disconnected().
auto_reconnect=False,
)
else:
port = self._detect_serial_port()
logger.info(f"Connecting via serial: {port}")
self.mc = await MeshCore.create_serial(
port=port,
auto_reconnect=self.config.MC_AUTO_RECONNECT,
# Disable library auto-reconnect — same bug as TCP.
# We handle reconnection ourselves in _on_disconnected().
auto_reconnect=False,
)
# Read device info
@@ -953,7 +958,7 @@ class DeviceManager:
logger.error(f"Error handling new contact: {e}")
async def _on_disconnected(self, event):
"""Handle device disconnection."""
"""Handle device disconnection with auto-reconnect."""
logger.warning("Device disconnected")
self._connected = False
@@ -962,6 +967,25 @@ class DeviceManager:
'connected': False,
}, namespace='/chat')
# Auto-reconnect with backoff
for attempt in range(1, 4):
delay = 5 * attempt
logger.info(f"Reconnecting in {delay}s (attempt {attempt}/3)...")
await asyncio.sleep(delay)
try:
await self._connect()
if self._connected:
logger.info("Reconnected successfully")
if self.socketio:
self.socketio.emit('device_status', {
'connected': True,
}, namespace='/chat')
return
except Exception as e:
logger.error(f"Reconnect attempt {attempt} failed: {e}")
logger.error("Failed to reconnect after 3 attempts")
# ================================================================
# Command Methods (sync — called from Flask routes)
# ================================================================