Front-End Web & Mobile
Implementing Estimated Time of Arrival and Proximity Notifications for Delivery using Amazon Location Service
The development of location-based services is increasing at a rapid rate, supporting use cases such as asset track and delivery services. In this blog, we’ll show you how to implement an estimated time of arrival or proximity notification using Amazon Location Service. An example of this would be delivery of building materials (e.g., lumber, copper piping, electrical wire). Material security and receipt acknowledgment at a job site is a critical due to high material costs and scarcity. When combined with Amazon Simple Notification Service, you can be easily notified via email or SMS message. You’ll learn more about Amazon Location Service capabilities including Places, Maps, Routes, Trackers, and Geofences APIs.
Solution overview
In this post, we’ll show you how to perform the following steps:
- Use Quick Setup to create an AWS Amplify application and Amazon Location Service Map and Index.
- Create a notification topic and subscriber using Amazon Simple Notification Service.
- Use Amazon Location Service Routes APIs with AWS Amplify to notify a user when estimated time of arrival is five minutes or less for a delivery.
- Use Amazon Location Service Geofences APIs and Amazon EventBridge with AWS Amplify to notify you when a delivery is within 1 mile or less.
Prerequisites
- React Framework
- AWS Amplify (authentication, app hosting, CI/CD)
- Amazon EventBridge (receive Geofence events and invoke SNS)
- Amazon Location Service
- Amazon Simple Notification Service
- AWS CLI
- Foundational React application repository: https://github.com/mavi888/drop-the-box-demo
- Delivery ETA application repository: https://github.com/aws-samples/amazon-location-delivery-app
Scenario 1 : Estimated time of arrival alert architecture
In the first scenario, a subscriber to Amazon Simple Notification Service (Amazon SNS) is notified when a delivery vehicle is within a five-minute window of its destination. To support this Amazon Location Service’s Maps, Trackers and Routes APIs are leveraged to calculate the estimated time of arrival and notify when that time equals or is less than five minutes. In Figure 1, the users employ a React application that displays a map, the destination and updated tracker location. Using the Amazon Location Routes API, distance and estimated time of arrival can be retrieved and Amazon SNS used for delivering a notification back to the subscribed users.
Figure 1: Estimated time of arrival alert architecture
Scenario 2 : Proximity alert architecture
The second scenario leverages Amazon Location Service’s Maps, Trackers and Geofences APIs to monitor proximity and notify when the delivery vehicle has entered a pre-defined geofence. When a delivery vehicle enters a pre-defined geofence, an event occurs in Amazon EventBridge triggering Amazon Simple Notification Service and an email / SMS to the user.
Figure 2: Proximity Based Alert Architecture
Configuring React application with AWS Amplify and Amazon Location Service
For both scenarios, a React Application is created using AWS Amplify to leverage authentication and build and deploy services. The following steps will walk through setting up the React Application, necessary Identity and Access Management policy, Amazon Location Service elements including the Map and PlaceIndex, and finally the Amazon SNS topic and subscriber.
Set up React Application
You can clone the delivery eta repository and then configure AWS Amplify.
Set up AWS Amplify
Within the newly created React project, the AWS Amplify NPM dependency is installed and AWS Amplify is initialized.
1. Install the AWS Amplify CLI and configure your profile.
$ npm install -g @aws-amplify/cli
$ amplify configure
$ amplify init
2. Set up Amplify Authentication
AWS Amplify Authentication uses Amazon Cognito to set up authentication. Use Default Configuration with Social Provider.
$ amplify add auth
Please note that certain attributes may not be overwritten if you choose to use defaults settings.
Using service: Cognito, provided by: awscloudformation
*What do you want to do?* Apply default configuration with Social Provider (Federation)
*What domain name prefix do you want to use?* (deliveryappXXXX)
3. Update Cloud Resources
Update AWS Amplify with the changes.
$ amplify push
Set up Amazon Location Service Resources
For both the scenarios, a Map and Place Index resources need to be created.
Create Map
Create the map within the AWS CLI by providing a Name and selecting VectorEsriNavigation for the Map display.
$ aws location create-map –-map-name <MAP_NAME> –-configuration Style=VectorEsriNavigation
{
"CreateTime": "2021-07-08T15:14:42.016000+00:00",
"MapArn": "arn:aws:geo:<REGION>:<ACCOUNT_NUMBER>:map/<MAP_NAME>",
"MapName": "MAP_NAME"
}
Create PlaceIndex
Next create a PlaceIndex within the CLI where a name is provided and the data source set equal to Esri. This is used to identify the destination of the delivery vehicle.
$ aws location create-place-index –-index-name <INDEX_NAME> –-data-source Esri
{
"CreateTime": "2021-07-08T15:20:22.922000+00:00",
"IndexArn": "arn:aws:geo:<REGION>:<ACCOUNT_NUMBER>:place-index/<INDEX_NAME>",
"IndexName": "INDEX_NAME"
}
Create Customer Managed Policy in AWS Identity Access Management (AWS IAM) for Amazon Location Resources
For both scenarios, a customer managed policy is defined so that the application can access the map and place index. The authenticated role, amplify-deliveryapp-prod-XXXX, is accessed within AWS Identity Access and Management (IAM).
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"geo:GetMap*",
"geo:SearchPlaceIndexForText",
],
"Resource": [
"arn:aws:geo:<REGION>:<ACCOUNT_NUMBER>:map/<MAP_NAME>",
"arn:aws:geo:<REGION>:<ACCOUNT_NUMBER>:place-index/<PLACE_INDEX_NAME>"
]
}
]
}
Configuring Amazon Simple Notification Service
For both scenarios, Amazon Simple Notification Service will be leveraged to provide an email or SMS notifications to the user. This topic and subscriber were created using the following AWS CLI commands. First, we create the topic:
$ aws sns create-topic --name <TOPIC_NAME>
{
"TopicArn": "arn:aws:sns:<REGION>:<ACCOUNT_NUMBER>:<TOPIC_NAME>"
}
Once the topic is created, we can add a subscriber to the topic providing email or SMS details:
$ aws sns subscribe --topic-arn arn:aws:sns:<REGION>:<ACCOUNT-ID>:<TOPIC_NAME> --protocol email --notification-endpoint <EMAIL_ADDRESS>
{
"SubscriptionArn": "arn:aws:sns:<REGION>:<ACCOUNT_NUMBER>:<TOPIC_NAME>:<arn>"
}
Scenario 1 Technical Overview: Use Routes API to provide estimated time of arrival
The Routes API provides route calculators to determine distance, route, and estimated time of arrival. In this example, a tracker is created and updated simulating movement of a delivery vehicle. The Trackers API supports BatchUpdateDevicePosition action to share movement of a device. To identify where the device is at any time, the GetDevicePosition action provides latitude and longitude of a known device and its associated tracker. With this information it can be used to feed the current tracker location on a repeating basis until the estimated time of arrival is less than or equal to the user specified time. This approach provides a better estimate of delivery as it can take into account, current traffic conditions which may impact arrival of the delivery vehicle.
Create a Route Calculator
The first step is to create a Route Calculator using the Amazon Location Service CLI.
$ aws location create-route-calculator -–calculator-name <CALCULATOR_NAME> --data-source Esri
{
"CreateTime": "2021-05-24T19:34:22.586000+00:00",
"CalculatorArn": "arn:aws:geo:<REGION>:<ACCOUNT_NUMBER>:route-calculator/<CALCULATOR_NAME>",
"CalculatorName": "CALCULATOR_NAME"
}
Add CalculateRoute policy
To calculate the route using the Routes API, we need to add a policy entry to the existing customer managed policy created above to our auth role for the CalculateRoute action.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"geo:GetMap*",
"geo:SearchPlaceIndexForText",
"geo:CalculateRoute"
],
"Resource": [
"arn:aws:geo:<REGION>:<ACCOUNT_NUMBER>:map/<MAP_NAME> ",
"arn:aws:geo:<REGION>:<ACCOUNT_NUMBER>:place-index/<PLACE_INDEX_NAME> ",
"arn:aws:geo:<REGION>:<ACCOUNT_NUMBER>:route-calculator/<CALCULATOR_NAME> "
]
}
]
}
Create a Tracker for Scenario 1
To track a delivery vehicle’s location, it is necessary to create a tracker. A tracker provides device location history as well as current updates. To create a tracker, you can use the console or the following CLI command:
$ aws location create-tracker –-tracker-name <TRACKER_NAME>
{
"CreateTime": "2021-05-24T19:34:22.586000+00:00",
"TrackerArn": "arn:aws:geo:<REGION>:<ACCOUNT_NUMBER>:tracker/<TRACKER_NAME>",
"TrackerName": "TRACKER_NAME"
}
Add GetDevicePositionHistory Policy
In order for the React application to be able to access device positions through the Trackers API, we need to enable it through an additional entry in the customer managed policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"geo:GetMap*",
"geo:SearchPlaceIndexForText",
"geo:GetDevicePositionHistory",
"geo:CalculateRoute"
],
"Resource": [
"arn:aws:geo:<REGION>:<ACCOUNT_NUMBER>:map/<MAP_NAME>",
"arn:aws:geo:<REGION>:<ACCOUNT_NUMBER>:place-index/<PLACE_INDEX_NAME> ",
"arn:aws:geo:<REGION>:<ACCOUNT_NUMBER>:tracker/<TRACKER_NAME> ",
"arn:aws:geo:<REGION>:<ACCOUNT_NUMBER>:route-calculator/<CALCULATOR_NAME> "
]
}
]
}
Determine the distance and duration with the CalculateRoute action
The Trackers API provides an action, GetDevicePositionHistory, that returns the location of the prescribed device in longitude and latitude for all its positions. Using this information, the React application uses the Routes API action, CalculateRoute. Passing in the route calculator name, DeparturePosition and DestinationPosition, the CalculateRoute Action will return distance and DurationSeconds. For this example, the DeparturePosition is continually updated with the current position of the device returned by GetDevicePositionHistory.
let parameter = {
CalculatorName: <CALCULATOR_NAME>,
DeparturePosition: [departurelong, departurelat],
DestinationPosition: [destinationlong, destinationlat]
};
client.calculateRoute(parameter, (err, data) => {
if (err) console.log(err);
if (data) {
const deliveryETA = data.Legs[0].DurationSeconds;
.......
}
Notify when duration is met
If the DurationSeconds equals or is less than five minutes, Amazon SNS is used to update the subscribers that the delivery service is close to the destination. The Amazon SNS TopicArn for this example is stored in an environment variable.
// Create publish parameters
let params = {
Message: 'ETA is 5 mins', /* required */
TopicArn: process.env.REACT_APP_SNS_TOPIC_ARN
};
// Create promise and SNS service object
var publishTextPromise = new AWS.SNS({credentials}).publish(params).promise();
// Handle promise's fulfilled/rejected states
publishTextPromise.then(
function(data) {
console.log(`Message ${params.Message} sent to the topic ${params.TopicArn}`);
console.log("MessageID is " + data.MessageId);
}).catch(
function(err) {
console.error(err, err.stack);
});
Create Customer Managed Policy in AWS IAM for Amazon SNS
For Amazon SNS to perform the publish action, you will need to create an AWS IAM customer managed policy for the Amazon SNS topic and attach the policy to your authenticated role.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sns:Publish",
"Resource": "arn:aws:sns:us-west-2:365819409441:EtaSns"
}
]
}
Run simulated device script for estimated time of arrival or proximity alerts
In order to simulate the delivery vehicle, a script places updates to the Trackers API that then simulates motion of the delivery vehicle to the map and eventually triggers the geofence with an ENTER event. The following script provides a simple means to update location states. The core component is using the AWS CLI command:
The delivery vehicle will follow a route to a destination after taking this script and modifying it with prescribed longitude and latitude values.
#!/bin/bash
TRACKER_NAME=eta-tracker
DEVICE_ID=eta-device
function update_position()
{
Position=$1
CURRENT_TIME=$(date +%s)
aws location batch-update-device-position --tracker-name $TRACKER_NAME --updates "DeviceId=${DEVICE_ID},Position=${Position},SampleTime=${CURRENT_TIME}"
}
update_position "-74.053945,40.711939"; sleep 30
update_position "-74.055747,40.719095"; sleep 30
update_position "-74.053173,40.726575"; sleep 30
update_position "-74.050040,40.730803"; sleep 30
update_position "-74.044160,40.733665"; sleep 30
update_position "-74.038195,40.736982"; sleep 30
update_position "-74.033303,40.741859";
The delivery vehicle will follow a route to a destination after taking this script and modifying it with prescribed longitude and latitude values.
Scenario 1 : Testing estimated time of arrival alert
1. To test the application, go to the AWS Amplify Console and select your application.
2. Login with your credentials or if you haven’t created an account yet, create an account.
Figure 3: Login Page of the Delivery Application
Your application will look like the following after performing the sign in:
Figure 4: Delivery Application with Search and Track functionality
3. Run the script described in the previous section to simulate movement of the tracker and the specific device identifier.
4. Select the Track button in the application. The first location will appear with a sequential number related to the script latitude and longitude entries. The ETA text will update based on the DurationSeconds returned in the calculateRoute action.
Figure 5: Testing ETA notification with single tracker location
When ETA is less than or equal to five minutes, an Amazon SNS notification is triggered to a subscribed endpoint. Below is an image of the tracker showing an ETA of five minutes.
Figure 6: Testing eta with several tracked locations
This will then trigger an email-based notification as shown below.
Figure 7: ETA notification
Scenario 2 Technical Overview: Create a proximity-based notification using a geofence
In the second scenario, a focus is on distance proximity of the delivery vehicle. In this scenario, we create a statically sized geofence that is a box in shape of x miles by x miles. At approximately 40 degrees of latitude, a single degree is approximately 69 miles. Longitude is approximately 54.6 miles. Using the formula below we can calculate the degree per mile.
1 degree longitude / 54.6 miles = 0.01835 degree/mile
1 degree latitude / 69 miles = 0.014492 degree/mile
These values can be used to create a box with dimensions approximately 1 mile from destination or a two-by-two-mile box. Using this, the destination longitude and latitude acts as input in a simple function shown here in pseudocode to calculate the vertices used in a geofence polygon. The values destination_longitude and destination_latitude represent the destination for delivery. Taking this point and adding or subtracting we can create a box around this destination as shown below.
destination_longitude = X
destination_latitude = Y
longitude_degree_per_mile = 0.018315
latitude_degree_per_mile = 0.014492
geofence_pt1_longitude = X - longitude_degree_per_mile
geofence_pt1_latitude = Y + latitude_degree_per_mile
geofence_pt2_longitude = X + longitude_degree_per_mile
geofence_pt2_latitude = Y + latitude_degree_per_mile
geofence_pt3_longitude = X + longitude_degree_per_mile
geofence_pt3_latitude. = Y - latitude_degree_per_mile
geofence_pt4_longitude = X - longitude_degree_per_mile
geocence_pt4_latitude. = Y - latitude_degree_per_mile
Below is a diagram showing the geofence_pt locations in comparison to the destination.
Figure 8: Creating geofence geometry
Before we can define the geofence, a geofence collection needs to be created.
Create a geofence collection
A geofence collection is first created to store any geofences. This is accomplished through the use of the CLI, create-geofence-collection.
$ aws location create-geofence-collection --collection-name eta-geofence-collection
{
"CollectionArn": "arn:aws:geo:<region>:<account id>:geofence-collection/eta-geofence-collection",
"CollectionName": "eta-geofence-collection",
"CreateTime": "2021-05-18T18:55:55.188000+00:00"
}
Create a geofence
A geofence is then created via a Geometry JSON definition. Note The Geometry JSON requires the following information and the points need to be specified in counter-clockwise fashion as shown in the figure above. If we replace our previously identified points, the Geometry JSON would appear as follows (Note: Polygons must be closed so we repeat pt_1 longitude and latitude and values must be of type double):
{"Polygon":
[
[
[geofence_pt1_longitude, geofence_pt1_latitude],
[geofence_pt2_longitude, geofence_pt2_latitude],
[geofence_pt3_longitude, geofence_pt3_latitude],
[geofence_pt4_longitude, geofence_pt4_latitude],
[geofence_pt1_longitude, geofence_pt1_latitude]
]
]
}
Using the CLI, the geofence is created via the following command:
$ aws location put-geofence --collection-name <GEOFENCE_COLLECTION_NAME> --geofence-id 1 --geometry '{"Polygon":[[
[-74.051403,40.758758],
[-74.051403,40.729772],
[-74.014773,40.729772],
[-74.014773,40.758758],
[-74.051403,40.758758]]]}'
{
"CreateTime": "2021-05-27T14:10:50.750000+00:00",
"GeofenceId": "1",
"UpdateTime": "2021-05-27T14:10:50.750000+00:00"
}
Create a Tracker for Scenario 2
To track a delivery vehicle’s location, it is necessary to create a tracker. A tracker provides device location history as well as current updates. This requires the use of create-tracker and associate-tracker-consumer CLI commands. The CreateTracker action creates the tracker to be used and AssociateTrackerConsumer binds the tracker to the geofence collection. As a tracker enters or exits a geofence, this will generate an event that can be used to trigger various actions. To create a tracker, use the following CLI command:
$ aws location create-tracker --tracker-name <TRACKER_NAME>
{
"CreateTime": "2021-05-24T19:34:22.586000+00:00",
"TrackerArn": "arn:aws:geo:<REGION>:<ACCOUNT_NUMBER>:tracker/<TRACKER_NAME>",
"TrackerName": "<TRACKER_NAME>"
}
Associate the tracker with the geofence collection we use the following CLI command:
$ aws location associate-tracker-consumer --consumer-arn arn:aws:geo:<REGION>:<ACCOUNT-ID>:geofence-collection/<GEOFENCE_COLLECTION_NAME> --tracker-name <TRACKER_NAME>
Create Customer Managed Policy in AWS IAM for GetDevicePositionHistory
In order for an application to be able to access device positions, we need to enable it via a customer managed AWS IAM policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "geo:GetDevicePositionHistory",
"Resource": "arn:aws:geo:<REGION>:<ACCOUNT_NUMBER>:tracker/<TRACKER_NAME>"
}
]
}
Integrate the ENTER event with Amazon Simple Notification Service
As a delivery vehicle enters a geofence, an ENTER event is created and this is sent to Amazon EventBridge. Amazon EventBridge is a middleware service that can be configured to receive the events and then forward events and details to a target. In this example, the target is the Amazon Simple Notification Service.
Configure Amazon EventBridge
Amazon EventBridge is used to receive Amazon Location Service ENTER events in the geofence collection. First, we create an event bus using the following CLI command.
$ aws events create-event-bus --name <EVENT_BUS_NAME>
{
"EventBusArn": "arn:aws:events:<REGION>:<ACCOUNT-ID>:event-bus/<EVENT_BUS_NAME>"
}
Next, we create an event pattern for the event bus.
$ aws events put-rule --name <EVENT_BUS_RULE_NAME> --event-pattern "{\"source\": [\"aws.geo\"],\"detail-type\": [\"Location Geofence Event\"],\"detail\": {\"EventType\": [\"ENTER\"]}}" --state ENABLED --event-bus-name <EVENT_BUS_NAME> { "RuleArn":
"arn:aws:events:<REGION>:<ACCOUNT_NUMBER>:rule/<EVENT_BUS_NAME>/<EVENT_BUS_RULE_NAME>" }
Finally, we add a target to the event pattern for the event bus using the previously created Amazon SNS topic using its ARN. Amazon EventBridge access to the topic is provided by the Amazon SNS Resource Policy, that allows within the account the ability to publish a message.
$ aws events put-targets --rule <EVENT_BUS_RULE_NAME> --targets "Id"="1","Arn"="arn:aws:sns:<REGION>:<ACCOUNT-ID>:<TOPIC_NAME>" --event-bus-name <EVENT_BUS_NAME>
{
"FailedEntryCount": 0,
"FailedEntries": []
}
Scenario 2 : Testing a proximity alert
1. To test the application, it is first accessed at the AWS Amplify URL.
2. Run the script described in the section, Run Simulated Device Script for Estimated Time of Arrival or Proximity Alerts, to simulate movement of the tracker and the specific device identifier.
3. Select the Track button in the application. The first location will appear with a sequential number related to the script latitude and longitude entries. For proximity-based notification, once the delivery vehicle enters the geofence location, a Amazon SNS notification is triggered. The following image shows the tracker movement.
Figure 9: Testing proximity using geofence and multiple tracker locations
Once the geofence is breached the following notification message will occur. You will notice the body of the message is a JSON payload in the image below. This body can be formatted using transformation of the input to the target as documented here.
Figure 10: Proximity notification
Infrastructure Cleanup Scenario 1
To prevent additional charges being posted to your account, please follow the steps to delete the resources.
Delete the Map
Delete the map via the following command.
$ aws location delete-map --map-name <MAP_NAME>
Delete the Place Index
Delete the place index via the following command.
$ aws location delete place-index --index-name <INDEX_NAME>
Delete the Route Calculator
Delete the route calculator via the following command.
$ aws location delete-route-calculator --calculator-name <CALCULATOR_NAME>
Delete the Amazon SNS Topic
Deleting a topic via the following command.
$ aws sns delete-topic --topic-arn arn:aws:sns:<REGION>:<ACCOUNT-ID>:<TOPIC_NAME>
Unsubscribe from the Topic
Remove the created subscription from the topic via the following command.
$ aws sns unsubscribe --subscription-arn arn:aws:sns:<REGION>:<ACCOUNT_ID>:<TOPIC_NAME>:<SUBSCRIPTION_ID>
Delete the Tracker
Delete the tracker via the following command.
$ aws location delete-tracker --tracker-name <TRACKER_NAME>
Infrastructure Cleanup Scenario 2
To prevent additional charges being posted to your account, please follow the steps to delete the resources.
Delete Amazon EventBridge Target
Delete the target via the following command.
$ aws events remove-targets --rule <EVENT_BUS_RULE_NAME> --ids 1 --event-bus-name <EVENT_BUS_NAME>
Delete Amazon EventBridge Rule
Delete the rule via the following command.
$ aws events delete-rule --name <EVENT_BUS_RULE_NAME> --event-bus-name <EVENT_BUS_NAME>
Delete the Amazon EventBridge Bus
Delete the bus via the following command.
$ aws events delete-event-bus --name <EVENT_BUS_NAME>
Delete the Amazon SNS Topic
Delete the topic via the following command.
$ aws sns delete-topic --topic-arn arn:aws:sns:<REGION>:<ACCOUNT_ID>:<TOPIC_NAME>
Unsubscribe from Topic
Remove the created subscription from the topic via the following command.
$ aws sns unsubscribe --subscription-arn arn:aws:sns:<REGION>:<ACCOUNT_ID>:<TOPIC_NAME>:<SUBSCRIPTION_ID>
Delete the Geofence Collection and Tracker
Delete the geofence collection via the following command.
$ aws location delete-geofence-collection --collection-name <GEOFENCE_COLLECTION_NAME>
Delete the tracker via the following command.
$ aws location delete-tracker --tracker-name <TRACKER_NAME>
Delete the Map
Delete the map can be done via the following command.
$ aws location delete-map --map-name <MAP_NAME>
Delete the Place Index
Delete the place index can be done via the following command.
$ aws location delete place-index --index-name <INDEX_NAME>
Delete Resources created by AWS Amplify
You can run the following AWS Amplify CLI command to delete all of the resources tied to the project from the cloud:
$ amplify delete
You can also follow the AWS Amplify Cleanup process.
Conclusion
In the previous solution, demonstration of Amazon Location Service’s Maps, Geofencing and Tracking services into an estimated time of arrival and proximity solution was performed. Expanding this solution further, ETA and proximity information could be combined with delivery routing data to draw correlations with delivery arrival and overall customer satisfaction. You can follow the deployment tutorial on GitHub or start building your own solutions using Amazon Location by reading the developer guide, which provides a conceptual overview and practical examples to help you understand the features provided by Amazon Location and how to use them.