AWS IoT for ESP32 v1.0.0
An ESP-IDF based solution
AWS IoT for ESP32


The solution is built on top of the ESP-IDF framework. The AWS IoT solution is provided as a library as a set of non-blocking APIs to the application layer.

The below image represents the layered design.


  1. AWS IoT Device provisioning using claim certificates
  2. AWS IoT MQTT Data Ingest
  3. OTA with AWS Jobs using https
  4. Device configuration using JSON with BLE
  5. Non-blocking APIs


Lib System


The lib_system module initializes the system and puts the system in one of the following mode based on device configuration.

  1. Init mode: The device will perform the system initialization in this state. In case the device is not provisioned, it enters the Device Configuration mode or runs the user application.
  2. Idle mode: In this mode the device will not run user application and will continue to remain in Idle state unless it is reset. The device will enter into this mode when system initialization fails.
  3. Configuration mode: If the device is not provisioned then the system enters into configuration mode and awaits for WiFi Credentials, AWS IoT endpoint and Certificates. The device should be configured using BLE.
  4. Normal mode: If the device is already provisioned with thing certificate then it enters normal mode. The user application runs in this mode. The system library handles most of AWS IoT processing overhead and also system events. Some of the operations are listed below.
    • Flash storage operations.
    • Handles AWS IoT operations, like:
      • Publish and Subscribe.
      • Shadow updates.
      • Device jobs.
    • Accepts and manages OTA firmware update requests.
  5. OTA mode: This state takes care of remotely updating the device by receiving the new firmware from the cloud. Device will store the new firmware to the next OTA partition. After successful update, it will reboot from new partition. In case of interruption (WiFi disconnection, file download fail, timeout, or flash write fail), it will discard the OTA process and reboot from the current partition. Refer to the ESP-IDF's official OTA documentation for more details.

The system library callbacks application handler to notify the application about system events such as connection & disconnection events. It also ensures that all pending flash operations are performed before executing system reset.

Following libraries gets initialized when SYSTEM_init() function is called.

  • lib_events
  • lib_flash
  • lib_wifi
  • lib_aws
  • lib_ble
  • lib_ota

System state machine

The below image represents the system state machine.



The lib_aws module connects the device to AWS IoT. It provides simple MQTT APIs to send and receive messages using simple publish and subscribe APIs and callbacks. The communication between the device and AWS is secure by TLS v1.2, and authentication with AWS IoT requires X.509 thing certificates. Without unique thing certificate the device cannot authenticate and connect with AWS IoT.

When the device is provisioned with thing certificates it can authenticate and connect with AWS. If the device is not provisioned then the library can provision it.

AWS provides several ways to provision a device and install unique client certificates on it. This library implements Device Provisioning by Claim process. The provisioning process requires a claim certificate that allows the device to connect with AWS to only generate and install a new thing certificate for the device. This provisioning check and provisioning process happens during the AWS_init call.

The library provides APIs for registering application callbacks to handle AWS IoT Shadow updates and AWS IoT Jobs. When a new message is received on a subscribed topic the message gets pushed into a ring buffer. The application must read the ring buffer to process the received message.

Provisioning methods

There are three ways by which the device can use thing certificates using this library.

  1. Using claim certificates.

    The device by itself will acquire thing certificates from AWS & register as a thing on AWS IoT device registry (provision by claim) for the first time. Then it re-uses those thing certificates for subsequent connections. If you choose this method then you should configure claim certificates in the s_sysConfig variable.

    sample configuration:

    extern const uint8_t aws_root_ca_pem_start[] asm("_binary_aws_root_ca_pem_start");
    extern const uint8_t claim_certificate_pem_crt_start[] asm("_binary_claim_certificate_pem_crt_start");
    extern const uint8_t claim_private_pem_key_start[] asm("_binary_claim_private_pem_key_start");
    systemInitConfig_st s_sysConfig = {
    .pWifiSsid = <your wifi ssid>,
    .pWifiPwd = <your wifi password>,
    .awsConfig = {
    .pHostNameStr = <your aws iot endpoint>,
    .pClaimTemplateStr = <your provisioning template name>,
    .port_u16 = 8883,
    .pRootCaStr = (char *)aws_root_ca_pem_start,
    .pCaimCertStr = (char *)claim_certificate_pem_crt_start,
    .pClaimPrivateKeyStr = (char *)claim_private_pem_key_start
    System configuration structure. The application should define the system configuration variable and c...
    Definition: lib_system.h:72
  2. Using thing certificates.

    This means that you already have thing certificates for your device and you just want to use them instead of running provision by claim process on device. If you choose this method then you should configure thing certificates in the s_sysConfig variable instead of claim certificates.

    sample configuration:

    extern const uint8_t aws_root_ca_pem_start[] asm("_binary_aws_root_ca_pem_start");
    extern const uint8_t thing_certificate_pem_crt_start[] asm("_binary_thing_certificate_pem_crt_start");
    extern const uint8_t thing_private_pem_key_start[] asm("_binary_thing_private_pem_key_start");
    systemInitConfig_st s_sysConfig = {
    .pWifiSsid = <your wifi ssid>,
    .pWifiPwd = <your wifi password>,
    .awsConfig = {
    .pThingNameStr = <your thing name>,
    .pHostNameStr = <your aws iot endpoint>,
    .port_u16 = 8883,
    .pRootCaStr = (char *)aws_root_ca_pem_start,
    .pThingCertStr = (char *)thing_certificate_pem_crt_start,
    .pThingPrivateKeyStr = (char *)thing_private_pem_key_start
  3. Using thing certificates, received as device configuration from the BLE application.


The flowchart below serves as a reference from the application developer’s perspective.



To update the device firmware an AWS IoT Job for firmware update (Job) must be created. This job consists of a job document which contains an https download link to the firmware file.

The firmware update job must be created from the AWS IoT dashboard and must specify the target device or device group. Once the job is created, the device gets notified and requests for the job document. It then parses the job document to retrieve the download link and puts the system in the OTA mode and firmware update process starts running.

OTA state machine

The below image represents the state machine transitions during the OTA process within the ota library.

Lib Flash


For storing data from application we have assigned 256 bytes of non-volatile storage of the flash memory. This flash library is initialized during SYSTEM_init() call.

The system library handles flash operations in an asynchronous way. On calling system reset API, the system library ensures that all pending flash operations are performed before executing system reset. To restart a device always use the SYSTEM_restart API.




The table below lists services and its characterisitcs offered by BLE library.

Services Characteristics UUID Permissions
Service 1
UUID: 5704246a-5d4c-4f19-9b53-157d8824063d
Char 1 15ba8b82-df9a-46dc-865a-177a17ad9035 Read, Write, Notify
Char 2 20a62cd0-93ba-41e2-96b0-31b1aa131909 Read, Write, Notify
Char 3 3a21768b-174a-41bc-8b25-b9c1ebfb7510 Read, Write, Notify
Char 4 43c5e37d-b664-4b4a-aa33-032bbaf7133f Read, Write, Notify

BLE State machine