Skip to content

scriptbuzz/aws-iot-esp32-arduino

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

70 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

aws-iot-esp32-arduino

License: MIT Platform: ESP32 Framework: Arduino Cloud: AWS IoT Core Protocol: MQTT Language: C++ Demo: YouTube

A complete, foundational solution for connecting an ESP32 to AWS IoT Core over secure MQTT — publishing live sensor data with NTP timestamps to the cloud and receiving LED control commands from AWS.


ESP32 to AWS IoT

Table of Contents


Overview

This project demonstrates two-way MQTT communication between an ESP32 microcontroller and AWS IoT Core:

Direction Topic Payload
ESP32 → AWS MQTT_PUB_TOPIC JSON with epoch timestamp + hall-effect sensor reading
AWS → ESP32 MQTT_SUB_TOPIC ON or OFF to control the built-in LED

The ESP32 connects to an NTP server to timestamp sensor readings, and controls a programmable LED (GPIO 13) based on commands received from the cloud.

This solution uses the Adafruit HUZZAH32 (WROOM32-based), but any generic ESP32 development board supported by the Arduino IDE will work.

ESP32 DevKit

Watch the final integration demo: youtu.be/6Ir94C9GlVk


Prerequisites

Requirement Details
AWS Account Needed to create an AWS IoT Thing, certificates, and policy
ESP32 board Adafruit HUZZAH32 or any Arduino-compatible ESP32 module
Arduino IDE With USB-serial driver for your specific ESP32 model
Sensors / Actuators This solution uses the ESP32's built-in hall-effect sensor and programmable LED

AWS IoT Configuration

1. Get your IoT Endpoint

  1. Sign in to the AWS IoT Console
  2. In the left nav, select Settings
  3. Copy the Device data endpoint — it will look like:
    xxxxxxxxxxxxxx.iot.us-east-1.amazonaws.com
    

2. Create an IoT Policy

  1. In the left nav, go to Security > Policies, then Create a policy
  2. Enter a name (e.g. esp32_iot_policy)
  3. Select Advanced mode and paste the policy below
  4. Click Create

Note: This policy grants broad permissions for prototyping. Restrict it to specific topics and actions before any production use.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:*",
      "Resource": "*"
    }
  ]
}

3. Create an IoT Thing & Certificates

  1. Go to Manage > All devices > Things > Create > Create a single thing

  2. Enter a Thing name — you'll use this in secrets.h as AWS_THINGNAME

  3. Click Next, then select Auto-generate a new certificate

  4. Download all four files:

    File Used for
    Device certificate (.crt) AWS_CRT in secrets.h
    Private key (.key) AWS_PRIVATE in secrets.h
    Public key (not needed in firmware)
    Amazon Root CA 1 Pre-filled in secrets.h
  5. Click Activate, then Attach Policy and select the policy you created

  6. Click Register Thing


Arduino IDE Setup

1. Install the IDE & Board Support

  1. Download and install the Arduino IDE

  2. Install the USB-serial driver for your ESP32 model

  3. Open Preferences and add the following URL to Additional Board Manager URLs:

    https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
    
    Arduino board manager URL setting
  4. Go to Tools > Board > Boards Manager, search esp32 (by Espressif Systems), and install

  5. Select Tools > Board > ESP32 Arduino > ESP32 Dev Module

    ESP32 board selection

2. Install Required Libraries

Go to Sketch > Include Library > Manage Libraries and install the following:

Library Author Purpose
ArduinoJson Benoit Blanchon Serialize sensor data to JSON
NTPClient Fabrice Weinberg Get real-time timestamps from NTP servers
arduino-mqtt Joel Gaehwiler Lightweight MQTT client

ArduinoJson library

NTPClient library

If a library isn't found in the manager, download the ZIP from its GitHub repo and use Sketch > Include Library > Add .ZIP File.

Add ZIP library


Firmware

Main Sketch (mbx-iot-esp32.ino)

Create a new sketch (File > New) and paste:

// updated: 9/26/2020 by MBX
#include "secrets.h"
#include <WiFiClientSecure.h>
#include <MQTTClient.h>
#include <ArduinoJson.h>
#include "WiFi.h"
#include <NTPClient.h>
#include <WiFiUdp.h>

#define LED_PIN 13

WiFiClientSecure iot = WiFiClientSecure();
MQTTClient client = MQTTClient(256);

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "north-america.pool.ntp.org");


void connectToWiFi()
{
  Serial.println("\nConnecting to Wi-Fi");

  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    delay(200);
    Serial.print("..");
  }

  Serial.println("\nSUCCESS: Connected to Wi-Fi");
  Serial.print("Wi-Fi SSID:  ");
  Serial.println(WIFI_SSID);
}

void connectToAWSIoT()
{
  Serial.print("\n\nConnecting to AWS IoT");

  iot.setCertificate(AWS_CRT);
  iot.setPrivateKey(AWS_PRIVATE);
  iot.setCACert(AWS_CA);

  client.begin(AWS_ENDPOINT, 8883, iot);
  client.onMessage(messageHandler);

  while (!client.connect(AWS_THINGNAME)) {
    Serial.print(".");
    delay(200);
  }

  if (!client.connected()) {
    Serial.println("\nERROR: AWS IoT Connection Timeout");
    return;
  }

  client.subscribe(MQTT_SUB_TOPIC);

  Serial.println("\nSUCCESS: AWS IoT Endpoint Connected\n");
  Serial.print("\nAWS IoT Publish Topic:  ");   Serial.println(MQTT_PUB_TOPIC);
  Serial.print("\nAWS IoT Subscribe Topic:  "); Serial.println(MQTT_SUB_TOPIC);
  Serial.print("\nAWS IoT Thing Name:  ");      Serial.println(AWS_THINGNAME);
  Serial.print("\nAWS IoT Endpoint:  ");        Serial.println(AWS_ENDPOINT);
  Serial.println("\n");
}

void publishPayload()
{
  StaticJsonDocument<200> doc;
  doc["time"]     = timeClient.getEpochTime();
  doc["sensor01"] = hallRead();
  char jsonBuffer[512];

  serializeJson(doc, jsonBuffer);
  Serial.println(jsonBuffer);
  client.publish(MQTT_PUB_TOPIC, jsonBuffer);
}

void messageHandler(String &topic, String &payload) {
  Serial.println("\nAWS incoming MQTT topic: " + topic);
  Serial.println("\nAWS incoming MQTT payload: " + payload);

  if (payload == "ON")  digitalWrite(LED_PIN, HIGH);
  if (payload == "OFF") digitalWrite(LED_PIN, LOW);
}

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
  delay(2000);

  connectToWiFi();
  connectToAWSIoT();
  timeClient.begin();
}

void loop() {
  timeClient.update();
  publishPayload();
  client.loop();
  delay(1000);
}

Secrets File (secrets.h)

Create a new tab in the sketch named secrets.h and paste:

#include <pgmspace.h>

// Generated by the AWS IoT service
#define AWS_THINGNAME "yourThingName"

// https://docs.aws.amazon.com/iot/latest/developerguide/topics.html
#define MQTT_PUB_TOPIC "yourPublishTopic"
#define MQTT_SUB_TOPIC "yourSubscribeTopic"

const char WIFI_SSID[]     = "YourSSID";
const char WIFI_PASSWORD[] = "YourSSIDpassword";
const char AWS_ENDPOINT[]  = "YourAWSIoTEndpoint-ats.iot.us-east-1.amazonaws.com";

// Insert IoT Device Certificate generated by the AWS IoT service
static const char AWS_CRT[] PROGMEM = R"KEY(
-----BEGIN CERTIFICATE-----
insert your device cert here
-----END CERTIFICATE-----
)KEY";

// Insert IoT Device Private Key generated by the AWS IoT service
static const char AWS_PRIVATE[] PROGMEM = R"KEY(
-----BEGIN RSA PRIVATE KEY-----
insert your device private key here
-----END RSA PRIVATE KEY-----
)KEY";

// Amazon Root CA 1
// https://docs.aws.amazon.com/iot/latest/developerguide/server-authentication.html
static const char AWS_CA[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
rqXRfboQnoZsG4q5WTP468SQvvG5
-----END CERTIFICATE-----
)EOF";

Configuration Checklist

Update secrets.h with values gathered during AWS setup:

  • WIFI_SSID and WIFI_PASSWORD
  • AWS_ENDPOINT (your device data endpoint)
  • AWS_THINGNAME (your IoT Thing name)
  • AWS_CRT (device certificate contents)
  • AWS_PRIVATE (private key contents)
  • MQTT_PUB_TOPIC and MQTT_SUB_TOPIC

Then:

  1. Connect your ESP32 to your workstation via USB
  2. Select the correct COM/serial port in the Arduino IDE
  3. Upload the sketch to your ESP32
  4. Open the Serial Monitor at 115200 baud and confirm WiFi + AWS connectivity

Testing MQTT Connectivity

  1. Open the AWS IoT Console and navigate to Test > MQTT test client

  2. Subscribe to your publish topic (MQTT_PUB_TOPIC) — you should see JSON payloads arriving every second:

    { "time": 1601234567, "sensor01": 42 }
  3. Publish to your subscribe topic (MQTT_SUB_TOPIC) with payload ON or OFF (uppercase)

    • The LED on your ESP32 should respond immediately
    • The command will also appear in the Arduino Serial Monitor

Summary & Next Steps

This solution gives you a secure, bidirectional MQTT link between an ESP32 and AWS IoT Core. With this foundation in place, you can extend it using the full AWS ecosystem:

AWS Service Use Case
DynamoDB / Timestream Archive sensor readings in a database
Lambda Trigger serverless actions on sensor thresholds
SNS / SES Send alerts when values exceed limits
QuickSight Visualize device data in real time
SageMaker Feed data into ML models for predictive maintenance
Greengrass Run edge compute logic on the device itself

References

Resource Link
Espressif ESP32 espressif.com
Arduino IDE arduino.cc
ArduinoJson github.com/bblanchon/ArduinoJson
arduino-mqtt github.com/256dpi/arduino-mqtt
NTPClient github.com/arduino-libraries/NTPClient
AWS IoT Core aws.amazon.com/iot
Adafruit HUZZAH32 adafruit.com/product/3405
SparkFun ESP32 Thing sparkfun.com/products/13907
Moheeb Zara's AWS IoT guide aws.amazon.com/blogs/compute/…
Gourav Das's guide hackernoon.com
Mudassar Tamboli's guide medium.com/@mudassar.tamboli/…

MIT License © 2020 Mike Bitar

About

This solution demonstrates how to integrate Espressif's ESP32 microcontroller with the AWS IoT ecosystem using MQTT as the pub/sub protocol to exchange messages/commands between the ESP32 and the IoT service.

Topics

Resources

License

Stars

Watchers

Forks

Contributors