mpremote on Mac OS X: allow env var or option in config file to select default serial port to use
I'm using Mac OS X, and I'm struggling to get mpremote to do anything more than giving me a REPL.
This is the list of devices I get when trying to connect to an ESP32 DevKitC1 board:
mpremote connect list
/dev/cu.BLTH None 0000:0000 None None
/dev/cu.Bluetooth-Incoming-Port None 0000:0000 None None
/dev/cu.usbserial-0001 0001 10c4:ea60 Silicon Labs CP2102 USB to UART Bridge Controller
Issuing mpremote connect /dev/cu.usbserial-0001 connects to the board and gives me a REPL back. But any other command (fs, run, exec...) won't work as mpremote always assume that the device is has to connect to is the first in the previous list (/dev/cu.BLTH in my case).
As mpremote CLI syntax does not seem to allow specifying both the serial port to use and the action to perform (imagine something like mpremote -D /dev/cu.usbserial-001 fs ls), would it be possible to consider a shell env var à la ampy (or minicom) to tell it what serial port to use?
tools/mpremote: Add automatic reconnection feature
Summary
This PR adds automatic reconnection capability to mpremote and makes it the default behavior. When a MicroPython device disconnects, mpremote automatically reconnects to the same device, eliminating the need to manually restart the tool during development.
Reconnection is now enabled by default. Users can opt-out via:
- The
oncecommand for per-invocation control MPREMOTE_RECONNECTenvironment variable (supports 0/1/true/false/yes/no/on, case-insensitive)- Config file setting (
reconnect = Falsein~/.config/mpremote/config.py) - Priority:
oncecommand > env var > config file > default (enabled)
Key features:
- Always reconnects to the exact same port that was previously connected when originally started in
connect automode - Always reconnects to the exact same device (on any port) when started in
connect id:abc123mode - Preserves resume state through reconnections
- Handles Windows COM port timing issues with retry logic
Usage:
# Reconnect is now the default
mpremote repl
# Disable reconnect for this invocation
mpremote once repl
# Disable via environment variable
MPREMOTE_RECONNECT=0 mpremote repl
# Disable via config file
echo "reconnect = False" >> ~/.config/mpremote/config.py
This builds on the existing disconnect handling improvements that were previously merged.
Testing
Manual testing was performed on Linux with Pyboard D and Windows 11 with ESP32S2 devices. Tests used scripted USB power cycling (via uhubctl) to simulate disconnects and verify reconnection behavior. Testing covered default auto-reconnect, the once command opt-out, environment variable control (including priority override behavior where once takes precedence over MPREMOTE_RECONNECT=1), auto mode port-specific reconnection, ID mode device tracking across port changes, multiple device scenarios, resume state preservation, and environment variable parsing with various formats.
Trade-offs and Alternatives
Making reconnect the default is a breaking change for scripts that expect mpremote to exit on disconnect. These scripts will need to use the once command or set MPREMOTE_RECONNECT=0. However, the new default is more intuitive for the primary use case (interactive development).
Design decisions:
- Default changed based on maintainer feedback
- Always reconnects to the exact same port (even in auto mode) rather than any available device, prioritizing safety in multi-device environments
- Added retry logic with delays specifically for Windows COM port timing issues
- Multiple opt-out mechanisms with clear priority order provide flexibility for different use cases
oncecommand takes highest priority as it's the most explicit user intention
The code size increase from the reconnect logic is justified by the significant improvement in developer workflow.