{"id":11305,"date":"2025-12-04T21:40:40","date_gmt":"2025-12-04T20:40:40","guid":{"rendered":"https:\/\/bitacora.eniac2000.com\/?p=11305"},"modified":"2025-12-04T21:40:42","modified_gmt":"2025-12-04T20:40:42","slug":"trazabilidad-de-activos-con-lorawan-e-ia-generativa-desarrollo-de-la-plataforma-de-seguimiento-con-ia-generativa","status":"publish","type":"post","link":"https:\/\/bitacora.eniac2000.com\/?p=11305","title":{"rendered":"Trazabilidad de activos con LoRaWAN e IA generativa. Desarrollo de la plataforma de seguimiento con IA generativa"},"content":{"rendered":"<div class=\"seriesmeta\">Esta entrada es la parte 5 de 7 de la serie <a href=\"https:\/\/bitacora.eniac2000.com\/?series=trazabilidad-de-activos-con-lorawan-e-ia-generativa\" class=\"series-1870\" title=\"Trazabilidad de activos con LoRaWAN e IA generativa\">Trazabilidad de activos con LoRaWAN e IA generativa<\/a><\/div>\n<p class=\"wp-block-paragraph\">Llegados a este punto, el siguiente paso en el proyecto era el desarrollo de la aplicaci\u00f3n web de seguimiento de activos propiamente dicha. Para este proceso utilic\u00e9 el desarrollo asistido con IA generativa. En concreto, hice uso de Dyad para la generaci\u00f3n de c\u00f3digo. Las directivas principales fueron las siguientes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Desarrollo de un frontal web con capacidad para mostrar en un mapa OpenStreetMap la localizaci\u00f3n de usuarios que estuvieran haciendo uso de un dispositivo LoRaWAN.<\/li>\n\n\n\n<li>C\u00f3mputo en un <em>backend<\/em> desplegado en un servidor Debian, sin dependencias con sistemas cloud.<\/li>\n\n\n\n<li>Establecimiento de una asociaci\u00f3n entre usuarios y dispositivos, de tal manera que fuera posible asociar los primeros a los segundos, y guardar un registro hist\u00f3rico de dicha asociaci\u00f3n.<\/li>\n\n\n\n<li>Registro de los <em>gateways<\/em> que proporcionan informaci\u00f3n de los dispositivos de la plataforma.<\/li>\n\n\n\n<li>Capacidad de revisar las actividades de la dupla usuario-dispositivo.<\/li>\n\n\n\n<li>Registro hist\u00f3rico de mensajes recibidos por la plataforma.<\/li>\n\n\n\n<li>Uso de MQTT como plataforma de mensajer\u00eda interna entre el servidor ChirpStack y la aplicaci\u00f3n.<\/li>\n\n\n\n<li>Uso de una base de datos MariaDB.<\/li>\n\n\n\n<li>Secci\u00f3n de administraci\u00f3n para controlar las conexiones con el <em>backend<\/em>, MQTT y MariaDB.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/logo-asset-tracking-lorawan.png\" alt=\"\" class=\"wp-image-11310\" srcset=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/logo-asset-tracking-lorawan.png 1024w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/logo-asset-tracking-lorawan-300x300.png 300w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/logo-asset-tracking-lorawan-150x150.png 150w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/logo-asset-tracking-lorawan-768x768.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Un posible logo. Generado con IA<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">El proceso de desarrollo fue realizado de manera incremental, proporcionando un primer borrador de la arquitectura y de las funciones solicitadas, para ir ajustando de manera m\u00e1s fina en sucesivas iteraciones, lo que permit\u00eda ir evaluando la correcta generaci\u00f3n de c\u00f3digo por parte de Dyad, as\u00ed como corregir malas pr\u00e1cticas, errores e introducir mejoras en el sistema.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En este art\u00edculo entro en detalle de la arquitectura, las tecnolog\u00edas y las funcionalidades de la aplicaci\u00f3n web desarrollada. La principal caracter\u00edstica de la aplicaci\u00f3n es que est\u00e1 dise\u00f1ada para el seguimiento de dispositivos LoRaWAN con capacidades GPS. La plataforma no solo ofrece una visualizaci\u00f3n en tiempo real, sino tambi\u00e9n herramientas robustas para la administraci\u00f3n de usuarios, dispositivos y gateways, as\u00ed como un an\u00e1lisis hist\u00f3rico de actividades y mensajes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Arquitectura del Sistema: Un Enfoque Cliente-Servidor Distribuido<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">La aplicaci\u00f3n concibe bajo un modelo de arquitectura cliente-servidor, donde cada componente desempe\u00f1a un rol especializado, facilitando la escalabilidad, el mantenimiento y la separaci\u00f3n de responsabilidades. Esta estructura se compone de:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Frontend (Cliente Web):<\/strong> La interfaz de usuario interactiva, accesible mediante un navegador web.<\/li>\n\n\n\n<li><strong>Backend (Servidor API):<\/strong> El coraz\u00f3n de la l\u00f3gica de negocio, que orquesta las operaciones de datos y las integraciones externas.<\/li>\n\n\n\n<li><strong>Base de Datos (MariaDB):<\/strong> El repositorio persistente para todos los datos operativos y de configuraci\u00f3n.<\/li>\n\n\n\n<li><strong>Broker MQTT:<\/strong> Un componente externo crucial para la ingesta de datos en tiempo real desde los dispositivos LoRaWAN, que act\u00faa como canal de comunicaciones de la plataforma con respecto a sus sistemas auxiliares.<\/li>\n\n\n\n<li><strong>Servidor de Red LoRaWAN:<\/strong> El servidor ChirpStack descrito en cap\u00edtulos anteriores, que act\u00faa como componente externo. Este despliega una aplicaci\u00f3n que permite compartir los mensajes recibidos de los dispositivos por medio de una integraci\u00f3n HTTP POST.<\/li>\n\n\n\n<li><strong><em>Gateway<\/em> LoRaWAN: <\/strong>El dispositivo Heltec comentado anteriormente. Hace de interfaz entre el servidor ChirpStack y los dispositivos de campo.<\/li>\n\n\n\n<li><strong>Dispositivos LoRaWAN: <\/strong>Los dispositivos comentados en otros cap\u00edtulos. Tanto CubeCell como Dragino.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Esta divisi\u00f3n permite que el <em>frontend<\/em> se centre exclusivamente en la experiencia del usuario, mientras que el <em>backend<\/em> maneja la complejidad de la persistencia de datos, la comunicaci\u00f3n con dispositivos y la l\u00f3gica de negocio, desacoplando as\u00ed las capas y permitiendo su evoluci\u00f3n independiente.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Una acotaci\u00f3n con respecto a la integraci\u00f3n entre el servidor ChirpStack y el broker MQTT: si bien el propio ChirpStack se apoya en el servidor MQTT para el intercambio de mensajes entre sus diversos componentes, estas comunicaciones hacen uso de mensajes con codificaci\u00f3n binaria, que no son directamente utilizables para extraer informaci\u00f3n de ellos por parte de sistemas externos. Por ello, en mi caso, opt\u00e9 por realizar la integraci\u00f3n de la aplicaci\u00f3n definida en ChirpStack mediante un POST HTTP. Este post se env\u00eda a un servicio definido en Node-RED, que hace de pasarela hacia un topic MQTT espec\u00edfico, que es el consumido por la aplicaci\u00f3n de trazabilidad.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"816\" height=\"377\" src=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/node-red-post-mqtt.png\" alt=\"\" class=\"wp-image-11308\" srcset=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/node-red-post-mqtt.png 816w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/node-red-post-mqtt-300x139.png 300w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/node-red-post-mqtt-768x355.png 768w\" sizes=\"auto, (max-width: 816px) 100vw, 816px\" \/><figcaption class=\"wp-element-caption\">Flujo creado en Node-RED<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">En este sentido, otra posibilidad al respecto era hacer uso de una API REST definida en el <em>backend<\/em>, pero ten\u00eda ganas de emplear esta v\u00eda de integraci\u00f3n, aunque tiene como contrapartida que crea una dependencia con un sistema externo adicional, en este caso, mi servidor Node-RED.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Frontend: Una Experiencia de Usuario Reactiva y Tipada<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">El cliente web es una Single Page Application (SPA) construida con un <em>stack<\/em> tecnol\u00f3gico moderno, priorizando la reactividad, la robustez y la eficiencia del desarrollo.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Tecnolog\u00edas Clave del Frontend<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>React &amp; TypeScript:<\/strong> La combinaci\u00f3n de React para la construcci\u00f3n declarativa de interfaces y TypeScript para el tipado est\u00e1tico ofrece una base s\u00f3lida. TypeScript es invaluable en proyectos de esta envergadura, ya que detecta errores en tiempo de compilaci\u00f3n, mejora la refactorizaci\u00f3n y proporciona una documentaci\u00f3n impl\u00edcita del c\u00f3digo, lo que se traduce en una mayor mantenibilidad y menos errores en producci\u00f3n.<\/li>\n\n\n\n<li><strong>Vite:<\/strong> Utilizado como herramienta de construcci\u00f3n, Vite proporciona un entorno de desarrollo extremadamente r\u00e1pido gracias a su uso de m\u00f3dulos ES nativos y su <em>hot module replacement<\/em> (HMR) optimizado.<\/li>\n\n\n\n<li><strong>React Router:<\/strong> Gestiona la navegaci\u00f3n declarativa dentro de la SPA, permitiendo rutas anidadas y una experiencia de usuario fluida sin recargas de p\u00e1gina completas.<\/li>\n\n\n\n<li><strong>Shadcn\/ui &amp; Tailwind CSS:<\/strong> La interfaz se construye utilizando componentes de Shadcn\/ui, que a su vez se basan en Radix UI para la accesibilidad y Tailwind CSS para el estilado. Esta combinaci\u00f3n permite un desarrollo \u00e1gil de la UI, garantizando un dise\u00f1o consistente, responsive y altamente personalizable sin la sobrecarga de un framework CSS tradicional. Las clases de Tailwind se aplican directamente en el JSX, lo que facilita la comprensi\u00f3n del estilo de cada componente.<\/li>\n\n\n\n<li><strong>React Query (TanStack Query):<\/strong> Es la piedra angular para la gesti\u00f3n del estado del servidor. En lugar de manejar manualmente el fetching, caching, sincronizaci\u00f3n y actualizaci\u00f3n de datos as\u00edncronos, React Query automatiza estas tareas. Esto se traduce en menos c\u00f3digo boilerplate, un rendimiento optimizado (gracias al caching y background refetching), y una mejor experiencia de usuario con estados de carga y error bien gestionados.<\/li>\n\n\n\n<li><strong>React Map GL (Mapbox GL JS):<\/strong> Para la visualizaci\u00f3n de datos geoespaciales, se integra Mapbox GL JS a trav\u00e9s de su <em>wrapper<\/em> de React. Esto permite renderizar mapas vectoriales interactivos, a\u00f1adir marcadores personalizados para dispositivos y gateways, dibujar trayectorias y superponer capas de datos complejos como mapas de calor. La flexibilidad de Mapbox GL JS es crucial para representar la din\u00e1mica de los dispositivos LoRaWAN. Se utiliza un estilo de mapa basado en OpenStreetMap para una soluci\u00f3n de c\u00f3digo abierto.<\/li>\n\n\n\n<li><strong>Lucide React:<\/strong> Proporciona una colecci\u00f3n de iconos SVG ligeros y personalizables, utilizados para representar visualmente usuarios, dispositivos y gateways en el mapa y en las tablas.<\/li>\n\n\n\n<li><strong>Date-fns:<\/strong> Una biblioteca modular para la manipulaci\u00f3n y el formateo de fechas, esencial para presentar los timestamps de los mensajes y actividades de manera legible y localizada.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Estructura de Directorios del Frontend<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>src\/pages\/<\/code>: Contiene los componentes de nivel superior que corresponden a las rutas principales de la aplicaci\u00f3n (e.g., <code>Dashboard.tsx<\/code>, <code>UserManagement.tsx<\/code>).<\/li>\n\n\n\n<li><code>src\/components\/<\/code>: Agrupa componentes reutilizables m\u00e1s peque\u00f1os, desde elementos de UI b\u00e1sicos (como <code>Navbar.tsx<\/code>) hasta componentes complejos (como <code>MapComponent.tsx<\/code> o <code>TrajectoryLayer.tsx<\/code>).<\/li>\n\n\n\n<li><code>src\/services\/api.ts<\/code>: Centraliza todas las llamadas a la API REST del backend, encapsulando la l\u00f3gica de fetching y el manejo de errores para una interacci\u00f3n limpia con el servidor.<\/li>\n\n\n\n<li><code>src\/types\/index.ts<\/code>: Define las interfaces TypeScript para todas las entidades de datos (<code>User<\/code>, <code>Device<\/code>, <code>Message<\/code>, <code>Activity<\/code>, etc.), asegurando la coherencia de los datos entre el frontend y el backend.<\/li>\n\n\n\n<li><code>src\/lib\/utils.ts<\/code>: Contiene funciones de utilidad generales, como <code>cn<\/code> para combinar clases de Tailwind de forma condicional.<\/li>\n\n\n\n<li><code>src\/lib\/colors.ts<\/code>: Mapea clases de color de Tailwind a sus valores hexadecimales correspondientes, permitiendo el uso de colores din\u00e1micos en componentes que requieren valores directos (como las l\u00edneas de trayectoria en el mapa).<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Backend: El Motor de Datos y L\u00f3gica<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">El <em>backend<\/em> es un servidor Node.js que expone una API RESTful y se encarga de la ingesta de datos MQTT, la persistencia en MariaDB y la aplicaci\u00f3n de la l\u00f3gica de negocio.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Tecnolog\u00edas del Backend<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Node.js &amp; Express:<\/strong> Node.js, con su modelo de E\/S no bloqueante, es ideal para aplicaciones en tiempo real como esta, que manejan m\u00faltiples conexiones concurrentes (API REST, MQTT). Express simplifica la creaci\u00f3n de rutas, middleware y la gesti\u00f3n de solicitudes HTTP.<\/li>\n\n\n\n<li><strong>TypeScript:<\/strong> Al igual que en el frontend, TypeScript aporta robustez al <em>backend<\/em>, especialmente en la definici\u00f3n de interfaces para los datos que se intercambian con la base de datos y el cliente MQTT.<\/li>\n\n\n\n<li><strong>MariaDB Client (<code>mariadb<\/code>):<\/strong> Se utiliza un <em>pool<\/em> de conexiones para gestionar eficientemente las interacciones con la base de datos, optimizando el rendimiento y la resiliencia. Las consultas se parametrizan para prevenir ataques de inyecci\u00f3n SQL.<\/li>\n\n\n\n<li><strong>MQTT.js:<\/strong> Este cliente MQTT permite al <em>backend<\/em> suscribirse a <em>topics<\/em> espec\u00edficos del broker MQTT. Es el canal principal para recibir los mensajes de uplink de los dispositivos LoRaWAN.<\/li>\n\n\n\n<li><strong>UUID:<\/strong> Se emplea para generar identificadores \u00fanicos universales para todas las entidades (usuarios, dispositivos, mensajes, actividades, etc.), garantizando la unicidad en un entorno distribuido.<\/li>\n\n\n\n<li><strong>Date-fns:<\/strong> Fundamental para la conversi\u00f3n precisa de timestamps entre formatos Unix (utilizado en la base de datos para eficiencia) e ISO 8601 (utilizado en la API para interoperabilidad y legibilidad). Tambi\u00e9n se usa para c\u00e1lculos de tiempo, como el umbral de inactividad.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Funcionalidades Clave del Backend<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>API RESTful Completa:<\/strong> El <em>backend<\/em> expone endpoints para todas las operaciones CRUD (Crear, Leer, Actualizar, Eliminar) sobre usuarios, dispositivos, <em>gateways<\/em>, y para la consulta de mensajes, posiciones y actividades. Tambi\u00e9n incluye <em>endpoints<\/em> para la gesti\u00f3n de configuraciones (MQTT, MariaDB, App) y para pruebas de conectividad.<\/li>\n\n\n\n<li><strong>Procesamiento de Mensajes MQTT:<\/strong> <ul>    <\/ul> \n<li><strong>Ingesta en Tiempo Real:<\/strong> El cliente MQTT se suscribe a un <em>topic<\/em> configurable (e.g., <code>lorawan\/data<\/code>) para recibir mensajes de uplink.<\/li>\n\n\n\n<li><strong>Parseo Inteligente:<\/strong> Los mensajes LoRaWAN pueden variar en formato dependiendo del Network Server (The Things Stack, ChirpStack, etc.). El backend implementa una l\u00f3gica de parseo flexible para extraer campos clave como <code>devEui<\/code>, <code>timestamp<\/code>, <code>latitude<\/code>, <code>longitude<\/code>, <code>rssi<\/code>, <code>rumbo<\/code>, <code>velocidad<\/code>, <code>altitud<\/code> y <code>rxInfo<\/code> (informaci\u00f3n del <em>gateway<\/em>). Se manejan m\u00faltiples rutas para estos campos para asegurar la compatibilidad.<\/li>\n\n\n\n<li><strong>Normalizaci\u00f3n de Datos:<\/strong> Los datos extra\u00eddos se normalizan y se convierten a los tipos de datos adecuados (e.g., flotantes para coordenadas, enteros para RSSI, Unix timestamps para fechas).<\/li>\n<\/li>\n\n\n\n<li><strong>Gesti\u00f3n de Actividades de Dispositivos:<\/strong> <ul>    <\/ul> \n<li><strong>Detecci\u00f3n de Actividad:<\/strong> Cada mensaje con datos de posici\u00f3n contribuye a una \u00abactividad\u00bb.<\/li>\n\n\n\n<li><strong>Umbral de Inactividad:<\/strong> Un par\u00e1metro configurable (<code>activityInactivityThresholdSeconds<\/code>) define el tiempo m\u00e1ximo (en segundos) que un dispositivo puede estar sin enviar un mensaje antes de que su actividad actual se considere finalizada. Si un nuevo mensaje llega dentro de este umbral, la actividad existente se extiende; de lo contrario, se inicia una nueva actividad.<\/li>\n\n\n\n<li><strong>Persistencia:<\/strong> Las actividades se almacenan en la tabla <code>activities<\/code>, registrando el usuario, dispositivo, tiempos de inicio\/fin y coordenadas iniciales\/finales.<\/li>\n<\/li>\n\n\n\n<li><strong>Auto-creaci\u00f3n de Entidades:<\/strong> Si un mensaje MQTT llega de un <code>devEui<\/code> no registrado, el <em>backend<\/em> puede crear autom\u00e1ticamente un nuevo dispositivo con un nombre por defecto, simplificando la puesta en marcha.<\/li>\n\n\n\n<li><strong>Actualizaci\u00f3n de Gateways:<\/strong> La informaci\u00f3n de los <em>gateways<\/em> (\u00faltima vez visto, coordenadas) se actualiza din\u00e1micamente a partir de los metadatos <code>rxInfo<\/code> de los mensajes recibidos.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Base de Datos: MariaDB como Almac\u00e9n de Datos<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">MariaDB, una bifurcaci\u00f3n de MySQL, se utiliza como el sistema de gesti\u00f3n de bases de datos relacionales. Su robustez, rendimiento y compatibilidad con SQL est\u00e1ndar lo hacen ideal para esta aplicaci\u00f3n. Las principales tablas son las siguientes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>users:<\/strong> Almacena la informaci\u00f3n de los usuarios finales que se est\u00e1n siguiendo (nombre, email, icono, color).<\/li>\n\n\n\n<li><strong>devices:<\/strong> Registra los dispositivos LoRaWAN por su DevEUI, su nombre y el usuario al que est\u00e1n asociados.<\/li>\n\n\n\n<li><strong>positions:<\/strong> Almacena cada punto de posici\u00f3n reportado por los dispositivos (DevEUI, latitud, longitud, timestamp).<\/li>\n\n\n\n<li><strong>messages:<\/strong> Guarda una copia completa de cada mensaje MQTT recibido, incluyendo el payload y metadatos como RSSI y gateway de recepci\u00f3n.<\/li>\n\n\n\n<li><strong>activities:<\/strong> Representa un periodo de actividad de un dispositivo asociado a un usuario. Contiene la hora de inicio\/fin y las coordenadas inicial\/final.<\/li>\n\n\n\n<li><strong>gateways:<\/strong> Registra la informaci\u00f3n de los gateways LoRaWAN que han reportado mensajes (ID, nombre, ubicaci\u00f3n, icono, \u00faltima vez visto).<\/li>\n\n\n\n<li><strong>app_config:<\/strong> Almacena la configuraci\u00f3n de la aplicaci\u00f3n, como la direcci\u00f3n IP\/puerto del backend y el umbral de inactividad para las actividades.<\/li>\n\n\n\n<li><strong>mqtt_config:<\/strong> Guarda los detalles de conexi\u00f3n al broker MQTT (URL, puerto, topic, credenciales).<\/li>\n\n\n\n<li><strong>mariadb_config:<\/strong> (Para uso interno del backend) Almacena los detalles de conexi\u00f3n a la propia base de datos.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Integraci\u00f3n <em>Frontend-Backend<\/em>: Comunicaci\u00f3n Fluida<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">La comunicaci\u00f3n entre el <em>frontend<\/em> y el <em>backend<\/em> se realiza a trav\u00e9s de la API REST. El frontend utiliza la funci\u00f3n <code>getApiBaseUrl()<\/code> para construir din\u00e1micamente la URL base del backend, que se almacena en <code>localStorage<\/code> y puede ser configurada por el usuario en la secci\u00f3n de Administraci\u00f3n. Durante el desarrollo, <code>vite.config.ts<\/code> configura un proxy para redirigir las solicitudes <code>\/api<\/code> al backend, evitando problemas de CORS.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Las respuestas de la API se tipan rigurosamente con las interfaces definidas en <code>src\/types\/index.ts<\/code>, garantizando la seguridad de los datos. React Query gestiona el ciclo de vida de estas solicitudes, incluyendo la invalidaci\u00f3n de cach\u00e9 para mantener la UI sincronizada con los cambios en el servidor.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Interfaces y Secciones de la Aplicaci\u00f3n: Una Visi\u00f3n Detallada<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">La aplicaci\u00f3n se estructura en varias secciones, cada una dise\u00f1ada para una funcionalidad espec\u00edfica y con una interfaz de usuario optimizada.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. Dashboard<\/h3>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"785\" height=\"1024\" src=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-02-785x1024.png\" alt=\"\" class=\"wp-image-11312\" srcset=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-02-785x1024.png 785w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-02-230x300.png 230w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-02-768x1001.png 768w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-02-1178x1536.png 1178w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-02-1024x1335.png 1024w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-02.png 1399w\" sizes=\"auto, (max-width: 785px) 100vw, 785px\" \/><figcaption class=\"wp-element-caption\">Interfaz principal<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">El Dashboard es el centro de control en tiempo real, ofreciendo una visi\u00f3n consolidada del estado de los dispositivos y la red.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Mapa Interactivo (<code>MapComponent.tsx<\/code>):<\/strong> <ul>      <\/ul> \n<li><strong>Visualizaci\u00f3n de Dispositivos:<\/strong> Muestra la \u00faltima posici\u00f3n conocida de cada dispositivo como un marcador. Estos marcadores son iconos de Lucide personalizados, cuyo tipo y color se definen en la gesti\u00f3n de usuarios, permitiendo una identificaci\u00f3n visual r\u00e1pida. Al hacer clic, un <em>popup<\/em> muestra detalles como el usuario asociado, nombre del dispositivo, coordenadas, <em>timestamp<\/em> y los \u00faltimos datos de telemetr\u00eda (rumbo, velocidad, altitud).<\/li>\n\n\n\n<li><strong>Visualizaci\u00f3n de <em>Gateways<\/em>:<\/strong> Los <em>gateways<\/em> se representan con iconos espec\u00edficos (e.g., <code>Antenna<\/code>) y un color distintivo, mostrando su ubicaci\u00f3n y detalles al interactuar con ellos.<\/li>\n\n\n\n<li><strong>Trayectorias Hist\u00f3ricas (<code>TrajectoryLayer.tsx<\/code>):<\/strong> Para cada dispositivo, se dibuja una l\u00ednea que representa su trayectoria hist\u00f3rica. La longitud de esta trayectoria es configurable mediante un <em>slider<\/em> logar\u00edtmico, permitiendo al usuario visualizar desde los \u00faltimos minutos hasta un historial ilimitado. El color de la trayectoria coincide con el color asignado al usuario.<\/li>\n\n\n\n<li><strong>Mapa de Calor:<\/strong> Una capa opcional que visualiza la densidad de las posiciones hist\u00f3ricas de los dispositivos, \u00fatil para identificar \u00e1reas de mayor actividad. La opacidad de esta capa es ajustable.<\/li>\n\n\n\n<li><strong>Control de Capas por Usuario:<\/strong> Un panel lateral permite activar o desactivar la visibilidad de los marcadores y trayectorias de dispositivos asociados a usuarios espec\u00edficos, facilitando el an\u00e1lisis de subconjuntos de datos.<\/li>\n<\/li>\n\n\n\n<li><strong><em>Slider<\/em> de L\u00edmite Temporal de Trayectoria:<\/strong> Un control deslizante con una escala logar\u00edtmica que permite al usuario ajustar el periodo de tiempo para el cual se muestran las trayectorias de los dispositivos. Los valores van desde \u00abSin trayectoria\u00bb (0 horas) hasta \u00abIlimitado\u00bb, con puntos intermedios que representan minutos, horas, d\u00edas, meses o a\u00f1os.<\/li>\n\n\n\n<li><strong>Tablas de Resumen:<\/strong> <ul>    <\/ul> \n<li><strong>\u00daltimas Posiciones:<\/strong> Muestra las 5 posiciones m\u00e1s recientes de dispositivos \u00fanicos, con actualizaciones en tiempo real.<\/li>\n\n\n\n<li><strong>Dispositivos Activos:<\/strong> Lista todos los dispositivos registrados y la \u00faltima vez que se recibi\u00f3 un mensaje de ellos, formateado con <code>date-fns<\/code> (e.g., \u00abhace 5 minutos\u00bb).<\/li>\n\n\n\n<li><strong>\u00daltimos Mensajes Recibidos:<\/strong> Una tabla que muestra los 10 mensajes LoRaWAN m\u00e1s recientes, incluyendo detalles como el usuario, dispositivo, gateway, coordenadas, rumbo, velocidad, altitud, RSSI y timestamp.<\/li>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2. Gesti\u00f3n de Usuarios (<code>UserManagement.tsx<\/code>)<\/h3>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"460\" src=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-03-1024x460.png\" alt=\"\" class=\"wp-image-11313\" srcset=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-03-1024x460.png 1024w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-03-300x135.png 300w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-03-768x345.png 768w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-03.png 1419w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Gesti\u00f3n de usuarios<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Esta secci\u00f3n permite la administraci\u00f3n de los usuarios que interact\u00faan con la plataforma o cuyos dispositivos son rastreados.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Tabla de Usuarios:<\/strong> Presenta un listado paginado de todos los usuarios, con columnas para nombre, email, un previsualizador del icono y su color.<\/li>\n\n\n\n<li><strong>Formulario Modal (Creaci\u00f3n\/Edici\u00f3n):<\/strong> Un di\u00e1logo modal permite crear nuevos usuarios o editar los existentes. Los campos incluyen nombre, email, y selectores para elegir un icono de Lucide (e.g., <code>Car<\/code>, <code>Bike<\/code>) y un color de Tailwind (e.g., <code>blue-600<\/code>, <code>green-600<\/code>). Estos atributos visuales son cruciales para la representaci\u00f3n en el mapa.<\/li>\n\n\n\n<li><strong>Operaciones CRUD:<\/strong> Botones para editar y eliminar usuarios, con notificaciones de \u00e9xito\/error mediante <code>sonner<\/code>.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">3. Gesti\u00f3n de Dispositivos (<code>DeviceManagement.tsx<\/code>)<\/h3>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"461\" src=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-04-1024x461.png\" alt=\"\" class=\"wp-image-11314\" srcset=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-04-1024x461.png 1024w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-04-300x135.png 300w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-04-768x346.png 768w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-04.png 1422w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Gesti\u00f3n de dispositivos<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Administraci\u00f3n de los dispositivos LoRaWAN que env\u00edan datos a la plataforma.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Tabla de Dispositivos:<\/strong> Muestra el ID, DevEUI, nombre y el usuario asociado a cada dispositivo.<\/li>\n\n\n\n<li><strong>Formulario Modal (Creaci\u00f3n\/Edici\u00f3n):<\/strong> Permite registrar nuevos dispositivos o modificar los existentes. El campo DevEUI es cr\u00edtico y debe ser \u00fanico. Un selector desplegable facilita la asociaci\u00f3n de un dispositivo con un usuario existente o su desasociaci\u00f3n (<code>null<\/code>).<\/li>\n\n\n\n<li><strong>Operaciones CRUD:<\/strong> Funcionalidades completas para a\u00f1adir, editar y eliminar dispositivos.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">4. Gesti\u00f3n de Gateways (<code>GatewayManagement.tsx<\/code>)<\/h3>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"272\" src=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-05-1024x272.png\" alt=\"\" class=\"wp-image-11315\" srcset=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-05-1024x272.png 1024w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-05-300x80.png 300w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-05-768x204.png 768w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-05.png 1406w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Gesti\u00f3n de <em>gateways<\/em><\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Visualizaci\u00f3n y edici\u00f3n de la informaci\u00f3n de los <em>gateways<\/em> LoRaWAN que reenv\u00edan los mensajes de los dispositivos.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Tabla de <em>Gateways<\/em>:<\/strong> Lista los gateways por ID, nombre, coordenadas, icono y la \u00faltima vez que se recibi\u00f3 un mensaje a trav\u00e9s de ellos.<\/li>\n\n\n\n<li><strong>Formulario Modal (Edici\u00f3n):<\/strong> Permite modificar el nombre y el icono de un <em>gateway<\/em>. Campos como ID, latitud, longitud y \u00faltima aparici\u00f3n se muestran como solo lectura, ya que se actualizan autom\u00e1ticamente con los datos de los mensajes MQTT.<\/li>\n\n\n\n<li><strong>Confirmaci\u00f3n de Eliminaci\u00f3n:<\/strong> Un <code>AlertDialog<\/code> de Shadcn\/ui solicita confirmaci\u00f3n antes de eliminar un <em>gateway<\/em>, advirtiendo sobre posibles restricciones de clave for\u00e1nea.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">5. Historial de Actividades (<code>ActivityHistory.tsx<\/code>)<\/h3>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"786\" src=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-06-1024x786.png\" alt=\"\" class=\"wp-image-11316\" srcset=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-06-1024x786.png 1024w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-06-300x230.png 300w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-06-768x590.png 768w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-06.png 1399w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Historial de actividad<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Esta secci\u00f3n permite a los usuarios revisar las actividades pasadas de los dispositivos asociados.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Selecci\u00f3n de Usuario y Fecha:<\/strong> Un selector de usuario y un componente <code>Calendar<\/code> (de Shadcn\/ui) permiten filtrar las actividades. El calendario resalta din\u00e1micamente los d\u00edas en los que el usuario seleccionado tuvo actividad, consultando un endpoint espec\u00edfico del backend (<code>\/api\/users\/:userId\/activity-dates<\/code>).<\/li>\n\n\n\n<li><strong>Listado de Actividades del D\u00eda:<\/strong> Muestra una lista de las actividades registradas para el usuario y la fecha seleccionados, indicando el dispositivo, y las horas de inicio y fin.<\/li>\n\n\n\n<li><strong>Visualizaci\u00f3n de Trayectoria en Mapa:<\/strong> Al seleccionar una actividad de la lista, su trayectoria completa se carga y se visualiza en un mapa. Se utilizan marcadores espec\u00edficos (<code>PlayCircle<\/code> y <code>StopCircle<\/code> de Lucide) para indicar el inicio y el fin de la actividad, con popups informativos.<\/li>\n\n\n\n<li><strong>Exportaci\u00f3n GPX:<\/strong> Una funcionalidad clave es la capacidad de exportar la trayectoria de una actividad seleccionada en formato GPX. Esto permite a los usuarios descargar los datos de la ruta para su uso en software de mapeo externo, an\u00e1lisis o archivado. El GPX generado incluye <em>timestamps<\/em> en formato ISO 8601 UTC.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">6. Historial de Mensajes (<code>MessageHistory.tsx<\/code>)<\/h3>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"435\" src=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-08-1024x435.png\" alt=\"\" class=\"wp-image-11318\" srcset=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-08-1024x435.png 1024w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-08-300x127.png 300w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-08-768x326.png 768w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-08.png 1408w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Historial de mensajes<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Una vista tabular exhaustiva de todos los mensajes LoRaWAN recibidos y almacenados.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Tabla de Datos (<code>@tanstack\/react-table<\/code>):<\/strong> Utiliza <code>react-table<\/code> para renderizar una tabla de datos eficiente y rica en funcionalidades.<\/li>\n\n\n\n<li><strong>Columnas Detalladas:<\/strong> Cada fila representa un mensaje, mostrando campos como hora, usuario, dispositivo, DevEUI, gateway, latitud, longitud, rumbo, velocidad, altitud, RSSI y el payload raw.<\/li>\n\n\n\n<li><strong>Funcionalidades Avanzadas:<\/strong> <ul>    <\/ul> \n<li><strong>B\u00fasqueda Global:<\/strong> Un campo de entrada permite buscar texto en todas las columnas de la tabla.<\/li>\n\n\n\n<li><strong>Ordenaci\u00f3n por Columnas:<\/strong> Los usuarios pueden ordenar los datos haciendo clic en los encabezados de las columnas.<\/li>\n\n\n\n<li><strong>Paginaci\u00f3n:<\/strong> Controles de paginaci\u00f3n completos (primera, anterior, siguiente, \u00faltima p\u00e1gina) y un selector para ajustar el n\u00famero de filas por p\u00e1gina (10, 20, 50, 100).<\/li>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">7. Administraci\u00f3n (<code>Administration.tsx<\/code>)<\/h3>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"949\" src=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-07-1024x949.png\" alt=\"\" class=\"wp-image-11319\" srcset=\"https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-07-1024x949.png 1024w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-07-300x278.png 300w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-07-768x711.png 768w, https:\/\/bitacora.eniac2000.com\/wp-content\/uploads\/2025\/12\/lorawantracker-07.png 1397w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Secci\u00f3n de administraci\u00f3n<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Esta secci\u00f3n es cr\u00edtica para la configuraci\u00f3n y el mantenimiento del sistema, permitiendo ajustar las integraciones y par\u00e1metros operativos.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Configuraci\u00f3n del Backend:<\/strong> <ul>    <\/ul> \n<li><strong>IP y Puerto:<\/strong> Permite al usuario especificar la direcci\u00f3n IP y el puerto donde se ejecuta el servidor backend. Esta configuraci\u00f3n se guarda en <code>localStorage<\/code> del navegador y en la base de datos del backend (tabla <code>app_config<\/code>).<\/li>\n\n\n\n<li><strong>Umbral de Inactividad de Actividad:<\/strong> Un campo num\u00e9rico para definir el <code>activityInactivityThresholdSeconds<\/code>. Este valor es crucial para la l\u00f3gica de agrupaci\u00f3n de mensajes en actividades, ya que determina el tiempo m\u00e1ximo sin mensajes para que una actividad se considere finalizada.<\/li>\n\n\n\n<li><strong>Prueba de Conexi\u00f3n:<\/strong> Un bot\u00f3n permite verificar la conectividad con el backend configurado, mostrando el estado (\u00e9xito\/error) y un mensaje descriptivo.<\/li>\n<\/li>\n\n\n\n<li><strong>Configuraci\u00f3n MQTT:<\/strong> <ul>   <\/ul> \n<li><strong>Detalles del Broker:<\/strong> Campos para <code>brokerUrl<\/code>, <code>port<\/code>, <code>topic<\/code>, <code>username<\/code> y <code>password<\/code>. Esta configuraci\u00f3n se guarda en la tabla <code>mqtt_config<\/code> del backend.<\/li>\n\n\n\n<li><strong>Prueba de Conexi\u00f3n:<\/strong> Un bot\u00f3n que inicia una conexi\u00f3n de prueba ef\u00edmera al <em>broker<\/em> MQTT con la configuraci\u00f3n actual, informando sobre el \u00e9xito o el fallo. Tras guardar la configuraci\u00f3n, el cliente MQTT del <em>backend<\/em> se reconecta autom\u00e1ticamente con los nuevos par\u00e1metros.<\/li>\n<\/li>\n\n\n\n<li><strong>Configuraci\u00f3n MariaDB:<\/strong> <ul>   <\/ul> \n<li><strong>Detalles de la Base de Datos:<\/strong> Campos para <code>host<\/code>, <code>port<\/code>, <code>database<\/code>, <code>user<\/code> y <code>password<\/code>. Esta configuraci\u00f3n se guarda en la tabla <code>mariadb_config<\/code> del backend.<\/li>\n\n\n\n<li><strong>Prueba de Conexi\u00f3n:<\/strong> Un bot\u00f3n para verificar la conectividad con la base de datos MariaDB, esencial para asegurar la persistencia de datos.<\/li>\n<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Despliegue y Configuraci\u00f3n del Entorno<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Para la puesta en marcha de la aplicaci\u00f3n, se requiere una configuraci\u00f3n cuidadosa de ambos componentes, <em>frontend<\/em> y <em>backend<\/em>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Prerrequisitos<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Node.js (v18+)<\/li>\n\n\n\n<li>npm o Yarn<\/li>\n\n\n\n<li>Servidor MariaDB<\/li>\n\n\n\n<li><em>Broker<\/em> MQTT (e.g., Mosquitto)<\/li>\n\n\n\n<li><em>Token<\/em> de acceso de Mapbox (para el frontend)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Configuraci\u00f3n del Backend<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Variables de Entorno (<code>backend\/.env<\/code>):<\/strong> Se configuran las credenciales de la base de datos (<code>DB_HOST<\/code>, <code>DB_PORT<\/code>, <code>DB_USER<\/code>, <code>DB_PASSWORD<\/code>, <code>DB_DATABASE<\/code>) y el puerto del servidor <em>backend<\/em> (<code>PORT<\/code>).<\/li>\n\n\n\n<li><strong>Esquema de Base de Datos:<\/strong> El archivo <code>mariadb_schema.sql<\/code> se ejecuta para crear la base de datos y todas las tablas necesarias.<\/li>\n\n\n\n<li><strong><em>Seeding<\/em> (<code>npm run seed<\/code>):<\/strong> Un <em>script<\/em> de <em>seeding<\/em> (<code>backend\/src\/seed.ts<\/code>) permite poblar la base de datos con datos de prueba iniciales para usuarios, dispositivos, gateways, mensajes y actividades, facilitando el desarrollo y las demostraciones.<\/li>\n\n\n\n<li><strong>Inicio del Servidor:<\/strong> El servidor se inicia con <code>npm run dev<\/code> (para desarrollo con recarga autom\u00e1tica) o <code>npm start<\/code> (para producci\u00f3n).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Configuraci\u00f3n del Frontend<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Variables de Entorno (<code>.env<\/code> en la ra\u00edz):<\/strong> Se configura el token de acceso de Mapbox (<code>VITE_MAPBOX_ACCESS_TOKEN<\/code>).<\/li>\n\n\n\n<li><strong>Construcci\u00f3n:<\/strong> La aplicaci\u00f3n se construye con <code>npm run build<\/code>, generando los archivos est\u00e1ticos optimizados.<\/li>\n\n\n\n<li><strong>Despliegue con Systemd (Opcional):<\/strong> Para un despliegue robusto en entornos Linux, se proporciona un ejemplo de archivo de servicio <code>systemd<\/code>. Este servicio asegura que el frontend se ejecute en segundo plano, se inicie autom\u00e1ticamente al arrancar el sistema y se reinicie en caso de fallos, utilizando <code>npx serve -s dist -l 8083<\/code> para servir los archivos est\u00e1ticos.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusi\u00f3n<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">La plataforma de seguimiento GPS LoRaWAN representa una soluci\u00f3n integral y t\u00e9cnicamente sofisticada para la monitorizaci\u00f3n de activos en el \u00e1mbito IoT. Su arquitectura modular, el uso de tecnolog\u00edas de vanguardia en <em>frontend<\/em> y <em>backend<\/em>, y la cuidadosa implementaci\u00f3n de funcionalidades como la gesti\u00f3n de actividades, la visualizaci\u00f3n de trayectorias y la configuraci\u00f3n din\u00e1mica de integraciones, la posicionan como una herramienta potente y adaptable. Este proyecto no solo demuestra la viabilidad de construir sistemas complejos con stacks modernos, sino que tambi\u00e9n ofrece una base s\u00f3lida para futuras expansiones y personalizaciones en el creciente ecosistema LoRaWAN.<\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"seriesmeta\">Esta entrada es la parte 5 de 7 de la serie <a href=\"https:\/\/bitacora.eniac2000.com\/?series=trazabilidad-de-activos-con-lorawan-e-ia-generativa\" class=\"series-1870\" title=\"Trazabilidad de activos con LoRaWAN e IA generativa\">Trazabilidad de activos con LoRaWAN e IA generativa<\/a><\/div><p>Llegados a este punto, el siguiente paso en el proyecto<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1845,13],"tags":[412,489,517,548,1847,745,747,789,824,998,1853,1134,1177,1178,1862],"series":[1870],"class_list":["post-11305","post","type-post","status-publish","format-standard","hentry","category-generado-con-ia","category-informatica","tag-chirpstack","tag-cubecell","tag-debian","tag-dragino","tag-dyad","tag-gps","tag-gpx","tag-heltec","tag-ia","tag-lorawan","tag-mariadb","tag-mqtt","tag-node-red","tag-node-js","tag-openstreetmap","series-trazabilidad-de-activos-con-lorawan-e-ia-generativa"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=\/wp\/v2\/posts\/11305","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=11305"}],"version-history":[{"count":5,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=\/wp\/v2\/posts\/11305\/revisions"}],"predecessor-version":[{"id":11320,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=\/wp\/v2\/posts\/11305\/revisions\/11320"}],"wp:attachment":[{"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11305"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11305"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11305"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/bitacora.eniac2000.com\/index.php?rest_route=%2Fwp%2Fv2%2Fseries&post=11305"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}