Sistema de desarrollo e integración continua Over-The-Air para microcontroladores IoT
Abstract
Este Trabajo de Fin de Grado busca desarrollar un sistema de integración continua OTA para dispositivos IoT. El objetivo es garantizar la actualización, de manera automática, de los dispositivos en el momento que se produzca el lanzamiento de nuevas versiones de firmware. El sistema consta de los microcontroladores ESP32 que hacen de dispositivos IoT y una Raspberry Pi 4 que actúa como nodo central. La conexión se efectua mediante una red WiFi para proporcionar la comunicación local entre los dispositivos asi como conexión con los servidores que almacenen el versionado del firmware. El trabajo realizado demuestra que el sistema es eficaz a la hora de actualizarse Over-The-Air tanto con o sin la intervención de un usuario.
Full text
Equation Chapter 1 Section 1 Trabajo Fin de Grado Grado en Ingeniería de las Tecnologías de Telecomunicación Sistema de desarrollo e integración continua Over-The-Air para microcontroladores IoT Autor: Pablo García Ortega Tutor: Samuel Yanes Luis Dpto. Ingeniería Electrónica Escuela Técnica Superior de Ingeniería Universidad de Sevilla Sevilla, 2025
iii Trabajo Fin de Grado en Ingeniería de las Tecnologías de Telecomunicación Sistema de desarrollo e integración continua OverThe-Air para microcontroladores IoT Autor: Pablo García Ortega Tutor: Samuel Yanes Luis Profesor Sustituto Interino Dpto. Ingeniería Electrónica Escuela Técnica Superior de Ingeniería Universidad de Sevilla Sevilla, 2025
v Trabajo Fin de Grado: Sistema de desarrollo e integración continua Over-The-Air para microcontroladores IoT Autor: Pablo García Ortega Tutor: Samuel Yanes Luis El tribunal nombrado para juzgar el Proyecto arriba indicado, compuesto por los siguientes miembros: Presidente: Vocales: Secretario: Acuerdan otorgarle la calificación de: Sevilla, 2025 El Secretario del Tribunal
vii A mi familia A mis maestros
ix Agradecimientos A mi familia, por estar a mi lado en todo momento. A Marta por animarme a seguir. A Samuel por poder colaborar con él en este proyecto. Pablo García Ortega Sevilla, 2025
ÍNDICE DE TABLAS Tabla 1. Capas del modelo OSI 3 Tabla 2. Arquitectura del proyecto 9 Tabla 3. Proceso actualización OTA 16 Tabla 4. Endpoints de la API REST del microcontrolador 18 Tabla 5. Endpoints de la API REST del nodo central 19
xvii ÍNDICE DE FIGURAS Figura 1. Arquitectura de la red 1 Figura 2. ESP32 WROOM 32 2 Figura 3. ATMEL 2560 2 Figura 4. Sensor estacionamiento 4 Figura 5. Sensores IoT para domótica 4 Figura 6. Esquema de la integración completa 8 Figura 7. Configuración del IDE para ESP32 13 Figura 8. PlatformIO Build y Upload 13 Figura 9. Diagrama de bloques de los modulos del firmware 14 Figura 10. Esquema actualización OTA 15 Figura 11. Diagrama de flujo actualizacion OTA por web 17 Figura 12. Configuración del dominio en Cloudflare 20 Figura 13. Estructura de ficheros del nodo central 21 Figura 14. Descubrimiento servicios mDNS 23 Figura 15. Leer los pines del ESP32 24 Figura 16. Peticion POST a /write con curl 25 Figura 17. Encendido del led tras poner el pin 14 a 1 25 Figura 18. Obtención de la version del firmware del ESP32 26 Figura 19. Web configuración Actualización OTA 26 Figura 20. Actualizando firmware por OTA usando la web 26 Figura 21. Crear rama y hacer commit para nueva versión 27 Figura 22. Nuevo tag y exito del pipeline de creacion de la build 27 Figura 23. Artefacto del nuevo firmware 28 Figura 24. Descargar ultimo firmware desde Gitlab 28 Figura 25. Listado de todos los ESP32 en la web 29 Figura 26. Ver versión del firmware en la web 30 Figura 27. Ver estado de pines en la interfaz web 31 Figura 28. Cambio de estado de pin usando la web 32 Figura 29. Seleccionar el firmware para actualizar via web 32 Figura 30. Firmware actualizado correctamente a traves de la web 33 Figura 31. Comprobar los containers desplegados en el nodo central 34 Figura 32. Descargar el ultimo firmware al nodo central 34 Figura 33. Actualización de todos los dispositivos IoT desde el nodo central 35
1 INTRODUCCIÓN os sistemas basados en Internet of Things (IoT) han experimentado un crecimiento exponencial en la última década, impulsados por la necesidad de optimizar el control y la gestión de entornos industriales, comerciales y residenciales [1]. En 2023 existían 15.900 millones de dispositivos IoT funcionando globalmente, y está proyectado superar los 32.100 millones en 2030 [2]. Este aumento en el uso de dispositivos IoT se debe a que los microcontroladores son dispositivos pequeños, potentes, de bajo consumo y con una conectividad (WiFi, BLE, 5G) [3], haciendolos útiles en multiples ámbitos. El objetivo principal de este Trabajo de Fin de Grado es desarrollar e implementar un sistema de actualización remota y automática sin necesidad de conexión física al dispositivo IoT (ver figura 1). A la vez que se proporciona una interfaz para descubrir los dispositivos conectados a la red local para actualizaciones Over-The-Air (OTA). Figura 1. Arquitectura de la red 1.1 Que son los sistemas embebidos: microcontroladores y sus usos Los sistemas embebidos constituyen la base tecnológica de la automatización moderna, integrando hardware especializado y software optimizado para ejecutar tareas específicas en dispositivos que abarcan desde electrodomésticos inteligentes hasta sistemas robóticos industriales. En este ecosistema, los microcontroladores emergen como componentes críticos, mientras que los circuitos integrados WiFi habilitan capacidades de conectividad avanzadas. L El software es un gran arte, siempre puede ser mejorado. - Bill Gates -
Introducción 2 1.1.1 Qué son los microcontroladores Un microcontrolador (ver figuras 2 y 3) es un circuito integrado que consolida en un único chip una unidad central de procesamiento (CPU), memoria de acceso aleatorio (RAM), memoria no volátil (ROM/Flash), y periféricos de entrada/salida (E/S). A diferencia de los microprocesadores de propósito general, estos dispositivos están diseñados para aplicaciones embebidas donde la eficiencia energética, el costo reducido y la integración física son prioritarios [4] [5]. 1.1.1.1 Arquitectura interna y componentes clave La arquitectura típica de un microcontrolador IoT con circuito WiFi integrado tiene una CPU potente, debido a la sobrecarga computacional que genera una pila TCP/IP completa. Por ello es necesario utilizar microcontroladores como los basados en arquitecturas ARM Cortex-M (ej. STM32F4) o RISCV (ej. ESP32-C3). Los microcontroladores también disponen de memorias integradas como la RAM para almacenar datos de acceso rápido (ej. 520 KB en ESP32-WROOM-32) o la memoria flash que almacena firmware y configuraciones (ej. 4 MB en ESP32-WROOM-32) [6]. Se dispone también de periféricos especializados tales como: • Conversores analógico-digitales (ADC). Permiten leer señales analógicas, como la salida de un sensor de temperatura, y convertirlas en valores digitales que puede procesar el microcontrolador. • GPIOs, son los pines de entrada/salida del microcontrolador que pueden usarse, por ejemplo, para activar o desactivar relés que permiten encender o apagar luces de manera remota o automatizada. • PWM. Generan señales moduladas que permiten regular la velocidad de un motor o la intensidad de un LED. • SPI/I2C. Son interfaces de comunicación que permiten conectar el microcontrolador con dispositivos externos como sensores de temperatura, memorias o pantallas. Estos componentes permiten a los microcontroladores interactuar directamente con el entorno físico mediante sensores y actuadores, procesar datos localmente, y tomar decisiones autónomas sin dependencia de sistemas externos [5]. 1.1.2 Circuito integrado WiFi en IoT Los circuitos integrados WiFi para IoT, como el ESP32 de Espressif Systems, integran capacidades de conectividad inalámbrica siguiendo el modelo OSI (Open Systems Interconnection), permitiendo la interoperabilidad con redes IP [7] [8]. Figura 3. ATMEL 2560 Figura 2. ESP32 WROOM 32
3 3 Sistema de desarrollo e integración continua Over-The-Air para microcontroladores IoT 1.1.2.1 Capas del modelo OSI en Comunicaciones IoT El modelo OSI es un marco conceptual universal que describe cómo los datos se transfieren a través de una red, dividiendo la comunicación en siete capas independientes (Ver tabla 1). Este modelo se aplica como referencia en la mayoría de los sistemas de comunicación de red, aunque la implementación concreta de cada capa puede variar según la tecnología inalámbrica utilizada y el microcontrolador específico. Capa OSI Función principal Ejemplo en ESP32 (WiFi/BLE) Física (1) Transmisión y recepción de bits por el medio físico (radio, cable, etc.) Modulación de señales en 2.4 GHz (WiFi 802.11 b/g/n, BLE 2.4 GHz) Enlace (2) Organización de datos en tramas, control de acceso al medio, corrección de errores Protocolo MAC 802.11, controlador de enlace BLE Red (3) Enrutamiento de paquetes, direccionamiento IP Soporte de IPv4/IPv6; BLE suele usar direccionamiento propio Transporte (4) Comunicación extremo a extremo, control de flujo y errores TCP/UDP; L2CAP (BLE) Sesión (5) Gestión de sesiones de comunicación Manejada por protocolos de aplicación (MQTT, HTTP, etc.) Presentación (6) Traducción, cifrado y compresión de datos Cifrado TLS/SSL, codificación de datos Aplicación Interfaz directa con el usuario o aplicación, protocolos de alto nivel HTTP, MQTT, CoAP, WebSocket, etc. Tabla 1. Capas del modelo OSI
Introducción 4 1.1.2.2 Ventajas de la Integración WiFi en Microcontroladores La integración de WiFi en SoCs (System-on-Chip) como el ESP32 elimina la necesidad de modulos externos que auementarian tanto el coste como el tamaño [9]. Esto ha impulsado su adopción en aplicaciones como sensores de estacionamiento inteligente (ver figura 4) que reportan disponibilidad mediante APIs REST (Representational State Transfer) [10]. Figura 4. Sensor estacionamiento 1.2 Raspberry Pi (Rpi): Qué es y cómo se utiliza en IoT La RPi es un sistema embebido de placa única, compacto y de bajo coste, diseñado originalmente para enseñar informatica y programación, pero que se ha convertido en una plataforma muy popular para proyectos IoT, automatización y prototipado Avanzado [11]. Gracias a su potencia y versatilidad, la RPi se emplea frecuentemente como hub domótico, permitiendo controlar luces, sensores (ver figura 5) y electrodomésticos inteligentes desde una única plataforma centralizada. Figura 5. Sensores IoT para domótico
5 5 Sistema de desarrollo e integración continua Over-The-Air para microcontroladores IoT 1.2.1 Qué es la Rpi A diferencia de los microcontroladores tradicionales, la Rpi funciona como un miniordenador completo: integra un microprocesador, memoria RAM (desde 512 MB hasta 8 GB según el modelo), almacenamiento mediante tarjeta microSD, y múltiples puertos de entrada/salida como USB, HDMI, Ethernet, además de conectividad inalámbrica (WiFi y Bluetooth en la mayoría de los modelos recientes) [12]. Esto le permite ejecutar sistemas operativos basados en Linux (como Raspberry Pi OS), facilitando el desarrollo de aplicaciones complejas y el uso de lenguajes de programación como Python, C++ o Java [11]. 1.2.1.1 Arquitectura y components clave Las diferentes versions de RPi emplean procesadores ARM de 32 o 64 bits y RAM con suficiente potencia para tareas de procesamiento de datos, vision artificial o servidores web. Utiliza una tarjeta microSD para el sistema operativo y los datos, lo que facilita la actualización y el respaldo del software. Dispone de puertos USB para periféricos, HDMI para video, Ethernet y/o WiFi para red, y pines GPIO para interactuar con sensores, actuadores y otros dispositivos electrónicos. 1.3 El problema a resolver: programación remota de los microcontroladores Uno de los principales problemas de los sistemas IoT es su gestión, especialmente cuando se trata de dispositivos desplegados en grandes cantidades y ubicados en zonas de difícil acceso. A medida que las implementaciones IoT aumentan en escala, la actualización y mantenimiento de estos dispositivos se convierte en un desafío significativo [14]. Las actualizaciones de firmware son esenciales para corregir errores, solucionar vulnerabilidades de seguridad o añadir nuevas funcionalidades durante la vida útil de un dispositivo conectado [15]. Sin embargo, cuando los dispositivos están instalados en lugares remotos o de difícil acceso, el acceso físico resulta costoso o incluso imposible [16]. Este problema se magnifica por las limitaciones inherentes a muchos dispositivos IoT: restricciones de memoria, capacidad de batería y ancho de banda disponible, lo que complica aún más el proceso de actualización [15]. Además, la falta de mecanismos de actualización estandarizados puede conducir a prácticas de seguridad deficientes [17]. Todo esto hace que la actualización manual directa muchas veces sea imposible y que no haya forma de conectarse físicamente al dispositivo con un ordenador para actualizar el firmware utilizando programas especializados como JTAG [18]. De la necesidad de actualizar remotamente los dispositivos nace las actualizaciones OTA. 1.3.1 Programación remota y la necesidad de OTA (Over-The-Air) Las actualizaciones OTA permiten la distribución inalámbrica de firmware actualizado a todos los dispositivos de un sistema IoT, incluso aquellos ubicados en lugares de difícil acceso [16]. Para proporcionar este tipo de actualizaciones el dispositivo IoT permite la carga de forma inalámbrica de un nuevo firmware. Esto implica que dispone de el del hardware necesario para proporcionar conectividad inalámbrica y de un software adecuado para permitir la subida y posterior carga en el dispositivo del nuevo firmware. Existen dos aproximaciones diferentes a la hora de abordar el proceso de actualización OTA: 1. Actualización OTA de partición única: Implica actualizar directamente el firmware para reemplazar la versión existente. Aunque es simple de implementar, puede generar tiempos de inactividad significativos durante la instalación y presenta riesgos si la actualización falla [19]. 2. Actualización OTA de partición dual A/B: Utiliza dos particiones que pueden almacenar independientemente diferentes versiones del firmware, ofreciendo mayor seguridad al mantener siempre una versión funcional del sistema [19]. Este mecanismo se fundamenta en la duplicación de las particiones críticas del sistema (como boot y system) [20]
Introducción 6 1.4 Objetivos del Proyecto y requisitos El objetivo del Proyecto es crear un sistema de integración continua donde los nuevos firmwares desarrollados se compilen en la nube y sean usados por un nodo central para actualizar OTA y de manera automatica los microcontroladores. A su vez que creamos una interfaz web para que un usuario pueda conectarse y realizar operaciones manuals sobre los ESP32. Para realizar esto tendremos requisitos que deben implementarse en el microcontrolador, otros en la Rpi y otros en el gestor de repositorios. Los requisitos son los siguientes: • Publicación de los servicios del microcontrolador mediante mDNS: Este requisito se centra en la capacidad de los dispositivos ESP32 de anunciar los servicios que ofrecen dentro de una red local, utilizando el protocolo mDNS (Multicast DNS). mDNS permite que los dispositivos se descubran entre sí en la red sin necesidad de un servidor DNS centralizado. • Requisito de lectura de pines: Este requisito establece la necesidad de poder consultar el estado actual de los pines de entrada/salida digital del microcontrolador ESP32 a través de la red. Esto permite monitorizar remotamente el estado de sensores o interruptores conectados al dispositivo. • Requisito de escritura de pines: Este requisito define la necesidad de poder modificar el estado (alto/bajo) de los pines de salida digital del microcontrolador ESP32 a través de la red. Esto es fundamental para controlar actuadores como LEDs, relés u otros dispositivos conectados al ESP32, permitiendo una interacción remota con el entorno físico. • Requisito de obtener la versión del firmware en funcionamiento: Este requisito define la necesidad de poder modificar el estado (alto/bajo) de los pines de salida digital del microcontrolador ESP32 a través de la red. Esto es fundamental para controlar actuadores como LEDs, relés u otros dispositivos conectados al ESP32, permitiendo una interacción remota con el entorno físico. • Requisito de actualización OTA del firmware: Este requisito define la capacidad del sistema para actualizar el firmware del microcontrolador ESP32 de forma inalámbrica, conocido como OTA. Esto permite desplegar nuevas versiones del firmware a los dispositivos sin necesidad de acceso físico, lo cual es especialmente útil para dispositivos desplegados en ubicaciones remotas o de difícil acceso. • Requisito de integración continua del firmware de los microcontroladores: Este requisito se refiere a la implementación de prácticas de Integración Continua (CI) para el desarrollo del firmware de los ESP32. Esto implica automatizar el proceso de compilación y empaquetado del firmware cada vez que se realizan cambios en el código fuente. • Requisito de actualización de todos los microcontroladores de la red: Este requisito establece la necesidad de un mecanismo para actualizar el firmware de manera coordinada o masiva en todos los ESP32 que forman parte del sistema. Esto necesita un sistema de gestión que pueda orquestar el despliegue de actualizaciones a múltiples dispositivos simultáneamente. • Requisito de dockerización de los servicios del nodo central: Este requisito se enfoca en la infraestructura del backend o nodo central que interactúa con los dispositivos ESP32. Especifica que los servicios que componen este nodo central (servidor web y API) deben ser empaquetados y desplegados utilizando contenedores Docker.
7 7 Sistema de desarrollo e integración continua Over-The-Air para microcontroladores IoT
Metodología 14 2.2.2.3 Código del firmware del ESP32 El código del firmware del ESP32 está disponible en el repositorio de GitLab del proyecto. Este firmware implementa un servidor REST para gestionar los pines GPIO del microcontrolador y habilita actualizaciones OTA mediante la librería ElegantOTA. En primer lugar, el firmware realiza la configuración y conexión a la red WiFi, generando automáticamente un hostname único basado en los últimos dígitos de la dirección MAC del dispositivo. Esto facilita tanto la identificación como el acceso al ESP32 dentro de la red local. Una vez conectado, el dispositivo inicia un servidor REST utilizando la librería WebServer, exponiendo varios endpoints: `/read` permite consultar el estado de todos los pines GPIO configurados como salidas, `/write` actualiza el estado de estos pines a partir de una petición JSON, y `/reset` reinicia el microcontrolador de forma remota. Además, el endpoint `/version` proporciona información sobre la versión y la fecha de compilación del firmware. Para la comunicación entre cliente y servidor, utilizamos el formato JSON mediante la librería ArduinoJson, lo que facilita la integración con aplicaciones externas y sistemas de monitorización. El código también implementa la gestión de rutas no encontradas, devolviendo mensajes de error detallados para facilitar la depuración. La funcionalidad de actualización OTA se implementa gracias a la librería ElegantOTA, que añade una interfaz web embebida y callbacks para monitorizar el progreso, gestionar errores y reiniciar automáticamente el dispositivo tras una actualización exitosa. Por último, el firmware integra mDNS para anunciar el dispositivo en la red local bajo un nombre legible, como `tfg-iot-XXXX.local`, facilitando su descubrimiento y acceso sin necesidad de conocer la dirección IP. Todo el ciclo principal de ejecución (`loop`) está diseñado para ser no bloqueante, utilizando la función `millis()` en lugar de `delay()`, lo que asegura la capacidad de respuesta del servidor web y del sistema OTA en todo momento. Todo lo anterior compondría los bloques del firmware de nuestro microcontrolador (ver figura 9). Figura 9. Diagrama de bloques de los modulos del firmware
15 15 Sistema de desarrollo e integración continua Over-The-Air para microcontroladores IoT 2.2.3 Funcionamiento de OTA: particiones y proceso de actualización El proceso de actualización OTA no consiste simplemente en enviar nuevo código a un dispositivo; requiere una arquitectura robusta que garantice la integridad del sistema incluso ante fallos durante la actualización (ver Figura 10). Figura 10. Esquema actualización OTA 2.2.3.1 Particiones de memoria y su función El mecanismo de actualización OTA en el ESP32 requiere una configuración específica de la memoria flash del dispositivo, que incluye al menos dos particiones de aplicación y una partición de datos dedicada a OTA. Esta estructura es esencial para garantizar la fiabilidad y seguridad del proceso de actualización remota del firmware [30]. Las dos particiones de aplicación, comúnmente denominadas `ota_0` y `ota_1`, permiten alojar diferentes versiones del firmware. Mientras el sistema ejecuta el firmware desde una de estas particiones, la otra queda disponible como destino para la nueva versión durante una actualización. Este enfoque posibilita que el dispositivo siga funcionando normalmente mientras se escribe la nueva imagen en la partición inactiva, evitando interrupciones en el servicio [31]. Por su parte, la partición de datos OTA almacena información crítica que indica al bootloader cuál de las particiones de aplicación debe utilizarse durante el arranque. Tras completar una actualización, el sistema puede verificar la integridad de la nueva imagen antes de modificar la configuración de arranque para que el dispositivo utilice la partición actualizada. Si se detecta algún fallo, es posible implementar mecanismos de rollback [30], devolviendo el sistema a la versión anterior de firmware y asegurando así la robustez y la recuperación ante errores en el proceso de actualización
Metodología 16 2.2.3.2 Proceso de actualización OTA y rollback El proceso de actualización OTA está diseñado para garantizar la seguridad y la fiabilidad del dispositivo durante la instalación de nuevas versiones de firmware. Este mecanismo (ver tabla 3) aprovecha la arquitectura de doble partición y el uso de una partición de datos OTA, permitiendo que el sistema pueda recuperar automáticamente una versión anterior en caso de fallo [30]. Así, se minimiza el riesgo de dejar el dispositivo inoperativo tras una actualización defectuosa. Paso Acción principal Objetivo Resultado esperado 1 Identificación de la partición inactiva Seleccionar el destino seguro para la nueva actualización sin afectar la operación actual Se determina cuál de las particiones es donde se debe alojar la nueva actualización 2 Descarga y escritura de la nueva imagen Transferir el firmware actualizado al dispositivo y almacenarlo de forma segura La nueva versión del firmware se guarda en la partición inactiva mientras el sistema sigue operativo 3 Verificación de integridad Comprobar que la imagen descargada no está dañada ni ha sido alterada Solo se procede si la imagen es válida; si no, se aborta la actualización 4 Actualización de la partición de datos OTA Indicar al bootloader que debe arrancar desde la nueva partición en el siguiente reinicio El sistema queda preparado para probar la nueva versión en el próximo arranque 5 Reinicio del dispositivo Aplicar el cambio de firmware cargando la nueva imagen El dispositivo arranca desde la nueva partición con el firmware actualizado 6 Autodiagnóstico del nuevo firmware Verificar que la nueva versión funciona correctamente y que los servicios críticos están operativos Si el diagnóstico es exitoso, se valida la actualización; si falla, se inicia el rollback 7 Validación o rollback automático Garantizar la fiabilidad del sistema, restaurando la versión anterior en caso de fallo El dispositivo marca la nueva versión como estable o, si hay problemas, revierte automáticamente a la versión previa Tabla 3. Proceso actualización OTA 2.2.3.3 La libreria ElegantOTA La librería ElegantOTA se usa para implementar el proceso de actualización OTA en dispositivos IoT. Esta solución proporciona tanto APIs como interfaces web que permiten gestionar el proceso de actualización OTA sin necesidad de implementar manualmente todos los pasos técnicos requeridos por el mecanismo estándar [32]. ElegantOTA automatiza y simplifica el proceso de actualización OTA al incluir un servidor web embebido que expone una interfaz gráfica accesible desde la ruta `/update` (ver figura 11). A través de esta interfaz, el usuario puede cargar fácilmente un nuevo firmware o archivos del sistema de ficheros, sin requerir conocimientos avanzados de redes o manejo de particiones. Además, la librería ofrece APIs
17 17 Sistema de desarrollo e integración continua Over-The-Air para microcontroladores IoT específicas que permiten iniciar y controlar el proceso de actualización OTA directamente desde el código del dispositivo, integrándose con los principales frameworks de desarrollo para ESP32, como Arduino IDE y PlatformIO. Ademas ofrece los endpoints /ota/start y /ota/upload para actualizar el firmware directamente via API. Figura 11. Diagrama de flujo actualizacion OTA por web 2.2.4 Programación del ESP32-WROOM-32. Microservidor REST Un servidor REST es una implementación de servicios web que implementa los principios arquitectónicos definidos por Roy Fielding en el año 2000 [33]. En el contexto IoT, estos servidores actúan como intermediarios para la comunicación entre dispositivos, aplicaciones y sistemas en la nube.
Metodología 18 2.2.4.1 Endpoints de nuestra API En el firmware de nuestros ESP32 tenemos configurada la API con una serie de endpoints básicos (ver tabla 4) que unidos a los que proporciona la librería ElegantOta permiten la configuración necesaria para nuestro Proyecto: Endpoint Método Función /versión GET Obtiene la version y la fecha del ultimo commit /ota/start GET Inicializa la actualización OTA /ota/upload POST Sube el binario del firmware a usar en la actualización OTA /read GET Lee y devuelve el estado actual de los pines del dispositivo /write POST Modifica el estado de un pin especifico en el dispositivo Tabla 4. Endpoints de la API REST del microcontrolador 2.2.5 Programación del ESP32-WROOM-32 – multicast DNS (mDNS) mDNS es un protocolo diseñado para facilitar la resolución de nombres en redes locales sin depender de un servidor DNS centralizado [23]. Utiliza el puerto 5353 y la dirección multicast 224.0.0.251, permitiendo que los dispositivos conectados a la misma red puedan anunciar su presencia y descubrir a otros sin necesidad de configuraciones adicionales, lo que se conoce como “Zero-configuration networking”. Esta característica resulta especialmente útil en entornos IoT, donde es habitual que nuevos dispositivos deban integrarse y comunicarse automáticamente con el resto del Sistema [34]. Por ejemplo, al implementar mDNS en un ESP32, se puede asignar un nombre de host legible, como “sensor-temperatura.local”, en lugar de tener que recordar una dirección IP numérica. Además, el ESP32 puede anunciar los servicios que ofrece, como un servidor web o una API REST, lo que permite que otros dispositivos o aplicaciones en la red local lo descubran y accedan a sus funciones sin intervención manual. Así, si un usuario conecta un nuevo microcontrolador a la red, podrá localizarlo fácilmente desde su ordenador o smartphone simplemente accediendo a “sensor-temperatura.local” en el navegador, sin necesidad de buscar la IP o modificar la configuración de red. Esta funcionalidad simplifica enormemente la integración y gestión de dispositivos en redes IoT.
19 19 Sistema de desarrollo e integración continua Over-The-Air para microcontroladores IoT 2.3 Rpi: API REST La API del nodo central del sistema debe proporcionar varias funcionalidades críticas: • Descubrimiento de dispositivos: Utilizando mDNS para encontrar todos los dispositivos ESP32 en la red local. • Actualización de los firmwares: subida de los binarios a los microcontroladores. • Lectura/escritura de pines: comunicación con los ESP32 para leer y escribir el estado de sus pines. El siguiente archivo muestra que la API REST (ver tabla 5), hecha en Python mediante la librería FastApi, que se dedica a descubrir los dispositivos y a ejecutar tareas de actualización mediante los siguientes endpoints: Endpoint Método Función /iot-devices GET Listado de dispositivos detectados /version/{ip} GET Consulta y devuelve la version del firmware del dispositivo /update-firmware/{ip} POST Inicia actualización OTA del dispositivo especificado recibiendo el binario del nuevo firmware /read/{ip} GET Lee y devuelve el estado actual de los pines del dispositivo seleccionado /write/{ip} POST Modifica el estado de un pin especifico en el dispositivo correspondiente Tabla 5. Endpoints de la API REST del nodo central 2.4 Rpi: interfaz Web El frontend del sistema central de actualización OTA está diseñado como una página web estática que proporciona una interfaz para la gestión de dispositivos y actualizaciones en la red local. Esta interfaz permite visualizar todos los dispositivos descubiertos, consultar información relevante como la versión actual del firmware o el nombre de cada dispositivo, y gestionar el proceso de actualización. Para lograr esta funcionalidad, se ha utilizado un fichero HTML como base para la estructura de la página, mientras que el fichero JavaScript se encarga tanto de la interacción dinámica con el DOM como de la comunicación con el backend a través de la función nativa fetch, que permite realizar peticiones de red y actualizar la interfaz en tiempo real según los dispositivos detectados. El desarrollo del frontend se ha realizado utilizando el IDE WebStorm, que facilita la edición, depuración y organización del código, además de ofrecer herramientas avanzadas para la gestión de proyectos web. Todo el frontend está alojado en la Raspberry Pi, que actúa como servidor central en la arquitectura, permitiendo que cualquier usuario conectado a la red local pueda acceder fácilmente a la interfaz desde su navegador, sin necesidad de instalar software adicional.
Metodología 20 2.5 Rpi: Servidor web Para hacer accesibles los servicios que ofrece el nodo central (frontend y API REST) necesitamos un servidor web. Usamos Caddy [35] como servidor web unificado para: • Servir el frontend estático (HTML/CSS/JS). • Actuar como proxy inverso para la API REST del backend • Gestionar TLS automático mediante integración con Cloudflare. Gracias al uso de Caddy y su archivo de configuración Caddyfile se simplifica mucho el despliegue y gestión de los servicios que tienen que ofrecerse a través del servidor web. En nuestro caso, usamos Cloudflare y su API para poder usarlo como servidor DNS y poder usar dominios TLD (ver figura 12) y certificados TLS válidos en el entorno de nuestra red local. Figura 12. Configuración del dominio en Cloudflare 2.6 Dockerización del nodo central La dockerización del nodo central representa un avance significativo en la arquitectura de nuestro sistema de actualización OTA, especialmente al implementarse sobre una RPi. En este contexto, Docker no solo aporta portabilidad y aislamiento, sino que transforma la RPi en un verdadero servidor de servicios capaz de gestionar de forma eficiente y segura los procesos críticos del sistema. La RPi asume así el papel de nodo central, orquestando la API, el frontend y el servidor web, y permitiendo que cada uno de estos servicios se ejecute en su propio contenedor, completamente aislado de los demás. Esto previene conflictos de dependencias y facilita la gestión de versiones, ya que cada servicio puede actualizarse, reiniciarse o revertirse de manera independiente y controlada. Además, Docker Compose permite definir y gestionar configuraciones complejas de múltiples contenedores de forma declarative. En definitiva, la integración de Docker en la RPi convierte este dispositivo en un nodo central robusto, flexible y fácilmente gestionable dentro de nuestro sistema de actualización OTA. Permite desplegar, escalar y mantener los servicios críticos de manera eficiente, asegurando que el sistema de actualización remota sea fiable y sencillo de operar, incluso cuando el entorno evoluciona o requiere cambios rápidos en la infraestructura. 2.6.1 Containerización de los servicios Docker se encarga de la creación de los diferentes servicios. En nuestro caso temenos el servicio esp32ota-webserver que configura el servicio del servidor web con Caddy y esp32-ota.api que se encarga de configurar python y de poner en funcionamiento la API. En el docker-compose.yml podemos ver como se configuran los servicios y las redes que se usan. El servicio esp32-ota.api hace uso de la red del anfitrión para el descubrimiento de nuestros dispositivos IoT que se anuncian usando mDNS, es por eso que el network_mode está como “host”.
21 21 Sistema de desarrollo e integración continua Over-The-Air para microcontroladores IoT 2.6.2 Estructura de archivos Todos los servicios serán montados con docker, asi que necesitamos instalarlo en nuestra Rpi siguiendo la documentación oficial [36] . Con docker instalado necesitamos clonar todo el codigo de la aplicacion que se encuentra en el repositorio https://gitlab.com/esp32-ota/app de gitlab. Una vez descargado nos quedará una estructura de archivos (ver figura 13) que separará la logica de la aplicación en los siguientes directorios: Figura 13. Estructura de ficheros del nodo central • bin/: esta carpeta contiene scripts que son necesarios para la actualización automatica de los dispositivos IoT. • docker/: este directorio contiene toda la configuración tanto de docker como de los servicios que monta (caddy como webserver y configuracion para la API de Cloudflare). • public/: aqui temenos la interfaz web que proporciona el servidor web a los usuarios. src/: en esta carpeta está el código en python de nuestra API. 2.7 Integración y entrega continua (CI/CD) La integración y entrega continua representan un paradigma fundamental en el desarrollo de software moderno, permitiendo a los equipos entregar valor de manera más rápida y consistente. 2.7.1 Fundamentos del CI/CD La integración continua (CI) es una práctica de desarrollo de software en la que los desarrolladores integran frecuentemente cambios de código en un repositorio compartido, donde cada integración es verificada mediante una compilación automatizada y pruebas para detectar errores rápidamente [37]. Esta metodología surgió como respuesta a los desafíos del desarrollo tradicional, donde las integraciones manuales de código resultaban en procesos lentos y propensos a errores, especialmente en equipos grandes [38]. Por otro lado, la entrega continua (continuous delivery o CD) es un enfoque de ingeniería de software donde los equipos producen software en ciclos cortos, asegurando que puede ser liberado de forma confiable en cualquier momento [39]. Este enfoque facilita la reducción del coste, tiempo y riesgo del proceso de implementación a través de versiones más incrementales en aplicaciones de producción. Es importante distinguir entre entrega continua y despliegue continuo: Mientras que la entrega continua automatiza las integraciones de código hasta el punto donde está listo para producción (pero requiere aprobación manual para el despliegue), el despliegue continuo automatiza completamente el proceso hasta la implementación en producción [40].
Metodología 22 2.7.2 Implementación del CI/CD en nuestro Proyecto Para la gestió de las versions del firmware del ESP32 integramos un pipeline CI/CD en Gitlab mediant el fichero de configuración .gitlab-ci.yml. Con esto conseguimos que cada vez que se genere un tag en el Proyecto se cree un artefacto que contiene el binario que representa el nuevo firmware que fue generado tras la build del código. Este artefacto es posteriormente descargado y usado para la actualización de los ESP32 de manera automatica. por nuestro nodo central.
23 23 Sistema de desarrollo e integración continua Over-The-Air para microcontroladores IoT 3 RESULTADOS EXPERIMENTALES sta sección presenta los puntos principales y descubrimientos obtenidos durante la implementación del nuestro proyecto. Se describen los procedimientos realizados, las pruebas efectuadas y los datos recogidos con el objetivo de evaliar el funcionamiento de la arquitectura propuesta. 3.1 Pruebas con el microcontrolador Las pruebas que se van a realizar tienen que confirmar el funcionamiento esperado de nuestro firmware del microcontrolador ESP32 y cumplir con los requisitos funcionales siguientes para dar por válido nuestro firmware. 3.1.1 Requisito de publicación de los servicios mediante mDNS Nos conectamos a la subred donde están conectados nuestros ESP32 y ejecutamos el commando ‘dnssd -B’ que listará todos los tipos de servicio anunciados por mDNS (ver figura 14). Figura 14. Descubrimiento servicios mDNS Como podemos ver, se listan las diferentes instancias que coinciden con el nombre que le hemos dado y el tipo de servicio HTTP. E Los microprocesadores se están metiendo en todo. En un futuro cercano no habrá ningún accesorio -salvo una escoba, acasoque no tenga un procesador dentro. - Arthur C. Clarke -
Resultados experimentales 30 3.3.2 Requisito de obtener la version del firmware en funcionamiento Para ver la version pulsamos sobre el boton ‘Ver versión’ al lado del dispositivo cuya version queramos comprobar. Una vez hecho esto se hará la peticion necesaria y se mostrará el resultado en un popup (ver figura 26) Figura 26. Ver versión del firmware en la web Podemos ver en los paquetes de la red que se realiza una petición al backend al endpoint /versión seguido de la ip del dispositivo cuya versión se quiere consultar y se pinta en el popup la respuesta.
31 31 Sistema de desarrollo e integración continua Over-The-Air para microcontroladores IoT 3.3.3 Requisito de leer/escribir pines Para leer/escribir pines debemos pulsar en la pagina principal sobre el botón ‘leer pines’ asociado al dispositivo que queramos acceder. Esto abrirá un popup donde se puede ver el estado de los pines (ver figura 27) y se pueden modificar los pines del 12 al 15. Figura 27. Ver estado de pines en la interfaz web Para modificar el estado de los pines solo hay que pulsar sobre el botón ‘Cambiar’ al lado del pin que deseemos cambiar de estado (ver figura 28). Esto hará una llamada /write al backend seguido de la ip del dispositivo cuyo pin queremos cambiar diciendole que cambie de estado.
Resultados experimentales 32 Figura 28. Cambio de estado de pin usando la web Como podemos ver al cambiar el pin 12, que corresponde al LED rojo, este se enciende. 3.3.4 Requisito de actualizar el firmware La actualización del firmware se realiza al pulsar sobre el botón ‘Actualizar firmware’ del dispositivo deseado. Cuando se hace esto se abre un selector de archivos donde pondemos seleccionar el binario que queremos subir (ver figura 29) para actualizar el dispositivo. Figura 29. Seleccionar el firmware para actualizar via web
33 33 Sistema de desarrollo e integración continua Over-The-Air para microcontroladores IoT Una vez hecho esto se hace una petición al backend al endpoint update-firmware seguido de la ip del dispositivo que queremos actualizar y se manda como ‘Form Data’ el binario en la propiedad file para que el back haga las peticiones pertinentes y proceda a la actualización (ver figura 30). Figura 30. Firmware actualizado correctamente a traves de la web En el caso de que la actualización diese un error, el popup mostraria el mensaje de que no se pudo actualizar, dando así feedback al usuario independientemente del resultado de la operación.
Resultados experimentales 34 3.4 Pruebas del nodo central El nodo central es una Rpi con los servicios dockerizados. Es el eje central de nuestro proyecto. 3.4.1 Requisito de dockerización de los servicios del nodo central Nos conectamos al docker y haciendo uso del comando ‘docker ps’ (ver figura 31) podemos comprobar si los servicios que definimos en el fichero docker-compose.yml están correctamente desplegados. Figura 31. Comprobar los containers desplegados en el nodo central Tal y como está especificado en el docker-compose.yml hay dos servicios desplegados, el webserver con nombre ‘esp32-ota.webserver’ y el backend con nombre ‘esp32-ota.api’. 3.4.2 Requisito de actualización de todos los microcontroladores de la red La actualización desde el nodo central tiene dos pasos, primero la ejecución del script download-lastfirmware que consigue descargar el ultimo firmware disponible desde Gitlab (ver figura 32). Figura 32. Descargar el ultimo firmware al nodo central
35 35 Sistema de desarrollo e integración continua Over-The-Air para microcontroladores IoT Una vez tenemos el ultimo firmware cargado en el nodo central, solo tenemos que ejecutar el script update-all-devices (ver figura 33) que primero obtiene un listado de todos los dispositivos para posteriormente hacer las peticiones necesarias al back para cargar en cada dispositivo el nuevo firmware. Figura 33. Actualización de todos los dispositivos IoT desde el nodo central Como podemos comprobar se realiza la actualización de cada dispositivo y se muestra si la actualización fue exitosa o no con una relación final de todos los dispositivos de la red que fueron actualizados o no.
Resultados experimentales 36
37 37 Sistema de desarrollo e integración continua Over-The-Air para microcontroladores IoT 4 CONCLUSIONES Y MEJORAS FUTURAS ste trabajo de fin de grado ha tenido como objetivo principal desarrollar y evaluar un sistema fiable y eficiente de actualización OTA de microcontroladores con un nodo central como coordinador del sistema y haciendo uso de herramientas de integración continua para facilitar el desarrollo del firmware de los microcontroladores ESP32. A su vez proporcionamos una interfaz web para ejecutar acciones de manera manual sobre los microcontroladores del sistema. 4.1 Resumen de los resultados obtenidos A lo largo del trabajo se han alcanzado los siguientes resultados 4.1.1 Implementación y configuración de los microcontroladores Se han integrado con exito los microcontroladores ESP32 en nuestro sistema de actualización OTA. La configuración del microservidor REST y la implementación de la libreria ElegantOTA ha permitido tanto la gestion remota de pines como la actualización OTA del firmware. Tambien mediant el uso de mDNS hemos conseguido anunciar el servicio de la API a la red, de manera que los ESP32 puedan ser encontrados por otros usuarios de manera sencilla. 4.1.2 Desarrollo de la API REST en el nodo central La creación de una API en el nodo central ha sido clave para la coordinación de todos los elementos que lo integran, ofreciendo capacidades de gestion mas potentes que si nos comunicaramos directamente con el servidor REST de los microcontroladores. La API integra descubrimiento de los microcontroladores usando mDNS, gestion de pines y actualización OTA del firmware. 4.1.3 Creación de la interfaz web La interfaz web permite gestionar los recursos de la API del nodo central de una manera visual, facilitando la interacción con el sistema por parte del usuario. En la web se ha integrado lo necesario para usar todos y cada uno de los endpoints creados en la API del nodo central. 4.1.4 Integración del servidor web Gracias al servidor web Caddy hemos podido añadir una capa de seguridad a nuestro sistema usando Cloudflare y un dominio para conseguir cifrado TLS en nuestras comunicaciones HTTP. Aparte de esto el servidor web sirve de forma sencilla los archivos de la interfaz web y sirve de proxy inverso para redirigir las peticiones a la API del nodo central. E La ciencia nunca resuelve un problema sin crear otros diez más. - George Bernard Shaw -
Conclusiones y mejoras futuras 38 4.1.5 Dockerizacion de los servicios del nodo central Usando docker facilitamos la integración de cambios futuros en nuestros diferentes servicios, actualizando nuestros contenedores y ejecutando un solo commando tendriamos los servicios actualizados y funcionando con la seguridad de que todo funcionará sin problemas. 4.1.6 Integración continua en el desarrollo del firmware de los microcontroladores Se ha implementado un flujo de integración continua en Gitlab donde cada vez que se genera un tag se genera el binario del firmware y se almacena de manera que el nodo central puede descargarlo y actualizer los microcontroladores sin intervención del usuario. 4.1.7 Pruebas de funcionamiento Se han realizado diferentes pruebas para determiner el funcionamiento esperado segun los requisitos. Se han testeado las actualizaciones OTA del firmware y la escritura y lectura de pines tanto directamente sobre los microcontroladores como a traves de la web del nodo central. También se ha probado la ejecución de scripts automaticos para la actualización de los ESP32 y el correcto funcionamiento de la integración continua. 4.2 Posibles mejoras Estos resutlados sientan las bases para futuras mejoras y extensions del sistema, incluyendo integración de cifrado extremo a extremo en los microcontroladores, actualizaciones de todos los dispositivos en paralelo e incluso operaciones mas complejas sobre el conjunto de ESP32. 4.2.1 Mejoras de seguridad Aunque la comunicación entre el cliente que usa la interfaz web y el nodo central están encriptadas, se usa HTTPS, la comunicación con los microcontroladores no lo está. La mejora consistiria en implementar certificados firmados en los microcontroladores o incluso el uso de un tunel VPN ubicando los microcontroladores en una red que sepamos segura completamente. 4.2.2 Actualización en paralelo de todos los dispositivos Ahora mismo cuando se ejecuta una actualización global de todos los microcontroladores, se ejecuta de manera secuencial sobre cada dispositivo para tener el control total del proceso. La actualización consistiria en implementar herramientas asincronas para hacer una actualización simultaneal de los microcontroladores, lo que reduciría mucho el tiempo de ejecución de estas actualizaciones generales. 4.2.3 Mejoras en la integración continua La implementación que hemos hecho de la integración continua consiste simplemente en la creación de un artefacto con el binario resultante de la build del código del microcontrolador cuando se crea un tag nuevo. Se deberían crear diferentes pipelines para cada estado del desarrollo del firmware, desde la implementación de nuevas funcionalidades hasta el despliegue en un entorno real, cada una con sus pruebas especificas e incluso generación de releases dado el caso.
39 39 Sistema de desarrollo e integración continua Over-The-Air para microcontroladores IoT