Introduction

In this tutorial we will check how to setup a simple Flask server on the Raspberry Pi and send HTTP POST requests to it from the ESP32. Then, we will access the body of the request on the Raspberry Pi.

The Python version used on this tutorial was 3.5.3 and it was tested on a Raspberry Pi 3 model B+, running version 4.9 of Raspbian, installed using NOOBS. Additionally, a DFRobot’s ESP32 module integrated in a ESP32 development board was used.

The Python code

The Python code for this tutorial is very similar to what we have been covering before. As usual, we start by importing the Flask class from the flask module, to setup the whole HTTP server.

Additionally, we will need to import the request object from the flask module, so we can later access the body of the request sent by the client.

After the imports, we need to create an instance of the Flask class.

from flask import Flask, request

app = Flask(__name__)

Now that we have our app object, we can proceed with the configuration of the routes of the server. We will have a single route called “/post”, since we are going to test it against POST requests. Naturally, you can call it what you want, as long as you use the endpoint you defined in the client code.

Additionally, we will also limit the actual HTTP methods that this route accepts. You can check a more detailed guide on how to do it on this previous post.

This will ensure that the route handling function will only be executed when the client makes a POST request.

@app.route('/post', methods = ["POST"])
def post():

The route handling function will be very simple. We will just access the body of the request to print it and then return an empty answer to the client. Note that it is common that the answer of a POST request does not contain any content, since a success HTTP response code is, in many cases, enough for the client to know the operation was executed.

So, to get the actual request body, we simple need to access the data member of the request object. We will simply print the result so we can later confirm it matches the content sent by the client.

After that, as already mentioned, we return the response to the client, with an empty body.

print(request.data)
return ''

To finalize and to start listening to incoming requests, we need to call the run method on our app object. As first input we pass the ‘0.0.0.0’ IP, to indicate the server should be listening in all the available IPs of the Raspberry Pi, and as second input we pass the port where the server will be listening.

The full Python code for the Raspberry Pi is shown below.

from flask import Flask, request

app = Flask(__name__)

@app.route('/post', methods = ["POST"])
def post():

    print(request.data)
    return ''

app.run(host='0.0.0.0', port= 8090)

The Arduino code

We start with the includes of the libraries we will need to both connect the ESP32 to a wireless network and also to make the HTTP POST requests. These are the Wifi.h and the HTTPClient.h libraries, respectively.

We will also need to declare the credentials to connect to the WiFi network, more precisely the network name and the password.

Then, in the Arduino setup function, we take care of connecting the ESP32 to the WiFi network.

#include <WiFi.h>
#include <HTTPClient.h> 

const char* ssid = "yourNetworkName";
const char* password =  "yourNetworkPassword";

void setup() {

  Serial.begin(115200);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  Serial.println("Connected to the WiFi network");

}

The HTTP POST requests will be performed on the Arduino main loop function. To be able to perform the requests, we will need an object of class HTTPClient.

HTTPClient http;
Now, we need to call the begin method on our HTTPClient object, to initialize the request. As input of the method, we need to pass the endpoint to which we want to send the request.
The destination endpoint will be composed by the IP of the server, the port where it is listening and the route we want to reach. The port was specified in the Python code and it is 8090. The route is “/post“, which was also specified in the Python code.
To get the local IP address of the Raspberry Pi, the simplest way is opening a command line and sending the ifconfig command, as explained in greater detail here.
Also, take in consideration that both the ESP32 and the Raspberry Pi need to be connected to the same WiFi network for the code shown in this tutorial to work.
http.begin("http://192.168.1.92:8090/post");
Since we are sending a POST request, we need to specify the content-type of the body, so the server knows how to interpret it. In this introductory example, we will send just a “Hello World” string, which means we can define the content-type as plain text.
The content-type is sent in the request as a header, which we can specify by calling the addHeader method of the HTTPClient object. This method receives as first input the name of the header and as second input its value.
http.addHeader("Content-Type", "text/plain"); 
To send the actual request, we need to call the POST method on the HTTPClient object, passing as input the body of the request, as a string.
Note that this method returns as output the HTTP response code in case the request is successfully sent. Otherwise, if an internal error occurs, it returns a number lesser than zero that can be used for error checking.
int httpResponseCode = http.POST("POSTING from ESP32");
In case of success, we simply print the returned HTTP code, just to confirm that the request was correctly received by the Flask server.
Serial.println(httpResponseCode);
To finalize, we call the end method on the HTTPClient, to free the resources.
http.end(); //Free resources
You can check the final code below. Note that it includes some additional checks to ensure we are sending the request only if the ESP32 is still connected to the WiFi network, and also to confirm the HTTP Post request was sent with success and no internal error has occurred.
#include <WiFi.h>
#include <HTTPClient.h> 

const char* ssid = "yourNetworkName";
const char* password =  "yourNetworkPassword";

void setup() {

  Serial.begin(115200);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  Serial.println("Connected to the WiFi network");

}

void loop() {

 if(WiFi.status()== WL_CONNECTED){   //Check WiFi connection status

   HTTPClient http;   

   http.begin("http://192.168.1.92:8090/post");
   http.addHeader("Content-Type", "text/plain");             

   int httpResponseCode = http.POST("POSTING from ESP32");   //Send the actual POST request

   if(httpResponseCode>0){

    Serial.println(httpResponseCode); 

   }else{

    Serial.println("Error on sending POST");

   }

   http.end();  //Free resources

 }else{

    Serial.println("Error in WiFi connection");   

 }

  delay(10000);  //Send a request every 10 seconds

}

Testing the code

To test the code, first run the Python code to start the server. After that, compile and upload the Arduino code to the ESP32, using the Arduino IDE.
Once the procedure finishes, open the Arduino IDE serial monitor. After the ESP32 is connected to the WiFi network, it should start sending the requests to the Flask server and printing the result status code, as shown below at figure 1.

ESP32 Result from sending HTTP POST to Flask Server on the RPI 3.png
Figure 1 – HTTP status code returned by the server to the ESP32.

If you go back to the Python prompt where the Flask server is running, you should get a result similar to figure 2, where it shows the messages sent by the ESP32 getting printed.
Raspberry Pi Flask Server receive HTTP Post from ESP32


Figure 2 – ESP32 messages printed on the Flask server, running on the Raspberry Pi.

Leave a Reply

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

Captcha loading...