`pio device monitor` doesn't reconnect proactively when resetting ESP32
Original post to the community: https://community.platformio.org/t/how-can-pio-device-monitor-detect-disconnection/48477?u=riywo
I’m looking for a way to reconnect serial monitor automatically when the device is unplugged then plugged, or pushed the RST. Especially because I want to capture logs from setup(). I’m using Seeed XIAO ESP32 S3 from Windows 11.
Although pio device monitor has auto reconnection by default (#3939), it doesn’t recognize the disconnection itself until I hit any key. Once I hit a key, it tries to send the key and raises an exception, thus reconnects:
(I hit a key)
Disconnected (ClearCommError failed (PermissionError(13, 'The device does not recognize the command.', None, 22)))
Reconnecting to COM14 Connected!
I wonder whether we have a workaround or we can add a new feature to do some keepalive check proactively so that it can reconnect immediately?
I'll try to create a PR when I have a time, but please let me know if someone has already solved this problem.
I quickly analyzed the code base with a workaround (not working).
I tried a custom filter to inject a code at runtime. However, because miniterm's writer() thread blocks at console.getkey(), I couldn't stop the current terminal programmatically. (And probably serial.read() in reader() as well.)
So, probably we need to tweak Terminal not to block entirely, but it might be a larger change.
I'll also dig deeper to tweak the VSCode extension to use Microsoft's serial monitor instead since my main objective is achieving both auto-reconnection when reset and auto-disconnection (and reconnection) when upload.
import threading
import time
import sys
from platformio.public import DeviceMonitorFilterBase
class Foo(DeviceMonitorFilterBase):
NAME = "foo"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
print("Filter initialized", file=sys.stderr)
# Try a simpler thread first
self.keepalive_thread = threading.Thread(
target=self._send_keepalive,
daemon=True
)
self.keepalive_thread.start()
print(f"Thread started: {self.keepalive_thread.is_alive()}", file=sys.stderr)
def _send_keepalive(self):
"""Send periodic keepalive"""
print("Thread function started", file=sys.stderr)
alive = True
while alive:
terminal = self.get_running_terminal()
if terminal:
try:
terminal.serial.write(b'\x00')
except Exception as e:
print(f"Keepalive error: {e}", file=sys.stderr)
terminal.pio_unexpected_exception = e
terminal.stop()
alive = False
break
time.sleep(1)
Filter initialized
Thread function started
Thread started: True
--- Terminal on COM14 | 9600 8-N-1
--- Available filters and text transformations: colorize, debug, default, direct, esp32_exception_decoder, foo, hexlify, log2file, nocontrol, printable, send_on_enter, time
--- More details at https://bit.ly/pio-monitor-filters
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H
Hello, world!
Hello, world!
Hello, world!
Keepalive error: WriteFile failed (PermissionError(13, 'The device does not recognize the command.', None, 22))
# But paused here.