The data flow is as follows:

  • A device uses I2C temperature sensor and sends data to the AWS IoT periodically
  • An AWS IoT rule intercepts temperature data and stores it into the DynamoDB table
  • A device gets synchronised with its AWS IoT shadow
  • A frontend with OAuth is running on AWS S3, talking to the device shadow to either get the device state, or set the device state (turn it on/off)

Build instructions

First of all, you'll need to create Google and/or Facebook OAuth2 Client, so that users will be able to login into the heater application.

For Google: visit Google Cloud Console, click Create credentials -> OAuth client ID -> Web application, and enter some name, e.g. "AWS Heater", and click "Create". It will show your client ID and secret; copy client ID, you'll need it soon. And don't close the tab for now: when your stack is instantiated, you'll need to get back here and enter the Authorized JavaScript origin.

For Facebook: visit Facebook Apps, click "Add a New App", enter some name, like, "My Heater", pick a category, click "Create App ID". When the app creation is done, you'll see the app dashboard. Don't close the tab for now: when your stack is instantiated, you'll need to get back here and enter the Website URL.


git clone https://github.com/cesanta/mongoose-os.git  # Clone mongoose-os repo
cd mongoose-os/fw/examples/aws_iot_smart_heater       # Go to the  example project

mos flash mos-esp8266                           # Install Mongoose OS
DEVICE_ID=$(mos config-get device.id)           # Get device ID
mos put init.js                                 # Copy init.js on the device
mos config-set aws.shadow.enable=true           # Enable AWS IoT shadow API
mos wifi WIFI_SSID WIFI_PASSWORD                # Setup WiFi
mos aws-iot-setup --aws-iot-policy=mos-default  # Provision on AWS IoT

npm --prefix ../helpers/cloudformation-helpers install ../helpers/cloudformation-helpers

# We'll also need to create a separate S3 bucket for helper functions:
aws s3 mb s3://my-cf-helpers

# Get the endpoint address for your AWS account, you'll need to provide it as
# a parameter for your stack:
AWS_IOT_ENDPOINT=$(aws iot describe-endpoint --output text)

# Now, "package" the template. Packaging includes copying source code of the
# helper functions from local machine to the s3 bucket we created above,
# and adjusting the template appropriately. It's all done in one step:
aws cloudformation package \
    --template-file aws_iot_heater_template.yaml \
    --s3-bucket my-cf-helpers \
    --output-template-file packaged_template.yaml

# Generate Oauth IDs on Google and Facebook
GOOGLE_CLIENT_ID=YOUR_GOOGLE_CLIENT_ID
FACEBOOK_CLIENT_ID=$YOUR_FACEBOOK_CLIENT_ID

STACK_NAME=my-heater

# The command above has created a new template file: packaged-template.yaml.
# Now, instantiate AWS stack using this template. Feel free to choose another
# stack name.
aws cloudformation create-stack \
    --stack-name $STACK_NAME \
    --parameters \
        ParameterKey=DeviceID,ParameterValue=$DEVICE_ID \
        ParameterKey=EndpointAddress,ParameterValue=$AWS_IOT_ENDPOINT \
        ParameterKey=GoogleClientID,ParameterValue=$GOOGLE_CLIENT_ID \
        ParameterKey=FacebookClientID,ParameterValue=$FACEBOOK_CLIENT_ID \
    --capabilities CAPABILITY_IAM \
    --template-body file://packaged_template.yaml

# Wait until the stack creation is completed (it may take a few minutes).
aws cloudformation wait stack-create-complete --stack-name my-heater

# Alternatively, you can use the web UI to check the status and read event
# details: https://console.aws.amazon.com/cloudformation/home

# When the stack is created, get the name of the created S3 bucket:
aws cloudformation describe-stacks --stack-name $STACK_NAME

# look for the following:
#  ...
#  {
#      "Description": "Name of the newly created S3 bucket", 
#      "OutputKey": "S3BucketName", 
#      "OutputValue": "S3_BUCKET_NAME"
#  },
#  {
#      "Description": "URL of the s3 bucket", 
#      "OutputKey": "S3BucketWebsite", 
#      "OutputValue": "APP_URL"
#  }
#  ...

S3_BUCKET_NAME=GENERATED_S3_BUCKET_NAME
APP_URL=GENERATED_APP_URL
# $S3_BUCKET_NAME is the name of the bucket, and $APP_URL is the URL...
Read more »