Skip to content

How to Connect NodeMCU to AWS IoT Core

send data from nodemcu to AWS IoT Core

This post is part three in a three part series of steps to connect Connect NodeMCU to AWS IoT Core. In the last two post we did the following:

  1. Created a “Thing” in AWS IoT and generated the certificates.
  2. Converted the certificates and keys to .der format

Now we are ready to configure and program the NodeMCU. There are two parts in this:

  1. Upload the certificates and keys in NodeMCU flash memory
  2. Program the NodeMCU

Upload the certificates and keys in NodeMCU SPIFFS memory:

Did you know each ESP8266 allows you to partition the system flash such that you can use it to store both code and support a file system?

This filing system can be used to store infrequently changing data such as; web pages, configurations, sensor calibration data, certificates, etc. Of course, we can do without this step but then we would have to copy the certificates in our code. That will make the certificates a part of every code version and increase the size as well. Instead, we will put the certificates ‘as is’ into the memory and read the certificates in our code.

It has another benefit. The certificates and the code are independent. Changing one does not require us to change another.

To upload the certificates and key to NodeMCU, we will use the ESP8266 sketch data upload tool. The steps to do that are discussed in details in the following articles:

Upload Files to ESP8266 SPIFFS

The above post uses a file called “config.txt” as example. Follow the steps but instead of the config.txt file, place the three .der files created in the previous step.

If you are interested to learn more about how to use the SPIFFS, you can refer to the following post:

The ESP8266 SPIFFS File System – Complete Beginner Guide

We have now successfully uploaded the certificates and the key to the NodeMCU. We will now dive into the program.

Connect NodeMCU to AWS IoT Core to send Data:

We will try sending the following message from the NodeMCU:

{

      "Message" : "Hello from NerdyElectronics.com" - 0

}

The zero in the end of the message is actually a count variable and we will update the count every time we send the message. We will send the message at every 5 seconds. So, we should receive the messages with the values 0-1-2-3…

We will need three information to edit in the program:

  1. The Wifi SSID or name
  2. The Wifi password
  3. The AWS endpoint of the thing which we created

To retrieve the AWS endpoint, login into the AWS Console and open the IoT core Services. In the AWS IoT screen, click on Manage > Things from the left navigation panel. Open the thing that you created and select “Interact“. There you can see the endpoint.

AWS Iot Thing endpoint API

Program to Connect NodeMCU to AWS IoT Core and send data:

/******************************************************************************************
Connect NodeMCU to AWS IoT Core.
Publish Messages from NodeMCU to the Core
   
Tutorial by https://nerdyelectronics.com :
1)  AWS IoT - Create a Thing
    https://nerdyelectronics.com/iot/how-to-create-a-thing-in-aws-iot/ :
2)  Convert Certificates from .pem to .der format
    https://nerdyelectronics.com/iot/how-to-convert-certificates-from-pem-to-der-format/ :
3)  Connect NodeMCU to AWS IoT Core
    https://nerdyelectronics.com/iot/how-to-connect-nodemcu-to-aws-iot-core/ :
  
*********************************************************************************************/
   
#include "FS.h"
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
   
// Update these with values suitable for your network.
   
const char* ssid = "XXXXXXXXX";   //Edit this line and put in your Wifi Name
const char* password = "XXXXXXXXXXXXXX";   //Edit this line and put in your Wifi Password
int count = 0;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");
   
const char* AWS_endpoint = "XXXXXXXXXXX-ats.iot.us-east-2.amazonaws.com"; // Edit your AWS Endpoint here
  
void callback(char* topic, byte* payload, unsigned int length) 
{
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < 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];  //buffer to hold the message to be published
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 with your uploaded file name
  if (!cert) 
  {
    Serial.println("Failed to open cert file");
  }
  else
    Serial.println("Successfully opened cert file");
  
  delay(1000);
  
  if (espClient.loadCertificate(cert)) // add the thing certificate to the client
    Serial.println("cert loaded");
  else
    Serial.println("cert not loaded");
  
  // Load private key file
  File private_key = SPIFFS.open("/private.der", "r"); //replace private with your uploaded file name
  if (!private_key) 
  {
    Serial.println("Failed to open private cert file");
  }
  else
    Serial.println("Successfully opened private cert file");
  
  delay(1000);
  
  if (espClient.loadPrivateKey(private_key))  // add the private key to the client
    Serial.println("private key loaded");
  else
    Serial.println("private key not loaded");
  
  // Load CA file
  File ca = SPIFFS.open("/ca.der", "r"); //replace ca with your uploaded file name
  if (!ca) 
  {
    Serial.println("Failed to open ca ");
  }
  else
    Serial.println("Successfully opened open ca");
  
  delay(1000);
  
  if (espClient.loadCACert(ca))   // add the AWS root certificate to the client
    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 > 5000) 
  {
    lastMsg = now;
    count++;
    //create the message to be sent
    snprintf (msg, 75, "{\"Message\": \"Hello from NerdyElectronics.com\" - %d}", count); 
    Serial.print("Publish message: ");
    Serial.println(msg);
  
    // publish messages to the topic "outTopic"
    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
}

You can download the code from here.

Do make sure to update the following lines:

  1. Line number 23const char* ssid = "XXXXXXXXX"; – Add your Wifi Name here
  2. Line number 24const char* password = "XXXXXXXXXXXXXx" Add your Wifi password here
  3. Line number 29const char* AWS_endpoint = "XXXXXXXXXXX-ats.iot.us-east-2.amazonaws.com"; Add your AWS Endpoint here.
  4. Line number 193snprintf (msg, 75, "{\"Message\": \"Hello from NerdyElectronics.com\" - %d}", count); This is the line where we create the message which we want to send.
  5. Line number 198client.publish("outTopic", msg); – In this line we publish the message we created in line 193. We publish it to the topic “outTopic”. If you want to publish the message to some other topic, edit the topic name here.

Check received messages in AWS IoT – Subscribe to Topic

So, we have started transmitting. Let us now check in the AWS IoT Core if we are receiving them.

In the AWS IoT Core screen, click on “Test” in the left Navigation panel. Then click on “Subscribe to a topic“. Add the topic name “outTopic” or the topic name that you have mentioned and click on “Subscribe to topic

AWS IoT subscribe to Topic

We should start seeing the messages sent by our NodeMCU in AWS now.

AWS IoT message received

Send Message from AWS IoT – Publish to Topic

We will now send messages from AWS IoT console to our NodeMCU

In the AWS IoT “Test” where we subscribed to topic, click on “Publish to a topic“. Add the topic name “inTopic“. This is the topic which the NodeMCU subscribes to.

client.subscribe("inTopic");

AWS IoT Publish to Topic

 

Now, when you click on “Publish to topic“, we can see the message in the the Arduino Serial Monitor:

message received by nodemcu from AWS IoT Publish

That’s it. We have successfully communicated with AWS.

I hope you have enjoyed doing this. Please do let me know in the comments what you think.

3 thoughts on “How to Connect NodeMCU to AWS IoT Core”

Leave a Reply

Your email address will not be published. Required fields are marked *