Skip to content
Agustín Sánchez Martín edited this page Mar 21, 2023 · 12 revisions



METEOGPS

Índice

1. Primeros Pasos

Debido a la complejidad que aparece al intentar desarrollar un sistema que emplee tecnología de tipo OSINT y tras conversar con el profesor se decide que la mejor opción es desarrollar un sistema relacionado con la tecnología GPS.

Por lo tanto la primera duda que nos apareció en la cabeza fue ¿Que debemos hacer? Por sentido común e intentando aproximarnos lo máximo posible a la realizad y al uso más cotidiano que le damos a la tecnología GPS decidimos desarrollar una aplicación en este caso móvil que integre varias funcionalidades.

La primera idea fue la de desarrollar un GPS que partiendo de un origen se pudiese elegir un destino y fuese capaz de generar una ruta e indicar el camino a seguir.

Para ello estudiamos las diferentes librerias que había. Encontramos la que más se adaptaba a nuestras necesidades. GMP (Google Maps Platform) que pese a ser gratuita, hasta un máximo de peticiones te obliga a introducir la cuenta bancaria como se puede observar en la siguiente imagen:

Por lo tanto decidimos introducir pequeñas funcionalidades:

  • Generación de una ruta desde un origen a un destino, mostrando las indicaciones necesarias para llegar al destino.
  • Mostrar localizaciones teniendo las coordenadas de diferentes puntos en un mapa creado de forma dinámica.
  • Mostrar el tiempo en una localización.

Una vez decidido la funcioalidad pensamos cual sería la plataforma sobre la que desarrollar la aplicación, Android, IOS...

Debido a la alta complejidad de desarrollo que hay para hacer aplicaciones nativas en IOS, debido a que se necesita un ordenador específico de la marca Apple y que el lenguaje cambia mucho al igual que ocurre con plataformas como puede ser Flutter todo apuntaba a que el sistema sería desarrollado para sistemas Android.

Una vez que teniamos estas ideas en la cabeza y donde iba a ser desarrollado comenzamos con el desarrollo del sistema.

(Back to top ↑)

2. Propuesta final

2.1 Primeras aproximaciones

En primer lugar para desarrollar el primer punto de los propuestos buscamos que API-REST podria suministrarnos la información necesaria. Encontramos el servicio Here de la que podiamos obtener mapas, obtener indicaciones de un trayecto y obtener mapas con diferentes coordenadas.

2.1.1 Generación de una ruta

Por lo tanto asi se desarrollo el primer apartado Generación de una ruta donde en primer lugar se obtiene la localización inicial y tras seleccionar el destino se puede obtener la ruta mediante indicaciones y un mapa con la ruta dibujada.

2.1.2 Tiempo

El segundo punto fue intentar obtener una api donde se pudiese obtener la temperatura de un lugar partiendo de las geocoordenadas y tras analizar las diferentes posibilidades gratuitas nos decantamos por la libreria Weatherapi, debido a su simplicidad, cantidad de información y al número máximo de peticiones que se le puede realizar ésta fue la elegida. Para ello desarrollamos una interfaz que toma la localización actual y muestra el pronóstico actual de la temperatura y un desglose de éste en horas.

2.2 Marco de propuesta

Intentando desarrollar un poco más el sistema y aumentar las funcionalidades se pensó en diferentes acciones que se puedan desarrollar

2.2.1 Gasolineras

Nos planteamos la idea de mostrar puntos de interés cerca de la localización actual, el problema que nos surgía era encontrar algun sistema que nos proporcionase la información de forma gratuita, una muy famosa es TripAdvisor pero al igual que pasa con GMP era gratutia n solicitudes al día pero tenías la obligación de introducir una tarjeta bancaria para configurar el método de pago.

Hasta que encontramos una página que suministraba la geolocalización de gasolineras con el precio de los diferentes carburantes de ahí salio la idea de desarrollar una interfaz que muestre la información de las gasolineras más próximas y localizarlas todas en un mapa.

2.2.2 Galeria

Intentando abstraernos de la información obtenida de API-REST (del exterior) se nos ocurrió una interfaz que mostrase el metadata de una imagen realizada con el teléfono móvil.

2.2.3 Trayectoria

A petición del profesor tras mostrar los avances que teniamos nos pidió implementar una funcionalidad de la cual pudisesemos generar una ruta por la que hubiesemos pasado, para ello creamos una pantalla que captura cada n segundos la localización y al acabar muestra un mapa con la trayectoria realizada.

2.3 Herramientas utilizadas

El sofware usado para el desarrollo de la aplicación es:

  • Android Studio 2022.1.1: Para el desarrollo de la aplicación en android.
  • Visual Studio Code 1.75.1: Como editor de texto auxiliar para agilizar la codificación del sistema.
  • Postman v10.10.3 : Para el desarrollo de las llamadas en postman.

2.4 Arquitectura

Los principales componentes son:

  • Dispositivo móvil: Este es el dispositivo utilizado por el usuario para acceder al sistema de localización. Puede ser un teléfono inteligente, una tableta u otro dispositivo móvil con capacidad de conexión a internet y GPS. Al usar un teléfono móvil en lugar de un emulador que proporciona el propio android studio facilita la captura de localizaciones reales, el emulador la simula.
  • API REST: La API REST es el mecanismo utilizado para la obteción de los datos de las rutas, del tiempo…
  • Aplicación móvil: La propia aplicación desarrollada para que el usuario pueda acceder al sistema de localización.

No se utilzian servidores ni base de datos ya que todos los datos se obtienen directamente de las ya mencionadas API REST.

(Back to top ↑)

3. Descripción del sistema

El sistema esta formado por 5 diferentes módulos:

  • Generación de una ruta. Teniendo en cuenta la localización actual insertamos el lugar de destino.
  • Tiempo, calcula el tiempo de la localización actual o de una seleccionada.
  • Galería, calcula la posición y dirección de una imagen seleccionada desde la galeria.
  • Gasolineras, búsqueda de las gasolineras por proximidad en función de la localización actual.
  • Trayecto, calcula la ruta recorrida de forma física.

3.1 Generación de una ruta

En la pestaña de ruta, en un primer momento comprueba si está habilitada geolocalización del teléfono y si tiene permisos para poder usar la localización, una vez confirmadas se calcula la localización actual, rellenando los datos de la parte superior.

Si en el buscador introducimos una dirección se realizará un cálculo proporcionando las posibles soluciones a la búsqueda introducida. Una vez seleccionada en el desplegable la dirección que más se aproxima se realizan los siguientes cálculos:

  • El tiempo estimado que se tarda en llegar.
  • Listado de todas las indicaciones necesarias para llegar al destino.
  • Imagen de la ruta desde el inicio hasta el punto definido como destino.

Cálculo de la localización, se debe introducir el destino para poder comenzar Se calcula las indicaciones para llegar al destino y hora estimada de llegada.

Se realiza la búsqueda del destino y se proporcionan diferentes soluciones. Generación del mapa de la ruta desde el inicio hasta el punto definido.

3.2 Tiempo

Cuando entramos en la pestaña del tiempo al igual que pasa en la pestaña de ruta se comprueba que tenemos la localización encendida. Entonces muestra el tiempo y el pronóstico del día de hoy de la localización actual, aunque se puede realizar búsquedas de un lugar concreto.

Módulo del tiempo
  • En la parte superior se muestra la ciudad/localización.
  • A continuación un buscador donde poder introducir diferentes ciudades.
  • En el centro de la pantalla se muestra la temperatura en grados celcius.
  • Al final de la pantalla un listado en formato horizontal con el pronóstico para las próximas horas, desglosado por horas, grados y velocidad del viento en kilómetros hora.

3.3 Gasolineras

Al igual que ocurren en el resto de apartados se comprueba que se tenga la localización activada y que la aplicación tenga permisos sobre esta. En función de la localización actual se comprueban las gasolineras próximas.

Mediante el uso de la fórmula del semiverseno y las coordinadas actuales y las coordenadas de destino (las gasolineras) se calcula la distancia y se comprueba si la distancia es menor a la definida (por defecto se buscan las gasolineras menores a 10 Km), se representa con el siguiente fragmento de código:

// Método main que lanza la aplicación
public static void main(String[] args) {

		// Listado de coordenadas (gasolineras)
		List<String> list = ...
		
		// Coordenadas iniciales
		double lat1 = 0.0000;
		double lon1 = -0.0000;
		
		double maxDistance = 10; // Máxima distancia en km

		for (String location : list) {
			
			String[] chain = location.split(",");
			
			double lat2 = Double.parseDouble(chain[0]);
			double lon2 = Double.parseDouble(chain[1]);
			double distance = haversine(lat1, lon1, lat2, lon2);
			if (distance <= maxDistance) {
				System.out.printf("%f,%f,\n", lat2, lon2);
			}
		}
	}

// Fórmula del semiverso
public static double haversine(double lat1, double lon1, double lat2, double lon2) {
		double dLat = Math.toRadians(lat2 - lat1);
		double dLon = Math.toRadians(lon2 - lon1);
		lat1 = Math.toRadians(lat1);
		lat2 = Math.toRadians(lat2);

		double a = Math.pow(Math.sin(dLat / 2), 2) + Math.pow(Math.sin(dLon / 2), 2) * Math.cos(lat1) * Math.cos(lat2);
		double c = 2 * Math.asin(Math.sqrt(a));
		return R * c;
	}

Se muestra la siguiente información:

  • Precio de la gasolina 95 octanos.

  • Precio de la gasolina 98 octanos.

  • Dirección de la gasolinera.

  • Horario.

  • Precio del diésel normal.

  • Precio del diésel premium.

  • Nombre de la gasolinera.

  • Localización actual.

Por defecto se muestran las gasolineras a menos de 10 Km con la posibilidad de aumentar el rango usando el slider. En la parte inferior se muestra un mapa con todas las gasolineras que se han encontrado.

Localización actual y listado de gasolineras por proximidad.
Por defecto el rango de búsqueda es de 10.

Mapa con todas las gasolineras.

3.4 Galería

A diferencia del resto de secciones, en esta no se hace uso de forma directa de la geolocalización actual del sistema, la interfaz consta de:

  • Imagen seleccionada.
  • Texto donde se representa la localización.
  • Botón para abrir la galería.
  • Imagen de un mapa que muestra donde fue tomada la imagen.

Abriendo la galería y seleccionando una imagen se recogen los metadatos de ésta y se calcula la localización y un mapa del punto exacto donde ha sido tomada la fotografía.

Módulo de galeria

3.5 Trayectoria

La pestaña consiste en calcular la una trayectoria de forma física, al hacer click en el botón de Iniciar Ruta se comienza a calcular la localización cada 15 segundos, una vez pulsado Detener Ruta se genera un mapa con la trayectoria seguida. Para poder realizar esto es necesario la creación de un hilo que de forma secundaria recoja la localización actual que se va guardando en una lista y para terminar se realiza una línea uniendo las localizaciones que se han ido calculando cada 15 segundos. El tiempo debe ser pequeño debido a que si se calcula cada mucho tiempo al realizar el trazado se superpondrá por encima de edificios.

Interfaz inicial con el botón de iniciar.

Realizando el cálculo de la ruta

Tras calcular el trayecto se genera el mapa.

Posibilidad de ampliar el mapa

(Back to top ↑)

4. API-REST

La aplicación se ha desarrollado utilizando los diferentes servicios de localización que proporciona la API-REST hereapi. Las llamadas utlizadas son:

Localizaciones

Localización

Proporciona un listado de localizaciones en función del filtro por el que se ha introducido.

Url

https://geocode.search.hereapi.com/v1/geocode?apikey=***&q=***

Variable Descripción
apiKey Valor de la api que proporciona permisos para hacer consultas
q Valor, ciudad, código postal, longitud/latitud.

Resultado:

{
    "items": [
        {
            "title": "string",
            "id": "string",
            "resultType": "string",
            "localityType": "string",
            "address": {
                "label": "string",
                "countryCode": "string",
                "countryName": "string",
                "stateCode": "string",
                "state": "string",
                "county": "string",
                "city": "string",
                "postalCode": "string"
            },
            "position": {
                "lat": 0,
                "lng": 0
            },
            "mapView": {
                "west": 0,
                "south": 0,
                "east": 0,
                "north": 0
            },
            "scoring": {
                "queryScore": 0,
                "fieldScore": {
                    "postalCode": 0
                }
            }
        }
    }

Localización en un mapa

Dados unas geocordenadas se pintan en un mapa.

Url

https://image.maps.ls.hereapi.com/mia/1.6/mapview?apiKey={{api_key}}&ctr=&z=18&poi=&w=600&h=600&ml=es&ppi=200

Variable Descripción
apiKey
ctr Listado de geolocalizaciones separadas por coma.
w Anchura de la imagen.
h Altura de la imagen.
ml Idioma.
ppi Resolución de la imagen.
z Zoom sobre la localización.

Resultado

Resultado de la llamada

Ruta

Proporciona una imagen de la ruta partiendo de una latitud y longitud inicial hasta una latitud y longitud de destino.

Url

https://image.maps.ls.hereapi.com/mia/1.6/routing?apiKey=...&waypoint0=...,...&waypoint1=...,...&lc=1652B4&lw=6&t=0&ppi=320&w=800&h=500

Variable Descripción
apiKey Valor de la api que proporciona permisos para hacer consultas
waypoint0 valor de 'Latitud,Longitud'.
waypoint1 valor de 'Latitud,Longitud'.
lc Código rgb del color de la linea que indica el camino.
lw Grosor de la linea que indica el camino.
ml Idioma de las etiquetas.
w Anchura de la imagen
h Altura de la imagen
t Tipo de mapa, (0 = normal)
ppi Resolución de la imagen que indica el camino.

Resultado

Como resultado se obtiene una image.

Tiempo

Tiempo

Petición que nos proporciona el tiempo de una localización, por nombre o por longitud y latitud.

Url

https://api.weatherapi.com/v1/forecast.json?key=&q=&days=1&aqi=yes&alerts=yes

Variable Descripción
key Valor de la api que proporciona permisos para hacer consultas
q Valor, ciudad, código postal, longitud/latitud
days Número de días que queremos el prónostico

Resultado

    {
        "location": {
            "name": "string",
            "region": "string",
            "country": "string",
            "lat": 0,
            "lon": 0,
            "tz_id": "string",
            "localtime_epoch": 0,
            "localtime": "string"
        },
        "current": {
            "last_updated_epoch": 0,
            "last_updated": "string",
            "temp_c": 0,
            "temp_f": 0,
            "is_day": 1,
            "condition": {
                "text": "string",
                "icon": "string",
                "code": 0
            },
            "wind_mph": 0,
            "wind_kph": 0,
            "wind_degree": 0,
            "wind_dir": "string",
            "pressure_mb": 0,
            "pressure_in": 0,
            "precip_mm": 0,
            "precip_in": 0,
            "humidity": 0,
            "cloud": 0,
            "feelslike_c": 0,
            "feelslike_f": 0,
            "vis_km": 0,
            "vis_miles": 0,
            "uv": 0,
            "gust_mph": 0,
            "gust_kph": 0,
            "air_quality": {
                "co": 0,
                "no2": 0,
                "o3": 0,
                "so2": 0,
                "pm2_5": 0,
                "pm10": 0,
                "us-epa-index": 0,
                "gb-defra-index": 0
            }
        },
        "forecast": {
            "forecastday": [
                {
                    "date": "2023-02-06",
                    "date_epoch": 0,
                    "day": {
                        "maxtemp_c": 0,
                        "maxtemp_f": 0,
                        "mintemp_c": 0,
                        "mintemp_f": 0,
                        "avgtemp_c": 0,
                        "avgtemp_f": 0,
                        "maxwind_mph": 0,
                        "maxwind_kph": 0,
                        "totalprecip_mm": 0,
                        "totalprecip_in": 0,
                        "totalsnow_cm": 0,
                        "avgvis_km": 0,
                        "avgvis_miles": 0,
                        "avghumidity": 0,
                        "daily_will_it_rain": 0,
                        "daily_chance_of_rain": 0,
                        "daily_will_it_snow": 0,
                        "daily_chance_of_snow": 0,
                        "condition": {
                            "text": "string",
                            "icon": "string",
                            "code": 1000
                        },
                        "uv": 0,
                        "air_quality": {
                            "co": 0,
                            "no2": 0,
                            "o3": 0,
                            "so2": 0,
                            "pm2_5": 0,
                            "pm10": 0,
                            "us-epa-index": 0,
                            "gb-defra-index": 0
                        }
                    },
                    "astro": {
                        "sunrise": "08:18 AM",
                        "sunset": "06:39 PM",
                        "moonrise": "07:21 PM",
                        "moonset": "09:03 AM",
                        "moon_phase": "Waning Gibbous",
                        "moon_illumination": "100",
                        "is_moon_up": 0,
                        "is_sun_up": 0
                    },
                    "hour": [
                        {
                            "time_epoch": 0,
                            "time": "0",
                            "temp_c": 0,
                            "temp_f": 0,
                            "is_day": 0,
                            "condition": {
                                "text": "string",
                                "icon": "string",
                                "code": 1000
                            },
                            "wind_mph": 0,
                            "wind_kph": 0,
                            "wind_degree": 0,
                            "wind_dir": "string",
                            "pressure_mb": 0,
                            "pressure_in": 0,
                            "precip_mm": 0,
                            "precip_in": 0,
                            "humidity": 0,
                            "cloud": 0,
                            "feelslike_c": 0,
                            "feelslike_f": 0,
                            "windchill_c": 0,
                            "windchill_f": 0,
                            "heatindex_c": 0,
                            "heatindex_f": 0,
                            "dewpoint_c": 0,
                            "dewpoint_f": 0,
                            "will_it_rain": 0,
                            "chance_of_rain": 0,
                            "will_it_snow": 0,
                            "chance_of_snow": 0,
                            "vis_km": 0,
                            "vis_miles": 0,
                            "gust_mph": 0,
                            "gust_kph": 0,
                            "uv": 0,
                            "air_quality": {
                                "co": 0,
                                "no2": 0,
                                "o3": 0,
                                "so2": 0,
                                "pm2_5": 0,
                                "pm10": 0,
                                "us-epa-index": 0,
                                "gb-defra-index": 0
                            }
                        }
                    ]
                }
            ]
        },
        "alerts": {
            "alert": []
        }
    }    

Indicaciones

Dados unas geocordenadas se pintan en un mapa.

Url

https://image.maps.ls.hereapi.com/mia/1.6/mapview?apiKey={{api_key}}&ctr=&z=18&poi=&w=600&h=600&ml=es&ppi=200

Variable Descripción
apiKey
ctr Listado de geolocalizaciones separadas por coma.
w Anchura de la imagen.
h Altura de la imagen.
ml Idioma.
ppi Resolución de la imagen.
z Zoom sobre la localización.

Resultado

Resultado de la llamada

Tiempo

Tiempo

Dados unas geocordenadas se obtiene la informacion meteorológica.

Url

https://api.weatherapi.com/v1/forecast.json?key=***&q=***&days=***&aqi=yes&alerts=yes

Variable Descripción
apiKey
q Valor, ciudad, código postal, longitud/latitud.
days Número de días de los que se pretende obtener el resultado
aqi Altura de la imagen.
alerts Pronóstico desglosado en horas.

Resultado

{
    "routes": [
        {
            "id": "String",
            "sections": [
                {
                    "id": "String",
                    "type": "String",
                    "actions": [
                        {
                            "action": "String",
                            "duration": 0,
                            "length": 0,
                            "instruction": "String",
                            "offset": 0,
                            "direction": "String",
                            "exit": 0
                        }
                    ],
                    "departure": {
                        "time": "String",
                        "place": {
                            "type": "String",
                            "location": {
                                "lat": 0.0,
                                "lng": 0.0
                            },
                            "originalLocation": {
                                "lat": 0.0,
                                "lng": 0.0
                            }
                        }
                    },
                    "arrival": {
                        "time": "String",
                        "place": {
                            "type": "String",
                            "location": {
                                "lat": 0.0,
                                "lng": 0.0
                            },
                            "originalLocation": {
                                "lat": 0.0,
                                "lng": 0.0
                            }
                        }
                    },
                }
            }
        }
    ]
}

(Back to top ↑)