In this tutorial, we will learn how to build an IoT application using the AWS Cloud Platform. The application will get sensor data from the Raspberry Pi and send it to the AWS IoT Core. This data will be stored in IoT Analytics and plotted in a graph using QuickSight.
Contents
- Hardware Requirements
- Initial Setup
- Setting up AWS IoT Core
- Setting up the Raspberry Pi
- Creating a rule for IoT Core
- Testing your rule
- Setting up Amazon QuickSight for visualization
1. Hardware Requirements
- Raspberry pi 3
- Light Dependent Resistor (or any sensor)
- 1 μf capacitor
- Breadboard
- Jumper cables
NOTE: You can use any sensor you like. Here we will be using the LDR as an example.
2. Initial Setup
- You will have to first create an AWS account. (This process requires your credit card details to verify that you are not a robot.)
NOTE: You can use the free trial to follow this tutorial.
3. Setting up AWS IoT Core
- In the search bar present at the AWS Management Console page search for “IoT Core” and click it.
- Once the IoT Core page opens, on the left menu you will see an option called “Manage”, under this select “Things”.
- In the “Things” page click on “Register a Thing”.
- Click on the button that says “Create a Single Thing”.
- Give your new “Thing” a name and click on next I’ll call mine “light-sensor”.
- Next, we’ll create the keys and certificates required to authenticate our requests to AWS. For this click on the “Create Certificate” button. We will be using the one-click certificate creation method.
- Once your certificates and keys are created you will get an option to download them. Download the 4 documents, we will need them while setting up the Raspberry Pi.
- When you try to download the root CA certificate you will be taken to a page as shown below. Choose the “RSA 2048 bit key” under “Amazon Trust Services Endpoints (preferred)”. A new tab will open. Copy the contents of that page and paste it into a file called “root-CA.crt”.
- Once you have downloaded all the required certificates click on “Activate” and then click “Done”.
- Next, under the “Secure” section on the menu present on the left side, select the “Policies” option.
- In the policies page click on the “Create a policy” button.
- Give the policy a name and then fill the “Action” with iot:* and “Resource ARN” with * and also select “Allow” under effect. Finally, click on “Create”.
- Now we have to attach our “Thing” and “Policy” to our “Certificate”. To do this follow the steps in the short video below.
4. Setting up the Raspberry Pi
- Make all the connections required to run the photocell as shown in the diagram below.
For a more detailed tutorial on the LDR click here
- First, let us create a directory, in the Raspberry Pi, that we will be working in called “tryAWS” and cd into it.
mkdir tryAWS
cd tryAWS
- Now lets create a virtual environment and activate it.
virtualenv venv
source venv/bin/activate
- Now we are ready to install the required packages.
pip install Rpi.GPIO
pip install AWSIoTPythonSDK
- Create a python script called “ldr_data.py” and save the below code in it. This is the function that returns brightness data. You can replace it with the code for the sensor that you are using.
You can also get the code from GitHub here
#measuring the light intensity using a photocell
import RPi.GPIO as GPIO,time,os #import the libraries
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
def RCtime(RCpin): # function start
reading=0
GPIO.setup(RCpin,GPIO.OUT)
GPIO.output(RCpin,GPIO.LOW)
time.sleep(4) # time to discharge capacitor
GPIO.setup(RCpin,GPIO.IN)
while (GPIO.input(RCpin) == GPIO.LOW):
# the loop will run till the capacitor is charged
reading += 1
# measuring time which in turn is measuring resistance
return reading
- Next, save the following python script in a file called “basicShadowUpdater.py”. This is the script that will use MQTT to update the “Shadow” of the “Thing”.
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTShadowClient
import logging
import time
from datetime import datetime
import json
import argparse
import ldr_data
# Custom Shadow callback
def customShadowCallback_Update(payload, responseStatus, token):
# payload is a JSON string ready to be parsed using json.loads(...)
# in both Py2.x and Py3.x
if responseStatus == "timeout":
print("Update request " + token + " time out!")
if responseStatus == "accepted":
payloadDict = json.loads(payload)
print("~~~~~~~~~~~~~~~~~~~~~~~")
print("Update request with token: " + token + " accepted!")
print("brightness: " + str(payloadDict["state"]["desired"]["brightness"]))
print("~~~~~~~~~~~~~~~~~~~~~~~\n\n")
if responseStatus == "rejected":
print("Update request " + token + " rejected!")
def customShadowCallback_Delete(payload, responseStatus, token):
if responseStatus == "timeout":
print("Delete request " + token + " time out!")
if responseStatus == "accepted":
print("~~~~~~~~~~~~~~~~~~~~~~~")
print("Delete request with token: " + token + " accepted!")
print("~~~~~~~~~~~~~~~~~~~~~~~\n\n")
if responseStatus == "rejected":
print("Delete request " + token + " rejected!")
# Read in command-line parameters
parser = argparse.ArgumentParser()
parser.add_argument("-e", "--endpoint", action="store", required=True, dest="host", help="Your AWS IoT custom endpoint")
parser.add_argument("-r", "--rootCA", action="store", required=True, dest="rootCAPath", help="Root CA file path")
parser.add_argument("-c", "--cert", action="store", dest="certificatePath", help="Certificate file path")
parser.add_argument("-k", "--key", action="store", dest="privateKeyPath", help="Private key file path")
parser.add_argument("-p", "--port", action="store", dest="port", type=int, help="Port number override")
parser.add_argument("-w", "--websocket", action="store_true", dest="useWebsocket", default=False,
help="Use MQTT over WebSocket")
parser.add_argument("-n", "--thingName", action="store", dest="thingName", default="Bot", help="Targeted thing name")
parser.add_argument("-id", "--clientId", action="store", dest="clientId", default="basicShadowUpdater", help="Targeted client id")
args = parser.parse_args()
host = args.host
rootCAPath = args.rootCAPath
certificatePath = args.certificatePath
privateKeyPath = args.privateKeyPath
port = args.port
useWebsocket = args.useWebsocket
thingName = args.thingName
clientId = args.clientId
if args.useWebsocket and args.certificatePath and args.privateKeyPath:
parser.error("X.509 cert authentication and WebSocket are mutual exclusive. Please pick one.")
exit(2)
if not args.useWebsocket and (not args.certificatePath or not args.privateKeyPath):
parser.error("Missing credentials for authentication.")
exit(2)
# Port defaults
if args.useWebsocket and not args.port: # When no port override for WebSocket, default to 443
port = 443
if not args.useWebsocket and not args.port: # When no port override for non-WebSocket, default to 8883
port = 8883
# Configure logging
logger = logging.getLogger("AWSIoTPythonSDK.core")
logger.setLevel(logging.DEBUG)
streamHandler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
streamHandler.setFormatter(formatter)
logger.addHandler(streamHandler)
# Init AWSIoTMQTTShadowClient
myAWSIoTMQTTShadowClient = None
if useWebsocket:
myAWSIoTMQTTShadowClient = AWSIoTMQTTShadowClient(clientId, useWebsocket=True)
myAWSIoTMQTTShadowClient.configureEndpoint(host, port)
myAWSIoTMQTTShadowClient.configureCredentials(rootCAPath)
else:
myAWSIoTMQTTShadowClient = AWSIoTMQTTShadowClient(clientId)
myAWSIoTMQTTShadowClient.configureEndpoint(host, port)
myAWSIoTMQTTShadowClient.configureCredentials(rootCAPath, privateKeyPath, certificatePath)
# AWSIoTMQTTShadowClient configuration
myAWSIoTMQTTShadowClient.configureAutoReconnectBackoffTime(1, 32, 20)
myAWSIoTMQTTShadowClient.configureConnectDisconnectTimeout(10) # 10 sec
myAWSIoTMQTTShadowClient.configureMQTTOperationTimeout(5) # 5 sec
# Connect to AWS IoT
myAWSIoTMQTTShadowClient.connect()
# Create a deviceShadow with persistent subscription
deviceShadowHandler = myAWSIoTMQTTShadowClient.createShadowHandlerWithName(thingName, True)
# Delete shadow JSON doc
deviceShadowHandler.shadowDelete(customShadowCallback_Delete, 5)
# Update shadow in a loop
loopCount = 0
while True:
brightness = ldr_data.RCtime(12)
timestamp = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
JSONPayload = '{"state":{"desired":{"time":"' + str(timestamp) + '","brightness":'+str(brightness) +'}}}'
print("\n", JSONPayload,"\n")
deviceShadowHandler.shadowUpdate(JSONPayload, customShadowCallback_Update, 5)
loopCount += 1
time.sleep(1)
- Now move all the certificates that you downloaded into this directory. At the moment your working directory should look something like this.
- Now we need to find your “endpoint”, for that go to Manage>Things>(your thing)>interact in the AWS IoT core console.
- Now, to run the python script you will have to pass the following arguments :
- -e endpoint
- -r root CA
- -c Certificate file path
- -k private key file path
- -p port (we will be using 8883)
- -n targeted thing name
- -id targeted client id
- Run the command. It should look something like this:
- You should see an output like this:
- You can also check it on the AWS console. Go to Manage>Things>(your thing)>Shadow, it should look like this.
5. Creating a rule for IoT Core
- In the IoT Core menu, select “Rules” under the “Act” category.
- Click on “Create a rule”.
- Enter a name and a short description for the new rule that we have created.
- In the rule Query statement enter the following :
SELECT cast(state.desired.brightness as decimal) as brightness, timestamp() as timestamp FROM '$aws/things/light-sensor/shadow/update'
- Now click on add action under “Set one or more actions” and choose “Send a message to IoT Analytics”, then click “Configure action”.
- Select “Quick Create IoT Analytics Resource” and enter a resource prefix and click “Quick Create”.
- Click on “Add Action”.
- Then finally click “Create Rule”.
6. Testing your rule
- Run the python script in your Raspberry Pi for a few iterations.
- Open the IoT Analytics page and go to “Data Sets”.
- Now click the three dots beside your data set and choose “run now”.
- You should see the required data in the result preview.
7. Setting up Amazon QuickSight for visualization
- In the search bar present in the AWS Management Console, search for “QuickSight” and select the option.
- Then in the page that opens select “Sign up For QuickSight”.
- In the options given for the plans choose “standard”, as that is enough for this tutorial. After that click on continue.
- In this page enter an account name and make sure to select the box that says “AWS IoT Analytics” and also choose the same “region” you used to set up IoT Analytics. Then click “Finish”.
- Once you are into Quicksight click on the “Create New Analysis” button.
- Then click on “New Dataset”.
- Choose the “AWS IoT Analytics” data source.
- Choose your “Dataset” and then click on “Create data source”.
- Then, click on “Visualize”.
- Under visual types choose your preferred “Visual Type”. We will be using “line chart” and drag & drop your data into the respective axes. In this example I have moved the “timestamp” into the x axis box and “brightness” into the y axis box.
- You can also change the aggregate by opening the drop-down menu of the field.
You now have your sensor data from the Raspberry Pi plotted graphically using QuickSight on AWS cloud.
I hope you have a clear understanding of how we can use the AWS IoT core and IoT Analytics to plot the sensor data. Any feedback or questions are welcome, leave them in the comments section below.