ESP32 Arduino: HTTP server over soft AP

In this ESP32 tutorial, we will check how to setup an asynchronous HTTP web server with the device operating as soft Access Point. The tests of this ESP32 tutorial were performed using a DFRobot’s ESP-WROOM-32 device integrated in a ESP32 FireBeetle board.


Introduction

In this ESP32 tutorial, we will check how to setup an asynchronous HTTP web server with the device operating as soft Access Point.

Thus, in order for a client to be able to reach the HTTP server, we don’t need to connect it to a router but rather to the WiFi network hosted by the ESP32.

The possibility of setting a HTTP server on the ESP32 working as soft AP is very useful since in real application scenarios, an IoT device may be deployed in a WiFi network to which the credentials are not known in code compile time.

Thus, we need to have a way of setting those credentials for the ESP32 to be able to connect to the WiFi network.

Although this could be done using, for example, serial communication, this would be impractical for some commercial applications where it will be the end user making the initial configuration for the device to start operating.

Thus, a possible way of solving this problem is making the ESP32 operate as soft AP when connected for the first time, starting a HTTP server that serves a configuration HTML webpage for the user to input the name and password of the WiFi network to which the device should connect to to be able to reach the Internet and operate.

One good example is a possible commercial IoT thermostat, which makes measurements of the environment temperature and sends it to the Internet. In this case, each unit would need to be configured for operating in each users’ house and thus this type of method for an initial configuration would be a good solution.

Naturally, designing this type of interface is a more complex scenario and in this introductory example we will set the server to simply return a “hello world” message.

Nonetheless, the HTTP web server examples from previous posts can also be tested with the ESP32 operating as soft AP, and they already include a tutorial on how to serve HTML and JavaScript. You can check more on the “Related Posts” section.

If you haven’t yet configured the ESP32 Arduino libraries needed for setting an asynchronous HTTP web server, please check here how to do it.

The tests of this ESP32 tutorial were performed using a DFRobot’s ESP-WROOM-32 device integrated in a ESP32 FireBeetle board.

If you prefer a video tutorial, please check my YouTube channel below:


The code

In terms of coding, this example will be based on two previous tutorials we have been covering for the Arduino environment. The first one is how to set a soft AP (which can be consulted here) and the second one is how to configure a HTTP web server on the ESP32 (you can check it here).

One important thing to mention is that the HTTP server will be configured the exact same way it would be if we were connecting the ESP32 to a WiFi network hosted by a router, like we have been doing in the previous tutorials.

So, in terms of implementation, the interface we use to configure the server doesn’t need the awareness of which type of WiFi network is being used.

In terms of coding, we start by the includes needed. To set the soft AP, we need to include the WiFi.h library and the ESPAsyncWebServer.h library.

#include "WiFi.h"
#include "ESPAsyncWebServer.h"

In order for other devices to be able to connect to the soft AP, we need to specify its SSID (network name) and the password protecting it. We will declare these credentials as global variables.

const char *ssid = "MyESP32AP";
const char *password = "testpassword";

To finish the global declarations, we will need an instance of the AsyncWebServer class, which exposes a high level API that will allow us to configure the web server.

Remember from the previous tutorials that the constructor for this class receives as argument the port where the server will be listening for incoming HTTP requests. As usual, we will use the default HTTP port, which is 80.

AsyncWebServer server(80);

Moving on to the setup function, we will start it by opening a serial connection, since we will need to print the IP of the ESP32 for the client to be able to reach it.

Serial.begin(115200);

To start the soft AP, we simply need to call the softAP method of the WiFi external variable (this is the same variable we use to connect the ESP32 to a WiFi network).

This method receives as first input the name of the WiFi network we want to set and as second input its password. Just as a note, setting a password is not mandatory and we could have not specify it if we wanted our Access Point to be open.

WiFi.softAP(ssid, password);

As mentioned, we will need to know the ESP32 IP, in order for the client connected to its network to be able to send requests to it. We can obtain the IP by calling the softAPIP method on the same WiFi variable.

Serial.print("IP address: ");
Serial.println(WiFi.softAPIP());

Now that we have handled the WiFi network part, we need to set the server. To do it, we simply need to bind a route to a handling function, which will be executed when HTTP requests are performed to that route.

We will use the “/hello” route and set the server to listen to incoming HTTP GET requests.

The route handling function will simply return an HTTP OK code (200) and a “Hello World” message.

The code for this configuration can be seen below. If you need a detailed explanation on all the parameters and functions used in this configuration, please consult this post.

server.on("/hello", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", "Hello World");
});

To start the server, we need to call the begin method on our server object, so it starts listening and handling the incoming requests.

With this call, we finish the setup function and since the server works asynchronously, the Arduino loop may be left empty. The final source code can be seen below.

#include "WiFi.h"
#include "ESPAsyncWebServer.h"

const char *ssid = "MyESP32AP";
const char *password = "testpassword";

AsyncWebServer server(80);

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

  WiFi.softAP(ssid, password);

  Serial.println();
  Serial.print("IP address: ");
  Serial.println(WiFi.softAPIP());

  server.on("/hello", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", "Hello World");
  });

  server.begin();
}

void loop(){}


Testing the code

To test the code, compile it and upload it to your ESP device and then open the Arduino IDE serial monitor. Once the soft AP is set, the IP of the ESP32 should get printed to the monitor, as shown in figure 1. Copy that IP.

ESP32 soft AP device IP.png

Figure 1 – IP of the ESP32.

At that moment, the WiFi network should already be detectable by your computer. Look for it in the available WiFi networks and connect to it using the password we have defined on the code. Figure 2 shows the network being detected on a machine running windows 8.

ESP32 soft AP detected on Windows 8 machine.png

Figure 2 – WiFi network hosted by the ESP32 being detected on Windows 8.

To finalize, after connected to that network, open a web browser of your choice and type the following in the address bar, changing #yourEspIp# by the value you have copied from the serial monitor.

http://#yourEspIp#/hello

You should get an output similar to figure 3, which shows the “Hello world” message being returned.

ESP32 HTTP server Hello World over soft AP Arduino.png

Figure 3 – ESP32 server returning the message to the client.


Related posts

Advertisements

34 Replies to “ESP32 Arduino: HTTP server over soft AP”

      1. Hi! That’s actually weird.

        Maybe your version of the Arduino core had some bug on those functions. You can try to pull the latest version and test.

        If the error persists, my recommendation is to post a issue on the GitHub page of the ESP32, since it is working fine for me.

        If you have another ESP at hand, you may also test to check if it isn’t a hardware related problem.

        Like

    1. Hi!

      The HTML for that may be a little bit more complicated than the examples I’ve been sharing, it is not easy to explain in a comment.

      But a simple way is having a form on your HTML code with two inputs, one for the ssid and another for the pass.

      Then, on submit, you need to process the post request body and store the credentials in the non volatile storage, so you can later use to connect to the WiFi network.

      Unfortunately I don’t have any tutorial for that yet, but it involves coding in HTML, which may be easy or not depending if you feel comfortable with it.

      Note however that there are already WiFi managers for the ESP32:
      https://github.com/zhouhan0126/WIFIMANAGER-ESP32

      I haven’t tried them yet, but they should be the fastest way to get everything setup.

      Best regards,
      Nuno Santos

      Like

    1. Hi!

      Taking into account the documentation, the webserver should be able to handle multiple clients:
      https://github.com/me-no-dev/ESPAsyncWebServer#why-should-you-care

      Nonetheless I haven’ yet tested that specific use case where multiple clients are connecting simultaneously, so I cannot confirm.

      But when you mention it cannot handle parallel requests, how did you try it? Multiple requests from the same machine?

      Or have ou tried to connect a lot of stations to the soft AP? I think the soft AP has a maximum limit of simultaneous stations it can handle, which is not very high. I don’t recall the exact number, but I think it was something around 4.

      Best regards,
      Nuno Santos

      Like

  1. Hello
    Thank you for this tutorial, it is very interesting and tonight I’m going to sleep less stupid!
    I made a few years ago a thermostat with an arduino, ds18b20 … but that only worked internally (no wifi, BLE, …) now I have a esp32 (wemos d1 r32) and the goal is to make my esp32 communicate with an app via app inventor without going through the internet box.
    I am in the right place!
    I launched the program via the arduino IDE and it works fine, my smartphone connects well to the ESP32.
    I think I understand a little how everything works. Only I would like to know in general how to receive data sent by the APP and send sensor information. The goal would be to display temperatures on the APP and send the set temperature to esp32.
    Maybe there will be a tutorial on these actions?
    sorry for my English
    Thank you and continued to offer tutorials. They are very educational

    Liked by 1 person

    1. Hi!

      Thank you very much for your feedback, I’m very happy to know that you are finding the tutorials useful 🙂

      In your case, it’s more like an architectural decision in the first place, since there are plenty of options to solve your problem.

      To send data from the app to the ESP, a easy way is to setup a HTTP server, as done in this tutorial.

      If you want to send data from the ESP to the app, you can make it listening to HTTP requests (acting like a server) and having the ESP sending HTTP requests to it:
      https://techtutorialsx.com/2017/05/20/esp32-http-post-requests/

      Note that this is for a simple not scalable quick solution.

      If you want for instance to develop a product to sell with lots of ESPs and people using their own app, then I would send the ESP data to a remote server with a database and have the app also connect to that server, with the client credentials, and fetch the data to display it.

      As mentioned, there are plenty of options and that is the most interesting part of using an ESP32. It is a very powerful device that gives us higher level functionalities and allows us to focus on the architecture rather than having to optimize every bit of our program to be able to run in a resource constrained device.

      Hope this helps you achieving your goal.

      PS: You English is fine, I’m also not a native English speaker, so don’t worry 🙂

      Best regards,
      Nuno santos

      Like

  2. Hello,
    I’m trying to read a sensor, and send the data to a connected device via HTML. THe problem I’m having is the “server.on(“/hello”, HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, “text/plain”, “Hello World”);
    });” lambda. I understand how it works, but I don’t want to have to query the ESP continuously. Is there a way to send info directly to the connected device without using the pointer? OR, is there a way for the “server.on” statement to simply “send” the updated HTML variables/HTML page to the connected device.

    I’m currently using your sketch from above and it works great. I just need to modify it slightly. I’m a novice so, maybe I’m going about this all wrong. Sure would appreciate any guidance.

    Thank You,
    Charles

    Liked by 1 person

    1. Hi Charles,

      I did not understand your architecture very well. Are you trying to read the sensor and make that reading “available” in the ESP using the webserver code?

      When you say connected device, are you refering to something like a desktop or a laptop that is receiving the HTML from the ESP32 and displaying it in a web browser?

      Assuming that that is the architecture, then it is normal that you query the ESP whenever you want to get the current measurement.

      If when you say you don’t want to continuously query the ESP, I’m assuming that you want to get the new measurements in “real time”, like you want to see the current sensor value as soon as it changes.

      If that’s the case, constantly polling the ESP will indeed not scale.

      Unfortunately, you cannot update or push the updated HTML to the client when a new measurement is available. HTTP works the other way around, the client is the one who asks the server for the data.

      As a solution, I would establish a persistent socket or websocket connection, so the ESP could send the data to the reader whenever it has a new sensor measurement.

      Note that it would be a completely different architecture from the one shown in this tutorial.

      I don’t have any socket tutorial for the ESP, but I have some on web sockets:
      https://techtutorialsx.com/2017/11/03/esp32-arduino-websocket-server/
      https://techtutorialsx.com/2017/11/01/esp32-arduino-websocket-client/

      For the sockets, you can check the example from the Arduino libraries:
      https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFi/examples/WiFiClient/WiFiClient.ino

      The WiFiClient there is basically an abstraction for a socket connection.

      A final note: The lambda is just the third argument of the on method, not the whole statement.

      In short, a lambda is an anonymous function. So, instead of formally declaring a function with a name and a header, you can use the lambda for a more compact code, since you are not going to reuse the function that you pass to the on method.

      Hope this helps, but let me know a little bit more about your application so I cant try to help a little bit more.

      Best regards,
      Nuno Santos

      Like

  3. Anyone else seeing this error?
    C:\Users\grri0002\Documents\Arduino\SimpleWiFiServer\SimpleWiFiServer.ino\SimpleWiFiServer.ino.ino:4:31: fatal error: ESPAsyncWebServer.h: No such file or directory

    compilation terminated.

    Multiple libraries were found for “WiFi.h”
    Used: C:\Program Files (x86)\Arduino\hardware\espressif\esp32\libraries\WiFi
    Not used: C:\Users\grri0002\Documents\Arduino\libraries\WiFi
    exit status 1
    Error compiling for board MH ET LIVE ESP32MiniKit.

    Liked by 1 person

    1. Hi!

      Never experienced that error so I cannot be of much help. Maybe someone who has already seen it can help.

      Nonetheless, did you follow the procedure I’ve indicated in a previous tutorial to install the libraries? Worked fine for me:
      https://techtutorialsx.com/2017/12/01/esp32-arduino-asynchronous-http-webserver/

      Other option is to open an issue on the GitHub page of the ESP async libraries, so maybe someone can help there.

      Best regards,
      Nuno Santos

      Like

    1. Hi!

      Thanks for the feedback 🙂

      What do you mean with putting data using the WiFi.softAP functionality?

      Do you want to expose an endpoint to return the dht11 sensor data?

      Best regards,
      Nuno Santos

      Like

  4. I am definitely missing something.
    If I setup ESP32 as AP; then it is a hot spot is that correct ??
    If it is a hot spot can I use it to access the Internet. ?????????
    Why you may ask , since you already have your router and you access the Internet using THAT router ??? The answer is:
    I need a SEPERATE access to the internet to use Sonos Speaker. I have TWO sonos on my original wifi network and I want to ISOLATE the 3rd from the other two.

    Like

    1. Hi!

      When you set up the ESP32 as a soft AP, the ESP32 will act as kind of a router by itself, not as an hot spot.

      This means that multiple devices can connect and talk to the ESP32like they were connecting to any other WiFi network, but they will not be able to reach the Internet.

      This means you can use the soft AP feature even if there is no router / WiFi network connected to the Internet nearby.

      Think of it like an ad-hoc WiFi network that your ESP32 will host.

      A usual use case for soft AP is the following: You buy an IoT device that needs to connect to your WiFi network to function, but when you power it off the first time, it doesn’t know the name of your network nor the password.

      Naturally, if it could connect to your WiFi network without your consent, it would be a major security flow.

      So, somehow you need to insert the credentials of your WiFi network in your IoT device.

      To solve this, that device can setup a soft AP with a pre-defined network name and password (probably indicated in your device’s instructions) and then you can use your smartphone, tablet or computer to connect to that temporary network to access, for example, a webpage that will ask for your home WiFi network credentials.

      Then, you input the credentials and after that point, your IoT device can connect to your Home WiFi Network, and have access to the internet and reach remote servers or whatever else it needs for its functionality.

      Of course that this is one common use case, there are others.

      I’ve never used the devices you mentioned so I cannot be of much assistance there, but I think the soft AP functionalities are not what you are looking for.

      I’m not aware though if there is some “HotSpot” mode that the ESP32 can host, but if you happen to find some way of making it work like that, please let us know since it would be very interesting. 🙂

      Hope this clarifies.

      Best regards,
      Nuno Santos

      Like

      1. Thank you for taking the time to respond.
        Let me summarize what I understood from your response.
        1. To access the Internet you need a “physical” router with proper User ID and PW ( using ISP)
        2. Any capable device connected to THIS SSID, can SHARE the internet access.
        3. ESP32 AP is a “private” wifi with it’s own SSID and PW, that has nothing to do with the “other” wifi.
        4. Why you need such private wifi network. Well. it is private to start with and TOTALLY ISOLATED from the outside world. You can have your own web server , you can attach sensors and control them……etc.
        5. and here is the confusing part. Suppose I want to connect my sensor to the cloud. What do I do ??
        Is that possible ??? .

        Liked by 1 person

        1. You’re welcome 🙂

          Regarding your list:
          1 – Correct
          2 – When you say share, are you referring to something like a hotspot?
          3 – Correct
          4 – Correct, in short. The long answer is, the ESP32 can actually act as a soft AP and also be connected to a WiFi network hosted by a router, so there’s the possibility to “pass” content from one network to the other. Nonetheless, it’s not like an hotspot, you would have to implement that “passing” logic yourself in the code (never tested it myself, but in theory it should be possible)
          5 – That’s simple, you just need to connect your ESP32 to the WiFi network of a router and program it to read the sensor data and send it to the cloud server using some protocol (HTTP, MQTT, raw sockets, websockets…). No need for a soft AP here as long as you have access to the device and can specify the network credentials in your code.

          You can check here a tutorial that covers something similar using the ESP8266. The code for the ESP32 would be the same except for some library includes that have changed from the ESP8266 to the ESP32:
          https://techtutorialsx.com/2017/01/08/esp8266-posting-json-data-to-a-flask-server-on-the-cloud/

          Hope this clarifies. 🙂

          Best regards,
          Nuno Santos

          Like

          1. I feel more comfortable now…after reading your comments which make a lot of sense.
            My comments on point 2 is rather simple. All I meant is: In my WiFi network the router is connected to the internet. Any device like a laptop can have access to the Internet once it is connected to the router wifi SSID. That what I meant about sharing the Internet. In other words The router allow or disallow a device to have access to the internet.

            Your comments suggest that the ONLY way to allow sensors to connect to the cloud IS to connect to the network that have access to the Internet. How about BRIDGING. I never used it but it indicates that I can LINK the two together and keep my private network ( AP) private I do not know if this is true.

            One thing I forgot to mention in the benefit of AP, is the fact that you can EXTEND the range of the original wifi and in this case you HAVE access to the internet for devices connected to the AP.

            IN my view this area has a lot of details that need to be covered in more details.

            Liked by 1 person

            1. Hi,

              You are right regarding point 2.

              Regarding bridging, I’m not sure if it’s possible or not, I’ve never worked with it.

              Nonetheless, some device inside the network(s) will eventually have to be connected to the Internet to reach the remove server, at least as far as I’m aware.

              But even if what you mention is possible in theory, please take in consideration that it may not be possible to implement it using the ESP32.

              One place you can ask around for more complex architectures / functionalities that have not yet been explored is in the IDF GitHub page, since IDF is the official development framework for the ESP32.

              The Arduino core is built on top of IDF, so if a functionality is available in IDF, it should be usable in the Arduino core.

              Here is the link:
              https://github.com/espressif/esp-idf

              You can also take a look at the IDF documentation:
              https://docs.espressif.com/projects/esp-idf/en/latest/

              I agree with you regarding the need for more details but the truth is there are still many things that are not clear if the ESP32 is capable of handling or not.

              Personally, I’ve stumbled across many awesome features by analyzing parts of the Arduino core / IDF source code, which I did not know they exist.

              Let us know if you are able to find an answer since it will definitely be helpful for others 🙂

              Best regards,
              Nuno Santos

              Like

  5. Followup to my last question.
    The reason is on my WiFi network the router is connected to the Internet. On this network I have TWO Sonos Speakers. I need to install 3rd one BUT on a seperate Network that have access to the Internet.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s