Full text
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA INGENIERÍA INFORMÁTICA APLICACIÓN LOYMERBUS LOYMERBUS APPLICATION Realizado por Samuel Hindley López Tutorizado por Eduardo Guzmán De los Riscos Departamento Lenguajes y Ciencias de la Computación UNIVERSIDAD DE MÁLAGA MÁLAGA, septiembre 2016 Fecha defensa: El Secretario del Tribunal
5 Resumen: Hoy en día gracias a la tecnología móvil y el Internet podemos consultar todo tipo de información y realizar todo tipo de transacciones en cualquier momento. El transporte público se ha acabado uniendo a esta moda con páginas web y aplicaciones móviles donde consultar horarios, precios, etc. Loymerbus, una pequeña empresa de Málaga, con una flota de autobuses limitada se ha quedado atrás en este sentido. Con cientos de clientes todos los días de la Axarquía, siguen sin forma de ver cualquier tipo de información sobre las rutas de estos autobuses. Este proyecto tiene esto en cuenta y trata de solucionar este problema con el desarrollo de una aplicación móvil híbrida que puede ser ejecutada en Android, iOS, Windows Phone y web. Su objetivo es ofrecer a los usuarios una aplicación simple y fácil de usar donde pueden consultar, en todo momento, los horarios y los precios insertando la salida y el destino, un mapa y una imagen de las rutas que siguen los autobuses, e incluso el tiempo que se tendría que esperar si hubiera algún autobús en ruta hacia la parada en la que te encuentres. Para esto último es necesario no solo una aplicación para el usuario, sino también una aplicación secundaria que iría en el móvil del conductor del autobús para poder acceder a su GPS y tener en cuenta su posición. Palabras claves: móvil, aplicación, Android, iOS, Windows, web, Ionic, AngularJS, horarios, geolocalización, autobús.
6 Abstract: Nowadays, thanks to mobile technology and the Internet we can get all kinds of information and make all kinds of transactions at any time. Public transport has ended up joining this trend with websites and mobile applications where you can check out timetables, prices, etc. Loymerbus, a small company in Málaga, with a limited fleet of buses has fallen behind in this sence. With hundreds of clients everyday in the Axarquía, they still have no way of seeing any kind of information about the routes of these buses. This project bears this in mind and tries to solve this problem with the development of a hybrid mobile application that can run on Android, iOS, Windows Phone and web. It’s objective is to offer users a simple and easy to use application where you can get timetables and prices at any time inserting the departure and destination, a map and an image of the routes the buses follow, and even the amount of time that you would have to wait if there were a bus on route to the bus stop you are at. For this last element, it is necessary for not only one application for the user, but another secondary application which would be on the bus drivers mobile to access the GPS and take into account its position. Keywords: mobile, application, Android, iOS, Windows, Ionic, AngularJS, timetables, geolocation, bus.
7 Índice general Índice general ........................................................................................................... 7 Capítulo 1. Introducción ....................................................................................... 9 1.1 Motivación ..................................................................................................... 9 1.2 Objetivos ..................................................................................................... 11 1.3 Materiales y tecnología usada ..................................................................... 12 1.4 Contenido de la memoria ............................................................................ 13 Capítulo 2. Conocimientos previos ....................................................................15 2.1 Ionic 2 .......................................................................................................... 15 2.2 Angular 2 ..................................................................................................... 15 2.3 TypeScript ................................................................................................... 16 2.4 Firebase ...................................................................................................... 17 2.5 Apache Cordova .......................................................................................... 17 2.6 npm (Node Package Manager) ................................................................... 18 Capítulo 3. Especificación de requisitos ...........................................................19 3.1 Recopilación de datos ................................................................................. 19 3.2 Aplicación Loymerbus ................................................................................. 20 3.2.1 Requisitos funcionales .......................................................................... 20 3.2.2 Requisitos no funcionales ..................................................................... 22 3.3 Aplicación Loymerbus GPS ......................................................................... 23 3.3.1 Requisitos funcionales .......................................................................... 23 3.3.2 Requisitos no funcionales ..................................................................... 24 Capítulo 4. Análisis y diseño ..............................................................................25 4.1 Casos de uso .............................................................................................. 25
8 4.1.1 Aplicación Loymerbus ........................................................................... 25 4.1.2 Aplicación Loymerbus GPS .................................................................. 30 4.2 Arquitectura ................................................................................................. 32 4.2.1 Arquitectura cliente-servidor ................................................................. 32 4.2.2 Arquitectura Modelo Vista Controlador ................................................. 33 4.3 Estructura y diseño ...................................................................................... 34 Capítulo 5. Desarrollo ..........................................................................................37 5.1 Base de datos ............................................................................................. 37 5.2 Creación y configuración del proyecto ......................................................... 39 5.3 Aplicación Loymerbus ................................................................................. 42 5.3.1 Buscar ................................................................................................... 42 5.3.2 Mapa ..................................................................................................... 46 5.3.3 Ruta ...................................................................................................... 48 5.3.4 Contacto ............................................................................................... 49 5.3.5 Ajustes .................................................................................................. 50 5.3.6 Tiempo estimado de llegada ................................................................. 52 5.4 Aplicación Loymerbus GPS ......................................................................... 54 Capítulo 6. Conclusiones y trabajo futuro .........................................................61 6.1 Conclusiones ............................................................................................... 61 6.2 Trabajo futuro .............................................................................................. 62 Bibliografía ...............................................................................................................65
9 Capítulo 1. Introducción 1.1 Motivación Las tecnologías hoy en día avanzan a un ritmo increíble e incluso difícil de seguir. La aparición del Internet ha revolucionado las comunicaciones a tal punto que actualmente es el medio preferido de comunicación para nuestro día a día. En casi todo lo que hacemos usamos el Internet: hablar con un amigo, pedir comida, comprar ropa, compartir fotos, … Antes del uso extendido del Internet, si querías estar al tanto de las ultimas noticias tenías que acercarte a por un periódico, pero hoy, un par de clics es suficiente para leer cualquier tipo de noticia de fuentes variadas. En el año 1990 con la aparición del primer cliente y servidor web, las capacidades del Internet comenzaron a notarse en los ámbitos informáticos de universidades y centros de investigación, y más tarde, en entidades públicas, instituciones o empresas privadas de todo el mundo. En la figura 1.1 podemos ver la cantidad de usuarios en Internet hoy día comparado con hace unos 10-15 años para tener una mejor idea del crecimiento e importancia del que estamos hablando: Fig. 1.1: Usuarios de Internet en el mundo (Fuente: http://www.internetlivestats.com/internet-users/)
16 - Controladores: Son los archivos con formato .ts (TypeScript) y son los encargados de inicializar y modificar la información que contiene nuestra aplicación en todo momento, es decir, la lógica que hay detrás de ella. - Enlace de datos bidireccional: Esto se usa mucho ya que nos permite tener una sincronización de datos entre el modelo y la vista de manera automática. De este modo, cuando el modelo cambia, la vista refleja ese cambio automáticamente y viceversa. Esto nos permite cambiar cualquier dato fácilmente en el controlador o ser notificados fácilmente de algún cambio que se ha producido en la vista. 2.3 TypeScript TypeScript es un lenguaje de programación gratuito y libre creado por el también creador del lenguaje C#, Anders Heilsberg, y mantenido por Microsoft. Es un superconjunto de JavaScript, que esencialmente se basa en el estándar ECMAScript 6 añadiendo tipado estático y objetos basados en clases. TypeScript = ES6 + Types + Annotations Incluye varios aspectos de la programación orientada a objetos como la herencia, interfaces, o incluso funciones lambdas. A través de un compilador permite traducir el código TypeScript a JavaScript original para que lo entiendan los navegadores web. Los dos conceptos más usados en los controladores de nuestra aplicación son los siguientes: - Tipos: El tipado en TypeScript nos permite mantener un registro de la intención con la que se crea una variable o función, por ejemplo, si creamos una variable de tipo string y se le intenta asignar un array el compilador de TypeScript propagará un error. No es necesario asignar el tipo de una variable (como ocurre en JavaScript) pero puede ser útil para asegurarnos de que los tipos de los objetos son los esperados y son correctos. - Clases: Esto nos permite definir clases de un modo similar en la programación orientada a objetos, en JavaScript podemos simular el comportamiento de clases, pero con TypeScript nos lo ponen muy fácil sobre todo para desarrolladores acostumbrados a trabajar con “objetos”.
17 2.4 Firebase Fundado en 2011 y comprado por Google en 2014, Firebase es una plataforma de desarrollo móvil en la nube. Es lo que se conoce como “Backend como Servicio”, que básicamente provee de una API para guardar y sincronizar datos en la nube en tiempo real. Entre sus características están: - Muy fácil implantación. - Sincronización instantánea. Cuando cambia el valor de una variable, se actualiza en todos los dispositivos automáticamente. - Provee de un sistema para trabajar offline, lanzando una sincronización cuando se retoma la conexión con el servidor. - Los datos de guardan en un JSON estándar, por ello es 100% multiplataforma mediante API REST. - Hosting y dominio personalizado gratis. Este año han ampliado mucho las funcionalidades de este producto creando así un gran repertorio de herramientas para desarrolladores incluyendo elementos como analíticas, notificaciones push, almacenamiento en la nube, etc. 2.5 Apache Cordova Originalmente creado por Nitobi, fue comprado por Adobe Systems en 2011 y lo llamó PhoneGap. Más tarde sacaron una versión open-source con el nombre que lleva hoy día. Es un framework de desarrollo para aplicaciones móviles muy popular por el hecho de que permite a desarrolladores construir aplicaciones usando CSS3, HTML5 y JavaScript en vez de tener que depender de plataformas como Android, iOS o Windows Phone. Encapsula este código según la plataforma a la que se exporta y extiende el funcionamiento del HTML y del JavaScript para funcionar en el dispositivo. El resultado es una aplicación hibrida que no es realmente nativa ya que el renderizado de las vistas se realiza siempre con web views pero tampoco son completamente basadas en web porque podemos acceder a funciones nativas del dispositivo como la cámara, almacenamiento, GPS, etc. Esto último es uno de los puntos más importantes para nuestra aplicación ya que sin la tecnología de Apache Cordova, que crea la base de Ionic, no podríamos acceder a las funciones del GPS del dispositivo móvil y este trabajo de fin de grado no hubiera sido posible.
18 2.6 npm (Node Package Manager) Fue desarrollado por Isaac Z. Schlueter a raíz de la frustración con la administración de paquetes para Node.js. Está escrito a día de hoy enteramente en JavaScript y es instalado de forma automática con la instalación de Node.js. Nos permitirá instalar todos los paquetes de las tecnologías que hemos mencionado antes, mantenerlos actualizados y solucionar dependencias entre ellas, todo a través de la línea de comandos.
19 Capítulo 3. Especificación de requisitos La especificación de requisitos de un sistema consiste en una colección de elementos en los que se describen los servicios que ha de ofrecer ese sistema y las restricciones asociadas a su funcionamiento. Esta descripción completa del comportamiento del sistema a desarrollar se suele clasificar en dos grupos: - Requisitos funcionales: Son el tipo más común de requisitos. Identifican los servicios y acciones que el sistema debe proporcionar, normalmente en respuesta a una entrada externa. - Requisitos no funcionales: Este tipo de requisitos nos dicen las restricciones en el diseño o la implementación, es decir, restricciones que afectaran al correcto funcionamiento del sistema. A continuación vamos a comentar la recopilación de datos que se ha llevado a cabo antes de realizar nada, para ya sacar los requisitos en base a toda esta información. 3.1 Recopilación de datos El primer paso en la ejecución de este Trabajo de Fin de Grado consistió en entrar en contacto con la empresa Loymerbus para pedirles permiso para usar su nombre en la documentación de este trabajo de fin de grado, ya que figuraba en el listado de marcas registradas en el Gobierno de España. A través de correo electrónico me cedieron esos permisos además de un documento con el horario de todos los trayectos y los precios. Tras varios intercambios de correos conseguí más información necesaria como el descuento que se le aplica a los que tienen la tarjeta de pensionista, los horarios de las rutas a Vélez-Málaga que no figuraban ni en los documentos que me enviaron y algunos logos de la empresa para poder seguir algunas pautas en cuanto a colores para el diseño de la aplicación. Realicé alguna que otra visita a la oficina central en Torre del Mar para tener fotos de la oficina por fuera y conocer el horario de apertura. Para las localizaciones exactas de las paradas hice uso de Google Maps para encontrar las que ya conocía y el resto, preguntando a amigos de los pueblos que me faltaban.
20 3.2 Aplicación Loymerbus 3.2.1 Requisitos funcionales - RF01 - Mostrar un menú lateral: La aplicación debe permitir abrir un menú lateral con todas las secciones de la aplicación para poder cambiar de una a otra con facilidad. - RF02 - Introducir datos para la consulta de horarios: El usuario debe poder introducir todos los datos necesarios para buscar información relevante sobre los horarios de los autobuses. RF02.1 - Introducir parada de salida: Podrá seleccionar la parada de autobús de salida de una lista de posibilidades. RF02.2 - Introducir parada de destino: Podrá seleccionar una parada de destino de los posibles destinos según la salida seleccionada. RF02.4 - Introducir si es pensionista: Podrá indicar si dispone o no de la tarjeta de pensionistas de la Junta de Andalucía para disfrutar de un descuento. - RF03 - Modificar datos para la consulta de horarios: El usuario debe poder modificar todos los datos necesarios para buscar información relevante sobre los horarios de los autobuses. RF03.1 - Modificar parada de salida: Podrá cambiar la parada de autobús de salida seleccionada de una lista de posibilidades. RF03.2 - Modificar parada de destino: Podrá cambiar la parada de destino seleccionada de los posibles destinos según la salida seleccionada. RF03.3 - Modificar si es pensionista: Podrá modificar si dispone o no de la tarjeta de pensionistas de la Junta de Andalucía para disfrutar de un descuento. RF03.4 - Modificar fecha: Por defecto se muestra la fecha del día actual, pero se podrá modificar la fecha del año actual de un listado de meses y días del mes seleccionado. - RF04 - Obtener datos sobre los horarios: La aplicación debe poder conectarse a la base de datos y obtener los datos de las horas y los precios según las paradas y le fecha que haya introducido el usuario. - RF05 - Mostrar información de los horarios: Una vez introducidos los datos necesarios y pulsado el botón para buscar horarios, se deberán mostrar, en una ventana nueva, los resultados correspondientes cargados de la base de datos. RF05.1 - Horas de salida: Se presentarán las horas de salida en una tabla de cada resultado de la búsqueda. RF05.2 - Horas de llegada: Se presentarán las horas de llegada en una tabla de cada resultado de la búsqueda.
21 RF05.3 - Precios: Se presentarán los precios en una tabla de cada resultado de la búsqueda. RF05.4 - Error: Si no hay viaje disponible para la fecha seleccionada se mostrará un texto explicando el error que ha ocurrido. - RF06 - Mostrar un mapa con las rutas: La aplicación debe cargar un mapa de Google Maps donde mostrar información sobre las rutas que siguen los autobuses. RF05.1 - Localización de paradas: Se mostrará un marcador en la localización exacta de cada parada de autobús junto con un título de la población a la que corresponde. RF05.2 - Rutas entre paradas: Habrá líneas trazadas entre todas las paradas representando el camino que sigue cada autobús. - RF07 - Mostrar una imagen del esquema de las rutas: Se podrá consultar una imagen de un tamaño y una resolución considerable de un esquema ilustrativo de las direcciones que siguen los autobuses y los cambios de autobús necesarios. - RF08 - Soporte multilenguaje: El usuario tendrá la posibilidad de elegir entre varios idiomas (inglés, español, francés y alemán) para cambiar el idioma de la aplicación entera. - RF09 - Introducir parada para consultar tiempo de espera: El usuario insertará la parada en la que se encuentra de un listado de posibles paradas de autobús. - RF10 - Calcular tiempo estimado de llegada: Una vez especificado la parada la aplicación deberá calcular el tiempo que tardará el autobús en llegar a la parada seleccionada haciendo uso de la API de Google Maps, si y solo si se ha determinado que hay un autobús en ruta. - RF11 - Mostrar resultados del tiempo estimado de llegada: Se le comunicará al usuario el resultado de la búsqueda y del cálculo a través de una ventana emergente. RF11.1 - Tiempo de espera: Mostrará el tiempo que tardará en llegar el autobús a la parada de interés en minutos. RF11.2 - Error: Si ha ocurrido algún error, los autobuses no están en servicio o simplemente se ha determinado que no hay ningún autobús en ruta, se le mostrará al usuario un texto diciendo que no hay ningún autobús en ruta hacia esa parada en ese momento y que consulte por favor el horario.
22 3.2.2 Requisitos no funcionales - RNF01 - Conexión a Internet: La aplicación necesita conexión a Internet para el acceso a la base de datos. Sería proporcionada por el propio dispositivo (móvil, tablet, u ordenador). - RNF02 - Usabilidad: Dado que la aplicación se puede acceder desde diferentes dispositivos con diferentes resoluciones y tamaños de pantalla, la interfaz debe ser adaptable permitiendo a cualquier usuario usar las funciones y disfrutar de la interfaz de usuario sin importar el dispositivo que use. - RNF03 - Tecnologías web: Las tecnologías y lenguajes de programación deben ser HTML, CSS y JavaScript, es decir, propios de la web. Con esto podremos desarrollar una aplicación móvil hibrida que se pueda exportar a dispositivos con sistemas operativos Android, iOS o Windows Phone, incluso con el propio navegador web.
23 3.3 Aplicación Loymerbus GPS 3.3.1 Requisitos funcionales - RF01 - Indicar línea: El conductor del autobús deberá poder indicar qué ruta seguirá. - RF02 - Activar funciones del GPS: La aplicación Loymerbus GPS tendrá un botón para activar todas las funciones necesarias para la localización del autobús. RF02.1 - Mostrar activación del seguimiento por GPS: Mostrará una ventana emergente indicando que la activación del seguimiento por GPS ha tenido éxito. RF02.2 - Activar funcionamiento en segundo plano: Activa el funcionamiento en segundo plano para que se pueda seguir transmitiendo su posición, aunque no esté en primer plano la aplicación. RF02.3 - Inicializar la base de datos: Se inicializarán los campos necesarios en la base de datos según el autobús que sea y según la parada desde la que partirá. RF02.4 - Iniciar la actualización de información: Se activará una función que se ejecutará cada 10 minutos para actualizar la información en la base de datos de forma periódica. RF02.5 - Iniciar escucha de eventos: Si un usuario solicita el tiempo de espera la aplicación deberá ser capaz de escuchar eventos emitidos por la aplicación principal para responder actualizando su ubicación actual. - RF03 - Desactivar funciones del GPS: Habrá otro botón encargado de desactivar todas las funciones necesarias para el seguimiento del autobús. RF03.1 - Mostrar desactivación del seguimiento por GPS: Mostrará una ventana emergente indicando que la desactivación del seguimiento por GPS ha tenido éxito. RF03.2 - Desactivar funcionamiento en segundo plano: Dejará de permitir que la aplicación siga corriendo en segundo plano. RF03.3 - Desactivar temporizador para actualización de datos: Borrará el temporizador de 10 minutos para dejar de actualizar la base de datos. RF03.4 - Cancelar escucha de eventos: Desvinculará la aplicación de la base de datos para dejar de recibir emisiones de eventos por parte de la aplicación principal.
24 3.3.2 Requisitos no funcionales - RNF01 - Conexión a Internet: La aplicación necesita conexión a Internet para el acceso a la base de datos. Sería proporcionada por el propio dispositivo (móvil, tableta, u ordenador). - RNF02 - Usabilidad: Dado que la aplicación se puede acceder desde diferentes dispositivos con diferentes resoluciones y tamaños de pantalla, la interfaz debe ser adaptable permitiendo a cualquier usuario usar las funciones y disfrutar de la interfaz de usuario sin importar el dispositivo que use. - RNF03 - Tecnologías web: Las tecnologías y lenguajes de programación deben ser HTML, CSS y JavaScript, es decir, propios de la web. Con esto podremos desarrollar una aplicación móvil hibrida que se pueda exportar a dispositivos con sistemas operativos Android, iOS o Windows Phone, incluso con el propio navegador web. - RFN04 - Conexión a GPS: El dispositivo deberá permitir el acceso a la ubicación del dispositivo para poder obtener la localización del autobús en cualquier momento.
25 Capítulo 4. Análisis y diseño 4.1 Casos de uso En esta sección se muestran los diferentes casos que derivan de los requisitos funcionales especificados en el capítulo anterior. 4.1.1 Aplicación Loymerbus Fig. 4.1: Diagrama de casos de uso de la aplicación Loymerbus
32 4.2 Arquitectura Podríamos distinguir dos tipos de arquitecturas en este proyecto: por un lado la arquitectura cliente-servidor en la que los clientes son las aplicaciones de los usuarios y la de los conductores, y el servidor hemos decidido que será Firebase. Por otro lado en cuanto a organización de clases y funciones, se ha seguido el patrón que establece Angular, MVC (Modelo Vista Controlador). 4.2.1 Arquitectura cliente-servidor Es una estructura de software en el que aislamos al cliente del servidor y los conectamos a través del Internet. Esta conexión solo se realiza cuando el cliente envía una petición al servidor, en cuyo caso, ya sea la aplicación Loymerbus o Loymerbus GPS, el servidor responde con lo que se haya solicitado, pero nunca podrá iniciar la conexión el servidor. Por lo tanto, nuestro servidor Firebase nos suministra un servicio: darnos la información de la base de datos, para que cuando todos los clientes que estén en ejecución así lo soliciten, siempre tengamos a nuestro servidor respondiendo a todas las peticiones. Fig. 4.3: Illustración de la base de datos en tiempo real de Firebase
33 4.2.2 Arquitectura Modelo Vista Controlador Al estar usando Angular, seguimos el conocido patrón Modelo Vista Controlador. Un patrón muy conocido en cuanto a la arquitectura de software donde define tres partes interconectadas para separar el funcionamiento interno del software y aislarla de la información a la que se accede en la base de datos y de lo que es presentado al usuario. Fig. 4.4: Arquitectura Modelo Vista Controlador 4.2.3 Modelo Es la capa donde se trabaja con los datos, es decir, contiene los métodos para acceder a la información y también para actualizarla. Estos datos son los que tendremos almacenados en Firebase y en nuestro caso los correspondientes selects, updates, inserts, etc. lo hace la API de Firebase. Por lo tanto, aunque a lo largo de esta memoria veremos métodos como update(), son simplemente métodos de la librería de AngularFire (la librería que conecta Firebase con Angular) y pertenecen al controlador.
34 4.2.4 Vista La vista, como su nombre indica, contiene el código de nuestra aplicación que va a producir la visualización de las interfaces de usuario, es decir el código HTML y CSS. Desde la vista se trabaja con los datos del modelo, pero no se realiza un acceso directo a ellos. 4.2.5 Controlador Contiene todo el código necesario para responder a las acciones que se solicitan en la aplicación, como visualizar un elemento, realizar una búsqueda, etc. Es la capa que sirve de enlace entre el modelo y la vista, aunque normalmente su responsabilidad no es manipular directamente los datos, en nuestro caso, al no tener servidor dedicado a la manipulación de datos, sino que tenemos un servidor para proveer los datos, todos los cálculos y llamadas a la API para obtener datos de Firebase se han realizado desde los controladores. 4.3 Estructura y diseño Gracias a Ionic, la interfaz de usuario, así como los estilos usados para Android, iOS y Windows Phone, se adaptan según la plataforma en la que estén. Ionic ayuda mucho con la estructura de la aplicación ya que crea una plantilla limpia desde cero siguiendo las pautas de diseño nativas de iOS y Windows, y en el caso de Android, las de Material Design. Esto nos permite tener una base con estilos ya aplicados, pero a la vez 100% personalizables al gusto del desarrollador. En este caso se han mantenido la mayoría de los estilos que trae Ionic por defecto con el objetivo de ofrecer una experiencia de usuario familiar y conocida, y mantenerlo lo más simple posible para que todo tipo de persona pueda usarlo con facilidad. El hecho de usar estilos de la interfaz nativa de cada plataforma es muy importante, ya que cualquier persona podrá coger la aplicación y aprender fácilmente cómo funciona y dónde está el menú, por ejemplo, porque sigue la misma estructura que las demás aplicaciones modernas. En la figura 4.1 se puede ver un ejemplo de las diferencias según la plataforma y de la estructura inicial que nos aporta nuestro proyecto:
35 Fig. 4.5: Menú lateral en Android, iOS y Windows Phone En cuanto a los colores, para mantener el branding de la empresa Loymerbus se han extraído los colores de este logo, que son los mismos usados en todos los autobuses: Fig. 4.6: Logo de Loymerbus
36 Siendo los colores primarios de la aplicación el rosa y el azul, estos se pueden usar en la aplicación a través del fichero themes/app.variables.scss donde Ionic nos lo pone fácil para modificar los colores primarios, secundarios, etc. que se usan en toda la aplicación, así como componentes más específicos. Se aplica el rosa a los componentes primarios (botones, textos importantes, …) y el azul para la barra de navegación. $toolbar-background: #2196F3; $toolbar-text-color: white; $toolbar-md-text-color: white; $toolbar-md-button-color: white; $toolbar-ios-button-color: white; $colors: ( primary: #db107c, secondary: #32db64, danger: #f53d3d, light: #f4f4f4, dark: #222, favorite: #69BB7B );
37 Capítulo 5. Desarrollo 5.1 Base de datos Para las funcionalidades de esta aplicación no es necesario una base de datos muy complicada con la que poder hacer operaciones SQL complejas o crear tablas con relaciones entre sí, ya que las consultas necesarias son bastantes sencillas de realizar debido a la simplicidad de la información, siendo la mayor parte cadenas de texto representando los nombres de los pueblos de salida y llegada, las horas de llegada y salida, números con las coordenadas exactas, y los precios. Es decir, las operaciones que se realizarán serán simplemente para consultar textos y números en concreto según los que se introducen en los campos de texto. Por esta razón basta con un modelado NoSQL con el que poder escalar horizontalmente con facilidad en caso de añadir más líneas de autobuses o más paradas. Como hemos mencionado en la introducción, Firebase encaja perfectamente con este perfil ya que nos permite tener una base de datos en forma de JSON sobre la que podemos realizar consultas e incluso actualizarla haciendo uso de su API y los métodos correspondientes que nos proporcionan, ahorrando así el trabajo de crear nuestra propia API para traer información de nuestra base de datos. En la figura 5.1 podemos ver la cantidad de funcionalidades que trae Firebase: Fig. 5.1: Características de Firebase
38 La información recopilada se ha transformado en un fichero JSON con una estructura específica para facilitar la lectura y acelerar las búsquedas (más adelante en la sección 5.3.1 de búsqueda se explicará porque se ha estructurado de esta manera) quedando así: { "trayectos": [ { "salida": "Canillas de Albaida", "lat": 36.845524, "lng": -3.985473, "destinos": [ { "destino": "Cómpeta", "precio": 1.16, "dias": [ { "lmxjv": [ {"horaSalida": "07:00", "horaLlegada": "07:15"}, {"horaSalida": "09:30", "horaLlegada": "09:45"}, {"horaSalida": "15:30", "horaLlegada": "15:45"} ] }, { "sabado": [ {"horaSalida": "09:00", "horaLlegada": "09:10"}, {"horaSalida": "15:30", "horaLlegada": "15:45"} ] }, { "domingo": [ {"horaSalida": "09:00", "horaLlegada": "09:10"}, {"horaSalida": "18:00", "horaLlegada": "18:15"} ] } ] }, { "destino": "Sayalonga", "precio": 1.27, "dias": [ { "lmxjv": [ {"horaSalida": "07:00", "horaLlegada": "07:40"}, {"horaSalida": "09:30", "horaLlegada": "10:05"}, {"horaSalida": "15:30", "horaLlegada": "16:05"} ] }, { "sabado": [ {"horaSalida": "09:00", "horaLlegada": "09:25"}, {"horaSalida": "15:30", "horaLlegada": "16:05"} ] }, { "domingo": [ {"horaSalida": "09:00", "horaLlegada": "09:25"},
39 {"horaSalida": "18:00", "horaLlegada": "18:30"} ] } ] } ... Como se puede, ver hay varios trayectos, todos con su correspondiente pueblo de salida que representan a las diferentes paradas de autobús, identificadas por el nombre de ese pueblo y las coordenadas exactas de la parada en sí. Desde cada parada de autobús se puede llegar a otras por un determinado precio, y estas son accesibles a través de diferentes viajes a diferentes horas del día, según el día de la semana, con sus correspondientes horas de salida y horas de llegada. 5.2 Creación y configuración del proyecto La creación y configuración del proyecto se podría separar en tres fases, todas ellas con ciertas instalaciones y configuraciones que realizar: - Ionic: creación del proyecto base. - Firebase: conexión con la base de datos y hosting. - GitHub: creación y subida a repositorio privado para control de versiones. Antes de iniciar la creación del proyecto se necesita NPM, un administrador de paquetes JavaScript, que nos permitirá instalar y mantener actualizados los paquetes necesarios de Ionic y Apache Cordova, y más adelante los de Angular 2, Firebase y AngularFire 2. Es el instalador de paquetes predeterminado de Node.js por lo que basta con instalar Node.js para tener también instalado NPM. Una vez instalado NPM se procede a instalar los paquetes de Ionic 2 y Apache Cordova (desde una línea de comandos): npm install -g ionic@beta cordova Para iniciar un proyecto nuevo ejecutamos: ionic start loymberbus sidemenu --v2 Con las opciones “sidemenu” indicamos que nos cree una plantilla de un proyecto que tenga menú lateral, “v2” para indicar que vamos a usar la versión nueva de Ionic que hace uso del remodelado Angular 2, y por último indicar que ahora se usa por defecto el lenguaje de programación TypeScript en vez de JavaScript frente a
40 versiones anteriores, debido a que el desarrollo de Angular 2 se ha realizado con este lenguaje de Microsoft. Ya está el proyecto creado y listo para su uso y para la creación de las diferentes páginas (secciones) de la aplicación, pero antes de nada hay que indicar para qué plataformas se estará desarrollando: ionic platform add android ionic platform add ios ionic platform add windows ionic platform add browser Dentro de la carpeta que se ha creado hay una típica estructura de proyecto Cordova donde podemos instalar plugins nativos para extender la funcionalidad de la aplicación, y crear archivos específicos para nuestro proyecto. Fig. 5.2: Jerarquía de ficheros del proyecto
41 Para el uso de Firebase se tiene que usar AngularFire, la librería de conexión entre AngularJS y Firebase. Para ello instalamos sus correspondientes paquetes con NPM igual que antes: npm install angularfire2 firebase --save Inicializamos el proyecto Firebase: firebase init Siguiendo las instrucciones que se muestran e indicando que la carpeta “www” será la que se suba a Firebase, ya que es la que contiene todos los ficheros necesarios para ser ejecutado en la web. Por último, con “firebase deploy” se envía el contenido de la carpeta “www” a nuestro proyecto Firebase en la nube. Este comando se ha ejecutado de forma continua durante la realización de este proyecto para aprovechar el hosting gratuito y tener siempre la última versión de la aplicación web ejecutándose en el servidor de Firebase (https://loymerbus.firebase.com). Ahora podemos incluir en nuestro proyecto Ionic las referencias a nuestro Firebase para poder hacer uso del JSON en nuestra base de datos. Con indicar en el fichero app.ts el proveedor que usaremos, ya se puede inyectar al constructor de cualquier página la referencia a la base de datos de Firebase para su uso en cualquier sección de la aplicación. ionicBootstrap( MyApp, [ FIREBASE_PROVIDERS, defaultFirebase('https://loymerbus.firebaseio.com'), { provide: TranslateLoader, useFactory: (http: Http) => new TranslateStaticLoader(http, 'assets/i18n', '.json'), deps: [Http] }, TranslateService ], {} ); constructor(@Inject(FirebaseRef) public ref:Firebase, public af: AngularFire… Ya está la base de datos y el proyecto Ionic creado, ambos funcionando y ejecutándose en Firebase. Como último paso, antes de iniciar el desarrollo de la aplicación, para asegurar un correcto entorno de desarrollo y flujo de trabajo, se ha creado un repositorio privado en GitHub donde tener alojado el código y poder hacer
48 5.3.3 Ruta Fig. 5.8: Esquema illustrativo de rutas y paradas Para entender mejor la ruta que hacen los autobuses y ver lo desvíos y cambios de autobuses que son necesarios hacer para llegar a determinadas paradas, se ha realizado el típico esquema que suelen tener las líneas del metro o autobuses colgadas en las paradas. Se ha realizado desde cero con Adobe Photoshop CC 2015 en forma de imagen JPEG que va incluido en la sección de “Ruta” con un tamaño considerable para tener suficiente calidad. Se puede hacer scroll tanto en el eje Y como en el eje X para ver al completo la ruta. El código HTML del mismo se encuentra en el fichero loymerbus/pages/route/route.html, sin necesidad de controlador, debido a que se trata de mostrar simplemente una imagen informativa con ciertos estilos aplicados para darle ese tamaño. <ion-content class="route"> <ion-scroll scrollX="true" scrollY="true" zoom="true" overflowscroll="false" style="width: 100%; height: 100%"> <div class="route-img"></div> </ion-scroll> </ion-content> <style> .route-img { width: 1920px; height: 1080px; background: url('img/ruta.jpg') no-repeat; }
49 </style> 5.3.4 Contacto La aplicación incluye también una sección de contacto con una ficha informativa sobre la oficina central del Grupo Loymer que se encuentra en Torre del Mar, para poder hacer cualquier tipo de consulta sobre sus servicios. Para ello se incluye una foto de la oficina, la dirección exacta de la misma, así como un botón que nos abre Google Maps para poder navegar hasta su ubicación exacta (si está Google Maps instalado en el dispositivo se abre en ella, sino se abre en el navegador predeterminado que tengamos). La página web oficial (en la fecha de la realización de este proyecto no estaba en funcionamiento), el número de teléfono sobre el cual podemos pinchar para abrir la aplicación de teléfono que se tenga en el dispositivo y realizar directamente la llamada; un correo electrónico que al igual que en el caso del número de teléfono, podemos pinchar sobre él para abrir la aplicación de correo predeterminada que tengamos configurada. Por último, el horario de apertura de la oficina, que se ha obtenido preguntando a uno de los empleados. Fig. 5.9: Sección "Contacto" en Android, iOS y Windows Phone
50 5.3.5 Ajustes Fig. 5.10: Sección "Ajustes" en Android, iOS y Windows Phone El único cambio de configuración de interés en esta aplicación es el cambio de idioma, pudiendo elegir entre: español, inglés, alemán y francés. Para la traducción se ha empleado una librería de NPM llamado ng2-translate: npm install ng2-translate --save Este paquete permite usar el estándar i18n de internacionalización en aplicaciones que usan Angular 2. Para ello se ha tenido que crear una carpeta assets dentro de www, y dentro de esa, otra carpeta llamada i18n, que contendrá un fichero JSON por cada uno los idiomas que queremos incorporar a nuestra aplicación. Con el siguiente formato “CÓDIGO_IDIOMA”.json. En este caso cuatro: - es.json (español) - en.json (inglés) - de.json (alemán) - fr.json (francés) Cada una de ellas sigue la misma estructura: una clave y su correspondiente valor en el idioma que corresponda. Por ejemplo, cada fichero contiene todos los títulos de las secciones traducidas, es decir, todos tienen la clave “search”, y de valor “Search” en inglés, “Buscar” en español, “Suche” en alemán, y “Chercher” en francés.
51 Así con todos los nombres de las secciones, así como cualquier otra palabra estática que se encuentra en la aplicación. Para poder hacer uso de estas traducciones lo primero es realizar las correspondientes importaciones y configuración de los proveedores en el fichero app.ts: translateConfig() { let userLang = navigator.language.split('-')[0]; userLang = /(de|en|es|fr)/gi.test(userLang) ? userLang : 'es'; this.translate.setDefaultLang('en'); this.translate.use(userLang); } } Además de la creación de un método nuevo para cargar y usar el idioma del navegador (si está disponible), y en caso de que no, o en caso de ser un idioma que no soporte nuestra aplicación se usará el inglés por defecto. Llamamos este método en el constructor de nuestra aplicación. Es necesario también añadir el símbolo “pipe” a cada página de nuestra aplicación que requiera traducciones para poder usar expresiones del tipo {{“key” | translate}} en el HTML correspondiente de la página. Con esta simple expresión estamos indicando a nuestra aplicación que coja la traducción para la clave “key” (por ejemplo, ”search”, “cancel”, “monday”, etc.), usando el idioma que esté configurado en ese momento, ya sea porque se haya cargado al iniciar la aplicación o porque el usuario ha seleccionado otra diferente en esta sección. Para cambiar de idioma basta con seleccionar la que se desea activar y el idioma de la aplicación entera es cambiada de forma instantánea. Esto ocurre ya que al cambiar una de las opciones de la lista de idioma se llama al método onChange del controlador: onChange(lang) { this.translate.use(lang); } Como podemos ver, hace uso de uno de los métodos de la librería ng2-translate para cambiar el idioma al valor que se le haya pasado como parámetro.
52 5.3.6 Tiempo estimado de llegada A los usuarios se les permite también consultar el tiempo estimado de llegada (o ETA de sus siglas en inglés, Estimated Time of Arrival) del autobús a la parada en la que se encuentran. Si hay algún autobús en camino, se mostrará al usuario un tiempo aproximado que se ha calculado en tiempo real empleando Google Maps, que tiene en cuenta la distancia y el tráfico que hay en ese momento. Se ha intentado emular la mayoría de líneas de autobuses existentes en los que basta con introducir la parada de interés y pulsar el botón “BUSCAR”. Fig. 5.11: Sección "ETA" en Android, iOS y Windows Phone Para conseguir esto, es necesaria la localización del autobús. En el caso de la empresa Loymerbus con la que estamos tratando, no tienen GPS instalado en los autobuses. Por esta razón es imposible extraer su ubicación a través de este medio. Sin embargo, se puede aprovechar un dispositivo que sí que tendría todo conductor con él y que llevaría en el autobús: su móvil. Los teléfonos móviles hoy día permiten acceder fácilmente a su geolocalización a través de su GPS interno. Por tanto, con una aplicación secundaria instalada en el móvil del conductor (o en un móvil secundario que se dejara en el autobús para hacer la función de GPS), podríamos actualizar en nuestra base de datos la ubicación del autobús cuando haga falta y desde la aplicación del usuario realizar los cálculos necesarios.
53 Se han estudiado dos soluciones para realizar esta tarea, de las cuales se ha elegido una y se ha descartado la otra. A continuación, se explican cada una de ellas y por qué se ha usado una y no otra: - Tener en ejecución, en segundo plano, nuestra aplicación y que vaya actualizando la ubicación del autobús cada cierta cantidad de metros recorridos. Vigilancia constante de trayecto de autobús. Ubicación de autobús actualizada constantemente. Mayor consumo de batería. Mayor consumo de datos. - Tener en ejecución, en segundo plano, nuestra aplicación y que actualice la ubicación del autobús solo cuando se solicita el ETA desde la aplicación de usuario. Solo actualiza ubicación cuando es requerida. Menos consumo de batería. Menor consumo de datos. Es obvio que tener una aplicación en segundo plano consume más batería, en la primera opción algo más que en la segunda debido a que actualizaría la base de datos muchas más veces, esto también conllevaría más consumo de datos. La primera opción es interesante para tener también un seguimiento de los trayectos de los autobuses en caso de que la empresa lo requiera, pero ahora mismo no buscamos eso. La segunda opción tardaría algo más de tiempo, ya que tenemos que lanzar el evento a la aplicación secundaria para indicarle que alguien está solicitando el tiempo de espera que le queda y se necesita la ubicación actualizada para realizarlo. En el primer caso tendríamos siempre la ubicación actualizada. A pesar de esto se ha sacrificado un poco de velocidad de respuesta y se ha optado por la segunda opción. En la siguiente sección explicaremos con detalle cómo funciona esta aplicación secundaria que hemos comentado y cómo se actualiza todos los datos necesarios para darle al usuario esta opción.
54 5.4 Aplicación Loymerbus GPS Como se ha dicho anteriormente, es necesario disponer de una segunda aplicación móvil, que llamaremos “Loymerbus GPS”, y que iría instalada en el móvil del conductor del autobús. La base de datos y la creación y configuración del proyecto sería exactamente de la misma forma que se ha visto en las secciones 5.1 y 5.2 de esta memoria. Esta aplicación secundaria estaría ejecutándose en todo momento en segundo plano y tiene que acceder a la geolocalización del dispositivo, por lo que tendremos que hacer uso de algún plugin de Cordova para acceder a funciones nativas del dispositivo. En este caso background-mode y geolocation: cordova plugin install cordova-plugin-background-mode cordova plugin install cordova-plugin-geolocation Con los plugins ya instalados podemos hacer las correspondientes importaciones de sus librerías para acceder a sus métodos. Antes de nada, se han tenido que realizar algunos cambios en la base de datos. Hemos añadido un apartado “gps” donde hay dos campos “bus1 y “bus2”; cada uno representa un autobús para una ruta diferente. Dentro de cada autobús tienen los mismos campos que detallaremos a continuación: - lat: la latitud del autobús. Se actualiza, si y solo si, un usuario ha solicitado un tiempo de espera. - lng: la longitud del autobús. Se actualiza, si y solo si, un usuario ha solicitado un tiempo de espera. - latA: latitud del autobús. Cada 10 minutos se le asigna latB. - lngA: longitud del autobús. Cada 10 minutos se le asigna lngB. - latB: latitud del autobús. Cada 10 minutos es actualizado. - lngB: longitud del autobús. Cada 10 minutos es actualizado. - direction: dirección en la que se dirige el autobús. Se indica con el índice de la parada en nuestra base de datos y varía según el autobús. Para el “bus1” puede valer 0 o 5, Canillas de Albaida o Málaga, respectivamente. Para el “bus2” puede valer 7 o 5, Corumbela o Málaga, respectivamente. - nextStop: nos indica la próxima parada hacia la que se acerca el autobús. Con solo tener un teléfono móvil para sacar la ubicación de los autobuses y no un GPS con una vigilancia constante de cada uno, los recursos son bastantes limitados y se ha realizado un largo estudio sobre cómo sacar toda la información
55 necesaria para obtener unos resultados óptimos y satisfactorios para el usuario a la hora de simplemente introducir la parada en la que se encuentra. Vamos a justificar los datos anteriores que hemos tenido guardar en la base de datos y demostrar por qué son necesarios. Para ello es muy importante tener en cuenta las rutas que siguen los autobuses y el nombre de las paradas, por lo que se recomienda consultar de nuevo la imagen de la ruta en el apartado 5.3.3 Ruta: - De primeras, es necesario saber en qué dirección va el autobús en todo momento y cuál es la siguiente parada hacia la que se dirige. De aquí surgen las variables “direction” y “nextStop”. Esto es debido a limitaciones de Google Maps donde introducimos dos coordenadas y nos devuelve el tiempo y distancia entre ellos, pero no nos dice nada más. El fallo está claramente en que, si un usuario solicita, por ejemplo, ver cuánto le falta al autobús en llegar a Algarrobo el autobús podría estar según Google Maps a 2 minutos, pero ¿dónde se encuentra respecto a la parada de interés exactamente?, ¿se acerca o se aleja? Si está en ruta hacia Torre del Mar y el autobús se encuentra al oeste de Algarrobo está claro que el usuario ha perdido el autobús. Esto lo sabemos porque conocemos hacia qué parada se dirige el autobús y en qué dirección va. Veamos otro ejemplo para dejarlo lo más claro posible. Seguiremos usando Algarrobo como ejemplo. Si la siguiente parada es Torre del Mar igual que antes, pero va en dirección Canillas de Albaida, sabemos que el autobús se acerca hacia Algarrobo y todavía no se lo ha pasado. En este caso podemos mostrarle con éxito al usuario cuánto le falta al autobús en llegar a la parada de Algarrobo. Cabe destacar que en líneas más avanzadas de autobuses no ocurren estos problemas, ya que siempre hay dos paradas de autobús, uno en cada lado de la carretera con dirección constante. Aquí no ocurre esto, se trata de pueblos pequeños de la Axarquía y en la gran mayoría de los casos solo tienen una parada para ambos sentidos. También suele haber GPS integrado en todos los autobuses que realizan una especie de check-in automático cuando paran en determinadas paradas. Esto suprime la necesidad de saber en cada momento hacia qué parada va, ya que sabríamos en todo momento si ya ha visitado una parada o no. - Estos dos últimos datos como hemos visto son fundamentales y se consiguen con las coordenadas del autobús cada 10 minutos. De aquí las variables “latA”, “lngA”, “latB” y “lngB”. Es necesario actualizar cada 10 minutos estas coordenadas para saber en qué dirección va el autobús en cada momento. Se ha elegido 10 minutos porque es un tiempo bastante considerable para asegurarnos de que el autobús no esté parado más de ese tiempo y un tiempo que no sobrecargará la base de datos ni el móvil.
56 Veamos como hacemos esto con un par de ejemplos: Fig. 5.12: Ejemplo 1 para calcular dirección del autobús Tomamos como punto de referencia Málaga (para la línea Corumbela - Árchez se toma como punto de referencia el punto de “cambio de autobús”, pero funciona de la misma manera) y calculamos la distancia del autobús en el punto A a Málaga y lo mismo del punto B. El punto B es el más actualizado, entonces si es mayor esa distancia podemos afirmar que el autobús se aleja de Málaga, o lo que es lo mismo, se acerca a Canillas de Albaida. Es decir: SI Distancia Málaga-B > Distancia Málaga-A ENTONCES direction = Canillas de Albaida
57 Fig. 5.13: Ejemplo 2 para calcular dirección del autobús Si el autobús va en el sentido contrario, funciona de la misma manera: SI Distancia Málaga-B < Distancia Málaga-A ENTONCES direction = Málaga Con esto ya tenemos la variable “direction” actualizada, vamos a explicar cómo sacamos la variable “nextStop” actualizada. - En el mismo proceso anterior sacamos también la próxima parada del autobús, aprovechando las coordenadas A y B. El algoritmo consiste en un bucle en el que comparamos la distancia del autobús a nuestro punto de referencia Málaga, con la distancia del mismo punto a la siguiente parada. En el mejor de los casos la primera distancia será menor, por lo tanto, podemos confirmar que está entre Torre del Mar y Málaga, es decir su próxima parada es Torre del Mar (si tiene dirección Canillas de Albaida claro). Si la distancia del bus a Málaga es mayor, entraríamos en el bucle y calculamos la distancia a la siguiente parada, aumentando el rango; volvemos a comparar distancias y seguimos hasta que la distancia del autobús sea menor. Cuando consigamos eso sabremos entre qué dos paradas está, y con la dirección, si se acerca hacia una parada u otra. - Las variables “lat” y “lng” serán las coordenadas del autobús cuando un usuario solicite el tiempo de espera. Podríamos usar las coordenadas B que hemos mencionado antes, pero podrían estar, en el peor de los casos, 9 minutos equivocados.
64
65 Bibliografía [1] Beati, H. (2015). HTML5 y CSS3 para diseñadores. (1ª edición). Argentina: Alfaomega Grupo Editor Argentino [2] Sawyer McFarland, D. (2014). Programación JavaScript y jQuery. (3ª edición). España: Ediciones Anaya Multimedia [3] Tomás Gironés, J. (2015). El gran libro de Android. (4ª edición). España: Marcombo [4] Documentación Ionic 2. https://ionicframework.com/docs/v2/. Agosto 2016 [5] GitHub. https://github.com/. Septiembre 2016 [6] Integrating Firebase with AngularFire2 into AnhgularJS & Ionic 2. http://www.clearlyinnovative.com/integrating-firebase-with-angularfire2-into-angularjsionic2. Mayo 2016 [7] Ionic 2 | Integrating Google Maps. http://www.gajotres.net/ionic-2-integrating-googlemaps/2/. Enero 2016 [8] GitHub | Cordova Plugin Splashscreen. https://github.com/apache/cordova-pluginsplashscreen. Septiembre 2016 [9] Angular. https://angular.io/. Septiembre 2016 [10] Documentación Firebase. https://www.firebase.com/docs/. Julio 2016 [11] Canal de YouTube de Firebase. https://www.youtube.com/user/Firebase. Septiembre 2016 [12] Documentación de NPM. https://docs.npmjs.com/. Septiembre 2016 [13] Google Maps Distance Matrix API. https://developers.google.com/maps/documentation/distance-matrix. Septiembre 2016 [14] Google Maps Directions Service. https://developers.google.com/maps/documentation/javascript/directions. Agosto 2016 [15] Google Maps Distance Matrix Service. https://developers.google.com/maps/documentation/javascript/distancematrix. Septiembre 2016
66 [16] Ionic 2 & Angular2 Translate - Internationalize and Localize Your App. https://blog.thecodecampus.de/ionic2-angular2-translate-internationalizelocalize-app/. Junio 2016 [17] GitHub | ng2-translate. https://github.com/ocombe/ng2-translate. Septiembre 2016