File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -312,12 +312,17 @@ async def body() -> AsyncIterator[bytes]:
312312 "text" : f"Using MeshCore { fw ['tag' ]} ({ fw ['flavor' ]} )." ,
313313 })
314314
315- released = source is not None and source .connected
315+ # Always stop a matched source before esptool — even when
316+ # handshake failed, background reconnect still races the port.
317+ released = source is not None
316318 if released :
317319 yield _ndjson ({
318320 "type" : "line" ,
319321 "stream" : "stdout" ,
320- "text" : f"Releasing { port } ({ source .name } was connected)…" ,
322+ "text" : (
323+ f"Releasing { port } ({ source .name } "
324+ f"{ '' if source .connected else ' reconnect loop' } )…"
325+ ),
321326 })
322327 await source .stop ()
323328
@@ -350,7 +355,8 @@ async def body() -> AsyncIterator[bytes]:
350355 "stream" : "stdout" ,
351356 "text" : "Waiting for the board to finish rebooting…" ,
352357 })
353- await asyncio .sleep (3.0 )
358+ # ESP32-S3 USB companions often need >3s after flash.
359+ await asyncio .sleep (10.0 )
354360 await source .start ()
355361 yield _ndjson ({
356362 "type" : "line" ,
Original file line number Diff line number Diff line change @@ -330,12 +330,17 @@ async def body() -> AsyncIterator[bytes]:
330330 "text" : f"Using Meshtastic { fw ['version' ]} ({ fw ['mcu' ]} )." ,
331331 })
332332
333- released = source is not None and source .connected
333+ # Always stop a matched source before esptool — reconnect /
334+ # half-open serial still races the port when connected=False.
335+ released = source is not None
334336 if released :
335337 yield _ndjson ({
336338 "type" : "line" ,
337339 "stream" : "stdout" ,
338- "text" : f"Releasing { port } ({ source .name } was connected)…" ,
340+ "text" : (
341+ f"Releasing { port } ({ source .name } "
342+ f"{ '' if source .connected else ' reconnect loop' } )…"
343+ ),
339344 })
340345 await source .stop ()
341346
Original file line number Diff line number Diff line change @@ -71,6 +71,11 @@ def __init__(
7171 def name (self ) -> str :
7272 return "meshcore_usb"
7373
74+ @property
75+ def connected (self ) -> bool :
76+ """True while the MeshCore companion serial session is live."""
77+ return self ._connected
78+
7479 @property
7580 def is_running (self ) -> bool :
7681 return self ._running
Original file line number Diff line number Diff line change @@ -149,5 +149,18 @@ def test_erase_flag_omitted_from_cmd_when_false(self):
149149 self .assertIn ("--erase-all" , args )
150150
151151
152+ class TestMeshcoreSourceConnectedProperty (unittest .TestCase ):
153+ """Flash stream uses source.connected; SerialSource already exposes it."""
154+
155+ def test_meshcore_usb_exposes_connected (self ):
156+ from src .capture .meshcore_usb_source import MeshcoreUsbCaptureSource
157+ from src .config import MeshcoreUsbConfig
158+
159+ source = MeshcoreUsbCaptureSource (MeshcoreUsbConfig ())
160+ self .assertFalse (source .connected )
161+ source ._connected = True
162+ self .assertTrue (source .connected )
163+
164+
152165if __name__ == "__main__" :
153166 unittest .main ()
You can’t perform that action at this time.
0 commit comments