5

Create an iOS tracker application with Amazon Location Service and AWS Amplify

 2 years ago
source link: https://aws.amazon.com/blogs/mobile/create-an-ios-tracker-application-with-amazon-location-service-and-aws-amplify/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Create an iOS tracker application with Amazon Location Service and AWS Amplify

by Kyle Lee | on 01 JUL 2021 | in Amazon EventBridge, Amazon Location, AWS Amplify, AWS AppSync, Front-End Web & Mobile | Permalink | Comments |  Share

This article was written by Fernando Rocha Silva and Panna Shetty

Emergency management teams are constantly tackling one crisis after another, whether it is managing the COVID pandemic or battling raging wild fires across California. These frontline workers venture into dangerous situations to rescue those in need, potentially risking their own lives.

Firefighters go above and beyond the call of duty for the safety of others. To keep themselves safe, they follow policies and standard operating procedures that outline how to react quickly in emergency situations to avoid unnecessary risks. In the case of natural disasters such as forest fires, the scale of the event is too large to easily track the safety of each crew member by line of sight and a different approach is required. In these scenarios a muster point is established as a designated safety zone, or a geofence. This geofence cannot always be predetermined and may need to change in response to evolving conditions, thus emergency managers have to keep track of members in the field when location changes occur. One of the ways to improve this process is automating member tracking and response activity, so that emergency managers can quickly account for all members and then focus on recovery operations.

Emergency teams must be able to have their current location tracked so emergency managers who handle vital field communications can determine if they are in a compromised position and quickly establish a geofence. The emergency managers must be able to visualize in real-time the current status of members in the field and provide them with the location of the defined geofence. Each of the members must be able to see the current geofence on their device so they can quickly move to that location. Once the member is in the geofenced area, the emergency manager is notified.

Amazon Location Service provides capabilities such as maps, points of interest, geocoding, routing, geofences, and tracking to applications. You retain control of your location data with Amazon Location, so you can combine proprietary data with data from the service. Due to the service’s simplicity, you can bring sophisticated location-enabled applications with real-time data to production quickly.

Overview of solution

In the following architecture, we have two types of mobile clients securely connecting to a provisioned backend leveraging the Amplify libraries. In this particular example, we use the Amplify iOS library.

The iOS clients rely on Amazon Cognito for authentication and authorization, provisioned using the Amplify CLI authentication category. The Amplify DataStore is used to persist the data locally on the client side, providing capabilities that allow automatic synchronization of data between devices and the cloud. The DataStore relies on a GraphQL API layer powered by AWS AppSync connected to Amazon DynamoDB for data storage.

The AWS SDK is used to collect the geofences created in the Amazon Location Service using the Geofences API. The Tracker API is used to collect the team member (employee) current location and to identify ENTER and EXIT events that occur against the Geofence Collection associated to the tracker. Once geofence events occur, they are sent to Amazon EventBridge where a rule is triggered and the event is pushed to an AWS Lambda function. The event is then parsed and sent to AppSync, persisting the data on DynamoDB. The patrol client application detects the change in DynamoDB and updates the user current status.

The employee mobile application connects to Amazon Location’s Tracker via the Amazon Location SDK, once the latitude and longitude provided by the tracker crosses a geofence, an event is sent to EventBridge and a Lambda Function is triggered. This Lambda function updates DynamoDB via AppSync with the user’s information, marking them as safe or not. Another app, targeting the patrol officers, track the users and their safety status. Both mobile applications rely on Cognito for authentication and authorization. AWS Amplify is used by the mobile app to connect to Cognito, via Amplify Auth, and AppSync, via Amplify API and Amplify DataStore.

Data privacy

With Amazon Location Service, you retain control of your organization’s data. Amazon Location Service anonymizes all queries sent to data providers by removing customer metadata and account information.

Additionally sensitive tracking and geofencing location information, such as facility, asset, and personnel locations, never leave your AWS account. This helps to protect sensitive information from third parties, secure user privacy, and reduce your application’s security risks.

Walkthrough

The solution consists of three equally important pieces: Amazon Location Service tracker and geofence collection, the mobile clients alongside their supporting backends, and Amazon EventBridge.

You can deploy the solution by following the deployment tutorial on GitHub.

Amazon Location Service’s Tracker and Geofence Collections

Location Service adds capabilities such as maps, points of interest, geocoding, routing, geofences, and tracking to applications. In this example, we use the geofencing API to create a geofence collection, which represents the muster points that are collected at the user’s application, pointing to safe locations where they can move to; and tracking APIs, used at the application layer to detect the device’s current location as it moves.

As the device location is updated, Location Service detects if the current location is within a geofence from the geofence collection to generate events that are sent to Amazon EventBridge as ENTER or EXIT. Below, you see an example of an ENTER event generated by the tracker:

{
  "version": "0",
  "id": "aa11aa22-33a-4a4a-aaa5-example",
  "detail-type": "Location Geofence Event",
  "source": "aws.geo",
  "account": "636103698109",
  "time": "2020-11-10T23:43:37Z",
  "region": "eu-west-2",
  "resources": [
    "<GeofenceCollection-ARN>",
    "<TRACKER-ARN>"
  ],
  "detail": {
    "EventType": "ENTER",
    "GeofenceId": "<GEOFENCE-ID>",
    "DeviceId": "<DEVICE-ID>",
    "SampleTime": "2020-11-10T23:43:37.531Z",
    "Position": [
      -123.12390073297821,
      49.23433613216247
    ]
  }
}

iOS application, AWS Amplify, and the AWS SDK

The client applications are built in iOS (SwiftUI) and benefit from AWS Amplify’s Auth and DataStore categories to authenticate and authorize users with Cognito in addition to synchronize the user data to the cloud using AppSync and DynamoDB. Amplify is also used to create the AWS Lambda function that is triggered by EventBridge when a geofencing event occurs.

The image displays a mobile app where the user is represented as a center blue point, geofences are shows as red polygons in the map. The user is inside the geofence.

Collecting Geofences

We use the listGeofences API provided by the AWS SDK to collect the boundaries associated to the geofences created on Location Service.

@Published var overlays = [MKPolygon]()
    
func listGeofences() {
    let request = AWSLocationListGeofencesRequest()!
    request.collectionName = “<GEOFENCE-COLLECTION-NAME>”

    let result = AWSLocation.default().listGeofences(request)
    result.continueWith { (task) -> Any? in
        if let error = task.error {
            print("error \(error)")
        } else if let taskResult = task.result {
            var overlays = [MKPolygon]()
            
            for entry in taskResult.entries! {
                let polygonEntry = entry.geometry?.polygon![0]
                
                var polygons = [CLLocationCoordinate2D]()
                for polygon in polygonEntry! {
                    let lon = polygon[0] as! Double
                    let lat = polygon[1] as! Double
                    polygons.append(CLLocationCoordinate2D(latitude: lat, longitude: lon))
                }
                
                let polygon = MKPolygon(coordinates: polygons, count: polygons.count)
                overlays.append(polygon)
            }
            DispatchQueue.main.async {
                self.overlays = overlays
            }
        }
        return nil
    }
}
Swift

The overlay returned by listGeofences is used to draw the muster points on the client app.

Setting up the Tracker

To track the device’s position, let’s use the AWSLocationTracker API provided by the AWS SDK.

let locationTracker = AWSLocationTracker(
    trackerName: <YOUR-TRACKER-NAME>, 
    region: AWSRegionType.<YOUR-REGION>,
    credentialsProvider: AWSMobileClient.default())
Swift

When the user authorizes the mobile application to detect the device’s location, we kick off the location tracker using the user id as a device id. We also set a listener to intercept the response from Amazon Location Service after the position is transmitted.

func locationManagerDidChangeAuthorization(manager: CLLocationManager) {
        switch manager.authorizationStatus {
        case .authorizedWhenInUse:
            print("Received authorization of user location, requesting for location")
            let result = locationTracker.startTracking(
                delegate: self,
                options: TrackerOptions(
                    customDeviceId: Amplify.Auth.getCurrentUser()?.userId,
                    retrieveLocationFrequency: TimeInterval(5),
                    emitLocationFrequency: TimeInterval(20)),
                listener: onTrackingEvent)
            switch result {
            case .success:
                print("Tracking started successfully")
            case .failure(let trackingError):
                switch trackingError.errorType {
                case .invalidTrackerName, .trackerAlreadyStarted, .unauthorized:
                    print("onFailedToStart \(trackingError)")
                case .serviceError(let serviceError):
                    print("onFailedToStart serviceError: \(serviceError)")
                }
            }
        default:
            print("Failed to authorize")
        }
    }
Swift

When the user starts moving, we can intercept the new latitude and longitude:

func locationManager(
    manager: CLLocationManager, 
    didUpdateLocations locations: [CLLocation]) 
{
    print("Got locations: \(locations)")
    locationTracker.interceptLocationsRetrieved(locations)
}
Swift

Using Amazon EventBridge to trigger changes to the device’s safety status

The last piece of our solution is deployed by setting up an Amazon EventBridge rule to detect ENTER and EXIT geofencing events generated by the user’s device. This rule triggers an AWS Lambda function that leverages AppSync to update the DynamoDB table that contains the user’s safety attribute.

Here is what the Lambda function looks like:

/* Amplify Params - DO NOT EDIT
  API_MUSTERPOINTLOCATIONAPI_GRAPHQLAPIENDPOINTOUTPUT
  API_MUSTERPOINTLOCATIONAPI_GRAPHQLAPIIDOUTPUT
  ENV
  REGION
Amplify Params - DO NOT EDIT */

const https = require('https')
const AWS = require('aws-sdk')
const urlParse = require('url').URL
const region = process.env.REGION
const appsyncUrl = process.env.API_MUSTERPOINTLOCATIONAPI_GRAPHQLAPIENDPOINTOUTPUT

const request = (queryDetails, appsyncUrl, apiKey) => {
  const req = new AWS.HttpRequest(appsyncUrl, region)
  const endpoint = new urlParse(appsyncUrl).hostname.toString()

  req.method = 'POST'
  req.path = '/graphql'
  req.headers.host = endpoint
  req.headers['Content-Type'] = 'application/json'
  req.body = JSON.stringify(queryDetails)

  if (apiKey) {
    req.headers['x-api-key'] = apiKey
  } else {
    const signer = new AWS.Signers.V4(req, 'appsync', true)
    signer.addAuthorization(AWS.config.credentials, AWS.util.date.getDate())
  }

  return new Promise((resolve, reject) => {
    const httpRequest = https.request({ ...req, host: endpoint }, (result) => {
      result.on('data', (data) => {
        resolve(JSON.parse(data.toString()))
      })
    })

    httpRequest.write(req.body)
    httpRequest.end()
  })
}

const updateSafetyMutation = /* GraphQL */ `
  mutation updateUser($input: UpdateUserInput!) {
      updateUser(input: $input){
        id
        isSafe
        username
        _lastChangedAt
        _version
        _deleted
      }
    }
`
const queryUser = /* GraphQL */ `
  query getUser($id: ID!) {
        getUser (id: $id) {
            id
            username
            isSafe
            _version
         }
    }
`

exports.handler = async (event) => {
  const userId = event?.detail?.DeviceId
  console.log('new geofence event:', event)

  var queryResult = await request(
      {
        query: queryUser,
        variables: { id: userId },
      },
      appsyncUrl
    )
  console.log('query result', queryResult)


  const user = queryResult?.data?.getUser
  if (!user) {
    return {
      statusCode: 404,
      body: `User with id ${userId} not found in the database.`,
    };
  }

  const version = user?._version
  var result = await request(
    {
      query: updateSafetyMutation,
      variables: {
        input: {
            id: userId,
            isSafe: event?.detail?.EventType === "ENTER",
            _version: version
        },
      },
    },
    appsyncUrl
  )
  console.log('appsync result', result)
}
JavaScript

The Patrol Application shows a list of users, represented in red if they are unsafe and green, if they are safe.

Conclusion

This serverless architecture using Amazon Location Service in tandem with AWS Amplify, Amazon Cognito, AWS AppSync and other AWS services provides an effective and simple solution to manage and monitor personnel during an emergency.

The role of emergency managers is complex due to the nature of their job. With Amazon Location Service you can easily create simple applications with tracking, geofences, and other capabilities. The ability to quickly establish a geofence and track the movement of members in the field in real-time is critical for the safety of emergency workers, our everyday heroes!

Author bio

Fernando Rocha headshotFernando Rocha is a Solutions Architect who specializes in mobile technologies. He currently helps customers build their solutions on AWS Amplify and Amazon Location Service. Panna Shetty headshotPanna Shetty is a Sr. Technical Account Manager with Amazon Web Services (AWS), working with public sector customers. She has a background in software development and is currently pursuing her Master’s at Penn Engineering.

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK