Build a Serverless API for IoT Devices

Moheeb Zara
Jul 18 · 8 min read

Using AWS Lambda and API Gateway to publish messages to an AWS IoT Device

This is the first in a series of content around building serverless solutions for hardware developers and makers.

If you’re developing a connected hardware product, you might encounter a point where you’ll need to sensibly and securely communicate with these devices over the web in some way. It can become a daunting process to then begin developing a scalable cloud solution from the ground up. Serverless can provide a path to quickly iterating on a secure and highly scalable backend that can communicate with Internet of Things (IoT) devices. This leaves you with space to focus on what you want to implement vs the intricacies of DevOps.

What is serverless?

“Serverless is the native architecture of the cloud that enables you to shift more of your operational responsibilities to AWS, increasing your agility and innovation. Serverless allows you to build and run applications and services without thinking about servers. It eliminates infrastructure management tasks such as server or cluster provisioning, patching, operating system maintenance, and capacity provisioning.” — Amazon Web Services Serverless

This guide will walk you through creating a REST API with a single endpoint that will invoke a serverless function to publish a message to an IoT Device connected to an MQTT broker.

What we’ll cover:

  1. Setting up AWS Identity and Access Management (IAM) Policies
  2. AWS Lambda function for publishing IoT messages
  3. Using AWS IoT Core to create and manage a device
  4. Using the aws-iot-device-sdk for NodeJS
  5. Using Amazon API Gateway to create a REST interface

Prerequisites

IAM Policies

AWS Identity and Access Management or IAM, is a service for managing different roles and the policies that define their access to various resources and permissions within AWS.

In order for our Lambda function to publish messages to the AWS IoTData broker we’ll need to create a new Role with Policies that provide the neccesary permissions.

  1. Login to the AWS Console and navigate to the IAM service using the Services drop down.

2. Select “Roles” and then click “Create Role”.

3. On the following page select “AWS Service” for the trusted entity and “Lambda” as the service.

4. On the next page select these two policies. You can use the filter bar to find them quickly.

AWSLambdaBasicExecutionRole

AWSIoTDataAccess

The next page will offer the option to includes tags, you can skip this and move forward with naming and saving of your role.

AWS IoT Core

The AWS IoT core service helps provision and manage devices or groups of devices and their credentials.

In this step we will create a device and download a simple starter example that subscribes and publishes on IoTData topics.

Get started by navigating to https://aws.amazon.com/iot-core/

  1. Click “Get started” on “Configuring a device”.

2. Name your thing whatever you like.

3. Download the connection kit, it contains everything to run this application.

4. Perform these steps in a terminal, be sure to have Node 10 installed!

Keep your console and this application running throughout this guide — we’ll be using it later to verify messages are coming through from the AWS Lambda function!

5. Once you get this running go back to the IoT Core console and click Manage>Things and select your device.

6. From the interact tab make a note of this endpoint, we’ll need it for the AWS Lambda function!

Keep your console open and running, we’ll come back to it.

AWS Lambda

  1. Navigate to the AWS Lambda Console and click “Create a Function”.
  2. Select “Author from scratch”.

3. Name it whatever you like and set the runtime to Node.js 10.x.

4. For Permissions we’ll use the existing role we created in the last section and then “Create Function”.

You’ll be presented with something like this..

… and this, where the magic happens.

Note that in the designer tab we see that AWS IoT is shown on the right, this is because the role we assigned provides full access to AWS IoTData.

5. Go back to your Lambda function and paste this code in to the index.js window.

var AWS = require('aws-sdk');
var iotdata = new AWS.IotData({endpoint: 'YOUR-IOT-ENDPOINT'});
exports.handler = async (event, context) => {

var params = {
topic: 'topic_1',
payload: event.text,
qos: 0
}

return {
statusCode: 200,
body: JSON.stringify(await publishMessage(params))
}
}
const publishMessage = async (params) => {
return new Promise((resolve, reject) => {
iotdata.publish(params, function(err, data){
if(err){
console.log(err);
reject(err)
}
else{
console.log("success?");
resolve(params)
}
})
})
}

6. Change the endpoint to match your AWS IoT endpoint from the previous section.

7. Then click “Save” near the top right of the page.

8. In the drop down next to the “Test” button select “Configure New Test Event”.

Create a json object with a key called “text” with any arbitrary string as the value. This will be passed as the message to our IoT device.

9. Finally to confirm that our device receives the message published to AWS IoTData click “Test” and then check your terminal where the IoT device connection kit example is running!

After a few moments you’ll receive something that looks like this.

Running pub/sub sample application...
connect
message topic_1 Hello Robots!

AWS API Gateway

Amazon API Gateway is a fully managed service that makes it easy for developers to create, publish, maintain, monitor, and secure APIs at any scale. Its the ideal AWS service for creating a REST interface for a serverless AWS Lambda backend.

Normally you would want to add some level of authentication in front of your REST interface, for the purposes of this guide we will be creating an open endpoint. This is purely for education purposes. Meaning, if your project requires security there are a number of directions you can take.

  1. First, navigate to Amazon API Gateway console.

Note: Make sure as always that you’re creating this API under the same Region as your Lambda Function and IoT Device.

2. Create a New API.

3. Select REST as the protocol. Name it whatever you like and click create!

4. Select the Actions drop down and click Create Method.

5. Select POST as the method type and click the check mark.

6. Type the name of your Lambda Function until it shows as an option and select it. Click Create.

8. Click the Actions drop down again. Click Deploy API.

In this case we’ll call this deployment stage “Test”. Deployment stages are helpful when you want to test your API’s full functionality without affecting an in use production stage. Your users will love you.

10. When returning to your API, you will now see an Invoke URL. Think of this as the base URI of your API. Since we didn’t put the POST endpoint under a named resource, we can simply make a POST request to the base URI to kick off our Lambda Function.

11. In a separate terminal run the following command.

curl -H "Content-Type: application/json" -X POST -d '{"text": "test"}' your-invoke-url

If successful you’ll see a response that looks like this..

{"statusCode":200,"body":"{\"topic\":\"topic_1\",\"payload\":\"Hello Robots\",\"qos\":0}"}%

12. Next ensure our IoT device received the message over MQTT. Open the terminal window where the AWS IoT Device app is running. After a few moments you should see message received in the console that looks like this..

Congratulations! If you see this message then you’ve accomplished the goal of this guide!

So, what did we just do?

We created permissions for an AWS Lambda function to communicate with an IoT device that we created via publishing to the AWS IoTData queue through the HTTP protocol. Then we created a rest endpoint using AWS API Gateway to invoke our AWS Lambda Function. In short, we built a REST API that can communicate with an arbitrary IoT Device using a highly available and scalable service.

Services used:

This is a launchpad from which you can create managed, scalable, and cost effective IoT solutions without having to manage a myriad of resources and services.

The next step is running your IoT nodeJS application on an embedded device. Might be the right project if you’ve recently gotten your hands on the new Raspberry Pi 4.

In the next guide we’ll cover consuming data from IoT devices using AWS Lambda and Amazon DynamoDB to make queryable datasets. So stay tuned!

Thanks to James Beswick, chrismunns, and Eric Johnson

Moheeb Zara

Written by

Senior Developer Advocate at Amazon Web Services Past: Octoblu, HeatSync Labs, South West Maker Festival. Hardware hacker, artist, roboticist

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade