En el artículo Primeros pasos con MicroPython y Raspberry Pi Pico, nos centramos en cómo instalar, configurar y ejecutar MicroPython en un dispositivo Raspberry Pi Pico. En este artículo, nos centraremos en automatizar ese proceso y convertirlo en un flujo de integración continua (CI). El trasladar la automatización a CI garantizará que nuestro código sea aprobado cada vez que enviemos una confirmación al repositorio de código.
Ahora que hemos visto cómo empezar con MicroPython y el dispositivo Raspberry Pi Pico, nos interesa encontrar maneras de automatizar nuestro proceso de desarrollo de código un poco más. En el artículo Introducción a MicroPython y el Raspberry Pi Pico, hemos ejecutado algunos comandos diferentes para demostrar distintos conjuntos de funcionalidades del dispositivo Raspberry Pi Pico. En este artículo vamos a ver cómo automatizar uno de esos ejemplos utilizando scripts y después colocándolo en la CI. Veamos primero el ejemplo que hemos ejecutado desde el terminal:
Este comando nos ha proporcionado la información de la instancia de la máquina. En nuestro caso:
Esto nos indica que estamos ejecutando MicroPython versión 1.19.1 en una Raspberry Pi Pico utilizando el chip RP2040. En lugar de ejecutar este comando a través de un intérprete de comandos utilizando PuTTY o Thonny IDE, podemos ejecutar todo el proceso desde la línea de comandos utilizando una herramienta que viene incluida con la biblioteca de MicroPython. La herramienta Pyboard.py nos proporciona un mecanismo para ejecutar comandos directamente en el dispositivo de destino sin abrir un intérprete de comandos (o cargar nuevos archivos directamente en la placa). Además, nos proporciona otros comandos del sistema de archivos, como crear listas y copiar archivos a/desde el dispositivo de destino. Por ejemplo, se podría ejecutar el comando sys.implementation (indicado anteriormente) utilizando la herramienta Pyboard.py de la siguiente manera:
python pyboard.py --device $TARGET_PORT --command "import sys; print(sys.implementation)"
Donde $TARGET_PORT es el puerto COM en el que aparece tu dispositivo. Esto omite el paso PuTTY/Thonny IDE y permite la automatización.
Ahora que podemos automatizar la ejecución de comandos de forma remota en nuestro dispositivo de destino, deberíamos ser capaces de incluirlo todo en un script de Python. Verás que si utilizamos la biblioteca de Pyboard, resulta bastante sencillo. En este script de Python de ejemplo ejecutamos el mismo comando anterior con algún trabajo extra (como detectar automáticamente el puerto COM y añadir algunas comprobaciones basadas en aserciones). El principio, sin embargo, es el mismo: coger la instancia de la máquina y validar lo que creemos que estamos ejecutando.
Una vez que hayamos encapsulado todo esto en un script, podemos colocarlo en un sistema CI. Como de costumbre, estoy usando Gitlab para mi implementación, pero también mi propio "runner" (ejecutor) para programar el dispositivo Raspberry Pi Pico. Puedes seguir todo el proyecto aquí, pero el archivo que nos interesa es el script .gitlab-IC.yml.. Este contiene las "instrucciones" para que las compilaciones se realicen automáticamente cada vez que hago un cambio en el código y lo devuelvo a Gitlab.
Se producen varios "trabajos", pero solo hay uno que no implica el dispositivo Raspberry Pi Pico: la etapa de construcción de Docker. Construir un contenedor Docker encapsula nuestro entorno en algo así como una máquina virtual. Si ejecuto mi trabajo de CI dentro de un contenedor Docker, puedo ejecutarlo prácticamente en cualquier lugar (mientras respete unos requisitos mínimos). En este caso, no necesito ninguna biblioteca especial instalada en mi ordenador que esté conectada a mi dispositivo de destino porque el contenedor Docker viene con todo eso. La única distinción que debo hacer aquí es que mi contenedor Docker debe ejecutarse en modo "privilegiado" (o, al menos, con permiso explícito para acceder al dispositivo de destino); de lo contrario, no podrá comunicarse con el dispositivo de destino.
Una vez construido el contenedor Docker, puedo recuperar la imagen de Gitlab cada vez que se ejecuta un trabajo y entonces empieza la diversión. Verás que mis trabajos son cada vez más abstractos y, por tanto, más complejos. Finalmente, en el último trabajo, ejecutamos todo el proceso a través del framework de Pytest.
Si has leído algunos de mis artículos anteriores, como FPGA: Creación de flujos de integración continua para sistemas embebidos o PCB, Verificación de bajo coste para filtros digitales y analógicos y Configuración de hardware en el proyecto de bucle, te darás cuenta de que soy un gran aficionado al framework de Pytest. MicroPython no es diferente en este caso y sigo usando Pytest como la forma más sencilla de validar algunos de mis scripts de Python.
El último trabajo de CI al que se llama ejecuta el script de Pytest test_rpi_pico.py. Este es casi idéntico al script rpi_pico_check.py, solo que crea un informe de prueba. Como siempre, cogemos este informe y lo enviamos a Gitlab para que lo analice y podamos obtener esa pequeña sección de prueba que muestra los resultados de aprobación:
Figura 1: Resumen de la prueba para Pytest
Esta sencilla prueba valida la información que vimos en el artículo anterior. Lo más interesante de lo que hemos hecho aquí es la automatización. Cada vez que se modifica el código, realizamos una verificación para asegurarnos de que es el dispositivo que esperamos que sea. En este caso, estamos ejecutando la versión 1.19.1 de MicroPython en un Raspberry Pi Pico utilizando el chip RP2040.
En el primer artículo arriba mencionado recordamos los pasos manuales para la comunicación con un dispositivo Raspberry Pi Pico. Luego tomamos ese proceso manual y lo convertimos en un script. Después de automatizar el proceso a través de un script, analizamos cómo integrar el flujo de trabajo en un sistema de CI para después incorporarlo con Pytest. Después de revisar los ejemplos de este artículo, deberías poder escribir tus propios scripts e, incluso, integrarlos en CI.