Building a Slack Doorbell in 30 minutes

Mike Molinet
14 min readOct 30, 2016

--

This post was inspired by a great blog I found by Andrew McGill on how he built a Slack-powered doorbell for their office. Andrew did a great job highlighting the main parts, but when I went to replicate it, I realized there was a lot more to it than I thought. This is an expansion on Andrew’s idea with every step in the process (including code snippets) necessary for building your own Slack-powered doorbell.

First, some context: Our building for Branch is completely locked, and while employees have key cards to let themselves in, it doesn’t solve for the 15+ visitors that come to our office every day. And since our office manager is often away from her desk taking care of other company needs, visitors would often knock on the door, which disrupted our engineers multiple times per day. A loud, audible doorbell wasn’t an option because we didn’t want to disturb people with a noise every time someone was at the door. The only solution that solved all of our needs was a Slack-powered doorbell, and since there’s nothing standard out there, we built one ourselves, using Amazon’s IoT button and Andrew’s blog post as a guide.

What follows below is a step-by-step guide on everything you need to do to set up your own Slack-powered doorbell. It references a lot of AWS IoT documentation along the way which I’ve copied and pasted here for convenience and clarification (removing the unnecessary parts).

First, if you don’t have an AWS IoT button, you can order one here. After that, the main steps are: (1) Set up your device, and (2) Connect your device to Slack (and SMS, email, or whatever else you want).

— — — — — — —

Set up Your Device

#1 Sign in to the AWS IoT Console

If you do not have an AWS account, create one: (1) Open the AWS home page and choose Create an AWS Account. (2) Follow the online instructions. Part of the sign-up procedure involves receiving a phone call and entering a PIN using your phone’s keypad.

Sign in to the AWS Management Console and open the AWS IoT console.

On the Welcome page, choose Get started with AWS IoT.

If this is your first time using the AWS IoT console, you will see two options: Get started and Start interactive tutorial. Choose Get Started.

On the Resources page, if you don’t see a blue banner with Create a thing, Create a rule, Create a certificate, and Create a policy buttons, choose Create a resource.

#2 Create a Device in the Thing Registry

To connect a device to AWS IoT, they recommend that you first create a device in the thing registry. This registry allows you to keep a record of all of the devices that are connected to your AWS IoT account.

  1. Choose Create a thing, and then type a name for your device (e.g. Doorbell). You can also choose Add attribute to provide information about your device (for example, its serial number, manufacturer, and more) — no need to do this. Choose Create to add your device to the thing registry.
  1. Choose View thing to display information about your device.

In the right panel that appears, you’ll see a REST API endpoint, like this (I recommend you copy this and paste it somewhere for reference later):

https://a1bcd23ef4ghij.iot.us-west-2.amazonaws.com/things/doorbellButton/shadow

#3 Create and Activate a Device Certificate

Communication between your AWS IoT button and AWS IoT is protected through the use of certificates, which must be activated prior to use.

  1. Click “Create a Certificate”
  2. Check the “Activate” box. Choose 1-Click certificate create.
  1. On the Resources page, choose the Download private key and Download certificate links, and then save the private key and certificate to your computer.
  1. If you didn’t click “Activate”, then select the check box on the certificate, and from the Actions menu, choose Activate.

#4 Create an AWS IoT Policy

AWS IoT policies are used to authorize your button to perform AWS IoT operations. Your button will present its certificate when sending messages to AWS IoT. To allow your button to perform AWS IoT operations, you must create an AWS IoT policy and attach it to your device certificate.

  1. In the AWS IoT console, if you don’t see the Create panel, choose Create a resource.
  2. Choose Create a policy.
  3. In the Create a policy section, type a name for the policy (e.g. “DoorbellPolicy”). From the Action menu, choose iot:Publish.
  4. In the Resource field, type the ARN of your AWS IoT button, and then select the Allow check box.

Note: The ARN follows this format: arn:aws:iot:your-region:your-aws-account:topic/iotbutton/button-serial-number

For example:

arn:aws:iot:us-west-2:123456789012:topic/iotbutton/G030JF051234ABCD

To get “your-aws-account” number, go here and copy your Account ID.

Choose Add statement, and then choose Create.

Side Note: The settings explained in this step assume you are using an AWS IoT button which is programmed to publish on a specific MQTT topic: topic/iotbutton/button-serial-number. The policy created gives permission to publish to that topic. If you are not using an AWS IoT button, you should modify the ARN described above to contain the MQTT topic on which your device publishes. If your device is programmed to publish on myDevice/myTopic you would use the following ARN: arn:aws:iot:us-east-1:123456789012:topic/myDevice/myTopic.

#5 Attach an AWS IoT Policy to a Device Certificate

Now that you have created a policy, you must attach it to your device certificate. Attaching an AWS IoT policy to a certificate gives the device the permissions specified in the policy.

  1. From the AWS IoT console, choose your device certificate, and from the Actions menu, choose Attach a policy.
  1. In the Confirm dialog box, type the name of the AWS IoT policy you created in the previous step, and then choose Attach.

#6 Attach a Thing to a Certificate

To attach a certificate to a device in the thing registry:

  1. In the AWS IoT console, choose the certificate you want to attach, and from the Actions menu, choose Attach a thing.
  1. In the Confirm dialog box, type the name of the thing to which you will attach the certificate, and then choose Attach.
  1. To verify the thing is attached, double-click the certificate. The policy and thing should appear in the detail pane.

#7 Configure Your Device

Configuring your device allows it to connect to your Wi-Fi network. Your device must be connected to your Wi-Fi network to install the device certificate and to send messages to AWS IoT. All devices must have a device certificate in order to communicate with AWS IoT.

To configure your AWS IoT button:

Turn on your device

  1. Remove the AWS IoT button from its packaging, and then press and hold the button for 15 seconds until a blue blinking light appears.
  2. The button acts as a Wi-Fi access point, so when your computer searches for Wi-Fi networks, it will find one called Button ConfigureMe — XXX where XXX is a three-character string generated by the button. Use your computer to connect to the button’s Wi-Fi access point.
  3. The first time you connect to the button’s Wi-Fi access point, you will be prompted for the WPA2-PSK password. Type the last 8 characters of the device serial number (DSN). You’ll find the DSN on the back of the device, as shown here:

Copy your device certificate onto your AWS IoT button

To connect to AWS IoT, you must copy your device certificate onto the AWS IoT button.

  1. In a browser, navigate to http://192.168.0.1/index.html.
  2. Complete the configuration form.
  3. Type your Wi-Fi SSID and password. Note: The network must be 2.4 ghz. 5 Ghz networks don’t work on this and won’t appear in the network list.
  4. Browse to and select your certificate and private key.
  5. Select the Terms and Conditions check box. Your settings should now look like the following:
  1. Your button should now connect to your Wi-Fi and blink white, then green.

#8 Create an SNS Topic

You will use the Amazon SNS console to create an Amazon SNS topic.

  1. Open the https://console.aws.amazon.com/sns/.
  2. From the left pane, choose Topics, and on the right pane, choose Create new topic.
  3. Type a topic name and a display name, and then choose Create topic.
  1. Make a note of the ARN for the topic you just created.

Record the Topic name for reference later.

Connect your device to Slack

#1 Create an incoming webhook for Slack

  1. Go to https://yourdomain.slack.com/apps/manage/custom-integrations. (make sure to replace “yourdomain” with whatever your Slack domain is).
  2. Select “Incoming Webhooks” from the Table.
  3. Choose which channel to post to.
  4. Click the green button ‘Add incoming webhooks integration’. It’ll take you to a new screen with setup instructions.
  5. Copy the Webhook URL and save it for later. You can configure things here, but you don’t need to do much since most of it can be configured via the payload through the webhook. Here’s an example webhook URL:

https://hooks.slack.com/services/ABC123DEF/456GHI789/abcdefghijklm

#2 Create the Lambda Function

To create the Lambda function:

  1. In the AWS Lambda console, choose Create a Lambda function.

For the filter, type request, and then choose the https-request blueprint.

On the Configure triggers page, select the box to the left of the Lambda icon, and select AWS IoT from the drop down menu.

On the Configure triggers page, enter your button’s device serial number (DSN). Your DSN is printed on the back of your AWS IoT button. DON’T CLICK “GENERATE CERTIFICATE AND KEYS”. YOU SHOULD ALREADY HAVE THESE FROM THE PREVIOUS STEPS.

Ensure that the Enable trigger checkbox is selected and select Next.

  1. On the Configure function page, type a name and description for the Lambda function. In Runtime, choose Node.js 4.3.
  1. Scroll down to the Lambda function code section of the page. Delete the existing code and paste in the following (note: you’ll need to edit certain sections, per the instructions below this code block):
‘use strict’;var querystring = require(‘querystring’);var https = require(‘https’);var fs = require(‘fs’);exports.handler = function(event, context) {     console.info(‘Received event’, event);     // Build the post string from an object     var payload = JSON.stringify(payload = {“channel”: “#office”, “username”: “doorbell”, “text”: “<!here> Someone is at the door!”, “icon_emoji”: “:bellhop_bell:”});     console.info(‘Defined post_data’);     // An object of options to indicate where to post to     var post_options = {          host: ‘hooks.slack.com’,          port: ‘443’,          path: ‘/services/ABC123DEF/456GHI789/abcdefghijklm’,          method: ‘POST’,          headers: {               ‘Content-Type’: ‘application/json’,               ‘Content-Length’: payload.length          }     };     console.info(‘Defined Post options’);     var post_request = https.request(post_options, function(res) {     console.info(‘Started post_request’);     var body = ‘ABC’;     console.info(‘Defined post-request body’);     res.on(‘payload’, function(chunk) {     body += chunk;     console.info(‘Res.on’);     });     res.on(‘end’, function() {     context.done(body);     });     res.on(‘error’, function(e) {     context.fail(‘error:’ + e.message);     });     });     // post the data     post_request.write(payload);     post_request.end();};

Where:

“payload” data is the slack info you want to use, such as channel, username, text copy, icon.

payload = {“channel”: “#office”, “username”: “doorbell”, “text”: “<!here> Someone is at the door!”, “icon_emoji”: “:bellhop_bell:”}

“Path” is the stuff after “hooks.slack.com” for your integration

path: ‘/services/ABC123DEF/456GHI789/abcdefghijklm’

Remember when you made a Slack webhook earlier and it gave you a webhook URL? Now you parse that so you can replace the path code above with your specific url path.

So for example, if your link was:

https://hooks.slack.com/services/ABC123DEF/456GHI789/abcdefghijklm

Then just grab everything after “hooks.slack.com”. So in this example, we’ll grab “/services/ABC123DEF/456GHI789/abcdefghijklm” and paste it in the code above inside AWS Lambda’s online code editor.

Note: depending on how you configure the text payload, you may need to use something like <!here> or <@here> to simulate “@here” in the message. Test it to see what works and what doesn’t.

The code block will look something like this now:

  1. Scroll down to the Lambda function handler and role section of the page. For Role, choose Create a custom role.

The IAM console will open, allowing you to create an IAM role that Lambda can assume when executing the Lambda function.

  1. To edit the role’s policy to give it permission to publish to your Amazon SNS topic:

Choose View Policy Document.

Choose Edit to edit the role’s policy.

Replace the policy document with the following:

{
“Version”: “2012–10–17”,
“Statement”: [
{
“Effect”: “Allow”,
“Action”: [
“logs:CreateLogGroup”,
“logs:CreateLogStream”,
“logs:PutLogEvents”
],
“Resource”: “arn:aws:logs:*:*:*”
},
{
“Effect”: “Allow”,
“Action”: [
“sns:Publish”
],
“Resource”: “arn:aws:sns:us-west-2:123456789012:MyIoTButtonSNSTopic
}
]
}

Where

“us-west-2” is the region identified during setup

“123456789012” is your AWS account number

“MyIoTButtonSNSTopic” is the name you input when you created an SNS topic before.

Edit the code with your variables.

Choose Allow.

  1. Leave the settings on the Advanced settings page at their defaults, and choose Next
  1. On the Review page, choose Create function.

If it gives you an error about there not being a role, just hit “Previous”, and in the Role field, choose “Choose an existing role.” Then in the box below that appears called “Existing Role”, select the one that you just created. For some reason, the portal doesn’t always save your new role immediately upon creating it so if you save, it may not recognize a role as being selected.

Creating a Lambda Rule

Now that you have created a Lambda function, you can create a rule that invokes the Lambda function.

  1. In the AWS IoT console, choose Create a resource.
  2. Choose Create a rule.
  3. Type a name and description for the rule.
  1. Enter the following settings for the rule:

Attribute: *

Topic filter: iotbutton/your-button-serial-number

  1. For Choose an action, select Insert this message into a code function and execute it (Lambda).
  2. From Function name, choose your Lambda function name, and then choose Add action.

Choose Create to create your Lambda function.

Test Your Lambda Rule

Now that your button is configured and connected to Wi-Fi and you have configured an Amazon SNS topic, you can press the button to test your Lambda rule. You should receive a Slack message in the appropriate channel with the correct messaging.

I’ve also made a photoshop file that’s the right size, in the event you want to replace the default skin with a custom skin. You can download the PSD here (I promise it’s not malware). Preview below:

Once I printed it, I used an Exacto knife to remove the default skin, flipped the default skin over and placed the printout on top of it, trimmed around the edges using the default skin as a guide, removed the paper copy from the default skin (discard the default skin), used double-sided tape to tape this one in place, and then covered it with packaging tape to give it a protective coating (I trimmed off the excess tape with the Exacto knife).

Here’s the finished product:

— — — — — — —

Connect your device to SMS and Email

If you’d like to add additional notifications, like email and SMS, go to the SNS console.

Select the Topic you’d like to add notifications for. This bring you to a new page. Hit “Create Subscription”.

A modal pops up. For Protocol, select what notification format you’d like to use. We’ll do SMS. Enter in your phone number after selecting SMS in the format: 1–555–867–5309.

You’ll see the subscription now appear in the list.

Go to the AWS Lambda console, and choose Create a Lambda function.

  1. For the filter, type request, and then choose the Request blueprint.
  2. On the Configure triggers page, select the box to the left of the Lambda icon, and select AWS IoT from the drop down menu.
  1. On the Configure triggers page, enter your button’s device serial number (DSN). Your DSN is printed on the back of your AWS IoT button. DON’T CLICK “GENERATE CERTIFICATE AND KEYS”. YOU SHOULD ALREADY HAVE THESE FROM BEFORE.
  2. Ensure that the Enable trigger checkbox is selected and select Next.
  1. On the Configure function page, type a name and description for the Lambda function. In Runtime, choose Node.js 4.3.

Scroll down to the Lambda function code section of the page. Delete the existing code and paste in the following (note: you’ll need to edit some sections, per the instructions below this code block):

console.log(‘Loading function’);// Load the AWS SDKvar AWS = require(“aws-sdk”);// Set up the code to call when the Lambda function is invokedexports.handler = (event, context, callback) => {     // Load the message passed into the Lambda function into a JSON object     var eventText = JSON.stringify(event, null, 2);     // Log a message to the console, you can view this text in the Monitoring tab in the Lambda console or in the CloudWatch Logs console     console.log(“Received event:”, eventText);     // Create a string extracting the click type and serial number from the message sent by the AWS IoT button     var messageText = “Breaking Bread is starting soon!”;     // Write the string to the console     console.log(“Message to send: “ + messageText);     // Create an SNS object     var sns = new AWS.SNS();     // Populate the parameters for the publish operation     // — Message : the text of the message to send     // — TopicArn : the ARN of the Amazon SNS topic to which you want to publish     var params = {     Message: messageText,     TopicArn: “arn:aws:sns:us-west-2:123456789012:BreakingBreadTopic     };     sns.publish(params, context.done);};

Make sure to edit all the variable components: your message, your region, your AWS account number, and the SNS topic.

Choose an existing role. Select the one you used previously for the slack notifications. Hit Next.

Hit Create Function.

Test it out! You should get an SMS with the message when the button is clicked.

--

--