Josverl / micropython-stubber

Generate and maintain stubs for different MicroPython ports to use with VSCode and Pylance, PyRight, Thonny, PyCharm or MyPy
https://micropython-stubber.readthedocs.io
Other
180 stars 13 forks source link

mpflash: non-zero return code to indicate no device found #585

Open DavesCodeMusings opened 5 months ago

DavesCodeMusings commented 5 months ago

Is your feature request related to a problem? Please describe.

I would like to automate unattended downloading and flashing of firmware. But, it is difficult to use mpflash list to programatically determine if a microcontroller device is attached. Ideally, if no device is found, the script would exit right away rather than continue with an attempt to download and flash for a non-existent device.

Describe the solution you'd like

Currently the return code from mpflash list is always zero, no matter if a device is found or not. Having a non-zero return code when nothing is found would help a script determine if it should continue or exit.

For example:

mpflash list
if [ $? -ne 0 ]; then
  echo "No device found. Exiting."
  exit 1
else
  mpflash download
  mpflash flash
fi

Describe alternatives you've considered

Scraping lines of stdout might work, but it seems clumsy at best.

Additional context

With microcontroller board attached (return code is 0):

$ mpflash list ; echo $?

                 Connected boards
┏━━━━━━━┳━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┓
┃Ser.   ┃Fam.┃Board                      ┃Version┃
┡━━━━━━━╇━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━┩
│ttyUSB0│upy │ESP32_GENERIC_C3           │v1.23.0│
│       │    │ESP32C3 module with ESP32C3│       │
└───────┴────┴───────────────────────────┴───────┘
0

With no microcontroller board attached (return code is still 0):

$ mpflash list ; echo $?

    Connected boards
┏━━━━┳━━━━┳━━━━━┳━━━━━━━┓
┃Ser.┃Fam.┃Board┃Version┃
┡━━━━╇━━━━╇━━━━━╇━━━━━━━┩
└────┴────┴─────┴───────┘
0

Ideally, the second case would be a non-zero return code to indicate no board was found.

Josverl commented 5 months ago

Currently the exit code is used to indicate success ( 0) or an unrecoverable error.

I think its simpler, and has more flexibility to use --json output, and filter / count that with the [jq]() utility.

`mpflash list --json | jq '. | length'``

ref: https://jqlang.github.io/jq/manual/#length

No devices attached (windows):

$DEVCOUNT=$(mpflash list --json | jq '. | length')
echo $DEVCOUNT
0

Multiple devices attached (lnx)

DEVCOUNT=$(mpflash list --json | jq '. | length')
echo $DEVCOUNT
7

The count of specific devices, such as having a specific port or CPU

DavesCodeMusings commented 5 months ago

That could work. Thanks!

Though I just found out jq is not part of the base packages installed on the Raspberry Pi OS I'm wanting to automate for. So, a simpler way to find out if devices were attached or not would still be a "nice to have" feature.

Josverl commented 5 months ago

I have a quick PoC and would like your feedback:

:~/projects/micropython-stubber$ mpflash list ; echo $?

                                  Connected boards                                   
┏━━━━━━━┳━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━┓
┃Serial ┃Family     ┃Port   ┃Board                              ┃CPU        ┃Version┃
┡━━━━━━━╇━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━┩
│ttyACM0│micropython│stm32  │PYBV11                             │STM32F405RG│v1.23.0│
│       │           │       │PYBv1.1 with STM32F405RG           │           │       │
│ttyACM1│micropython│rp2    │RPI_PICO                           │RP2040     │v1.23.0│
│       │           │       │Raspberry Pi Pico with RP2040      │           │       │
│ttyACM2│micropython│rp2    │RPI_PICO_W                         │RP2040     │v1.23.0│
│       │           │       │Raspberry Pi Pico W with RP2040    │           │       │
│ttyACM3│micropython│samd   │SEEED_WIO_TERMINAL                 │SAMD51P19A │v1.23.0│
│       │           │       │Wio Terminal D51R with SAMD51P19A  │           │       │
│ttyUSB0│micropython│esp32  │ESP32_GENERIC                      │ESP32      │v1.23.0│
│       │           │       │Generic ESP32 module with ESP32    │           │       │
│ttyUSB1│micropython│esp8266│ESP8266_GENERIC                    │ESP8266    │v1.23.0│
│       │           │       │ESP module with ESP8266            │           │       │
│ttyUSB2│micropython│esp32  │ESP32_GENERIC_C3                   │ESP32C3    │v1.23.0│
│       │           │       │ESP32C3 module with ESP32C3        │           │       │
│ttyUSB3│micropython│esp32  │ESP32_GENERIC_S3                   │ESP32S3    │v1.23.0│
│       │           │       │Generic ESP32S3 module with ESP32S3│           │       │
└───────┴───────────┴───────┴───────────────────────────────────┴───────────┴───────┘
8

or with no boards connected:

mpflash list ; echo $?

No connected MCUs found.
0

However if I pass in a malformed command you get the error code assigned by the click cli project.

~/projects/micropython-stubber$ mpflash foobar ; echo $?
14:34:54 | ❌ Error: No such command 'foobar'.
255

I've not yet found a way to change the click errors into negative values or similar

I'm not sure if this would be useful , as there is no way to distinguish between a click error code or the number of attached/flashed mcus

what do you think ?

DavesCodeMusings commented 4 months ago

Sorry to take so long for a reply. I agree it's tough to tell what is a valid return code (as in a count) and what's an error (like your "no such command" 255 example.)

I'm not dead set on a return code. What would you think about another command-line option, similar to --json, that would remove all formatting from the output. For example, mpflash list --summary, or mpflash list --sparse (or whatever you want to call it) that would list each board's info concisely on a single line.

Output could be space or tab separated with no header and no separator lines, something like what's shown below:

ttyUSB0 micropython esp32   ESP32_GENERIC   ESP32   v1.23.0
ttyUSB1 micropython esp8266 ESP8266_GENERIC ESP8266 v1.23.0

Then to get a count of devices, it would just be a matter of counting lines in stdout.

Josverl commented 4 months ago

Why prefer this over installing the jq tool?

This will take me more time to create than it will save, And in the end it will still sometimes throw an error which will generate some lines of output.

So I'm still not sold on the value it provides.

DavesCodeMusings commented 4 months ago

I was thinking of the case of not having access to install packages on the machine. All of the Python stuff can be installed by a regular unprivileged user. Installing the jq package requires sudo privs.

As far as errors generating output, I assume that would go to stderr and not stdout.

Josverl commented 4 months ago

That would also mean that those users cannot flash several ports, such as stm32 and uf2 devices as these require sudo/root permissions as some point to add mount or udev rules. Effectively leaving the Esp ports, for which there are many different wrappers of esptool of various quality already.

So feel free to create a PR, but I see very little value in this approach.