AWS IoT: Creating your first cloud-bound device

Note: This article is in the process of being updated to accommodate the newly updated AWS IoT console.

In this post, we’ll learn to create a simple AWS IoT device and connect it to an AWS Lambda Function. This tutorial is AWS beginner friendly and all concepts and terms will be explained. We will use JavaScript, although using other languages is not significantly different.

Sections:
- What is AWS IoT
- Creating a device
- Connecting your device to AWS IoT 
- Subscribing your device to a topic
- Triggering an AWS Lambda function when publishing to a topic
- Using the MQTT Client for testing

What is AWS IoT?

AWS IoT is a platform to easily manage “Internet of Things” devices, also called “things”, permitting them to interact with each other. Much like any AWS service, AWS IoT can connect to other AWS cloud applications such as Lambda (explained further down). Any AWS IoT supported device such as a Raspberry Pi or an AWS IoT Button can be connected to the cloud. In this tutorial, we will be creating a virtual device in a computer.

Use-case example of AWS IoT

‘Things’ transmit data, called messages, through the Device Gateway where they are used to update a “device shadow” or put through a “rules engine”. A device shadow (or a thing shadow) is an object holding information about a device, which is updated when the state of the device is changed. The thing shadow eliminates the need to request information from the device to retrieve its state and reduces network traffic. The rules engine, as the name suggests, is a set of rules that messages can trigger, such as invoking AWS services.

AWS-IoT Cloud — Secure and efficient

We will focus on the rules engine as we want to connect our device to a Lambda function. Now that we understand the basics of AWS IoT, let’s create our first device.

Creating your first “thing”

Moving forward, I will use ‘thing’ and ‘device’ interchangeably.

1. Configuration and certificates 
Every IoT Device needs “certificates” and “policies” in order to give them the right accesses and permissions. Certificates protect the transmission of data between your devices and AWS IoT. Policies enable devices or users to access specific resources and actions. This is to prevent any connections that are unnecessary, as well as improve security all around.

Head over to the AWS IoT console and click on ‘Register a thing’. Give a name to your device and click ‘Create Thing’.

Go ahead and open further details of your new ‘thing’ by clicking on it. You will find more information regarding your device. At first glance, you will notice a thing ARN — Amazon Resource Name, which is a unique ID for your device.

Go to the Security tab, proceed to ‘Create certificate’ and follow the steps.

MyFirstThing > Security > Create Certificate

Once that is done, download all of the certificates into your workspace folder and click ‘Activate’. When downloading certificates and keys, make sure that the file extension is ‘.crt’ and ‘.key’, respectively, you will have to modify it.
Tip: Create another folder named ‘certs’ or ‘config’ and place all those files there.

At this point, you should have four files downloaded. Proceed to ‘Attach a policy’ and create a new policy.

Give a name to your policy and add a statement with ‘Action’ filled with ‘iot:*’, and fill ‘Resource ARN’ with *. The catch-all token * enables devices to have permissions to any policy such as connecting and publishing to a “topic” (described below). In ‘Effect’, make sure ‘Allow’ is selected. Proceed to ‘Create’.

Finally, attach your thing and policy to your certificate by opening the options menu and clicking ‘Attach policy’ and ‘Attach thing’.

You should see notifications pop up in the top right corner confirming your attachment.

Now that our configuration has been created, let’s move onto the SDK.

2. Downloading the JavaScript SDK for AWS IoT
If you are using another language, make sure to go to https://aws.amazon.com/iot/sdk/ to find yours.

Important: Instructions to download the AWS IoT device SDK for JavaScript can be found here. This will require you to download Node.JS and the SDK through NPM.

In your project folder, create a new file, in my case “device.js”, and insert the following code:

var awsIot = require('aws-iot-device-sdk');
// Config
var device = awsIot.device({
keyPath: <YourPrivateKeyPath>,
certPath: <YourCertificatePath>,
caPath: <YourRootCACertificatePath>,
host: <YourCustomEndpoint>
});

Edit keyPath, certPath, caPath with the path of the downloaded certificates. To find your host, head over to your device details and go to the ‘Interact’ tab.

Your configuration should look as below:

var awsIot = require('aws-iot-device-sdk');
// Config
var device = awsIot.device({
keyPath: "./certs/[xyz]-private.pem.key",
certPath: "./certs/[xyz]-certificate.pem.crt",
caPath: "./certs/root-ca.crt",
host: "[endpoint].iot.[location].amazonaws.com"
});

3. Connecting your device to the cloud

AWS IoT ‘things’ use MQTT to transfer messages between the cloud and other devices. The variable ‘device’ becomes an instance of mqtt.Client(). The full documentation of awsIot.device can be found in the GitHub repository.

After declaring the device configuration, we can start connecting the device to the cloud.

The code below will connect your virtual device to AWS IoT, as well as catch any errors in the process.

// Connect
device
.on('connect', function() {
console.log('Connected');
});
// Error
device
.on('error', function(error) {
console.log('Error: ', error);
});

Go ahead and run node device.js , and your console should display Connected. If nothing is displayed or an error pops up, verify that you have attached your policy and thing to your certificate.

Congratulations! You connected your device to AWS IoT.

4. Subscribing your device to a topic

When devices want to communicate with each other, messages go through what are called topics. Through topics, data is transmitted between publishing devices and subscribing devices. A message can only be sent if a device publishes to a topic, and that message can be received by another device only if it subscribes to that topic. Topics are part of the MQTT protocol.

Once your device is connected, we can subscribe to a topic using device.subscribe(topic); . Similarly, in order to publish to a topic, use device.publish(topic, message); . Note: topic is a string and message is an object converted to a string.

When subscribing to a topic, you receive messages through:

device
.on('message', function(topic, payload) {
console.log('message', topic, payload.toString());
});

The parameters of the function are topic, which is a string, and payload, which is the content of the message in JSON. Let’s test it! Your ‘connection’ and ‘receive’ code should look something like this:

// Connect
device
.on('connect', function() {
console.log('Connected');
// Subscribe to myTopic
device.subscribe("myTopic");
// Publish to myTopic
device.publish("myTopic", JSON.stringify({message: 'hello'})); });
// Receiving a message from any topic that this device is
// subscribed to.
device
.on('message', function(topic, payload) {
console.log('message', topic, payload.toString());
});

Running node device.js should display message myTopic {message: 'hello'} (in my case). In this case, we have subscribed to topic myTopic, published to it and printed the contents of the message. Voilà! You have subscribed and transmitted data through a topic. Next, we will be using topics in order to trigger Lambda functions.

5. Creating an AWS Lambda Function and connecting it to our ‘thing’
AWS Lambda is a computing platform that runs code in response to demand and events. This is useful as it enables serverless architectures for any type of applications.

AWS Lambda use-case

One way of triggering an AWS Lambda Function is using rules through a topic. We previously mentioned the AWS IoT Rules Engine, where a set of rules can be created in order to run other AWS services. We are going to create a rule that triggers a Lambda Function every time a ‘topic’ receives a message.

In the AWS IoT Console, head over to the ‘Act’ tab on the left and create a rule. Give a name to your rule and scroll down to ‘Message source’. Rules use SQL syntax to trigger an action. Fill the ‘Attribute’ input with a catch-all *, and as a topic filter, enter any topic. In this case, I will be using ‘myTopic’.

Scroll further down and click ‘Add action’, select ‘Invoke a Lambda function passing the message data’ and click ‘Configure action’. Since we don’t have any Lambda functions, let’s create a new one by clicking on ‘Create new resource’. This will open a new tab at the AWS Lambda console.

We use a basic template for our Lambda function. In the search bar, type ‘hello-world’ and select the Node.JS starter code.

Fill your Lambda function’s basic information by giving it a name. For ‘role’, select ‘Create new role from template(s)’, give your new role a name and select any Policy Template. Similar to policies, roles give permissions to your functions.

Scrolling further down, you will find your example code for your Lambda function. You will notice that all the data being received is put in the first parameter as a JSON object.

Once done, click ‘Create function’. Keep the tab open, as we will be revisiting it further down.

Go back to the first tab from our AWS IoT screen where we were redirected to AWS Lambda. Click the refresh button on the right of ‘Function name’ and select your lambda function.

Finish by adding the action and creating your rule. Now you have a Lambda function that is triggered every time a topic receives a message.

Head over to your code, edit topic names, and modify the data being sent to your topic — make sure that your message values are displayed in your Lambda function. Using the default template, your published code should look like the following:

device.publish(“myTopic”, JSON.stringify({
key1: ‘hello1’,
key2: ‘hello2’,
key3: ‘hello3’
}));

Run node device.js, and head over to your Lambda function page. Go to the ‘Monitoring’ tab and click on ‘View logs in CloudWatch’. CloudWatch is an AWS service that collects and tracks logs. These logs include errors, event triggers, and regular console logs.

You might see a similar graph to the screenshot, which means that your function has been triggered.

Next, go to the CloudWatch console, find the latest Log Stream and open it by clicking on it. You should find your Lambda function’s logs.

If you don’t see your logs, try refreshing the logs in a few minutes by clicking Retry next to ‘No newer events found at the moment’.

Congratulations! Your Lambda function is now connected to your topic.

Using the MQTT Client for testing

AWS IoT provides a tool in order to test your devices using an MQTT Client. With it, you can subscribe and publish to topics and receive messages from your devices. This facilitates testing between topics and makes sure messages are being delivered correctly.

Head over to “Test” tab on the AWS IoT console.

In order to subscribe to a topic, enter the topic’s name in the “Subscription Topic” input box. Click on “Subscribe to topic”.

Once subscribed, a feed of messages being sent to your topic will be displayed. For example, when running node device.js , you will see your message in the topic’s feed.

Output when running ‘node device.js’

Similarly, you can publish to a topic with a custom message by inputing a topic and editing the message in the editor.

Output of device.js from using MQTT Client

Recap:

You created an AWS IoT device with Node.JS which uses MQTT to communicate. Using this protocol, you published to a topic which triggered a Lambda function in AWS IoT using rules and printed the contents of it.

I hope this tutorial was useful. Please feel free to send me a message to samuel[at]tensoriot.com, and I’ll be happy to answer any questions.