Receiving AWS IoT messages in your browser using websockets

Along with AWS Lambda and the Realtime Messaging Platform

A few weeks ago AWS launched an interesting cloud service enabling secure, bi-directional communication between Internet-connected things (such as sensors, actuators, embedded devices, or smart appliances) and the AWS cloud over MQTT and HTTP.

With this service you can easily publish and receive messages from your “things”. But what if you need to receive those messages in a web page using Chrome or Safari? For example to build a web dashboard?

Well, you can’t … at least using only the AWS IoT SDKs.

Enter Realtime Messaging

The Realtime Messaging Platform allows you to build web applications that can receive messages sent from other applications directly in the user’s browser (or mobile device). Using the Realtime JavaScript SDK and the websocket protocol sending and receiving messages in the browser is a few API calls away.

Imagine we could capture an AWS IoT message and simply send it to a given Realtime pub/sub channel so the web browser subscribers could receive it? It’s not only doable but it’s very easy. We just need a way to capture the AWS IoT message.

Enter AWS Lambda

AWS Lambda is a compute service where you can upload your code to AWS Lambda and the service can run the code on your behalf using AWS infrastructure. Binding the code you upload to an event, like “new message from AWS IoT”, will allow you to call the Realtime RESTful API in order to publish the message to the appropriate Realtime channel. That simple.

Now we only need a way to bind our Lambda code (in this example a Node.JS function) to the AWS IoT message broker.

Enter the AWS IoT rules

One of the coolest parts of AWS IoT is the rules engine as it provides message processing and integration with other AWS services. You can use a SQL-based language to select data from message payloads, process the data, and send the data to other services, such as AWS Lambda. Voilà!

Defining a rule that invokes the Lambda function when a new message is sent is the last piece in our puzzle:

Message published in AWS IoT >> Invoke Lambda function >> Send message to Realtime >> Deliver message to web browser subscribers

Making it work

The AWS IoT provisioning is not a walk in the park but AWS provides a nice step by step quickstart guide. Follow this guide until you reach the “Configure and Test Rules” section.

If you’re there it means you can successfully publish and receive messages using your “thing” through the MQTT.fx JavaFX-based MQTT client.

Creating the AWS Lambda function

In order to send the AWS IoT message to the Realtime Platform we’ll need to write a Lambda function. In our example this function will send the AWS IoT message to the aws-iot Realtime channel.

Using the AWS Lambda console click the “Create a Lambda function” button (if you already have other functions defined) or the “Get Started Now” button (if it’s your first Lambda function).

Since I’ll be giving you the full code ahead you can skip the “Select blueprint” stage by clicking the “Skip” button in the page bottom.

Now it’s time to configure our Lambda function.

Enter iot_to_realtime in the name input field and copy/paste the following Node.js code into the “Lambda function code” text-area:

Note: Before proceeding you need to enter your Realtime appkey and private key in the function code above. If you don’t have a Realtime subscription yet you can get a free one at https://accounts.realtime.co/signup/

Keep index.handler in the Handler input field and select the “Basic execution role” in the Role dropdown. On the Role page choose Allow.

Back to the new function page choose Next and then Create Function.

On the page displayed, make a note of the function ARN. You will need it to create the AWS IoT rule.

Creating the rule to invoke the Lambda function

Now that we have the Lambda function ready it’s time to create the AWS IoT rule that will invoke the function when a message is published in test/topic.

In your text editor enter the following JSON document describing your new rule, entering your Lambda function ARN in the functionArn property.

Save the document as aws_iot_rule.json and run the following AWS CLI command to create the topic rule:

The rule is now created and all we need to do is give permission for the AWS IoT engine rule to invoke the Lambda function. This is done through the following AWS CLI command:

NOTE: You can easily extract your AWS Account ID from the function ARN (it’s the number before :function).

If all went well you got a JSON response from the AWS CLI and we are ready to test the AWS IoT/Realtime integration.

Bringing it all together

To test the AWS IoT/Realtime integration let’s start by subscribing the aws-iot channel in a web browser.

Open the console.realtime.co page in your preferred browser, enter your Realtime application key and click the connect button.

Your browser is now connected to a Realtime server and you are ready for subscribing data channels.

Now enter aws-iot in the channel input field and click the subscribe button.

You should be seeing something like this in your Realtime Console Log panel:

16:26:23 — SUBSCRIBED TO: aws-iot
16:26:23 — SUBSCRIBING TO: aws-iot…
16:24:59 — HEART BEAT DETAILS: Active — false | Time — 15 | Fails — 3
16:24:59 — USING: websocket
16:24:59 — SESSION ID: fceda1653cfb0241
16:24:59 — CONNECTION METADATA:
16:24:59 — CONNECTED TO: http://ortc-developers2-euwest1-s0001.realtime.co
16:24:58 — CONNECTING TO:
http://ortc-developers.realtime.co/server/2.1...

If you do see something like this it means you are subscribed to the channel.

Now we need to send a message from our AWS IoT “thing” using the MQTT.fx client (or any other MQTT compatible client).

Open the MQTT.fx client and connect to AWS IoT (you can follow this AWS IoT guide).

After connecting, select the Publish tab, enter test/topic in the topic input field and a JSON message like this in the message field:

{“message”:”Hello World”}

NOTE: if the message is not a well formed JSON object the Lambda function call will fail and no message will be sent to the Realtime server.

Now click the Publish button.

In your console.realtime.co browser window you should see the following log in the Log panel:

18:41:09 — RECEIVED AT aws-iot: {“message”:”Hello World”}

This means your AWS IoT “thing” message was delivered to your browser through the Realtime Platform. Yes!

What next?

This is simply a proof-of-concept but you can see the power behind it.

Imagine your AWS IoT “thing” is a temperature sensor that is publishing the current room temperature to an AWS IoT topic. With this approach you could relay these temperature messages to a web dashboard showing a real-time updated chart with the read values.

This approach allows any AWS IoT messages to be sent over the internet to browsers and mobile applications with a few simple configurations and you don’t need to run absolutely no server at all.

It’s the “serverless” brave new world.
Now it’s up to you and your imagination.

Go build :)

Show your support

Clapping shows how much you appreciated João Parreira’s story.