Dado que en la parte del módulo ESP32 el Bluetooth se trata de una interfaz abierta cualquiera puede crear una aplicación que haga uso de los servicios ofrecidos para mostrar información en la pantalla. Dadas mis inquietudes quería jugar/aprender un poco sobre el desarrollo de aplicaciones ios, así que la aplicación que he implementado está desarrollada en Swift para ios.
La aplicación consiste en una pantalla de configuración y estado con un mapa en la parte inferior. Tiene dos métodos de funcionamiento el primero, navegación clásica, permite seleccionar manteniendo pulsado en el mapa inferior un punto de destino y el tipo de transporte, ya sea andando o en coche. Cuando se pulsa el botón de navegación la aplicación nos guiará hacia los distintos puntos generados por la API de mapas de ios, y en la parte superior de la pantalla del móvil se nos darán las instrucciones precisas para llegar al destino, mientras que en el la pantalla del ESP32 aparecerá la orientación del siguiente punto de interés.
Otra manera de usar la aplicación es crear la ruta que deseada a mano usando el mapa. Manteniendo pulsado sobre el mapa crea un punto de interés y podemos crear tantos como deseemos. Para navegar hay que seleccionar la opción de "compass" y en la parte superior de la pantalla en vez de indicaciones nos aparecerá la distancia al siguiente punto de interés.
Captura de pantalla aplicación
Para la implementación he usado el entorno Xcode de la propia Apple y en la aplicación hago uso de las bibliotecas MapKit y CoreBluetooth también propias del entorno ios.
MapKit se encarga de gestionar el mapa que se muestra por pantalla y además es el responsable de ofrecer la API para obtener la ruta de navegación. Para gestionar el mapa la clase principal debe heredar de la clase MKMapViewDelegate para poder implementar los métodos que requiere la aplicación. Estos métodos son, el de gestión de la pulsación larga y un método requerido para poder mostrar la linea de la ruta de navegación. Los puntos que se van incluyendo se añaden a una lista global para luego poder ser leidos por el gestor de la posición.
Para poder obtener la posición la clase principal debe heredar de la clase CLLocationManagerDelegate incluida en las librerías por defecto de ios. Al heredar de esta clase podemos añadir el objeto CLLocationManager para que pueda llamar a los callbacks programados por nosotros. El callback implementado es:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
Cada vez que se actualiza la posición se llama a este método para que podamos gestionar la posición. En nuestro caso comprobar donde estamos y actualizar en caso necesario al siguiente punto de la ruta.
Esta es la parte más compleja debido a que se debe ir descubriendo las capas que rodean a las características BLE poco a poco. Para el Bluetooth la clase debe heredar de CBCentralManagerDelegate y CBPeripheralDelegate que son las que nos permiten implementar los distintos callbacks. El principal centralManagerDidUpdateState es el que gestiona los estados del Bluetooth, como cuando se enciende, se apaga, se resetea,... Para descubrir periféricos se usa el método centralManager que sirve tanto para cuando se descubre un nuevo periférico cuando en los argumentos se incluye didDiscover, como cuando nos conectamos con éxito al periférico deseado.
Una vez nos hemos conectado a los dispositivos se llama al método peripheral que permite buscar servicios y sus características. Cuando encontramos la característica que nos interesa la almacenamos para poder comunicarnos más tarde.
Para el envío de los datos se transforman a binario y se envían tal y como se puede ver en el trozo de código que se encuentra abajo.