The Internet of Things on AWS – Official Blog
How to get started with the new AWS IoT Core Device Location service
Introduction
The new AWS IoT Core Device Location feature allows Internet of Things (IoT) devices to retrieve and report their current location without relying on Global Positioning System (GPS) hardware. Devices and clients connected to AWS IoT Core can now use cloud-assisted Global Navigation Satellite System(GNSS), WiFi scan, cellular triangulation, and reverse IP lookup techniques with the AWS IoT Core Device Location feature to determine their GPS coordinates and overall location.
Geo-location information and location tracking are requirements in many Internet of Thing (IoT) applications. Segments such as logistics and automotive cannot deliver significant results without this data. Historically, Geolocation monitoring relies on specific hardware, like Global Positioning System (GPS) modules. If devices don’t have a GPS hardware, adding one or upgrading existing devices can be costly at scale or might not be feasible to implement. However, even with a built-in GPS hardware, there isn’t a guarantee that these devices will have constant connectivity to GPS satellites to retrieve and report their coordinates.
In this blog post, we’ll show how to get started with the AWS IoT Core Device Location. We’ll detail what steps you can take before using the feature and demonstrate how to use it to resolve your device’s location based on only its IP address.
Prerequisites
To follow through this blog post, you will need an AWS account, an AWS IoT Core supported region, permissions to create AWS IoT Rules, AWS Lambda Functions, AWS Identity and Access Management (IAM) roles and policies, and access to AWS CloudShell. We also assume you have familiar with the basics of Linux bash commands.
Walkthrough
For the demonstration in this post, you will resolve a device’s location by first publishing its IP address via an MQTT message to AWS IoT Core. Second, an AWS IoT Rule will forward the message to a Lambda function. Third, this Lambda function will call the AWS IoT Core Device Location feature, via the GetPositionEstimate API. Finally, the Lambda function will publish the device’s location data as an MQTT message back to the device or any MQTT client subscribed to the location response topic. The illustration below details what this solution will look like once fully implemented.
Step 1: Create AWS Lambda execution role and policy
From your AWS CloudShell environment implement the following commands:
- Create the environmental variables for the upcoming command
export ACCOUNT_ID=<Replace with your account ID> export REGION=<Replace with your region>
- Create the IAM execution role for the Lambda function using the create-role command
aws iam create-role --role-name "lambda-ex-ipAddressToDeviceLocationService" \ --assume-role-policy-document '{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }'
- Now we will create the policy document for the role’s permissions, run the command below to create the policy document
( jq -n \ --arg region "$REGION" \ --arg account_id "$ACCOUNT_ID" \ '{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "iotwireless:GetPositionEstimate", "Resource": "*" }, { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "iot:Publish" ], "Resource": [ "arn:aws:logs:\($region):\($account_id):*", "arn:aws:iot:\($region):\($account_id):topic/device/test-1/location/ipbased/response" ] }, { "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:\($region):\($account_id):log-group:/aws/lambda/ipAddressToDeviceLocationService:*" } ] }' ) > lambda_policy.json
- Use the put-role-policy command to attach the policy to the role
aws iam put-role-policy \ --role-name "lambda-ex-ipAddressToDeviceLocationService" \ --policy-name lambda-ex-ipAddressToDeviceLocationService-policy \ --policy-document file://lambda_policy.json
Use the get-role-policy command to check if the policy has been successfully attached
aws iam get-role-policy \ --role-name "lambda-ex-ipAddressToDeviceLocationService" \ --policy-name lambda-ex-ipAddressToDeviceLocationService-policy
Step 2: Create a Lambda Function
From your AWS CloudShell environment implement the following commands:
Our Lambda function has a dependency on the AWS SDK for Python (Boto3) SDK, and the new GetPositionEstimate API is supported on version 1.26.45 or later. In order to create a Lambda function with the latest version of Boto3, we will create and publish a Lambda layer.
- To Implement the lambda layer use the following commands
LIB_DIR=boto3-mylayer/python mkdir -p $LIB_DIR #(You may need to run this command 2 or 3 times so it can be resolved automatically) pip3 install boto3 -t $LIB_DIR cd boto3-mylayer zip -r /tmp/boto3-mylayer.zip . LAYER=$(aws lambda publish-layer-version --layer-name boto3-mylayer --zip-file fileb:///tmp/boto3-mylayer.zip) LAYER_ARN=$(jq -r '.LayerVersionArn' <<< "$LAYER")
- Implement the following commands to create your Lambda function deployment package
cd /home/cloudshell-user touch lambda_function.py cat > lambda_function.py <<EOF import json, boto3 from datetime import datetime iot_wireless_client = boto3.client('iotwireless') iot_data_client = boto3.client('iot-data') def lambda_handler(event, context): iot_wireless_response = iot_wireless_client.get_position_estimate(Ip={ 'IpAddress': event['ipAddress']}, Timestamp=datetime.now()) print(f"IoT Wireless Response: {iot_wireless_response}") iot_data_response = iot_data_client.publish( topic='device/test-1/location/ipbased/response', qos=0, payload=json.dumps({'location':json.loads(iot_wireless_response['GeoJsonPayload'].read())}) ) print(f"IoT Data Response: {iot_data_response}") EOF zip -r lambda_function.zip lambda_function.py
- Implement the commands below to create your Lambda function and add the Boto3 Lambda layer to it
LAMBDA_FUNCTION=$(aws lambda create-function --function-name ipAddressToDeviceLocationServiceFunction \ --zip-file fileb://lambda_function.zip --handler lambda_function.lambda_handler --runtime python3.9 \ --role arn:aws:iam::$ACCOUNT_ID:role/lambda-ex-ipAddressToDeviceLocationService) LAMBDA_ARN=$(jq -r '.FunctionArn' <<< "$LAMBDA_FUNCTION") aws lambda update-function-configuration \ --function-name ipAddressToDeviceLocationServiceFunction \ --layers $LAYER_ARN
Use the add-permission command to allow AWS IoT Core to invoke the Lambda function
aws lambda add-permission --function-name ipAddressToDeviceLocationServiceFunction \ --statement-id iot-events --action "lambda:InvokeFunction" --principal iot.amazonaws.com
Step 3: Create an AWS IoT Rule
You will create an AWS IoT Rule use the commands below from the AWS CloudShell session:
- Create the rule using the create-topic-rule command
( jq -n \ --arg lambda_arn "$LAMBDA_ARN" \ '{ "sql": "SELECT * FROM \"device/+/location/ipbased\"", "ruleDisabled": false, "awsIotSqlVersion": "2016-03-23", "actions": [{ "lambda": { "functionArn": "\($lambda_arn)" } }] }' ) > iot_rule_document.json aws iot create-topic-rule \ --rule-name "ip_address_to_device_location_service" \ --topic-rule-payload file://iot_rule_document.json
Step 4: Viewing device location using the AWS IoT MQTT client
To view MQTT messages in the MQTT client do the following:
- In the AWS IoT console, in the left menu, under Test, choose MQTT test client.
- In the Subscribe to a topic tab, enter the topic
device/test-1/location/ipbased/response
and then choose Subscribe
To publish a message to an MQTT topic do the following:
- In the Publish to a topic tab, enter the topic
device/test-1/location/ipbased
and then enter the below JSON as the Message Payload{ "ipAddress": "<replace-with-public-ip-address>" }
- Hit Publish to publish your message
The output from the publish request should look similar to the following:
{
"location": {
"coordinates": [
**Longitude**,
**Latitude**
],
"type": "Point",
"properties": {
"country": "United States",
"city": "New York",
"postalCode": "*****",
"horizontalAccuracy": 20,
"horizontalConfidenceLevel": 0.67,
"state": "New York",
"timestamp": "2023-01-04T20:59:13.024Z"
}
}
}
Cleaning Up
Be sure to remove the resources created in this blog to avoid charges. Run the following commands to delete these resources:
-
aws iot delete-topic-rule --rule-name "ip_address_to_device_location_service"
-
aws lambda delete-function --function-name "ipAddressToDeviceLocationServiceFunction"
-
aws iam delete-role-policy --role-name "lambda-ex-ipAddressToDeviceLocationService" --policy-name "lambda-ex-ipAddressToDeviceLocationService-policy"
-
aws iam delete-role --role-name "lambda-ex-ipAddressToDeviceLocationService"
Conclusion
In this post you learned how to get started with the new AWS IoT Core Device Location feature, key steps to take before using the feature, and information to help you resolve your device’s location based on only its IP address. In addition to resolving your device’s location using this feature, you can also take advantage of the Amazon Location Service to track the device’s location on a map. For a more in depth look at developing with the AWS IoT Core Device Location feature, please take a look at the developer guide and watch Send Geo Coordinates from IoT Devices to Amazon Location Service with the AWS IoT Rules Engine. If your application uses AWS IoT Core for LoRaWan please refer to this blog post for more information, Introducing the new AWS IoT Core Device Location feature to support Asset Tracking solutions.
About the authors
Yuri Chamarelli is an Amazon Web Services Solution Architect (AWS) based out of the United States. As an IoT specialist, he focuses on helping customers build with AWS IoT and accomplish their business outcomes. Yuri is a Controls engineer with over 10 years of experience in IT/OT systems and has helped several customers with Industrial transformation and Industrial automation projects throughout many industries.
Nicholas Switzer is an IoT Specialist Solutions Architect at Amazon Web Services. He joined AWS in 2022 and specializes in IoT and Edge Computing and works with customers in the connected product space. He is based in the US and enjoys building smart products that improve everyday life.