2 Comments

AWS IoT Help Button

We recently moved into our new building at 1034 Wealthy in Grand Rapids. The new building is much larger than our old one, and I find myself running around much more and stationing myself in different areas, depending on what I am actively doing.

To help ensure I can provide timely hands-on help—particularly for our printer (which is a common source of problems)—I procured one of the new AWS IoT buttons and programmed it to page me when pushed.

AWS IoT Button Overview

The AWS IoT Button is a simple device consisting primarily of a push button, an LED indicator, and a WiFi card. It can be configured to connect to the AWS IoT (Internet of Things) service in order to deliver data about button pushes. The data consists primarily of the type of button push (short, double, or long), but it also includes the button’s serial number and the battery voltage. This data can then be acted upon to do any number of interesting things using AWS or calling out to other services.

AWS IoT Button

Connectivity

The AWS IoT Button requires Internet connectivity to communicate with the AWS IoT service. When configuring the button, you choose a WiFi SSID to connect to and provide the appropriate passphrase. The button also receives an ARN identifier, so that it can be uniquely referenced within the AWS ecosystem.

Security

When configuring the AWS IoT Button, a new PKI certificate and private key are generated and uploaded to the button. This allows the button to communicate securely with AWS, and it allows AWS to validate the identity of that button. This becomes important when writing specific policies to enable button data to trigger events.

How I Use the AWS IoT Button

When someone presses the AWS IoT button, it kicks off a process which will simultaneously e-mail me, send me an SMS message, and show me a notification on Slack. The message contains a timestamp and an identifier for the button that was pressed (in case there are more such buttons deployed in the future).

I have set the expectation that if I am available, and not in a meeting or otherwise occupied, I will respond to a button push within five minutes. This is often much faster than someone would be able to locate me and request assistance otherwise. While there have been a few instances where people1 have pushed the button simply to test my response time, I’ve had over a dozen instances of legitimate button pushes. As a result of these, I was able to respond to the notification and assist with a printer problem in a timely fashion.

AWS IoT Help Button

I’m not sure how well this setup would scale, but for the moment, it is working well.

The AWS Service Flow

AWS IoT

AWS IoT is a platform to allow devices to interact with AWS cloud services.

For AWS IoT Buttons, there is a device or “thing,” rule, certificate, and policy associated with each physical button. A “device” associates a button (by serial number) with a particular HTTP REST endpoint and MQTT topic. The “certificate,” uploaded to the button during configuration, is linked to a “device” and allows the button to securely submit data, while also authenticating it to AWS. The “rule” specifies how messages from the MQTT topic are used, defining what actions to take when a query matches a message. A “policy” authorizes a specific device to take AWS IoT actions, such as publishing to an MQTT topic.

In my setup, I added the endpoint information for my “device” to the AWS IoT button, which is linked to the specific “certificate” I uploaded, along with its private key:

  • REST API Endpoint: https://a1914s730zztw0.iot.us-west-2.amazonaws.com/things
  • MQTT Topic: iotbutton/G030JF055234P6KJ

I gave the ‘device’ permission to publish to the MQTT topic:


{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "iot:Publish",
      "Effect": "Allow",
      "Resource": "arn:aws:iot:us-west-2:979276642162:topic/iotbutton/G030JF055234P6KJ"
    }
  ]
}

I specified that any messages received on the specific MQTT topic are forwarded to an AWS Lambda function:

  • Query String: SELECT * FROM 'iotbutton/G030JF055234P6KJ'
  • Action: Lamda Action; Function Name AWS_IoT_Button_aogr_1_resource_area

In this case, the messages are JSON-formatted data representing events containing the button’s serial number, battery voltage, and type of button push:


{
  "serialNumber": "G030JF055234P6KJ",
  "batteryVoltage": "1568mV",
  "clickType": "SINGLE"
}

AWS Lambda

As I have written about before2, AWS Lambda allows functions written in a few different languages (Python, Java, and Node.js) to be executed in response to events.

For my AWS IoT Button, I created a function to publish to an AWS SNS topic.

My Lambda function is quite simple;


// Node.JS 4.3 Runtime

const AWS = require('aws-sdk');
const SNS = new AWS.SNS({ apiVersion: '2010-03-31' });

function findTopicArn(topicName, cb) {
    SNS.createTopic({ Name: topicName }, (err, data) => {
        if (err) console.log(err, err.stack);
        else cb(data.TopicArn);
    });
}

function publishToTopic(params, cb) {
    SNS.publish(params, (err, data) => {
        if (err) console.log(err, err.stack);
        else cb(data.MessageId);
    });
}

exports.handler = (event, context, callback) => {
    
    console.log('Received event:', event.clickType);
    
    var datetime = new Date();
    
    var topicArn = findTopicArn('aws-iot-button-sns-topic', (topicArn) => {
    
        console.log(`Publishing to topic ${topicArn}`);
        
        var params = {
            Message: `aogr_1_resource_area help request at ${datetime}`,
            Subject: `Help Request: aogr_1_resource_area`,
            TopicArn: topicArn
        };
        
        var messageId = publishToTopic(params, (messageId) => {
            console.log(`Published to topic with messageId: ${messageId}`);    
        });
        
    } );
};

The function finds an SNS topic ARN by name, and then publishes a message to the topic. The event data is not actually passed along to SNS as this Lambda function is unique to the AWS IoT Button that I am using (specified in the “plan” for the “device” in AWS IoT), so I just send a custom message crafted for the purposes of the button. It would not be difficult to modify the function to send data about the button push (such as the push type), or send additional data from AWS IoT (such as the button serial number).

AWS SNS

AWS SNS allows sending push messages to subscribers of specific topics.

For my purposes, I created an AWS SNS topic called “aws-iot-button-sns-topic” to which I added two subscriptions: one e-mail and one SMS. As I wanted to receive notifications from pushes to the AWS IoT button, I used my e-mail address and mobile number. When messages are published to the topic from the Lambda function, I receive them via e-mail and on my phone.

Conclusion

While certainly not a very sophisticated use of IoT, creating the IoT Help Button provided a good opportunity for me to learn about AWS’s IoT offering. I also took the chance to build a nifty device which helps make me a little bit more effective at my job. I’m excited to try out connecting other devices to AWS IoT, so I can build something larger which drives a more complex set of services.


1. Shawn Anderson 2. Managing AWS Route 53 Hosted Zones with AWS Lambda and Managing AWS CloudFront Security Group with AWS Lambda