ESP32 Rest API Web Server GET and POST Examples with Postman API

In this tutorial, we will learn how to build a rest API web server using ESP32 that implements different REST APIs. We will create APIs that will be used to communicate with ESP32 using GET and POST requests. To send and receive data from ESP32 through REST APIs, we will use the postman application. Additionally, we will interface ESP32 with a BME280 sensor and an RGB LED. The ESP32 will acquire temperature, pressure, and humidity readings from the BME280 that we can get from ESP32 using an HTTP GET request. Whereas, we will use POST method to control the RGB LED. In summary, ESP32 rest API web server will present four different JSON based Rest APIs

  1. Temperature reading from BME280 (IP_address/temperature)
  2. Humidity reading from BME280 (IP_address/humidity)
  3. Pressure reading from BME280 (IP_address/pressure)
  4. Control RGB LED (IP_address/led)
ESP32 Rest API Web Server

We will require the following components for this project:

Required Components:

  • ESP32 development board
  • BME280 sensor
  • RGB LED
  • Connecting Wires
  • Breadboard

REST API Web Server ESP32 Circuit Diagram

In this section we will connect the ESP32 board with BME280 sensor and RGB LED to proceed with our project.

The connection of BME280 with the ESP32 board is very easy. We have to connect the VCC terminal with 3.3V, ground with the ground (common ground), SCL of the sensor with SCL of the module, and SDA of the sensor with the SDA pin of the ESP modules.

The I2C pin in ESP32 for SDA is GPIO21 and for SCL is GPIO22

BME280ESP32
VCC3.3V
GNDGND
SCLGPIO22
SDAGPIO21

ESP32 with RGB LED Module (Common Cathode)

We are using the common cathode RGB LED module for this project. The table below shows the connections we are using between the LED module and ESP32.

RGB LED ModuleESP32
RGPIO5
GGPIO18
BGPIO19
GND

The red, green, and blue pins of the RGB LED module will be connected with GPIO pins of ESP32 board. We will use GPIO, GPIO, and GPIO to connect with each colour pin. You can use any appropriate GPIO pin.

Schematic Diagram

Follow the schematic diagram below and connect the three devices accordingly.

All the connections between the devices are the same as we listed them in the tables above.

ESP32 with BME280 and RGB LED connection diagram
ESP32 with BME280 and RGB LED

You may like to read these BME280 tutorials:

Installing Required Libraries for ESP32 Rest API Web Server

Before we proceed further, you should make sure that you have the latest version of Arduino IDE installed on your system. Moreover, you should also install an ESP32 add-on in Arduino IDE. If your IDE does not have the plugin installed you can visit the link below:

Installing ESP32 library in Arduino IDE and upload code

Installing ArduinoJSON Library

You will have to install the ArduinoJSON library by Benoit Blanchon as we will be dealing with JSON script. Open your Arduino Library Manager by clicking Sketch > Include Library > Manage Libraries. Type ‘ArduinoJSON’ in the search tab and press enter. Install the library version 6.17.2 which is highlighted below.

Installing ArduinoJSON library version 6.17.2
ArduinoJSON library version 6.17.2

ESP32 Rest API Web Server Arduino Sketch

Our ESP32 (client) will make an HTTP GET request to the API server. As a response, we will receive a string consisting of the JSON object with details regarding the BME280 sensor data. Likewise, to control the RGB LED, the client will send a string consisting of JSON objects with details regarding the RGB values to ESP32.

Open your Arduino IDE and go to File > New to open a new file. Copy the code given below in that file. For this code to work with your ESP32 board you will have to replace the Wi-Fi network credentials.

#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>
#include <ArduinoJson.h>
#include <FreeRTOS.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

const char *SSID = "YOUR_SSID";
const char *PWD = "YOUR_PASSWORD";

const int red_pin = 5;   
const int green_pin = 18; 
const int blue_pin = 19; 

// Setting PWM frequency, channels and bit resolution
const int frequency = 5000;
const int redChannel = 0;
const int greenChannel = 1;
const int blueChannel = 2;
const int resolution = 8;

WebServer server(80);
 
Adafruit_BME280 bme;

StaticJsonDocument<250> jsonDocument;
char buffer[250];

float temperature;
float humidity;
float pressure;
 
void setup_routing() {     
  server.on("/temperature", getTemperature);     
  server.on("/pressure", getPressure);     
  server.on("/humidity", getHumidity);     
  server.on("/data", getData);     
  server.on("/led", HTTP_POST, handlePost);    
          
  server.begin();    
}
 
void create_json(char *tag, float value, char *unit) {  
  jsonDocument.clear();  
  jsonDocument["type"] = tag;
  jsonDocument["value"] = value;
  jsonDocument["unit"] = unit;
  serializeJson(jsonDocument, buffer);
}
 
void add_json_object(char *tag, float value, char *unit) {
  JsonObject obj = jsonDocument.createNestedObject();
  obj["type"] = tag;
  obj["value"] = value;
  obj["unit"] = unit; 
}

void read_sensor_data(void * parameter) {
   for (;;) {
     temperature = bme.readTemperature();
     humidity = bme.readHumidity();
     pressure = bme.readPressure() / 100;
     Serial.println("Read sensor data");
 
     vTaskDelay(60000 / portTICK_PERIOD_MS);
   }
}
 
void getTemperature() {
  Serial.println("Get temperature");
  create_json("temperature", temperature, "°C");
  server.send(200, "application/json", buffer);
}
 
void getHumidity() {
  Serial.println("Get humidity");
  create_json("humidity", humidity, "%");
  server.send(200, "application/json", buffer);
}
 
void getPressure() {
  Serial.println("Get pressure");
  create_json("pressure", pressure, "hPa");
  server.send(200, "application/json", buffer);
}
 
void getData() {
  Serial.println("Get BME280 Sensor Data");
  jsonDocument.clear();
  add_json_object("temperature", temperature, "°C");
  add_json_object("humidity", humidity, "%");
  add_json_object("pressure", pressure, "hPa");
  serializeJson(jsonDocument, buffer);
  server.send(200, "application/json", buffer);
}

void handlePost() {
  if (server.hasArg("plain") == false) {
  }
  String body = server.arg("plain");
  deserializeJson(jsonDocument, body);

  int red_value = jsonDocument["red"];
  int green_value = jsonDocument["green"];
  int blue_value = jsonDocument["blue"];

  ledcWrite(redChannel, red_value);
  ledcWrite(greenChannel,green_value);
  ledcWrite(blueChannel, blue_value);

  server.send(200, "application/json", "{}");
}

void setup_task() {    
  xTaskCreate(     
  read_sensor_data,      
  "Read sensor data",      
  1000,      
  NULL,      
  1,     
  NULL     
  );     
}

void setup() {     
  Serial.begin(115200); 

  ledcSetup(redChannel, frequency, resolution);
  ledcSetup(greenChannel, frequency, resolution);
  ledcSetup(blueChannel, frequency, resolution);
 
  ledcAttachPin(red_pin, redChannel);
  ledcAttachPin(green_pin, greenChannel);
  ledcAttachPin(blue_pin, blueChannel);
         
  if (!bme.begin(0x76)) {    
    Serial.println("BME280 not found! Check Circuit");    
  }    

  Serial.print("Connecting to Wi-Fi");
  WiFi.begin(SSID, PWD);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
 
  Serial.print("Connected! IP Address: ");
  Serial.println(WiFi.localIP());
  setup_task();    
  setup_routing();     
   
}    
       
void loop() {    
  server.handleClient();     
}

How does the Code Works?

Now, let us understand how each part of the code works.

Importing Libraries

Firstly, we will import the relevant libraries which are necessary for this project.
WiFi.h library is used to connect our ESP32 module with the local WIFI network. The Adafruit_Sensor and the Adafruit_BME280 libraries which we installed earlier are also included as they are necessary as we have to interface the sensor with the ESP32. The ArduinoJSON.h will be used for the JSON script.

#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>
#include <ArduinoJson.h>
#include <FreeRTOS.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

The WebServer object will be used to set up the ESP32 web server. We will pass the default HTTP port which is 80, as the input to the constructor. This will be the port where the server will listen to the requests.


WebServer server(80);

Then, we define the Adafruit_BME280 object named bme by setting it on the default I2C GPIO pins of ESP32.

Adafruit_BME280 bme;

The following three float variables will store the temperature, humidity and pressure readings acquired from the BME280 sensor.

float temperature;
float humidity;
float pressure;

RGB LED Parameters

The following lines specify the GPIO pins of ESP32 connected with each of the colour pins of the RGB LED. Here we are using the same GPIO pins as shown in the schematic diagram above. You can use any suitable output pin of ESP32.

const int red_pin = 5;   
const int green_pin = 18; 
const int blue_pin = 19; 

The following variables define the PWM frequency, channels and the bit resolution. The brightness of the LED will be controlled through the duty cycle. When we define the PWM parameters for each LED it includes the frequency of the signal, led channels and resolution. We have set the frequency at 5000 Hz. For defining the PWM channel we can choose between a total of sixteen PWM channels in ESP32. You can use any channel from 0-15. We have set the PWM channel to 0, 1, 2 for three LEDs respectively. Additionally, we have set the PWM resolution to 8 bits as it is the optimal resolution to obtain the maximum frequency. Although you can use resolution between 1-16 bits. As we are using 8-bit resolution, thus the duty cycle value will vary between 0-255 which we will map to 0-100%.

Recommended Reading: ESP32 PWM with Arduino IDE – LED fading example

// Setting PWM frequency, channels and bit resolution
const int frequency = 5000;
const int redChannel = 0;
const int greenChannel = 1;
const int blueChannel = 2;
const int resolution = 8;

ESP32 Rest API

The following function sends the request to the appropriate API handler.

void setup_routing() {     
  server.on("/temperature", getTemperature);     
  server.on("/pressure", getPressure);     
  server.on("/humidity", getHumidity);     
  server.on("/data", getData);     
  server.on("/led", HTTP_POST, handlePost);    
          
  server.begin();    
}

Our ESP32 Rest API server handles four different rest APIs. We will use the on() method on the server object to listen to the incoming HTTP requests. The server will receive a request on the following URLs:

  • /temperature: This will return the current temperature in degree Celsius
  • /pressure: This will return the current pressure in hPa
  • /humidity: This will return the current humidity in %
  • /data: This will return BME280 sensor data consisting of temperature, pressure and humidity

Here each resource (HTTP GET): “temperature”, “pressure”, “humidity” and “data” is allocated to its corresponding handler:

  • temperature -> getTemperature
  • pressure -> getPressure
  • humidity -> getHumisity
  • data -> getData

Moreover, the “led” resource will be used for the HTTP POST method. This Rest JSON API will be used to control the RGB LED. To start the API server, we will call the begin() on our server object.

The JSON payload consists of the information that the client requested via the ESP32 Rest API. We will include a tag, a value, and a unit for the GET method. For example, if the client requests the temperature then temperature, along with its value and unit will be sent.

StaticJsonDocument<250> jsonDocument;
char buffer[250];
void create_json(char *tag, float value, char *unit) {  
  jsonDocument.clear();
  jsonDocument["type"] = tag;
  jsonDocument["value"] = value;
  jsonDocument["unit"] = unit;
  serializeJson(jsonDocument, buffer);  
}
 
void add_json_object(char *tag, float value, char *unit) {
  JsonObject obj = jsonDocument.createNestedObject();
  obj["type"] = tag;
  obj["value"] = value;
  obj["unit"] = unit; 
}

We take BME280 sensor readings by using bme.readTemperature(), bme.readPressure() and bme.readHumidity(). These functions measure ambient temperature, barometric pressure and relative humidity respectively. We use a specific task that runs after every 60 seconds to acquire the BME280 sensor readings.

void read_sensor_data(void * parameter) {
   for (;;) {
     temperature = bme.readTemperature();
     humidity = bme.readHumidity();
     pressure = bme.readPressure() / 100;
     Serial.println("Read sensor data");
 
     vTaskDelay(60000 / portTICK_PERIOD_MS);
   }
}

The following functions will be used as handlers for their corresponding resources. The ESP32 Rest API will return a JSON payload to the client.

void getTemperature() {
  Serial.println("Get temperature");
  create_json("temperature", temperature, "°C");
  server.send(200, "application/json", buffer);
}
 
void getHumidity() {
  Serial.println("Get humidity");
  create_json("humidity", humidity, "%");
  server.send(200, "application/json", buffer);
}
 
void getPressure() {
  Serial.println("Get pressure");
  create_json("pressure", pressure, "hPa");
  server.send(200, "application/json", buffer);
}
 
void getData() {
  Serial.println("Get BME280 Sensor Data");
  jsonDocument.clear();
  add_json_object("temperature", temperature, "°C");
  add_json_object("humidity", humidity, "%");
  add_json_object("pressure", pressure, "hPa");
  serializeJson(jsonDocument, buffer);
  server.send(200, "application/json", buffer);
}

HTTP POST

The following function handles the POST payload received by the ESP32 API server after the client requests the “led” Rest JSON API. This will ultimately control the colour of the RGB LED. The JSON payload is deserialized using the deserializeJson() function. The RGB values for red, green and blue get saved in the integer variables ‘red_value’,’green_value’ and blue_value’ respectively. By using ledcWrite() we will generate the PWM with the duty cycle values accessed from the RGB values stored in their corresponding variables.

An empty payload is sent as a response to the client.

void handlePost() {
  if (server.hasArg("plain") == false) {
  }
  String body = server.arg("plain");
  deserializeJson(jsonDocument, body);

  int red_value = jsonDocument["red"];
  int green_value = jsonDocument["green"];
  int blue_value = jsonDocument["blue"];

  ledcWrite(redChannel, red_value);
  ledcWrite(greenChannel,green_value);
  ledcWrite(blueChannel, blue_value);

  server.send(200, "application/json", "{}");
}

setup()

Inside the setup() function, we will open a serial connection at a baud rate of 115200.

  Serial.begin(115200); 

By using ledcSetup(), we will initialize the PWM parameters for the RGB LED. This function takes in three parameters. The channel number, frequency, and resolution of the PWM channel.

  ledcSetup(redChannel, frequency, resolution);
  ledcSetup(greenChannel, frequency, resolution);
  ledcSetup(blueChannel, frequency, resolution);

Secondly, we will use ledcAttach() to attach the led pins to the respective channels.

  ledcAttachPin(red_pin, redChannel);
  ledcAttachPin(green_pin, greenChannel);
  ledcAttachPin(blue_pin, blueChannel);

Then, the BME280 sensor gets initialized and in case of failure, an error message is printed on the serial monitor.

  if (!bme.begin(0x76)) {    
    Serial.println("BME280 not found! Check Circuit");    
  }  

The following section of code will connect our ESP32 board with the local network whose network credentials we already specified above. After the connection will be established, the IP address of the ESP32 board will get printed on the serial monitor. This will help us to make a request to the server.

 Serial.print("Connecting to Wi-Fi");
  WiFi.begin(SSID, PWD);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
 
  Serial.print("Connected! IP Address: ");
  Serial.println(WiFi.localIP());

Moreover, call the following functions as well for a successful initialization of the project.

  setup_task();    
  setup_routing();     

loop()

Inside the loop() function we will call handleClient() on the server object so that the server can listen to the HTTP requests continuously.

void loop() {    
  server.handleClient();     
}

Demonstration

Make sure you choose the correct board and COM port before uploading your code to the board. Go to Tools > Board and select ESP32 Dev Module.

select esp32 board

Next, go to Tools > Port and select the appropriate port through which your board is connected.

Selecting COM PORT ESP32

Click on the upload button to upload the code into the ESP32 development board.
After you have uploaded your code to the development board, press its ENABLE button.

ESP32 enable reset button

In your Arduino IDE, open up the serial monitor and set the baud rate to 115200. You will be able to see the IP address of your ESP32 module after it successfully connects with the local Wi-Fi.

ESP32 Rest API Serial Monitor
Serial Monitor

Download and install the latest version of Postman in your system. We will test our ESP32 Rest API with this application.

Postman application logo

Now open the Postman app on your system and select the GET method. Type http://IP_ADDRESS/temperature and press the send button. Immediately we will get the response as a JSON payload.

ESP32 Rest API temperature data

Type http://IP_ADDRESS/pressure and press the send button. Immediately we will get the response as a JSON payload.

ESP32 Rest API pressure data

Type http://IP_ADDRESS/humidity and press the send button. Immediately we will get the response as a JSON payload.

ESP32 Rest API humidity data

Type http://IP_ADDRESS/data and press the send button. Immediately we will get the response as a JSON payload.

ESP32 Rest API BME280 sensor data

Now to control the RGB LED, select the POST option. Now type http://IP_ADDRESS/led then specify the RGB values and press the send button. Immediately the RGB LED will light up in the appropriate colour.

Here we are specifying red=255,green=0,blue=0 thus the RGB lights up in RED.

ESP32 Rest API POST
ESP32 Rest API Control RGB LED 1

Here we are specifying red=0,green=0,blue=255 thus the RGB lights up in Blue.

ESP32 Rest API POST 2
ESP32 Rest API Control RGB LED 2

To find the RGB values associated with a color, go to the following website: https://www.w3schools.com/colors/colors_picker.asp , pick your color and you will be able to obtain the RGB values.

RGB Value Picker

Watch the video below demonstration:

You may also like to read:

1 thought on “ESP32 Rest API Web Server GET and POST Examples with Postman API”

Leave a Comment