• No se han encontrado resultados

Diseño de un servicio GIS de tracking de camiones y contenedores

N/A
N/A
Protected

Academic year: 2023

Share "Diseño de un servicio GIS de tracking de camiones y contenedores"

Copied!
124
0
0

Texto completo

(1)

UNIVERSIDAD POLITÉCNICA DE CARTAGENA

Trabajo Fin de Grado

GRADO EN INGENIERÍA TELEMÁTICA

Diseño de un servicio GIS de tracking de camiones y contenedores

AUTOR: Erik García Hoyberg DIRECTOR: Alejandro S. Martínez Sala CO-DIRECTOR: Juan José Franco Peñaranda (Digio S.L.) Septiembre / 2022

(2)

2

Autor Erik García Hoyberg

E-mail del autor [email protected]

Director / mail Alejando S. Martínez Sala / [email protected]

Co-director / mail Juan José Franco Peñaranda (Digio S.L.) / [email protected] Título del TFG Diseño de un servicio GIS de tracking de camiones y

contenedores.

Resumen Existen numerosos procesos operacionales en la industria que requieren la gestión de la localización y seguimiento (tracking) de flotas de camiones y contenedores. Se propone definir un caso de uso genérico de contenedores móviles en un circuito logístico que son transportados por una flota de camiones. El resultado del proyecto puede ser un prototipo demostrativo comercial y de interés para un sector de la industria. El objetivo del proyecto es diseñar e implementar un servidor que gestione los datos de las coordenadas GPS de una flota de camiones y un conjunto de contenedores. Para validar el servicio se desarrollará un app en React Native para el móvil del conductor del camión; el app del conductor envía periódicamente las coordenadas GPS del camión mediante MQTT y el listado de los contenedores que se transportan. El backend del servidor se implementa con NodeJS, broker de MQTT basado EMQX y se usan las bases de datos MongoDB y PostGIS. El frontend está basado en Leaflet y permite visualizar la ubicación del camión y contenedores en un mapa. Finalmente, el servidor se encapsula en un contenedor de Docker para su despliegue en un servidor en la nube.

Titulación Grado en Ingeniería Telemática.

Departamento Tecnología de la Información y las Comunicaciones.

Fecha de presentación Septiembre - 2022

(3)

3

Agradecimientos

En primer lugar, al director de este proyecto y al profesor que más confianza ha depositado en mí en esta universidad, Alejandro Martínez Sala. Su metodología de trabajo metódica, reflexiva y organizada me ha enseñado que se puede trabajar menos y hacerlo mejor, si se hace de la manera correcta. Su conocimiento en ámbitos como protocolos de mensajería o estándares Bluetooth han sido claves para la correcta realización de este proyecto. También me gustaría agradecerle la pasión con la que desempeña su trabajo, pues ha sido uno de los profesores de los que más he aprendido en mi paso por la universidad.

Al codirector de este proyecto y mi mentor absoluto en cuanto a tecnologías y desarrollo de software, Juan José Franco Peñaranda. No solo ha conseguido hacer de mí un desarrollador competente, sino que me ha mostrado algo que me apasiona. Ha conseguido que el hecho de levantarme a trabajar cada día en lo que me gusta sea un placer. También me gustaría agradecerle su constante ayuda y dedicación hacia mi persona y este proyecto, el cual no habría sido posible sin sus conocimientos técnicos. Por último, agradezco su forma de ser, la cualidad que tiene de hacer crecer a todo el que le rodea.

A mi madre, por tener una paciencia infinita conmigo y por educarme en valores que no se aprenden en ningún lado. A mi padre, por apoyarme en todos mis proyectos y por inculcarme la ley del esfuerzo. Sin su apoyo incondicional, no habría llegado a donde estoy hoy.

A mi hermano y al resto de mi familia, que han perdonado todas mis ausencias y me han demostrado el cariño y admiración que sienten por mí.

A Alba, por compartir conmigo todos los momentos buenos que ha tenido este viaje y, sobre todo, por soportar a mi lado todos los momentos malos. Sin ti, esta llanura que he recorrido habría sido montaña.

Finalmente, a todos los profesores de la Universidad Politécnica de Cartagena. Al final de este camino, todos han dejado una huella en mí y siempre recordaré mi estancia en esta universidad como un camino difícil, pero agradable y que definitivamente vale la pena.

(4)

4

Índice

Capítulo 1. Introducción y objetivos ... 10

1.1 Introducción y objetivos ... 10

1.2 Herramientas software y elementos usados ... 12

1.3 Formación en tecnologías DevOps ... 14

1.4 Metodologías de trabajo ... 15

1.5 Estructura y organización del proyecto... 17

Capítulo 2. Diseño e implementación en React Native de la app del conductor. ... 18

2.1. Arquitectura app React Native ... 20

2.2. Generación listado contenedores con códigos QR ... 23

2.3. Consultas periódicas GPS y envío de datos JSON por MQTT ... 25

2.4 Funcionalidad adicional. ... 27

Capítulo 3. Diseño del backend y BBDD del servidor ... 28

3.1 Arquitectura del backend y BBDD ... 31

3.2 Gestión de geofence y eventos de entrada y salida ... 36

3.3 Almacenamiento datos en BBDD MongoDB ... 39

3.4 Procesamiento datos GPS y almacenamiento en BBDD PostGIS ... 42

Capítulo 4. Diseño e implementación del frontend GIS usando Leaflet ... 46

4.1 Arquitectura del frontend GIS de visualización basado en Leaflet ... 51

4.2 Gestión de rutas y control de la ubicación y stock de contenedores ... 56

4.3 Configuración y alta de clientes y geofences ... 59

4.4 Configuración y alta de conductores ... 61

4.5 Alta de usuarios del servicio y sistema de login y envío de datos seguro... 65

Capítulo 5. Despliegue en la nube. Pruebas de validación ... 69

5.1 Despliegue del servicio en la nube usando contenedores Docker... 73

5.1.1 Despliegue en la nube del backend ... 76

5.1.2 Despliegue en la nube del frontend ... 81

5.2 Despliegue automatizado usando GitHub Actions ... 85

5.3 Emulación app conductor ... 88

5.4 Emulación de la app conductor y rutas con clientes para validar funcionamiento del servidor ... 89

Capítulo 6. Conclusiones y trabajos futuros ... 105

6.1 Conclusiones... 105

6.2 Grado de consecución de los objetivos y formación adquirida ... 106

6.3 Trabajos futuros ... 108

Bibliografía y referencias ... 109

(5)

5

Anexos ... 110

Anexo 1. Estructura y organización del código ... 110

Anexo 2. MQTT y gestión de tópicos... 120

Anexo 3. Escaneo y filtrado mediante BLE. ... 122

(6)

6

Índice de figuras

Figura 1. Esquema general de nuestro servicio ... 11

Figura 2. Ejemplo de Arquitectura Hexagonal ... 15

Figura 3. Ejemplo de Tree Shake ... 16

Figura 4. Funcionamiento del Framework de React Native. ... 18

Figura 5. Esquema simplificado del rol de la aplicación React Native ... 19

Figura 6. Esquema del comportamiento en cuanto a elección de funcionalidad de la aplicación React Native ... 20

Figura 7. Esquema del funcionamiento de la autenticación y obtención de datos inicial de la aplicación React Native ... 21

Figura 8. Diagrama de flujo para determinar la funcionalidad a seguir ... 22

Figura 9. Esquema del funcionamiento del modo de uso mediante Listados QR ... 23

Figura 10. Diagrama de flujo sobre el funcionamiento de Scan BLE ... 25

Figura 11. Diagrama de funcionamiento del sistema de colas ... 27

Figura 12. Arquitectura general de nuestro servicio ... 28

Figura 13. Módulo del backend ... 29

Figura 14. Ejemplo de funcionamiento del Broker EMQX ... 31

Figura 15. Dashboard del Context Broker ... 32

Figura 16. Diagrama de las comunicaciones entre los módulos que componen el backend ... 33

Figura 17. Cronograma de la publicación y persistencia de un dato. ... 34

Figura 18. Cronograma sobre la recuperación de datos a mostrar en el frontend. ... 35

Figura 19. Cronograma de la creación de un nuevo Geofence en el sistema ... 36

Figura 20. Ilustración referente a un Geofence ... 37

Figura 21. Cronograma referente a la generación de eventos del sistema ... 38

Figura 22. Modelo de datos que definen a un usuario en el servidor ... 39

Figura 23. Modelo de datos que rigen las configuraciones de usuario en el servidor. ... 39

Figura 24. Modelo de datos que componen los eventos de nuestro servidor. ... 40

Figura 25. Configuración por defecto de nuestra BBDD Mongo ... 41

Figura 26. Conexión desde el servidor a nuestra BBDD Mongo ... 41

Figura 27. Modelo de datos que forma los mensajes referentes a la geolocalización ... 42

Figura 28. Modelo de datos de las rutas ... 43

Figura 29. Configuración de nuestra BBDD PostGRESQL ... 44

Figura 30. Conexión a nuestra BBDD PostGRESQL mediante KNEX ... 45

Figura 31. Flujo de renderizado de React ... 46

Figura 32. Ejemplo de menú tipo Drawer ... 47

Figura 33. Ejemplo de Dashboard basado estilizado con Material UI ... 48

Figura 34. Bundler de webpack ... 49

Figura 35. Primera versión de visualización de rutas y contenedores ... 51

Figura 36. Visualización de varios componentes localizados a escasos kilómetros ... 52

Figura 37. Visualización de contenedores cercanos en detalle ... 52

Figura 38. Visualización de la posición exacta de varios contenedores cercanos en detalle ... 52

Figura 39. Primera versión del formulario para crear un nuevo Geofence ... 53

Figura 40. Formulario para crear una ruta ... 54

Figura 41. Mapa del formulario para crear una ruta ... 54

Figura 42. Formulario de fechas para establecer un inicio y llegada esperados al crear una ruta ... 54

Figura 43. Cronograma de la comunicación del frontend y backend ... 55

(7)

7

Figura 44. Listado de rutas y detalle de una ruta ... 56

Figura 45. Listado de contenedores y detalles de un contenedor. ... 57

Figura 46. Formulario para crear un nuevo contenedor ... 57

Figura 47. Formulario para crear un nuevo Geofence ... 59

Figura 48. Cronograma del proceso de creación de un nuevo Geofence en el sistema ... 60

Figura 49. Listado de usuarios ... 61

Figura 50. Listado de usuarios y detalles de un usuario. ... 61

Figura 51. Formulario de creación de un nuevo usuario ... 62

Figura 52. Asignación de configuración a un usuario... 62

Figura 53. Configuración para el Scan BLE de un usuario ... 63

Figura 54. Cronograma de la creación de un nuevo usuario en el sistema ... 63

Figura 55. Cronograma de la creación o edición de la configuración de un usuario. ... 64

Figura 56. Cronograma de la creación, validación y autenticación de un usuario. ... 65

Figura 57. Inicio de sesión de un usuario. ... 66

Figura 58. Ejemplo del formato de un JSON Web Token ... 67

Figura 59. Datos que conforman nuestros JSON Web Token ... 67

Figura 60. Ejemplo de JSON Web Token creado ... 68

Figura 61. Ejemplo de flujo de despliegue mediante GitHub Actions ... 69

Figura 62. Imagen lightweight de Node en Docker Hub ... 70

Figura 63. Esquema de la infraestructura del funcionamiento de Docker ... 70

Figura 64. Esquema del despliegue de contenedores Docker ... 71

Figura 65. Secretos alojados en GitHub ... 75

Figura 66. Proceso de construcción de la imagen de nuestro servidor Fastify ... 76

Figura 67. Proceso de levantamiendo de varias imágenes en un contenedor ... 79

Figura 68. Contenedor Docker del backend ... 80

Figura 69. Proceso de construcción de la imagen Docker de nuestro frontend ... 81

Figura 70. Proceso de levantamiento de nuestra aplición mediante contenedores Docker ... 82

Figura 71. Configuración de nuestro servidor NGINX ... 83

Figura 72. Contenedor Docker de nuestro frontend ... 84

Figura 73. Flujo de trabajo para despliegue usando GitHub Actions ... 85

Figura 74. Ejecución de nuestro flujo de trabajo en GitHub ... 86

Figura 75. Ejecución de los distintos pasos de nuestro flujo de trabajo en GitHub ... 87

Figura 76. Contenedor Docker de la aplicación ... 87

Figura 77. Falseado de datos para emulación de la aplicación React Native ... 88

Figura 78. Creación de un nuevo usuario para la validación del servicio ... 89

Figura 79. Listado con el nuevo usuario creado ... 89

Figura 80. Creación de una nueva ruta para validar funcionamiento del servicio con la aplicación React Native emuladora ... 90

Figura 81. Login mediante token de acceso en el emulador de la aplicación React Native ... 91

Figura 82. Comienzo del envío de datos en el emulador de la aplicación React Native ... 91

Figura 83. Generación de ruta basada en los datos recibidos del emulador de la aplicación React Native ... 92

Figura 84. Generación de la ruta completa en la prueba del emulador de la aplicación React Native ... 93

Figura 85. Generación de evento en función de los datos obtenidos del emulador de la aplicación React Native ... 93

Figura 86. Visualización de la ruta completa con el evento generado y su geofence, en la prueba de validación del emulador de la aplicación React Native. ... 94

(8)

8

Figura 87. Creación de la primera ruta para la primera prueba real ... 94

Figura 88. Origen y destino de la ruta para la primera prueba real. ... 95

Figura 89. Creación de Geofence para la primera prueba real ... 95

Figura 90. Creación de un segundo geofence para la primera prueba real ... 96

Figura 91. Creación de contenedores para la primera prueba real ... 96

Figura 92. Vista del funcionamiento de la aplicación React Native en la primera prueba real .. 97

Figura 93. Resultados de los códigos QR escaneados en la primera prueba real ... 98

Figura 94. Envío de datos en la primera prueba real mediante la aplicación React Native ... 98

Figura 95. Generación de la ruta seguida en la primera prueba real ... 99

Figura 96. Generación del primer evento en la primera prueba real ... 99

Figura 97. Generación del segundo evento en la primera prueba real ... 100

Figura 98. Vista de la aplicación React Native en la segunda prueba real ... 101

Figura 99. Vista del funcionamiento del escaneo de la aplicación React Native en la segunda prueba real ... 102

Figura 100. Ruta generada en la segunda prueba real ... 103

Figura 101. Generación de evento en la segunda prueba real ... 103

Figura 102. Comprobación de la localización de los contenedores creados al finalizar las pruebas ... 104

Figura 103.Estructura código backend, capa superior ... 110

Figura 104. Estructura código backend, capa inferior ... 111

Figura 105. Estructura código backend, capa inferior ... 111

Figura 106. Estructura código backend, capa inferior ... 112

Figura 107. Estructura código backend, capa inferior ... 113

Figura 108. Estructura código backend, carpeta ‘framework’ ... 114

Figura 109. Estructura código frontend, capa superior ... 115

Figura 110. Estructura código frontend, capa inferior ... 116

Figura 111. Estructura código frontend, capa inferior ... 117

Figura 112. Estructura código frontend, carpeta ‘app’ ... 118

Figura 113. Estructura código aplicación React Native ... 119

Figura 114. Esquema de ejemplo del funcionamiento de red IoT basada en MQTT ... 120

Figura 115. Canales BLE ... 122

Figura 116. Payload de un paquete BLE ... 123

Figura 117. Formato de un paquete iBeacon ... 123

Índice de tablas

Tabla 1. Roles de cada tipo de usuario ... 11

Tabla 2. Acceso a distintas secciones del frontend en función del tipo de usuario ... 68

(9)

9

(10)

10

Capítulo 1. Introducción y objetivos

1.1 Introducción y objetivos

En la época de digitalización en la que vivimos, poco a poco nos acercamos a la aspiración de tenerlo todo controlado. Desde neveras inteligentes que nos programan la compra, hasta coches autopilotados que en un futuro no muy lejano nos llevarán a donde queramos.

El mundo de la digitalización lo abarca todo, y por eso la oportunidad de digitalizar un servicio de gestión de rutas y activos, me pareció muy ilusionante desde el principio. La geolocalización digital se encuentra más extendida de lo que pensamos: cuando pedimos comida a domicilio, en la mayoría de aplicaciones podemos ver la posición exacta en un mapa de nuestra comida.

Cuando hacemos un pedido online en Amazon, podemos ver donde esta el repartidor cuando se encuentra a escasos kilómetros de nuestra vivienda.

La geolocalización, como usuarios, nos aporta un valor increíble. Pero tendemos a olvidar un valor mucho mayor que va implícito: la capacidad de controlar cada ruta y movimiento en una empresa transportista, les abre una gran ventana de oportunidades de mejorar su negocio y obtener un mayor rendimiento de su trabajo. Una gestión de rutas digitalizada permitiría a una empresa tener un gran registro de datos sobre las rutas que sus transportistas han completado:

qué ruta hacia cierto destino es más rápida, cual es más corta en cuanto a longitud, nivel de satisfacción con las estimaciones de tiempo y el tiempo del recorrido real…

Estos datos permiten a las empresas tomar acciones que casi con certeza les va a llevar a ser más productivas y efectivas. Eligiendo las rutas más cortas y menos concurridas, gastarían menos gasolina. Eligiendo las rutas más rápidas, proporcionarían una mayor satisfacción a sus clientes. Y realizando estudios de satisfacción con datos reales, obtendrían con claridad cuáles son los puntos en los que pueden mejorar.

En nuestro caso de estudio, se ha realizado un proyecto de geolocalización de activos a pequeña – media escala. Los objetivos que se han tratado de conseguir con la realización de este proyecto son:

- Conseguir geolocalizar a tiempo real una serie de activos.

- Lograr una persistencia sobre los datos referentes a las localizaciones pasadas, presentes y futuras de un activo.

- Registrar un listado con rutas que transportan, han transportado o transportarán activos.

- Enlazar la geolocalización de activos con distintos eventos.

- Realizar una gestión de stock de activos basada en su geolocalización.

(11)

11 - Ser capaces de realizar dicha geolocalización con el mínimo de recursos posibles:

mediante un teléfono móvil y con la adición de dispositivos IoT con capacidad de comunicación BLE.

- Educarnos en el plan de negocio de una empresa transportista y comprender sus necesidades más básicas.

- Formarnos en tecnologías web avanzadas, y buenas prácticas en metodologías DevOps.

Para entender mejor la solución, incluimos un esquema básico del proyecto:

Figura 1. Esquema general de nuestro servicio

La manera en la que conseguiremos obtener un servicio avanzado con una experiencia de usuario satisfactoria es definiendo qué tipo de usuarios van a usar el servicio. En este proyecto, hemos considerado tres tipos de usuarios: Conductores, Managers logísticos y Administradores.

Definimos una pequeña tabla para visualizar el rol que tendrá cada clase de usuario en nuestra aplicación

Usuarios Conductores Managers Logísticos Administradores

Gestionar usuarios ❌ ❌

Capturar datos de geolocalización

Dirigir rutas

Controlar el

inventario de activos

Manejar eventos ❌

Gestionar recintos y puntos de interés

Tabla 1. Roles de cada tipo de usuario

(12)

12

1.2 Herramientas software y elementos usados

Las herramientas utilizadas tanto para el desarrollo como para el testeo del proyecto son las siguientes:

Node – versión 17.7.2. Framework utilizado para desarrollar el proyecto.

Postman – versión 9.25.1. Herramienta de desarrollo utilizada para realizar peticiones a nuestro backend y comprobar su correcto funcionamiento.

Visual Studio Code – versión 1.70.2. IDE de desarrollo.

WebStorm – versión 2021.2. IDE de desarrollo. Durante la realización del proyecto, se comenzó a utilizar la suite de trabajo IntelliJ.

Android Studio – versión 2020.3.1 Patch 3. Framework de Desarrollo para aplicaciones Android. Provee de herramientas como la creación de emuladores Android.

Docker – versión 20.10.13. Herramienta de código abierto que permite la virtualización en contenedores de nuestra aplicación

DockerHub – Repositorio online de imágenes que componen los contenedores de Docker.

GitHub – Como herramienta en la nube para versionar nuestro código.

GitHub Actions – Herramienta de GitHub que nos permite realizar flujos de trabajo automáticos en la nube.

Webpack – versión 5.73.0. Compilador de módulos de JavaScript que permite controlar la construcción y compilación de cada bloque de código.

Jest -versión 28.1.2. Librería de código abierto que permite el testeo de código.

React – versión 18.2.0. Framework de desarrollo de aplicaciones web basado en JavaScript, del entorno de Node.

Fastify – versión 3.29.0. Framework de desarrollo web basado en Node. Usado para desarrollar parte del backend.

Expo – versión 5.4.4. Es un conjunto de herramienta de ejecución y compilación de código en desarrollo que nos permite desarrollar una aplicación basada en React Native de manera cómoda. Desarrollado por Meta.

(13)

13

▪ TypeScript. Lenguaje de programación tipado basado en JavaScript.

▪ React Native – versión 0.69. Framework basado en React y JavaScript que nos proporciona un entorno de desarrollo para aplicaciones móvil muy flexible.

(14)

14

1.3 Formación en tecnologías DevOps

Uno de los grandes retos de este proyecto es realizar un correcto despliegue que sea capaz de automatizarse con tal de alcanzar el concepto de integración continua, con el objetivo de ser capaces que proporcionar actualizaciones y funcionalidades nuevas al servicio de manera eficaz y continuada.

Para lograr esto, nos hemos ayudado de contenedores Docker, que serán desplegados a través de unas pipelines determinadas. Estas pipeline, nos son más que flujos de trabajo que se programan para contener todos los procesos necesarios para realizar un despliegue:

compilación y construcción de la aplicación, asignación de variables de entorno (como dirección host y puertos), “contenerización” de los distintos módulos del proyecto y desplegar nuestro contenedor en un entorno reservado en la nube.

Como se puede ver, la obtención de conocimientos de esta área, es clave para poder relacionar todos los módulos de nuestro proyecto y obtener un servicio funcional; por eso, gran parte de este trabajo se ha dedica a la investigación de las tecnologías más usadas y eficientes de este ámbito, así como de distintas aplicaciones a nuestro caso de uso para obtener un flujo de despliegue que nos aporte valor.

(15)

15

1.4 Metodologías de trabajo

Para la realización de este proyecto, se ha intentado tomar como referencia metodologías de trabajo bien conocidas en el mudo del desarrollo de software. Algunas de estas metodologías son:

Metodología ágil. La metodología ágil en software envuelve un enfoque para la toma de decisiones en los proyectos basado en el desarrollo iterativo e incremental, donde los requisitos y soluciones del proyecto van evolucionando conforme el desarrollo avanza.

Desarrollo basado en el testeo. Metodología que se basa en desarrollar código con tests. Esta metodología indica que es una buena práctica realizar el test de una funcionalidad antes de escribirla en código. De esta manera obtenemos una claridad sobre la misma adicional, así como una garantía sobre el código desarrollado.

Integración continua. Metodología basada en el despliegue del producto de manera continua, ya sea mensualmente, semanalmente o en un caso ideal, diariamente.

Clean Code. Se ha tratado de aplicar fundamentos de código limpio con el objetivo de obtener un código lo más estructurado y mantenible posible. Algunos de estos fundamentos son:

⎯ Aproximación a la arquitectura hexagonal. En todos los componentes compositores de este proyecto, frontend, backend y aplicación basada en React Native, se ha tratado de aplicar una estructura hexagonal, donde las capas exteriores y más vulnerables corresponden a aquellas con las que el usuario suele interactuar, mientras que las interiores al core del funcionamiento de nuestro servicio (como puede ser la lógica de negocio aplicada).

Figura 2. Ejemplo de Arquitectura Hexagonal

(16)

16

⎯ Aislamiento de código. Para perservar el código lo más mantenible posible, se ha tratado de aislar cada funcionalidad al máximo posible. Un código muy enlazado o dependiente de otros segmentos de código suele provocar quebraderos de cabeza cuando hay que migrar una parte de él o simplemente actualizarla. De esta manera, por ejemplo en el frontend, si tuviéramos que cambiar el funcionamiento de una tabla, no tendría porque afectar en ningún momento a la sección que contuviese esa tabla.

⎯ Tree shaking. Esta técnica, en el desarrollo de software, es una técnica utilizada para eliminar el máximo de código intranscendente, optimizando la compilación y ejecución del resto del código.

Figura 3. Ejemplo de Tree Shake

En la Figura 4 podemos ver como exportamos todo el código de nuestro archivo

‘models’, dado que contendrá modelos de datos que nos harán falta. Sin embargo, advertimos como solamente exportamos el componente ‘TrackingComponent’ a las capas superiores, haciendo irrelevante todo el código por debajo de esta capa para su correcto funcionamiento. Esto optimizará la ejecución de componentes que necesiten llamar a ‘TrackingComponent’.

→ Variables declarativas. Se ha tratado de proponer nombres de variables y funciones de manera declarativa, que expresen su propósito, funcionalidad o naturaleza, con tal de obtener un código legible.

(17)

17

1.5 Estructura y organización del proyecto

Para comprender la estructura de esta memoria, la hemos dividido en cinco capítulos, sin contar el actual:

2. Diseño e implementación de la app del conductor. Explicación del framework utilizado para desarrollar la aplicación con la que el conductor realizará el tracking de activos.

Exposición de sus distintos modos de funcionamiento y descomposición de la app en módulos para facilitar su comprensión.

3. Diseño del servidor. Descripción de los distintos framework utilizados para desarrollar el servidor, que contendrá la mayor parte de lógica de negocio del servicio. Desarrollo de la implementación de la lógica de negocio y de la persistencia de datos. Diseño de la arquitectura desarrollada para lograr la integración entre todos los componentes del backend.

4. Diseño e implementación del frontend. Explicación del framework de desarrollo utilizado. Declaración de la estructura y diseños aplicados en relación a la experiencia de usuario. Desarrollo de las distintas secciones que componen el frontend. Explicación de la autenticación de peticiones y usuarios.

5. Pruebas y despliegue. Exposición de la estructura e infraestructura usada para desplegar el servicio. Explicación de las tecnologías usadas para realizar despliegues.

Desarrollo de las pruebas realizadas para validar el servicio.

6. Conclusiones y trabajos futuros. Declaración de conclusiones obtenidas con la finalización del proyecto. Evaluación de objetivos alcanzados. Valoración sobre los posibles trabajos futuros conforme al servicio logrado.

(18)

18

Capítulo 2. Diseño e implementación en React Native de la app del conductor.

Como ya hemos descrito anterior y brevemente, React Native es un framework basado en el lenguaje de JavaScript. Desarrollado por Meta Platforms Inc., React Native nos permite crear aplicaciones con elementos nativos de cada sistema operativo, ya sea en Android o iPhone. Esto quiere decir que cada aplicación que programemos en React Native traduce nuestros componentes en elementos visuales nativos reales; lo cual es de una gran importancia. Esto se debe a que, para ponernos en contraste, otros framework de desarrollo como Ionic o Cordova lo que hacen es sustituir dichos elementos visuales nativos por unos nuevos muy similares visualmente, y que imitan su comportamiento.

Figura 4. Funcionamiento del Framework de React Native.

Mientras esta característica de los framework mencionados es totalmente válida para crear una aplicación multiplataforma que funcione correctamente, es conocido que perjudica mucho en la rapidez y eficiencia de la misma, puesto que crear componentes nuevos y renderizarlos siempre será mucho más costoso de ejecutar y compilar que un componente nativo que ya está presente en el propio sistema operativo.

La función principal de nuestra aplicación basada en React Native, es la de transmitir el estado de la mercancía o contenedores a nuestro servidor. Como veremos a continuación, es capaz de realizar esta funcionalidad de varias maneras, dado que se ha intentado realizar una aplicación lo más flexible posible.

(19)

19

Figura 5. Esquema simplificado del rol de la aplicación React Native

Para lograr el comportamiento deseado de la aplicación, nos hemos ayudado de una serie de dependencias externas:

▪ React-native-ble-plx. Librería que nos permite escanear dispositivos BLE utilizando el módulo Bluetooth.

▪ Sp-react-native-mqtt. Librería que nos proporciona las herramientas adecuadas para poder establecer una conexión vía MQTT [2]. Usaremos estas herramientas para conectarnos al Context Broker y publicar mensajes.

▪ React-native-location. Dependencia que incluye un módulo de geolocalización que nos permite acceder a las coordenadas de nuestra ubicación en tiempo real.

▪ React-native-device-info. Dependencia que nos permite obtener información del dispositivo. Usada para estudiar la compatibilidad de distintas librerías y módulos durante el desarrollo.

▪ React-native-qrcode-scanner. Dependencia que nos permite escanear códigos QR.

Proporciona una funcionalidad que abre la cámara para escanear un código QR. Recupera los datos del código fácilmente

(20)

20

2.1. Arquitectura app React Native

El diseño de la arquitectura de nuestra aplicación basada en React Native se divide en varios componentes o módulos:

▪ Un componente visual, que incluye todos los elementes visuales que forman la interfaz de usuario.

▪ Un módulo de autenticación, que se encarga de autenticar cada inicio de sesión, así como cada mensaje entrante o saliente de la aplicación.

Figura 6. Esquema del comportamiento en cuanto a elección de funcionalidad de la aplicación React Native

(21)

21

Figura 7. Esquema del funcionamiento de la autenticación y obtención de datos inicial de la aplicación React Native

El funcionamiento de este módulo es el siguiente:

1. Se descompone el JSON WebToken introducido por el usuario en el Login. Se obtienen el ID de usuario y el token autenticador y se envían mediante una petición HTTP al servidor.

2. El servidor realiza una query a la base de datos de mongo buscando el ID de usuario proporcionado y obteniendo su token, en caso de que exista.

3. La base de datos mongo responde con el resultado de la query.

4. El servidor verifica que el ID de usuario existe y autentica el token recibido de la app contra el recibido en la base de datos.

5. Una vez autenticado, se permite al usuario acceder a la interfaz de usuario de la aplicación.

6. En ese momento, la aplicación realiza una petición HTTP para obtener la configuración del usuario y las rutas que pudiera tener asignadas.

7. El servidor recibe la petición y realiza queries a las bases de datos Mongo y PostGIS, para obtener la configuración y las rutas (si existiesen), respectivamente.

8. Sí existen, el servidor prepara la configuración y rutas recibidas para ser enviadas.

9. El servidor responde a la petición GET de la aplicación con los resultados.

(22)

22

▪ Un módulo funcional, que contiene la funcionalidad que aplica nuestra lógica de negocio. Dicha funcionalidad se puede descomponer en varias partes:

− Configurador dinámico. La aplicación solicitará a nuestro servidor la configuración elegida para el dispositivo. Esta configuración elegirá entre uno de los módulos explicados a continuación. Si no se especifica ninguna configuración, se cogerá una por defecto.

Figura 8. Diagrama de flujo para determinar la funcionalidad a seguir

− Ciclos de trabajo y escaneo BLE. Nuestra aplicación es capaz de realizar escaneos basados en BLE y de detectar todos los dispositivos en su radio de alcance.

Inmediatamente después de este escaneo, se realiza un filtrado basado en un UUID proporcionado. La idea es que cada dispositivo o sensor, esté configurado con este UUID para ser capturado por nuestra aplicación. Estos escaneos dependen de unos ciclos de trabajo.

− Escaneo por código QR. Si por el contrario el usuario no tuviese la necesidad de realizar escaneos constantes para comprobar que los contenedores siguen en el radio de alcance, la aplicación tiene la capacidad de registrar en un listado los contenedores presentes en el transporte. Esta funcionalidad asume que los contenedores no se verán desplazados fuera del transporte hasta llegar a su destino.

(23)

23

2.2. Generación listado contenedores con códigos QR

La generación del listado de contenedores mediante códigos QR corresponde a la funcionalidad mencionada anteriormente. Esta funcionalidad, en nuestra aplicación React Native, se puede dividir en tres fases:

▪ Fase de recepción de datos. Si del módulo funcional de configuración dinámico hemos recibido instrucciones sobre que la funcionalidad a utilizar es la de generación de listado mediante códigos QR, recibiremos también en el mismo mensaje un listado de los contenedores a registrar.

▪ Fase de registro de contenedores mediante escaneo de códigos QR. Si se desea utilizar esta funcionalidad, se presupone que cada contenedor lleva asociado un código QR, o que el transportista o usuario tenga a su disposición, como mínimo, un listado de códigos. El usuario o transportista procede a escanear los códigos QR. Esta operación se puede realizar tanto al inicio de una ruta como a su finalización.

▪ Fase de envío de posición en coordenadas GPS. Esta fase es común tanto en esta funcionalidad como en la de escaneo periódico BLE [3]. Periódicamente, en función de un parámetro, ya sea recibido en la configuración o por defecto si no se recibe, se envía la posición en coordenadas GPS al servidor.

También se indica que con el fin de hacer la aplicación lo más flexible posible, la funcionalidad de envío de posición en coordenadas GPS dentro de este módulo es opcional. Si no se especifica lo contrario en la configuración (por defecto), esta funcionalidad está activada. Si no se activa, al llegar al destino, para poder finalizar la ruta, tendrá que realizar un envío de posición obligatoria (como lo haría al inicio de la misma) para verificar la finalización de la ruta.

Figura 9. Esquema del funcionamiento del modo de uso mediante Listados QR

(24)

24 De esta manera, de forma resumida, el usuario puede: registrar contenedores mediante códigos QR y determinar el transporte de estos contenedores, registrando su origen y destino en coordenadas GPS.

Como nota final, cabe decir que por defecto el envío de todos los datos (tanto periódicos como no) se usará MQTT [2], aunque existe la posibilidad de usar HTTP.

(25)

25

2.3. Consultas periódicas GPS y envío de datos JSON por MQTT

Si se elige esta funcionalidad, la aplicación escaneará mediante BLE [3] cada cierto tiempo, en ciclos de trabajo que se repiten según otro tiempo establecido. Teniendo esto en cuenta, descomponemos la funcionalidad de este módulo:

▪ Fase de recepción de datos. Como en la funcionalidad anterior, si en la configuración de usuario recibida hemos obtenido que la funcionalidad es la de Scan BLE [3], también habremos recibido los parámetros relativos al tiempo de escaneo y al período de los ciclos de trabajo. Además, como en el caso anterior, se recibe información relativa a las rutas.

▪ Inicio de ruta. El conductor elige una ruta asignada. Pulsa sobre ‘Iniciar Ruta’.

Mientras el usuario elige la ruta, se inicializan los módulos de escaneo vía BLE [3] y de geolocalización

▪ Ciclos de trabajo. En el momento de inicio de la ruta, comienza el primer ciclo de trabajo.

Figura 10. Diagrama de flujo sobre el funcionamiento de Scan BLE

(26)

26 En la Figura 11 observamos el flujo que siguen nuestros ciclos de trabajo: en primer lugar se escanea por BLE [3] y se filtran los dispositivos escaneados en función del UUID recibido. En segundo lugar, se compone el mensaje GeoJSON, con parámetros como el número de secuencia, el ID del usuario escaneando, el ID de la ruta asociada o el timestamp (fecha de generación del paquete). Se publica el mensaje por MQTT [2] al tópico establecido. La aplicación entra en modo espera hasta que se cumpla el período fijado por el ciclo de trabajo. Una vez cumplido inicia el siguiente ciclo siguiendo los mismos pasos.

Al igual que la funcionalidad de listados mediante códigos QR, el conductor al pulsar sobre el botón que indica la finalización de la ruta, cesan los ciclos de trabajo.

(27)

27

2.4 Funcionalidad adicional.

La funcionalidad que desarrollaremos en este apartado es común para toda la aplicación.

En primer lugar, tenemos un sistema de colas muy simple, que entra en acción cuando un paquete no se ha podido publicar. Si esto pasa, cada paquete que posteriormente que se vaya generando se irá introduciendo en nuestro sistema de colas. En el momento que un paquete gestado se publique correctamente, ya no entrará en nuestro sistema de colas y se pausará la formación de paquetes durante unos instantes hasta que se hayan publicado, por orden de llegada, los paquetes almacenados en la cola. Una vez vaciada la cola, se resume la generación de paquetes GeoJSON y la funcionalidad normal de la aplicación.

Figura 11. Diagrama de funcionamiento del sistema de colas

Como se puede observar, nuestro sistema de colas es de tipo FIFO (First In First Out). Realmente se trata de un sistema muy simple que va guardando los mensajes no enviados en un Array.

En segundo lugar, existe la funcionalidad de crear una ruta. Si el usuario inicia sesión con su token y no tiene la ruta que deseaba asignada, existe un botón con ‘Crear ruta’. Al pulsarlo, el conductor automáticamente comienza la generación de paquetes en función del modo de uso (listado QR o Scan BLE [3]). Cuando se da este caso, al tópico contra el que apuntará la aplicación para poder publicar será el tópico general de la aplicación, de esta manera los datos se publicarán correctamente, con la excepción de que el camino seguido y la localización de los contenedores no estarán asignados a una ruta. En el funcionamiento normal de la aplicación, cuando se tiene rutas asignadas, el tópico contra el que se apunta es el ID de la ruta seleccionada.

(28)

28

Capítulo 3. Diseño del backend y BBDD del servidor

Nuestro backend está formado por varios módulos: un CRUD basado en Fastify, un context bróker basado en EMQX, un cliente MQTT, una base de datos relacional basada en PostGRES y una base de datos basada en MongoDB.

Figura 12. Arquitectura general de nuestro servicio

El orquestador principal en el backend será nuestro CRUD o servidor basado en Fastify, dado que esté contendrá implícitamente a nuestro Cliente MQTT, así como la mayoría de la lógica de negocio y funciones validadoras y autenticadoras.

(29)

29

Figura 13. Módulo del backend

Hemos decidido basar nuestro servidor en el framework web de Fastify por diversas razones.

Como su nombre sugiere, la principal característica de Fastify es la rapidez. Sus creadores afirman que actualmente es capaz de servir más de 30.000 peticiones por segundo. Además, en varios benchmark disponibles en la red se confirma que Fastify es ligeramente superior en cuanto a rapidez frente al framework de servidores web de JavaScript por excelencia, Express.

Fastify provee a los desarrolladores de herramientas complejas y variadas para atender cada petición según sus necesidades, como hooks, plugins o decoradores. Por otra parte, incluye el uso de esquemas basados en JSON para validar rutas y peticiones. Incluye un logger muy eficaz, el cual consume muy pocos recursos, conocido como Pino. Finalmente, es un framework enfocado a dotar de flexibilidad al desarrollo de código sin sacrificar eficacia y seguridad, siendo fácilmente integrable con técnicas de testeo de código y compatible con TypeScript.

Para complementar nuestro servidor basado en Fastify, nos hemos ayudado de diversas librerías externas:

▪ MQTT.js. Librería utilizada para realizar subscripciones y publicaciones dirigidos a nuestro Context Broker EMQX.

▪ Jsonwebtoken. Librería empleada para generar tokens seguros y validar tanto usuarios como peticiones.

▪ Bcrypt. Librería que complementa a Jsonwebtoken para encriptar y desencriptar distintos parámetros: tokens, contraseñas…

▪ PG. Librería de PostGRE SQL que nos permite utilizar funciones para realizar queries a nuestra base de datos PostGIS.

▪ Knex. Librería que actúa como un CRO de PostGRES, proporcionándonos una manera más sencilla de conectarnos y realizar consultas a nuestra base de datos PostGIS.

▪ MongoDB. Librería de MongoDB que utilizamos para conectarnos y realizar consultas a nuestra base de datos de MongoDB.

▪ Pino. Librería que usaremos como logger del servidor.

▪ Jest. Librería de testeo que destinaremos para realizar tests sobre nuestro código.

(30)

30

▪ Fastify/cors. Librería de CORS (intercambio de recursos de origen cruzado) que usaremos para controlar el acceso de peticiones HTTP hacia nuestro servidor.

▪ TypeScript. Lenguaje tipado basado en JavaScript del que haremos uso para desarrollar todo el código fuente.

▪ Convict. Librería que nos proporciona una plantilla de configuración. Usaremos esta plantilla para configurar el acceso a distintas bases de datos y para determinar varios parámetros necesarios: como la dirección host HTTP y puerto.

(31)

31

3.1 Arquitectura del backend y BBDD

Para comprender completamente el diseño de nuestra arquitectura en el backend, primero hemos de entender cómo funciona cada módulo y cómo se relacionan entre sí.

Comenzaremos con una breve explicación de la composición y funcionamiento de cada uno de ellos:

▪ Context Broker basado en EMQX. La responsabilidad del Context Broker es la de recibir y gestionar datos. Esto incluye realizar una serie de acciones determinadas, si son especificadas, en base a los datos recibidos. En nuestro caso de uso, el Context Broker recibe datos primariamente mediante MQTT [2], aunque también es capaz de recibir por HTTP. En términos más técnicos, el Context Broker es el principal encargado de gestionar suscripciones y tópicos.

Figura 14. Ejemplo de funcionamiento del Broker EMQX

Además, el Context Broker de EMQX nos proporciona una variedad de herramientas ya instaladas: un dashboard, distintos endpoints ya configurados, logs... a los que el administrador del sistema tiene acceso.

(32)

32

Figura 15. Dashboard del Context Broker

▪ Cliente MQTT. La función principal de nuestro cliente MQTT es la de suscribirse a tópicos para recibir datos provenientes del Context Broker. Una vez recibidos estos datos, realizará una autenticación y validación más extensiva de los mismos.

▪ CRUD basado en Fastify. Este módulo ha de ser capaz de desempeñar el papel de interconexionar los demás módulos. Es el encargado de proveer datos para su explotación a nuestro frontend, así como de gestionar las acciones recibidas desde el mismo. Tiene la capacidad de crear, leer, actualizar y eliminar datos, en función de nuestra lógica de negocio y de ciertos parámetros como acciones de un usuario, alarmas o eventos.

▪ Base de datos relacional basada en PostGRES. Se usará para garantizar la persistencia de datos con algunas correlaciones entre sí, como datos de geolocalización y rutas.

▪ Base de datos no-relacional basada en MongoDB.

De forma general, volviendo a poner el foco en el backend, estudiaremos su comportamiento mediante la relación de los distintos módulos.

(33)

33

Figura 16. Diagrama de las comunicaciones entre los módulos que componen el backend

Como ya hemos comentado, observamos en el esquema anterior que el Context Broker obtiene una serie de datos del exterior, y los provee a nuestro cliente MQTT. Nuestro cliente MQTT validará estos datos y realizará peticiones SQL para almacenarlos donde corresponda. Dichos datos serán extraídos de la base de datos relacional para su explotación en función de nuestro CRUD. Los datos se validan y complementan con otros datos obtenidos de nuestra base de datos no-relacional. De esta manera, nuestro backend tiene la capacidad de autenticar, establecer relaciones y de servir datos completos para su explotación en nuestro frontend.

Para entender mejor la funcionalidad de nuestra arquitectura, nos ayudamos de algunos cronogramas.

(34)

34

Figura 17. Cronograma de la publicación y persistencia de un dato.

1. El dispositivo publica los datos a un tópico vía MQTT [2].

2. El Context Broker recibe la publicación [2] de los datos asociada a un tópico.

3. El cliente MQTT obtiene los datos así mismo mediante una subscripción [2] al mismo tópico. Realiza una validación y un formateo de los datos obtenidos.

4. Realiza una petición SQL a nuestra base de datos relacional para guardar los datos donde correspondan.

(35)

35

Figura 18. Cronograma sobre la recuperación de datos a mostrar en el frontend.

1. El CRUD recibe y valida la petición del frontend.

2. Realiza la petición SQL a la BDD para obtener los datos requeridos.

3. Se realiza otra petición a la BDD no-relacional para autenticar y verificar los datos.

Se formatean para facilitar su explotación.

4. El CRUD envía los datos formateados.

Nuestro CRUD, que atiende peticiones del frontend, realizará peticiones SQL para recuperar los datos.

(36)

36

3.2 Gestión de geofence y eventos de entrada y salida

Para dotar de capacidad a nuestro sistema de registrar y gestionar eventos, nos ayudamos de Geofence. Desde nuestro frontend se permite al usuario crear, actualizar y gestionar nuestros Geofence. La arquitectura de la gestión de los mismos está incluida en el backend, así como la de los eventos provocados por ellos.

Figura 19. Cronograma de la creación de un nuevo Geofence en el sistema

1. El usuario crea un Geofence en el frontend y lo guarda. Los datos de ese Geofence se envían en una petición POST con el formato de un GeoJSON.

2. El CRUD recibe la petición y la valida. Autentica al usuario y compruebe que los datos recibidos son correctos.

3. Después de la validación, el CRUD realiza una petición SQL para guardar el Geofence en nuestra base de datos relacional, en su tabla correspondiente.

4. En el frontend, el usuario puede ver los Geofence existentes. Para ello se realiza una petición GET.

5. El CRUD después de validar y autenticar la petición realiza una solicitud SQL a la base de datos.

6. La base de datos responde con el resultado de la consulta.

7. El CRUD formatea los datos recibidos y los envía de vuelta al frontend como respuesta.

(37)

37 La arquitectura y funcionamiento del backend para eliminar y actualizar Geofence es similar.

Para proporcionar la capacidad de poseer y gestionar eventos a nuestro sistema, establecemos en cada validación de dato GPS recibido la comprobación de estar o no en un Geofence.

De esta manera, nuestro sistema es capaz de saber cuándo un dispositivo entra en un Geofence, que se encuentra en el mismo y de cuando sale de este.

Figura 20. Ilustración referente a un Geofence

En otras palabras, cuando nuestro sistema recibe un GeoJSON y compruebe que por primera vez se encuentra dentro de las coordenadas de un Geofence, se generará un evento de entrada. Y cuando se compruebe un GeoJSON que se encuentre fuera del Geofence después de un evento de entrada, se generará un evento de salida.

Para el siguiente cronograma supondremos que el cliente MQTT se encuentra subscrito a un determinado tópico MQTT [2].

(38)

38

Figura 21. Cronograma referente a la generación de eventos del sistema

1. Un dispositivo publica su GeoJSON al tópico.

2. El Context Broker recibe la publicación [2].

3. El cliente MQTT recibe el GeoJSON por subscripción [2].

4. Realiza una petición SQL para guardar el GeoJSON.

5. Realiza otra petición para obtener las coordenadas de los Geofence almacenados.

6. Se evalúa si las coordenadas del último GeoJSON recibidas se encuentran o no dentro del perímetro del Geofence.

7. Si lo están, se generará el evento de entrada. Si ya se había generado este evento y el GeoJSON recibido anterior al actual se encontraba en el Geofence, se generará el evento de salida.

(39)

39

3.3 Almacenamiento datos en BBDD MongoDB

Para entender la estructura de nuestra base de datos, es importante que primero definamos los modelos de datos de mayor importancia que ejercen en nuestra base de datos no relacional.

▪ Usuario: Forma el modelo de datos de cada usuario.

Figura 22. Modelo de datos que definen a un usuario en el servidor

Se tienen las siguientes propiedades:

− role: definen el rol del usuario. Como se puede ver en la zona superior de la figura:

administrador, administrador de la compañía, transportista o conductor y administrador logístico.

− id: identificador del usuario.

− name: nombre del usuario.

− token: token autenticador del usuario.

− email: propiedad opcional que contiene el email del usuario.

− company: propiedad opcional que contiene la compañía a la que pertenece el usuario.

▪ Configuración de usuario: contiene configuración del usuario, primariamente de transportistas.

Figura 23. Modelo de datos que rigen las configuraciones de usuario en el servidor.

(40)

40 Se tienen las siguientes propiedades:

− userId: contiene el identificador del usuario al que se aplica la configuración.

− scanInterval: incluye el tiempo en segundos de la duración de cada escaneo.

− workInterval: abarca el tiempo en segundos de la duración de cada ciclo de trabajo.

− sensorUUID: contiene el UUID de los contenedores a escanear.

− api: engloba la dirección URL sobre la cual mandará los datos GeoJSON de cada ciclo de trabajo.

▪ Eventos. Modelan los distintos eventos de nuestro sistema.

Figura 24. Modelo de datos que componen los eventos de nuestro servidor.

Se tienen las siguientes propiedades:

− type: determina el tipo del evento: entrada o salida de un geofence y contenedor perdido.

− routeID: incluye el identificador de la ruta donde se ha producido un evento.

− driverID: hace referencia al identificador del conductor que ha producido el evento.

− eventID: determina el identificador del evento generado.

− eventName: incluye el identificador del evento generado.

Normalmente, en el caso de los eventos, el identificador y nombre de estos suelen ser referentes al Geofence por el que han sido generados.

Por tanto, nuestra base de datos Mongo DB se encargará de almacenar tres colecciones de datos:

▪ Usuarios

▪ Configuraciones de usuario

▪ Eventos

Para insertar o recuperar datos de cada colección, se utilizan queries de Mongo. Para poder conectarnos satisfactoriamente a nuestra base de datos Mongo desde nuestro servidor Fastify, nos ayudamos de una configuración:

(41)

41

Figura 25. Configuración por defecto de nuestra BBDD Mongo

Después utilizaremos esta configuración para realizar la conexión:

Figura 26. Conexión desde el servidor a nuestra BBDD Mongo

(42)

42

3.4 Procesamiento datos GPS y almacenamiento en BBDD PostGIS

El procesamiento de datos GPS se relaciona intrínsecamente con nuestra base de datos relacional PostGIS. Realmente, es una base de datos relacional basada en PostGRESQL, pero siguiendo modelos de datos definidos en PostGIS.

Los principales modelos de datos que ejercen sobre nuestra base de datos PostGIS son:

▪ GeoJSON. Se utiliza este modelo para definir las coordenadas de un punto o Geofence.

Figura 27. Modelo de datos que forma los mensajes referentes a la geolocalización

Se tienen las siguientes propiedades:

− type: propiedad que se utiliza para incluir datos específicos en determinados GeoJSON, como podría ser aquel de generación de evento de entrada.

− desc: Descripción del GeoJSON.

− session: ID o nombre de la sesión en la que se están mandando datos.

− ns: número de secuencia del GeoJSON enviado.

− timestamp: fecha en la que se ha generado el GeoJSON.

− containers: propiedad opcional que incluye los contenedores o bultos del GeoJSON.

− routeID: propiedad opcional que contine el identificador de la ruta.

− driverID: propiedad opcional que contiene el identificador del transportista.

− geometry: incluye las propiedades geoespaciales del paquete.

→ type: determina si es un punto, recinto…

→ coordinates: incluye las coordenadas GPS del GeoJSON.

(43)

43 Nótese que las propiedades opcionales, como su nombre indica, no tienen por qué ir incluidas en todos los paquetes GeoJSON, sino solo en aquellos que sean necesarios en función del usuario y de la lógica de negocio.

▪ Rutas: el modelo de datos de nuestras rutas.

Figura 28. Modelo de datos de las rutas

Se tienen las siguientes propiedades:

− routeName: nombre de la ruta.

− routeID: identificador de la ruta.

− routeDescription: descripción de la ruta.

− routeDriverName: nombre del transportista asignado a esa ruta.

− routeDriverID: identificador del transportista asignado a esa ruta.

− status: incluye el estado de la ruta: activa, inactiva o finalizada.

− routeGeometry: contiene datos geoespaciales de la ruta.

→ origin: se refiere a las coordenadas de origen de la ruta.

→ destination: engloba las coordenadas del destino de la ruta.

− routeCreatedAt: fecha en la que se crea la ruta.

− routeExpectedStart: fecha en la que se prevee comenzar la ruta.

− routeExpectedFinish: fecha en la que se prevee la finalización de la ruta.

− routeDeadline: fecha opcional en la que se prevee la fecha límite para completar una ruta.

Para realizar consultas a nuestra base de datos PostGIS, usaremos queries de SQL. Para poder realizar estas queries, hemos de estar conectados a nuestra base de datos; como en el caso de Mongo, nos ayudamos de un fichero de configuración:

(44)

44

Figura 29. Configuración de nuestra BBDD PostGRESQL

(45)

45 Y mediante esta configuración, realizamos la conexión a nuestra base de datos, con ayuda del CRO de ‘knex’:

Figura 30. Conexión a nuestra BBDD PostGRESQL mediante KNEX

(46)

46

Capítulo 4. Diseño e implementación del frontend GIS usando Leaflet

Para el desarrollo del frontend de esta aplicación hemos utilizado React. React es una librería basada en JavaScript que se utiliza para crear interfaces de usuario. Fue desarrollado y es mantenido en gran parte por Meta (antiguamente Facebook).

React para muchos, es el framework de frontend más utilizado, por diversas razones:

▪ Curva de aprendizaje inicial no muy compleja.

▪ Código declarativo. React es un framework que se encarga de realizar el “trabajo sucio”

de manera ímplicita, por lo que el desarrollador puede centrarse exclusivamente en el desarrollo de la vista o interfaz gráfica. React actualizará y renderizará esta vista en función de una serie de datos o estados, lo que permite al programador crear código más legible y predecible.

▪ Rapidez. Como es normal, la experiencia de usuario en una página o aplicación web, se ve ampliamente potenciada si esta es capaz de proporcionar un renderizado y funcionalidad rápida y fluida. Como podemos ver en la Figura 32, React primero renderiza un DOM de manera virtual, que es una copia exacta del DOM real. Cada vez que se detecte un cambio o actualización en el DOM, React compara los componentes de ese DOM, cambiando solamente el que ha de ser actualizado. Por ejemplo, si en una vista tuviéramos un título de cabecera y una tabla con tres filas: al cambiar los datos de la segunda fila, React detectaría este cambio y volvería a renderizar únicamente esa segunda fila de la tabla, sin tocar el título, la tabla y las demás entradas.

▪ Reusabilidad. React es un framework que se basa en la creación y renderización de componentes. Un mismo componente se puede utilizar muchas veces; sin embargo, solo tendríamos que programarlo una única vez. Un ejemplo sería el menú lateral de una página.

Figura 31. Flujo de renderizado de React

(47)

47

▪ Testing. React ofrece diversas capacidades para que los desarrolladores puedan testear su código. Una de las más conocidas y usadas es la librería Jest, desarrollada originalmente también por Meta.

▪ Variedad. Al ser uno de los frameworks más utilizados, los aportes y librerías creados por la comunidad son incontables.

▪ Escalabilidad y mantenibilidad. React es un framework que permite integrar de manera sencilla plugins externos. Además, tiene la capacidad de renderizar de manera eficaz cientos y cientos de componentes. Estos y otros diversos motivos hacen que una aplicación basada en React sea fácil de actualizar, haciéndola más mantenible.

Para la realización de nuestro frontend basado en React, nos hemos ayudado de las siguientes librerías:

▪ MaterialUI. Es una librería de código abierto que se suele utilizar para el diseño de distintos componentes. Esta librería proporciona los elementos visuales de Google para poder ser customizados e implementados de manera sencilla. Por ejemplo, en la Figura 36 tenemos una serie de gráficas que son componente estilizados con MaterialUI, así como una cabecera y un menú tipo “drawer” que también son de MaterialUI.

Figura 32. Ejemplo de menú tipo Drawer

(48)

48

▪ React Router. Librería que se utiliza para asignar rutas a componentes. También nos permite navegar entre ellas con una gran cantidad de opciones: portar parámetros, navegar con estados, permitir rutas a ciertos usuarios… Es una librería indispensable para prácticamente cualquier aplicación de React.

▪ React Query. Librería avanzada que nos permite realizar peticiones en segundo plano.

Tiene una gran cantidad de opciones: cachear peticiones que aún no se han “producido”

(por ejemplo, al acceder a un componente se realiza una petición para adquirir ciertos datos; con react query, antes de acceder a él está petición se ha realizado en segundo plano y ha guardado los datos en una caché, por lo que, al acceder al componente, tenemos los datos ya disponibles), asignar estados o parámetros de tiempo para refrescar las peticiones con datos nuevos. Es una librería que a simple vista parece simple, pero incluye funcionalidades complejas que pueden resultar de gran ayuda. Mucha gente la define como una “manejador de estados”.

▪ Webpack. Es una librería de código abierto que se encarga de transformar módulos y bloques de código de frontend en bloques de código de HTML, CSS y JavaScript. Es decir, compila nuestra aplicación tomando nuestros módulos como dependencias dinámicas y genera archivos estáticos que contienen estos módulos. Teniendo una gran cantidad de opciones de compilación y ejecución, es una librería esencial para cualquier aplicación Web.

Figura 33. Ejemplo de Dashboard basado estilizado con Material UI

(49)

49

▪ EsLint y Prettier. EsLint es una librería que proporciona reglas sobre el formato de nuestro código a nuestro IDE de desarrollo, por ende, nos permite seguir el mismo formato en todo nuestro código. Prettier complementa a EsLint con reglas adicionales y además facilita mediante un formateador que aplica las reglas de estilo.

▪ Jest. Es nuestra librería para testear código.

▪ i18Next. Librería de traducción, por si en un futuro se quiere servir el contenido en un idioma distinto al castellano. Es una buena práctica usar este traductor para asignar textos, aunque no se traduzcan, puesto que estos se almacenan todos en un archivo JSON, y en el momento que cambie alguno (el contenido visual como imágenes y textos suelen ser los elementos más propensos a cambiar en una página web) simplemente el desarrollador lo cambiará en ese archivo y no en todas las secciones de código en las que esté ese texto.

▪ Leaflet. Es una librería de código abierto que nos permite renderizar mapas basados en OpenStreetMap. Se desarrolla en más detalle en el siguiente capítulo.

▪ Leaflet Draw. Librería que nos permite dibujar formas geométricas en un mapa de Leaflet. La usaremos para dibujar los recintos de nuestros Geofence.

▪ Leaflet MarkerCluster. Librería que nos permite agrupar elementos de geolocalización de un mapa en nodos o clústeres.

▪ Jsonwebtoken. Librería empleada para generar tokens seguros y validar tanto usuarios como peticiones.

▪ Bcrypt. Librería que complementa a Jsonwebtoken para encriptar y desencriptar distintos parámetros: tokens, contraseñas…

Figura 34. Bundler de webpack

(50)

50

▪ React-qr-code. Dependencia que nos permite generar nuestros propios códigos QR a partir de unos datos.

Finalmente, la arquitectura de nuestro frontend comprenderá las siguientes secciones:

− Login

− Dashboard

− Listado de usuarios

→ Formulario para crear un nuevo usuario.

→ Configuración de usuario. Editable.

− Listado de contenedores

→ Formulario para registro de contenedor.

→ Detalles de contenedor.

− Listado de rutas

→ Formulario para crear una nueva ruta.

→ Detalles de una ruta.

− Visualización de contenedores en Leaflet

− Listado de Geofence

→ Formulario para crear un nuevo Geofence.

→ Detalles de un Geofence.

− Listado de eventos

→ Detalles de un evento.

(51)

51

4.1 Arquitectura del frontend GIS de visualización basado en Leaflet

La arquitectura de nuestro frontend tenía como objetivo principal la visualización de la geolocalización de nuestros contenedores en un mapa. Para esto hemos utilizado Leaflet.

Figura 35. Primera versión de visualización de rutas y contenedores

Leaflet es una librería basada en JavaScript de código abierto, que principalmente se utiliza para crear mapas en aplicaciones web. Su mayor ventaja es su simpleza y eficacia, puesto que solo pesa 42 kB y funciona de manera perfecta y fluida en la mayoría de plataformas.

Gracias a que es una librería de código abierto, tiene una gran variedad de plugins y librerías adicionales, formando una potente herramienta para cualquier desarrollador que trabaje en una aplicación relacionada con GIS.

En la sección de nuestro frontend de visualización (tracking de activos), tendremos un mapa de leaflet que será capaz de: mostrar la posición de todos los contenedores, mostrar la posición de un contenedor, clickar sobre un contenedor y acceder a sus detalles.

Si visualizamos la posición de todos los contenedores, veremos que al principio tenemos clústeres. Sin embargo, si vamos haciendo zoom o “clickando”, observaremos que los clústeres se van separando, mostrando la posición real de nuestros contenedores.

(52)

52

Figura 36. Visualización de varios componentes localizados a escasos kilómetros

Figura 37. Visualización de contenedores cercanos en detalle

Figura 38. Visualización de la posición exacta de varios contenedores cercanos en detalle

(53)

53 Es decir, si en el recinto de un Geofence se encuentran varios contenedores, aparecerán agrupados en clústeres en una primera instancia. Como ya hemos visto, conforme hacemos zoom para ver más el mapa en detalle, vemos que se muestra la posición real de cada contenedor.

En la sección de Listado de Geofence, podemos acceder a la subsección de sus detalles, pinchando sobre uno de ellos, donde veremos un mapa con el recinto del Geofence.

También podemos acceder a la subsección de crear un nuevo Geofence, donde tendremos un mapa de Leaflet en el cual dibujar un recinto para la creación de un nuevo Geofence.

Figura 39. Primera versión del formulario para crear un nuevo Geofence

En la sección de rutas, podremos ver un listado de rutas, y accediendo a los detalles de una de ellas, tendremos un mapa de Leaflet en el que visualizaremos la ruta que ha seguido un determinado conductor. En la subsección de creación de una nueva ruta, tendremos un mapa en el que podremos indicar el origen y el destino de la nueva ruta.

Referencias

Documento similar

Debido al riesgo de producir malformaciones congénitas graves, en la Unión Europea se han establecido una serie de requisitos para su prescripción y dispensación con un Plan

Como medida de precaución, puesto que talidomida se encuentra en el semen, todos los pacientes varones deben usar preservativos durante el tratamiento, durante la interrupción

"No porque las dos, que vinieron de Valencia, no merecieran ese favor, pues eran entrambas de tan grande espíritu […] La razón porque no vió Coronas para ellas, sería

Además de aparecer en forma de volumen, las Memorias conocieron una primera difusión, a los tres meses de la muerte del autor, en las páginas de La Presse en forma de folletín,

Abstract: This paper reviews the dialogue and controversies between the paratexts of a corpus of collections of short novels –and romances– publi- shed from 1624 to 1637:

Después de una descripción muy rápida de la optimización así como los problemas en los sistemas de fabricación, se presenta la integración de dos herramientas existentes

entorno algoritmo.

La campaña ha consistido en la revisión del etiquetado e instrucciones de uso de todos los ter- mómetros digitales comunicados, así como de la documentación técnica adicional de