How to connect NodeMCU ESP8266 with AWS IoT Core using Arduino IDE & MQTT
(Last Updated On: June 3, 2021)

Table of Contents:

Overview:

In this tutorial, I will tell you How to connect NodeMCU ESP8266 with AWS IoT Core using Arduino IDE and MQTT Protocol. In this process, we will see how to create a thing in AWS IoT core, generating certificates and policy, How all AWS IoT core credentials are converted to .der format and directly downloaded into the NodeMCU ESP8266 SPIFFS file system. We will be developing a sketch that will marry ESP8266 and AWS IoT Core using MQTT Protocol.
this sketch requires the certificate files to be uploaded to the device’s flash rather than storing them inline with the script. This allows the same script to be used by multiple devices, that each read the required files from their internal flash storage.

You can watch the following video or continue to the reading of the below-written article

 

Introduction to AWS IoT Core:

Internet of Things (IoT) is being integrated with almost every device nowadays. There is a number of hardware and software IoT platforms are available in the market for building IoT based application. In my previous article, I have explained how to interface DHT22 with NodeMCU and post the Temperature and Humidity to the Thingspeak webserver. Likewise, we can interface sensors to the hardware development kits like ESP32ESP8266Raspberry Pi, Particleboards( AargonBoronXenon) and post data to the clouds like ThingspeakUbidotsAWS IoT Core, Microsoft Azure.

Amazon is not only in e-commerce but also focusing on IoT and providing cloud-based service named as AWS IoT. Here, AWS IOT stands for Amazon Web Service Internet of Things. This service allows us to connect our devices to the internet for processing, operating and exchanging data securely. Along with AWS IoT, the Amazon Web Services also provides tons of other features like virtual machine deployment, web-hosting, etc.

I have also made a tutorial on Temperature Data record on AWS IoT Core with NodeMCU-ESP32 using Arduino IDE and MQTT Protocol. 

If you are working with ESP32 you can check it out.

Requirements for this Tutorial :

  1. NodeMCU-ESP8266     Buy from Amazon
  2. Data Cable                    Buy from Amazon
  3. An active account on Amazon Web Services(AWS).
  4. Arduino IDE installed on your computer with ESP8266 board configuration

Steps involved in this tutorial:

  1. Creating a Thing in the AWS, generating a certificate and attaching a policy to it.
  2. Converting AWS credential(Certificate, Private Key, Root CA) from .pem to .der format
  3. Installing ESP8266 sketch data upload tool in Arduino IDE
  4. Arduino sketch and modifications according to the thing.
  5. Uploading AWS certificates & code to the NodeMCU ESP8266
  6. Testing/Subscription of thing on Amazon Web Services(AWS).
  7. Results& Data Logging.
1. Creating a Thing in the AWS IoT Core, generating a certificate and attaching a policy to it.

Check the following tutorial for step by step Explanation: How to create a thing in AWS IoT Core, its Certificates & policies

Setting up the AWS environment for these devices is pretty simple. check the following: Amazon AWS
and login to the AWS Management Console & search for IoT core in the Amazon Services, Find services search bar will help you in this regard. After getting into the IoT Core section, tap on the tab called “Manage” from the AWS IoT menu which is on the left side, tap on the register thing button if you haven’t added any devices till now. If you have previously added things just tap on the button named “Create” which is on the top right corner beside the iot-notifications Icon.

AWS IoT core Register ThingPicture: AWS IoT core Register Thing

Opt to create a single thing and Give your thing name, scroll down and tap on the Next button and then you are immediately offered the one-click certificate generation option. An individual X.509 certificate per device is the recommended way of interacting with AWS IoT services from devices, offering the ability to burn the private key into the device upon enrolment that is then never transferred across the internet alongside requests, a security win. Download the certificate and private key for each device, and also a root CA. Make sure to hit that activate button so the certificate can be used. finish the process by clicking on the “Done” button. If you need any assistance in this regard you can check the video tutorial.

AWS IoT core Certificates downloadPicture: AWS IoT core Certificates download tab

Next point is to create and attach a policy to the certificate, authorizing the authenticated device to perform IoT actions on IoT resources. for this tap on the “secure” tab from the AWS IoT menu which is on the left side, later go for the policies section. Now tap on the button named “Create” which is on the top right corner beside the iot-notifications Icon. give your policy name and fill the fields(Action, Resource ARN ) with a star “*” and check to Allow for Effect option then press the “create” button. 

Now tap on the certificates section which is right above the policies section, You will see a certificate which you have created earlier, tap on the three dots and choose to attach the policy, a pop will come showing your existing policies, check on the recent policy that you have created and attach. That’s it you have successfully created a thing, generated a certificate and attached policy to it.

2.Converting AWS IoT Core credential(Certificate, Private Key, Root CA) from .pem to .der format

There are two main methods for encoding certificate data.

  • DER = Binary encoding for certificate data
  • PEM = The base64 encoding of the DER-encoded certificate, with a header and footer lines added.
DER

DER: (Distinguished Encoding Rules) is a subset of BER encoding providing for exactly one way to encode an ASN.1 value. DER is intended for situations when a unique encoding is needed, such as in cryptography, and ensures that a data structure that needs to be digitally signed produces a unique serialized representation.

PEM

PEM: (Privacy-enhanced Electronic Mail) Simply a US-ASCII by base64 encoded DER certificate, certificate request, or PKCS#7, enclosed between typical PEM delimiters. ie “—–BEGIN CERTIFICATE—–” and “—–END CERTIFICATE—–“. PEM is an abbreviation for Privacy Enhanced Mail (RFC 1421 – RFC 1424), an early standard for securing electronic mail (IRTF, IETF). PEM never has been widely adopted as Internet Mail Standard but has become a staple standard in x509 pki (also called pkix)

Since our ESP8266 will not understand base64 encoding we will convert that certificate to Binary

Installing OpenSSL

The first thing to do is to make sure your system has OpenSSL installed: this is a tool that provides an open-source implementation of SSL and TLS protocols and that can be used to convert the certificate files into the most popular X.509 v3 based formats. here we will use it to convert the .pem files to .DER.

OpenSSL on Linux

If you’re using Linux, you can install OpenSSL with the following YUM console command:

If your distribution is based on APT instead of YUM, you can use the following command instead:

OpenSSL on Windows

If you’re using Windows, you can install one of the many OpenSSL open-source implementations: the one we can recommend is Win32 OpenSSL by Shining Light Production, available as light or full version, both compiled in x86 (32-bit) and x64 (64-bit) modes. You can install any of these versions, as long as your system supports them.

IMPORTANT: OpenSSL for Windows requires the Visual C++ 2008 Redistributables runtime in order to work.

OpenSSL is basically a console application, meaning that we’ll use it from the command-line: after the installation process completes, it’s important to check that the installation folder (C:\Program Files\OpenSSL-Win64\bin for the 64-bit version) has been added to the system PATH (Control Panel > SystemAdvanced Environment Variables): if it’s not the case, we strongly recommend to manually add it, so that you can avoid typing the complete path of the executable every time you’ll need to launch the tool.

Once OpenSSL will be installed, we’ll be able to use it to convert our SSL Certificates in various formats.

Now go to the folder where all the certificates are downloaded, The AWS certificate will be something like this “xxxxxxxxxx-certificate.pem.crt.txt” So now just rename that document to “xxxxxxxxxx-certificate.pem.crt”.

The following commands will convert the downloaded device certificate files to the correct format for this script.

> openssl x509 -in xxxxxxxxxx-certificate.pem.crt -out cert.der -outform DER 
> openssl rsa -in xxxxxxxxxx-private.pem.key -out private.der -outform DER
> openssl x509 -in AmazonRootCA1.pem -out ca.der -outform DER

Replace “xxxxxxxxxx” with your certificate name and AmazonRootCA1 will remain the same because there is no change

Example:

> openssl x509 -in 2b495edf21-certificate.pem.crt -out cert.der -outform DER 
> openssl rsa -in 2b495edf21-private.pem.key -out private.der -outform DER
> openssl x509 -in AmazonRootCA1.pem -out ca.der -outform DER

After executing these commands, you will see certificates save in the same folder with .der format, copy these DER-format files into a folder called data

3.Installing ESP8266 sketch data upload tool in Arduino IDE

Before going to ESP8266 sketch data upload tool make sure, your machine has the latest Arduino IDE installed locally, with the ESP8266 plugin installed. If you don’t know how to install ESP8266 plugin,
check out this article: NodeMCU programming with Arduino.

Now Let’s install Arduino ESP8266 filesystem uploader which packs the sketch data folder into the SPIFFS filesystem image, and uploads the image to ESP8266 flash memory.

  • Download the tool archive”ESP8266FS-0.4.0.zip” from the Git hub releases page.
  • In your Arduino sketchbook directory, create tools directory if it doesn’t exist yet. You can find the location of your sketchbook directory in the Arduino IDE at File > Preferences > Sketchbook location.
  • Unpack the tool into tools directory (the path will look like <sketchbook directory>/tools/ESP8266FS/tool/esp8266fs.jar).
  • Restart Arduino IDE.
  • Select “tools  > ESP8266 Sketch Data Upload” will be there.

Credits for this tool: Hristo Gochkov.

4.Arduino sketch and modifications according to the thing.

The following connects your NodeMCU ESP8266 to AWS IoT server then:
– publishes “hello world” to the topic “outTopic” every two seconds to the server.
– subscribes to the topic “inTopic”, printing out any messages that are coming from the server.

Open a new sketch file of Arduino IDE,  Copy & Paste the below code into that and save with some file name. i.e “ESP8266_AWS_IoTCore”

You have to make sure that the WiFi username and password are provided which is available in the range.

const char* ssid = "Electronics_Innovation";
const char* password = "subscribe";

Also, change the AWS_endpoint which is the address of the MQTT broker for your AWS account in a specific region.

const char* AWS_endpoint = "xxxxxxxxxxxxxx-ats.iot.us-west-2.amazonaws.com"; //MQTT broker ip

This AWS_endpoint can be found in the Custom Endpoint section of the Interact tab of your registered things. as shown below.

AWS_EndpointPicture: AWS End Point/ MQTT Broker IP

Make sure files name in the Sketch are matching with the names of your actual certificates in the data folder.

line no: 126> File cert = SPIFFS.open("/cert.der", "r"); //replace cert.crt eith your uploaded file name
line no:141 > File private_key = SPIFFS.open("/private.der", "r"); //replace private eith your uploaded file name
line no:158 > File ca = SPIFFS.open("/ca.der", "r"); //replace ca eith your uploaded file name

We are using the below code to publish “hello world” to the topic “outTopic” every two seconds to the server.
If you want to change the message you can change here. or if you want some sensor data your accommodate the sensor code here.

 long now = millis();
if (now - lastMsg > 2000) {
lastMsg = now;
++value;
snprintf (msg, 75, "{\"message\": \"hello world #%ld\"}", value);
Serial.print("Publish message: ");
Serial.println(msg);
client.publish("outTopic", msg);
Serial.print("Heap: "); Serial.println(ESP.getFreeHeap()); //Low heap can cause problems
}

Source Code & Program

/*Developed by M V Subrahmanyam - https://www.linkedin.com/in/veera-subrahmanyam-mediboina-b63997145/
Project: AWS | NodeMCU ESP32 Tutorials
Electronics Innovation - www.electronicsinnovation.com

GitHub - https://github.com/VeeruSubbuAmi
YouTube - http://bit.ly/Electronics_Innovation

Upload date: 07 October 2019

AWS Iot Core

This example needs https://github.com/esp8266/arduino-esp8266fs-plugin

It connects to AWS IoT server then:
- publishes "hello world" to the topic "outTopic" every two seconds
- subscribes to the topic "inTopic", printing out any messages
*/

#include "FS.h"
#include &lt;ESP8266WiFi.h&gt;
#include &lt;PubSubClient.h&gt;
#include &lt;NTPClient.h&gt;
#include &lt;WiFiUdp.h&gt;

// Update these with values suitable for your network.

const char* ssid = "Electronics_Innovation";
const char* password = "subscribe";

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

const char* AWS_endpoint = "xxxxxxxxxxxxxx-ats.iot.us-west-2.amazonaws.com"; //MQTT broker ip

void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i &lt; length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();

}
WiFiClientSecure espClient;
PubSubClient client(AWS_endpoint, 8883, callback, espClient); //set MQTT port number to 8883 as per //standard
long lastMsg = 0;
char msg[50];
int value = 0;

void setup_wifi() {

delay(10);
// We start by connecting to a WiFi network
espClient.setBufferSizes(512, 512);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

timeClient.begin();
while(!timeClient.update()){
timeClient.forceUpdate();
}

espClient.setX509Time(timeClient.getEpochTime());

}

void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("ESPthing")) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish("outTopic", "hello world");
// ... and resubscribe
client.subscribe("inTopic");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");

char buf[256];
espClient.getLastSSLError(buf,256);
Serial.print("WiFiClientSecure SSL error: ");
Serial.println(buf);

// Wait 5 seconds before retrying
delay(5000);
}
}
}

void setup() {

Serial.begin(115200);
Serial.setDebugOutput(true);
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
setup_wifi();
delay(1000);
if (!SPIFFS.begin()) {
Serial.println("Failed to mount file system");
return;
}

Serial.print("Heap: "); Serial.println(ESP.getFreeHeap());

// Load certificate file
File cert = SPIFFS.open("/cert.der", "r"); //replace cert.crt eith your uploaded file name
if (!cert) {
Serial.println("Failed to open cert file");
}
else
Serial.println("Success to open cert file");

delay(1000);

if (espClient.loadCertificate(cert))
Serial.println("cert loaded");
else
Serial.println("cert not loaded");

// Load private key file
File private_key = SPIFFS.open("/private.der", "r"); //replace private eith your uploaded file name
if (!private_key) {
Serial.println("Failed to open private cert file");
}
else
Serial.println("Success to open private cert file");

delay(1000);

if (espClient.loadPrivateKey(private_key))
Serial.println("private key loaded");
else
Serial.println("private key not loaded");

// Load CA file
File ca = SPIFFS.open("/ca.der", "r"); //replace ca eith your uploaded file name
if (!ca) {
Serial.println("Failed to open ca ");
}
else
Serial.println("Success to open ca");

delay(1000);

if(espClient.loadCACert(ca))
Serial.println("ca loaded");
else
Serial.println("ca failed");

Serial.print("Heap: "); Serial.println(ESP.getFreeHeap());
}

void loop() {

if (!client.connected()) {
reconnect();
}
client.loop();

long now = millis();
if (now - lastMsg &gt; 2000) {
lastMsg = now;
++value;
snprintf (msg, 75, "{\"message\": \"hello world #%ld\"}", value);
Serial.print("Publish message: ");
Serial.println(msg);
client.publish("outTopic", msg);
Serial.print("Heap: "); Serial.println(ESP.getFreeHeap()); //Low heap can cause problems
}
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(100); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(100); // wait for a second
}

 

5.Uploading AWS certificates & code to the NodeMCU ESP8266

Make sure that folder data should sit alongside with your Arduino code as shown below, for that you can move data folder into the Arduino code Folder.

AWS IoT core

Now open your Arduino code for ESP8266 and Select Tools > ESP8266 Sketch Data Upload menu item. This should start uploading the files into the ESP8266 flash file system. When done, the IDE status bar will display the SPIFFS Image Uploaded message. It might take a few minutes for large file system sizes.

Note: Make sure you have selected a board, port, and closed Serial Monitor.

Arduino ESP8266 filesystem uploaderPicture: Arduino ESP8266 filesystem uploader

  • To save time while uploading to these devices (both code and especially SPIFFS), set the upload baud rate as high as does not produce errors. That was 921600 for my devices, up from the default of 115200, saving a lot of time while iterating.
  • If you get errors when trying to upload the certificates to the device flash, you may not have SPIFFS enabled from the Arduino > Tools menu. Any of the SPIFFS storage size values will work, the certificates take up significantly less than 1 MB. All my devices had 4 MB of flash. If you ever change the board type then this setting is lost; I wiped my certificates several times while re-uploading code while I hadn’t noticed this, resulting in connection errors.

ESP8266 SPIFFS storage size valuesfor AWS IoT corePicture: ESP8266 SPIFFS storage size values for AWS IoT core Certificates

Once the Certificates are uploaded successfully, Now go for uploading of the Arduino sketch “ESP8266_AWS_IoTCore” the NodeMCU board by clicking on the upload button of Arduino IDE.

Once the script is uploaded you can view the output on the Serial Monitor. For debugging any potential issues with the certificates and policies, I used the command on this page. This checks the chain of trust between the client certificate and root CA, and checks that a TLS connection can be established. Potential issues could arise from the certificate not being activated in the AWS Console, or the device clock not having synced with the NTP server which prevents certificate validation.

6.Testing/Subscription of thing on Amazon Web Services(AWS IoT Core).

It’s time to get back to the AWS IoT Core and subscribe or the topic.
This Subscription topic bar can be found in the MQTT client section of the Test tab of your AWS IoT column. Just type outTopic and push subscribe to topic button as shown below.

AWS IoT core MQTT Client subscriptionPicture: AWS IoT core MQTT Client subscription

7.Results& Data Logging.

Hopefully, your device is now connected to your WiFi network, has authenticated itself with AWS, has the permissions to connect and publish to an IoT topic, and you’re seeing messages in MQTT client like this.

How to connect NodeMCU ESP8266 with AWS IoT Core using Arduino IDE & MQTTPicture: Final output of How to connect NodeMCU ESP8266 with AWS IoT Core using Arduino IDE & MQTT

You can follow the video to understand the whole process like how to create a thing in AWS IoT core, generating certificates and policy, How all AWS IoT core credentials are converted to .der format and directly downloaded into the NodeMCU ESP8266 SPIFFS file system.

Video Tutorial: Connecting NodeMCU with AWS IoT Core using Arduino IDE.

By Veeru

31 thoughts on “How to connect NodeMCU ESP8266 with AWS IoT Core using Arduino IDE & MQTT”
  1. Hi, Thanks for the wonderful tutorial. It was really helpful. I would like to know, how to create a permanent topic instead of a test in AWS IoT Core. Can you explain that part as well.

  2. Hi I could really do with your help . I am trying to get this to run on arduino 1.8.10.
    I can connect when I run and openssl connection string using my original certificates. This seems to indicate that certificates are happy.
    My DER files load fine too…..but it simply wont connect to MQTT on AWS end point. Get the error:
    cert loaded
    09:13:44.841 -> Success to open private cert file
    09:13:45.903 -> private key loaded
    09:13:45.936 -> Success to open ca
    09:13:46.966 -> ca loaded
    09:13:46.966 -> Heap: 38184
    09:13:46.966 -> b4:e6:2d:6d:d5:5fAttempting MQTT connection…pm open,type:2 0
    09:14:11.366 -> failed, rc=-4 try again in 5 seconds
    09:14:11.366 -> WiFiClientSecure SSL error: Unknown error code.

    PS I have attempted this by disabling the my firewalls, but I get the same response

    PLEASE HELP

  3. Thank you so much for the post, In case of AWS Greengrass, which “AWS_endpoint” shall I use?

  4. Thanks a lot. Finally, I succeeded in connecting ESP8266 with AWS IoT.
    MQTT is working perfectly.”Hello World” message published by esp8266 can be seen on aws test topic “

  5. Hi, My ESP8266 is not able to connect and I am getting RC -2 error. Heap size before attempting to connect is around 40k. Can you please let me know the Heap Size of your device, maybe mine is the memory Ram Issue.

  6. 12:23:17.356 -> ………..ip:192.168.43.97,mask:255.255.255.0,gw:192.168.43.1
    12:23:22.855 -> .
    12:23:22.855 -> WiFi connected
    12:23:22.855 -> IP address:
    12:23:22.855 -> 192.168.43.97
    12:23:26.049 -> pm open,type:2 0
    12:23:48.901 -> Heap: 40736
    12:23:48.936 -> Failed to open cert file
    12:23:49.940 -> cert not loaded
    12:23:49.940 -> Failed to open private cert file
    12:23:50.940 -> private key not loaded
    12:23:50.976 -> Failed to open ca
    12:23:51.969 -> ca failed

    Sir, Please help me I am getting These Errors How can I fix these

  7. This worked just like a boss, thank a lot!
    But can we have a limit on action and resource of the policy? The asterisk is just everything!
    Thank in advance!

  8. I have successfully used nodemcu and dht22 displaying results to esp web page
    I am working towards a project I have for my invention: to add a movement sensor and create an App to display performance data.
    I am using a Mac and on a brief scan through there is no Mac option for SSL connections etc
    Have I missed something ?
    Your project could help me connect my ESP8266 nodemcu (12E) 1.0 to AWS IoT and then use it for any of my/your projects / examples ….

    Any help out there ?

    Thanks in advance
    Charles

  9. Attempting MQTT connection…failed, rc=-2 try again in 5 seconds
    WiFiClientSecure SSL error: Chain could not be linked to a trust anchor.

  10. After using this command:

    openssl x509 -in xxxxxxxxxx-certificate.pem.crt -out cert.der -outform DER

    I’m getting below error:

    26024:error:2006D080:BIO routines:BIO_new_file:no such file:crypto\bio\bss_file.c:76:

    Unable to load certificate

    Pls help me with this!!

  11. Hi All,

    I keep getting:

    dhcp client start…
    ….ip:192.168.86.135,mask:255.255.255.0,gw:192.168.86.1
    .
    WiFi connected
    IP address:
    192.168.86.135
    Heap: 41632
    Success to open cert file
    cert loaded
    Success to open private cert file
    private key loaded
    Success to open ca
    ca loaded
    Heap: 38016
    Attempting MQTT connection…pm open,type:2 0
    11:41:10.892 -> failed, rc=-4 try again in 5 seconds
    11:41:10.892 -> WiFiClientSecure SSL error: Unknown error code.

    Has anyone resolved this ? Would greatly appreciate your help.

    Thanx,

    ramesh.

  12. I was able to get the DER’s uploaded, thank you. When I run the code in the IDE, I get the error ‘class BearSSL::WiFiClientSecure’ has no member named ‘loadCertificate’. I am new to ARduino and AWS so any pointers would be apreciated. Thank you

  13. The code failed to compile. getting error as below: please guide.
    In file included from C:\Users\user\Documents\Arduino\libraries\AWS_IOT\src\network_interface.h:35,
    from C:\Users\user\Documents\Arduino\libraries\AWS_IOT\src\aws_iot_mqtt_client.h:57,
    from C:\Users\user\Documents\Arduino\libraries\AWS_IOT\src\AWS_IOT.cpp:39:
    C:\Users\user\Documents\Arduino\libraries\AWS_IOT\src\network_platform.h:25:10: fatal error: mbedtls/platform.h: No such file or directory
    25 | #include “mbedtls/platform.h”
    | ^~~~~~~~~~~~~~~~~~~~
    compilation terminated.

    exit status 1
    Error compiling for board NodeMCU 1.0 (ESP-12E Module).

Leave a Reply