Tracking Amazon IOT Button Clicks using Lambda and DynamoDB

I purchased a programmable Amazon IOT Button to better understand how the button and AWS IOT Service work. I decided my first application is to simply maintain a running count of the button clicks, and view the running counts in a bar chart.

Tracking Amazon IOT Button clicks using AWS Lambda and DynamoDB

The application uses a combination of AWS IOT, API Gateway, Lambda, and DynamoDB. The Lambda Functions are written using Python 3.

Amazon IOT Button

The Amazon IOT button offers 3 different types of clicks.

  • SINGLE
  • DOUBLE
  • LONG

The type of click is provided to the Lambda Function. There are 3 values provided as part of the Lambda event.

{
    "serialNumber": "GXXXXXXXXXXXXXXXXX",
    "batteryVoltage": "xxmV",
    "clickType": "SINGLE" | "DOUBLE" | "LONG"
}

Tracking Clicks Using Lambda and DynamoDB

Here is the Lambda Function that gets triggered on a button click. The click type is captured, evaluated against a list of registered click types (single, double, and long), and, if registered, increments a value in the DynamoDB Table.

import boto3
import json
import logging
import os


registered_click_types = os.getenv('registeredClickTypes').split(',')
table = os.getenv('table')

logger = logging.getLogger()
logger.setLevel(logging.INFO)

db = boto3.resource('dynamodb')
table = db.Table(table)


class ClickTypeNotRegisteredException(Exception): pass


def lambda_handler(event, context):
    logger.info('Received event: ' + json.dumps(event))
    
    click_type = event['clickType'].lower()
    
    if not click_type in registered_click_types:
        raise ClickTypeNotRegisteredException('Uknown clickType: ' + click_type)
    
    table.update_item(
        Key={
            'type': click_type
        },
        UpdateExpression='SET counts = counts + :incr',
        ExpressionAttributeValues={
            ':incr': 1
        }
    )

There are 2 environment variables that denote the registered types of clicks and the name of the DynamoDB Table storing the running click counts.

{
    "registeredClickTypes": "single,double,long",
    "table": "clicks"
}

DynamoDB Table

The DynamoDB Table is called clicks and contains a running count for each type of click: single, double, and long. The partition key is a string, called type, that is the click type.

Items: [
    {
        "type": "single",
        "counts": 8
    },
    {
        "type": "double",
        "counts": 12
    },
    {
        "type": "long",
        "counts": 5
    },
]

API Gateway RESTful Endpoint To Retrieve IOT Button Stats

I created a RESTful endpoint using AWS API Gateway and Lambda that returns the running click counts for the Amazon IOT Button in JSON. Here is the Lambda Function written in Python 3.

import boto3
import logging
import os


registered_click_types = os.getenv('registeredClickTypes').split(',')
table = os.getenv('table')

logger = logging.getLogger()
logger.setLevel(logging.INFO)

db = boto3.resource('dynamodb')
table = db.Table(table)


def lambda_handler(event, context):
    counts = []
    
    # querying, but could scan, too.
    for click_type in registered_click_types:
        count = int(table.get_item(
            Key={
                'type': click_type
            }
        )['Item']['counts'])
    
        counts.append(count)

    return counts

The API Gateway endpoint is polled intermittently from a web page using JavaScript that displays the results in a bar chart.

Tracking Amazon IOT Button Clicks

This is a good starter project for understanding the AWS IOT Service and the Amazon IOT Button.

Contents