Blog de Amazon Web Services (AWS)

Location Service: Guía de primeros pasos para integrarlo a su proyecto web serverless

Los mapas siempre han sido parte fundamental en nuestras vidas desde el primer instante en que queremos saber, por ejemplo, cómo dirigirnos a un cierto punto de nuestra ciudad. Inicialmente eran guías físicas y con el paso del tiempo se han adaptado a la era digital. La ubicación en tiempo real también ha avanzado. Al día de hoy, existen muchas aplicaciones web y móviles que de alguna forma lo implementan: ya sea para delivery de comida, para transporte personal o inclusive para solicitar movilidad.

Al entender las necesidades de nuestros clientes, AWS lanzó Location Service y combina lo mejor de dos mundos: pago por uso e integración sencilla con su proyecto. Este le permite simplificar la tarea de los desarrolladores al momento de agregar a las aplicaciones funciones de ubicación, sin comprometer la seguridad de los datos y la privacidad del usuario.

En el siguiente informe estaremos enseñando cómo integrar mapas y ubicaciones a un proyecto web serverless con ReactJS y autenticación de usuarios usando distintos servicios como AWS Amplify, Amazon Cognito y Amazon Location Service.

Configurando el código fuente

Para comenzar a diseñar este proyecto necesitaremos contar con accesos (access key y secret access key) a una cuenta de AWS. En caso de que no la haya configurado, es conveniente revisar el siguiente procedimiento del servicio de Identity and Access Management (IAM). El objetivo de tener dichas claves generadas es para que luego podamos ejecutar comandos por línea de comando desde el código en ReactJS que generaremos más adelante. Una vez obtenidas ambas claves, debe configurar la CLI de AWS localmente. Dicho proceso lo puede hacer en el siguiente enlace de fundamentos de configuración.

En segundo lugar, necesitamos crear un proyecto web. En particular en este blog estaremos usando ReactJS, aunque usted puede integrarlo fácilmente con otros frameworks o librerías como Angular o Vue.

npx create-react-app my-locations-app
cd my-locations-app
npm start

A continuación, debe instalar las dependencias necesarias para Amplify y Location Service

npm install aws-sdk aws-amplify @aws-amplify/ui-react

Con la dependencia aws-sdk estaremos importando la librería correspondiente a Location Service, para que el cliente web pueda hacer peticiones al backend y obtener rutas y posiciones geográficas.

La dependencia aws-amplify importa el SDK de Amplify para luego integrar autenticación.  @aws-amplify/ui-react instalará los componentes de Amplify UI, un conjunto de herramientas de interfaz de usuario de código abierto, que encapsula los flujos de trabajo conectados a la nube dentro de los componentes de la interfaz de usuario. En esta ocasión utilizaremos las dependencias de interfaz para incorporar un formulario de Login y Registro fácilmente.

Añadiendo servicios al código fuente

Una vez instaladas todas las dependencias, nuestro primer paso es agregar autenticación por parte de usuarios a nuestro sitio web. Esto es importante ya que queremos restringir el acceso a los mapas solo a usuarios autenticados, es decir, solo los usuarios que cuenten con acceso al sitio web pueden hacer consultas de búsqueda de posición y rutas al backend diseñado en Amazon Location Service.

Para ello, lo primero que debemos hacer es añadir dicha capa de autenticación con Amplify.

amplify add auth

? Do you want to use the default authentication and security configuration? Default configuration

? How do you want users to be able to sign in? Username

? Do you want to configure advanced settings?  No, I am done.

amplify push

Finalmente, al dirigimos al servicio de Cognito en la consola de AWS podremos visualizar nuestro pool de usuarios creado. Inicialmente no tendremos personas registrados, pero no resulta un problema ya que en breve estaremos añadiendo el formulario de registro en nuestro portal web.

Si accedemos a la sección de Roles en el servicio de IAM, podremos ver que existen 3 roles asociados al haber integrado Cognito para autenticación.

Los roles los podemos identificar porque contienen parcialmente el nombre del proyecto creado en Amplify, en nuestro caso “locationsappdemo”. Cada uno de estos roles serán otorgados a nuestros usuarios cuando se autentiquen (o no) en el sitio web que estamos desarrollando. En particular, haremos hincapié en el finalizado en ‘authRole’, que mediante políticas podremos agregar o remover las acciones o permisos que pueden hacer nuestros usuarios.

Creando los recursos en Location Service

El siguiente paso es crear los recursos de Location Service necesarios para luego ser consultados desde el sitio web. Para ello, en el servicio lo primero que se creará será un mapa.

Para crear el recurso de mapa debe primero proporcionar el nombre y la descripción. Seguidamente deberá elegir un proveedor de datos, puede seleccionar ESRI o HERE. Como próximo paso, deberá seleccionar el tipo de facturación. Finalmente se pueden agregar etiquetas opcionales, que le permiten categorizar sus recursos para ayudar con la identificación, el control de permisos y la facturación.

Una vez creado el mapa, crearemos un índice de lugar o ‘Place Index’. Un índice de lugar es un motor de búsqueda geográfica que se puede utilizar para buscar puntos de interés, direcciones de calles (geocodificación) y coordenadas.

Esto lo necesitaremos ya que el usuario inicialmente escribirá la dirección de origen y de destino y Amazon Location Service retornará la ruta para ir desde un punto al otro. Para lograrlo, debemos traducir un origen en coordenadas geográficas, esto lo lograremos mediante el índice de lugar creado.

Finalmente, crearemos una calculadora de ruta, que utiliza su proveedor de datos elegido previamente para proporcionar el tiempo de conducción, la distancia y la geometría entre la ubicación que proporcionó.

Permitiendo acceso de los clientes a Location Service

Volviendo nuevamente al servicio de IAM, identificamos el rol terminado en authRole que creó Cognito explicado previamente en este documento. Añadiremos una política con los siguientes recursos ya creados, en nuestro caso se denominará AuthenticatedUsersAccessToLocationServices.

 

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "geo:*",
"Resource": [
"arn:aws:geo:REGION:ACCOUNTID:place-index/MyNewPlaceIndex",
"arn:aws:geo:REGION:ACCOUNTID:map/MyNewMap",
"arn:aws:geo:REGION:ACCOUNTID:route-calculator/LocationCalculator"
]
}
]
}

 

Una vez otorgada dicha política al rol, ahora nuestros usuarios pueden hacer consultas sobre los recursos que creamos.

Agregando los recursos a nuestro código fuente

– Login

En el punto de entrada de su aplicación (es decir, App.js, index.js o main.js), importe y cargue el archivo de configuración:

 import Amplify, { Auth } from 'aws-amplify';
import awsconfig from './aws-exports';
Amplify.configure(awsconfig);

Hay dos formas de agregar capacidades de autenticación a su aplicación:

  • Utilice componentes de interfaz de usuario prediseñados
  • Llamar a las API de autenticación manualmente

En nuestro caso, crearemos el flujo de inicio de sesión con Amplify Framework que tiene componentes de interfaz de usuario que puede utilizar y proporcionarán todo el flujo de autenticación (registro, validación de usuario, cambio de contraseña e ingreso).

A continuación, abra src/App.js y agregue el componente withAuthenticator.

import {AmplifyAuthenticator} from "@aws-amplify/ui-react";

Finalmente, su código debería ser similar al siguiente:

function App() {
return (
<AmplifyAuthenticator>
<HashRouter>
<Switch>
<Route exact path="/" component={CalculateRoute}/>
</Switch>
</HashRouter>
      </AmplifyAuthenticator>
);
}
export default App;

– Calculate Route

En otro archivo dentro del directorio /src, crearemos una nueva interfaz dividida en 3 componentes:

  1. Formulario para completar origen, destino y tipo de modo de viaje
  2. Mapa
  3. Ruta en color rojo basado en la entrada del usuario

El componente del formulario debe tener 3 entradas obligatorias del usuario: lugar de origen, destino y tipo de viaje. Una vez completo los campos, al hacer clic deberán ocurrir principalmente tres cosas:

  1. Traducir del lenguaje natural a coordenadas el origen
  2. Traducir del lenguaje natural a coordenadas el destino
  3. Con los valores retornados en los puntos anteriores, calcular la ruta y obtener una lista de puntos geométricos.

La siguiente función simplifica lo comentado previamente:

//CalculateRouteFormComponent onClick button
async function onClickSearch(from, to, travelMode){
 
if (from == null || to == null ){
alert("Fields can't be empty. Please, select a location.");
}
 
//Coordenadas de origen. calculateLatLong es una función asincrónica que recibe en texto la ubicación y retornará un array con los puntos geográficos encontrados.
var fromLocation = await calculateLatLong(from);
var fromCoordinates = fromLocation.Results[0].Place.Geometry.Point;
 
//Mismo caso que las coordenadas de origen, pero del destino
var toLocation = await calculateLatLong(to);
var toCoordinates = toLocation.Results[0].Place.Geometry.Point;
 
//La función recibe tres parametros: las coordenadas del origen y destino, y un string que representa el tipo de viaje (a pie o en auto)
calculateRoute(fromCoordinates, toCoordinates, travelMode).then( (result) => {
var dataToParse = result.Legs[0].Geometry.LineString;
setRoute( locationStepsToGeoJSON(dataToParse) );
});
 
}
 
 
 
//Retorna las coordenadas dado un lugar en string
const calculateLatLong = async(place) => {
var params = {
IndexName : YOURINDEXNAME,
Text: place
};
 
var data = client.searchPlaceIndexForText(params).promise();
return data;
}
 
 
 
//Retorna la ruta dadas dos coordenadas
const calculateRoute = async(fromCoordinates, toCoordinates, travelMode) => {
 
var params = {
CalculatorName : YOURCALCULATORNAME,
DeparturePosition : fromCoordinates,
DestinationPosition : toCoordinates,
IncludeLegGeometry : true,
TravelMode : travelMode,
DepartNow : true ,
DistanceUnit : 'Kilometers',
};
 
var data = client.calculateRoute(params).promise();
return data;
 
}

Finalmente necesitamos renderizar el mapa obtenido y la ruta. Este último es opcional y puede o no visualizarse.

//Renderiza el mapa y opcionalmente una ruta en color rojo.
<ReactMapGL
{...viewport}
width="100%"
height={window.innerHeight * 0.85}
transformRequest={transformRequest}
mapStyle={mapName}
onViewportChange={setViewport}
>
<div style={{ position: "absolute", left: 20, top: 20 }}>
<NavigationControl showCompass={false} showZoom={false}/>
</div>
 
{ route ? (
<React.Fragment>
<Source id="layerId" type='geojson' data={route} />
<Layer
id="layerId"
type="line"
source="layerId"
paint={{
'line-color': "#e53935",
'line-width': 3
}}
/>
</React.Fragment>
) : (
<div>
Click search to display a route.
</div>
) }
 
</ReactMapGL>

En caso de querer continuar aprendiendo basado en ejemplos, recomendamos leer los siguientes links, con ejemplos y guías para continuar

Conclusiones

En este informe descubrimos inicialmente cómo crear un proyecto web en ReactJS y hacer cálculos de rutas entre dos posiciones

Para comenzar a implementar, Location Service ofrece una capa gratuita durante los tres primeros meses de uso basado en solicitudes. El plan de precios de uso basado en solicitudes proporciona acceso a los datos de localización que se facturan en función de cada solicitud que la aplicación hace al servicio. Más allá de la capa gratuita de Amazon Location Service, paga por las solicitudes que la aplicación hace al servicio. Para más información puede visitar el siguiente link.

El servicio de ubicación de Amazon le permite hacer esto a bajo costo aprovechando además la funcionalidad de AWS Amplify, Amazon Cognito y Administración de acceso de AWS (IAM) para controlar el acceso a los recursos asociados.


Sobre el autor

Kevin Cortés Rodríguez es Arquitecto de Soluciones en AWS. Graduado de la carrera de Ingeniería en Informática, trabaja asistiendo y apoyando a los clientes del sector público en su “viaje a la nube” de AWS en proyectos que involucran arquitecturas escalables y serverless. Tiene gran interés en las áreas de desarrollo móvil, web, IOT y analítica de datos.

Revisores

Gustavo Fandiño es un Arquitecto de Soluciones para América Latina. Ha realizado proyectos de modernización, migración y microservicios. Dentro de sus objetivos está el expandir el uso de AWS en el territorio y colaborar muy de cerca con los partners y clientes, para facilitar el uso y adopción de soluciones costos eficientes en AWS.

Branko Straub es Arquitecto de Soluciones en Amazon Web Services para Sector Público en Chile. Branko ha ayudado a múltiples instituciones de Sector Público y Privado en la adopción tecnológica de nube en los últimos 5 años, ha ejecutado de manera exitosa proyectos con impacto social en la ciudadanía alrededor de América Latina.