February 6, 2019

Coffee Bot: Use an AWS IoT Button to post to Slack when coffee is brewed

By William Welbes

Let the office know when coffee is brewed at the push of a button

Coffee Bot Message in Slack

In our office at Centare, we have a lot of coffee drinkers. As coffee drinkers know, it's great to know when a fresh pot of coffee has been brewed. We have a #food-and-drinks channel on Slack that's great for this type of notification, but wanted to make it as simple as a push of a button to post. We also just wanted an excuse to do something fun with an AWS IoT Button.

We have an AWS IoT button stuck to the wall next to our coffee makers in the kitchen area of the office. The AWS IoT Button is a cloud programmable version of the Amazon Dash button that Amazon sells for developers to use to test the AWS IoT services. The Dash buttons are sold as buttons that a customer can place near where they would need to reorder products from Amazon with the simple click of a button. While the dash buttons are preconfigured for customers with specific product types, the AWS IoT button is intentionally open for developers to use. The button uses an internal battery that lasts for about 2,000 clicks and has a simple controller that connects over wifi to AWS services when clicked.

AWS IoT Button

Version one of this solution was implemented when we used HipChat, but we recently moved to Slack. We had to update the solution to work with Slack, so I took this opportunity to also add the ability to notify if regular or decaf coffee was brewed. The button supports a single click, double click or long press as the click types, so I leveraged double click to notify when decaf was brewed. We don't want those who scoff at decaf to show up thinking a cup of regular has been brewed - that could get ugly.

The plan is as follows. Configure the AWS IoT button to connect to wifi and communicate with the AWS IoT services when the button is pressed. Setup an AWS Lambda function that is triggered by the button press that will post to Slack and record the button press to AWS DynamoDB. Getting the notification is the real intent, but being able to query the data for number of pots brewed, frequency, etc. is just a nice add on for coffee nerds.

Coffee Bot Button in Centare Kitchen

Configure the AWS IoT button

Amazon has a great tutorial for the AWS IoT button that walks through the steps of getting it setup and configured on your wifi and communicating with your AWS account. They also provide an iOS and Android app that can be used to configure your IoT button, but I found that it wouldn't work when using IAM accounts that have Two-Factor authentication enabled. Using the device itself to do the configuration has a couple more manual steps, but it's also a better way of understanding what is being configured on AWS IoT and how that configuration is applied to the button.

You should be able to walk through the tutorial to setup your AWS IoT button to connect. The steps are as follows:

  • Register a Thing in the AWS IoT Thing registry for your AWS IoT Button
  • AWS uses the Thing registry to manage all AWS IoT devices that are communicating with the back end.

  • Create and activate a device certificate
  • The device certificate and private key pair are how the device uniquely and securely connects to the AWS IoT broker over MQTT - a lightweight messaging protocol often used for IoT devices. You can let AWS create the certificate/key pair for your and simply download the files to be used in the device configuration.

  • Attach an AWS IoT Policy to the device certificate you created
  • The policies are used to authorize your device to publish to an MQTT topic in AWS IoT Core.

  • Configure your AWS IoT button
  • Now that you have your device set up in the back end, you can provide the appropriate configuration details to the AWS IoT Button. If you press and hold the button for 15 seconds, the light with begin flashing to indicate it is in programming mode. It then begins broadcasting a wifi access point that you can connect to with your PC. If you browse to http://192.168.0.1/index.html while connected to the device, you'll see a form that allows you to specify the wifi SSID and password as well as spots for the certificate and key that the device will use. The "Configure Your Device" page on the AWS tutorial explains exactly how to perform this process. If configuration fails the first time, simply hold the button for 15 seconds to get back into configure mode on the device and rerun the process.

  • Test the connection sending messages over MQTT
  • Assuming setup succeeded, you should now be able to press the AWS IoT button and have it connect and send a message over MQTT. In the AWS IoT Console, you should be able to view messages in real time via the "Test" interface. The AWS IoT documentation has a nice walk through on how to navigate to the Test area and view the JSON messages coming in over MQTT.

Setup a Slack App

Next, we want to be able to connect to Slack and post messages to the #food-and-drink channel for all the coffee lovers among us. We need to setup a Slack app that will provide us with a URL that we can post messages to.

Login to Slack on the web and navigate to https://api.slack.com/. Click the button to "Start Building". Give your app a name - we called ours Coffee Bot. Once your app is created, you can add an app icon and color to make it a little more presentable when posting messages.

Once you've created your app, you need to setup an "Incoming Web Hook". This provides a simple REST endpoint on the Slack API that you can post messages to which in turn will be posted to a specified channel inside Slack. Slack's API documentation has great details about how to setup an incoming webhook for your app.

Once you've set up your Slack web hook, you'll be provided with a URL for posting messages. Copy that URL because you'll need it in the next step. You can also use a curl command in the terminal to post JSON to the URL and confirm that the endpoint is working by verifying the message appears in your selected Slack channel.

Use an AWS Lambda function to post to Slack and record to DynamoDB every time the button is pressed

Ok. We've got a button talking to AWS and an endpoint we can use to post messages to Slack. Now we can use an AWS Lambda function to tie the two together. For extra credit, we'll also store the data off to a DynamoDB table.

In the AWS console, navigate to the Lambda area and create a new function. I have used node.js 8.10, but you could use one of the other languages Lambda supports if you prefer. I've called the function coffeeBrewed.

With your function created, you need to create an event trigger that's tied to the IoT button press message. You'll see "AWS IoT" in the triggers area of the Lambda designer. You should configure the trigger to execute using a custom rule that specifies the IoT topic to trigger off of. (Note that it defaults to an "IoT button" configuration option, but we're choosing the other since our button is already setup and sending messages to IoT core.) You can configure a select statement in the rule that uses the serial number of your device if that's the topic it's sending messages to. Replace the serial number below with your serial number or topic as appropriate.

SELECT * FROM "iotbutton/G030JF058432G4H1"

Now that we have a trigger configured, we can setup the Lambda function method. Below is the node.js Lambda function to post to Slack and record to DynamoDB every time the button is pressed. If you want to simplify things, you can remove the recordEvent method that records a DynamoDB record and simply post to Slack.

This method is executed any time a button press occurs. The event parameter has the information from the JSON sent via MQTT when the button was pressed. The method pulls out the click type from the event and then connects to the Slack web hook via https. You should replace the constant for the web hook path with the path details you got when setting up your Slack web hook.

If you are going to record to DynamoDB, you will need to first create a DynamoDB table called coffee_button_press with a primary key called id that is a numeric type. You will also need to setup an IAM role that will allow your Lambda function to connect to DynamoDB and put an item (insert a row). Below is a policy statement for an IAM role to be able to perform putItem on the specific table resource called coffee_button_press.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "dynamodb:PutItem",
                "dynamodb:DeleteItem",
                "dynamodb:GetItem",
                "dynamodb:Query",
                "dynamodb:UpdateItem"
            ],
            "Resource": "arn:aws:dynamodb:*:*:table/coffee_button_press"
        }
    ]
}

Back in the Lambda method configuration, you'll see a place to select the Lambda Execution Role that will be used by your Lambda method. Update that role to the new IAM role you've created with access to the DynamoDB table.

That's it!... Go Click your Coffee Bot button

Assuming all is setup and connected, pressing your button should result in messages appearing in your Slack channel.

Coffee Bot Message in Slack

Don't fire too many test messages because you're bound to start having folks milling around the coffee pots looking for freshly brewed coffee!

As a Centarian, it's great to be able to play with technology and build fun things. In addition to building great software for our clients, we also get together from time to time and work on fun things like Coffee Bot.

Want to join us? Take a look at our careers page for current openings or just reach out. We'd love to hear about what you're working on!


William Welbes - Developer

About William Welbes

Will is a Solutions Architect and consultant at Centare with a passion for building great software. With over 15 years of experience in software development, he has helped clients develop solutions across many different industries.