5

I am using the default example SimpleWiFiServer that comes as an example from the ESP32:

#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>

#define LED_BUILTIN 2   // Set the GPIO pin where you connected your test LED or comment this line out if your dev board has a built-in LED

// Set these to your desired credentials.
const char *ssid = "MyNetwork";
//const char *password = "YourPassword";

WiFiServer server(80);


void setup() {
  pinMode(LED_BUILTIN, OUTPUT);

  Serial.begin(115200);
  Serial.println();
  Serial.println("Configuring access point...");

  // You can remove the password parameter if you want the AP to be open.

  //tcpip_adapter_dns_info_t dns_info;
  //dns_info.ip.u_addr.ip4.addr = IPAddress(192,168,4,1);
  //tcpip_adapter_set_dns_info(TCPIP_ADAPTER_IF_AP, TCPIP_ADAPTER_DNS_MAIN, &dns_info);
    
  WiFi.softAP(ssid);
  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);
  server.begin();

  Serial.println("Server started");
}

void loop() {
  WiFiClient client = server.available();   // listen for incoming clients

  if (client) {                             // if you get a client,
    Serial.println("New Client.");           // print a message out the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        if (c == '\n') {                    // if the byte is a newline character

          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println();

            // the content of the HTTP response follows the header:
            client.print("Click <a href=\"/H\">here</a> to turn ON the LED.<br>");
            client.print("Click <a href=\"/L\">here</a> to turn OFF the LED.<br>");

            // The HTTP response ends with another blank line:
            client.println();
            // break out of the while loop:
            break;
          } else {    // if you got a newline, then clear currentLine:
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }

        // Check to see if the client request was "GET /H" or "GET /L":
        if (currentLine.endsWith("GET /H")) {
          digitalWrite(LED_BUILTIN, HIGH);               // GET /H turns the LED on
        }
        if (currentLine.endsWith("GET /L")) {
          digitalWrite(LED_BUILTIN, LOW);                // GET /L turns the LED off
        }
      }
    }
    // close the connection:
    client.stop();
    Serial.println("Client Disconnected.");
  }
}

That initializes the ESP32 as an Access Point. On my phone I am able to see the network MyNetwork. If I connect to it and then open a my browser and go to 192.168.4.1 I am able to see the default page.

How can I change that code so that when I connect to that network it automatically open my browser going to http://192.168.4.1 ?

When researching on the internet I found this library that does that WiFiManager . That library helps you connect to an existing WiFi network. I do not want to do that. I only want that when I connect to MyNetwork my default page opens up just like when you connect to guest networks on hotels etc.

Other people on the internet have modified WiFiAPP.cpp and added these three lines of code:

tcpip_adapter_dns_info_t dns_info;
dns_info.ip.u_addr.ip4.addr = IPAddress(192,168,4,1);
tcpip_adapter_set_dns_info(TCPIP_ADAPTER_IF_AP, TCPIP_ADAPTER_DNS_MAIN, &dns_info);

That only makes my esp32 crash and does not work.

Has someone figure out a simple way to open a popup window (captive portal) pointing to http://192.168.4.1 once you connect to the ESP32 access point?

Lastly I found this example but that is using esp8266.

5
  • 2
    How you get things like automatic browser opening on an wifi connection event to happen depends on your operating system. It's not something I have ever heard of. The normal thing to do is set up a "captive portal" that redirects all requests to itself, so you open a browser and wherever you try and go to it responds with the portal page. There's an example in the bundled DNSServer library that does that.
    – Majenko
    Aug 24, 2020 at 17:32
  • Sorry I meant to say "captive portal" English is not my first language. @Majenko
    – Tono Nam
    Aug 24, 2020 at 17:40
  • @Majenko i have an Android v8 phone ... at AP connection it automatically browses to the captive portal page ... my previous phone required manual browsing to any unencrypted (http:) webpage
    – jsotola
    Aug 24, 2020 at 21:58
  • @jsotola That's usually something the phone does by itself. Apples try opening the page captive.apple.com/hotspot-detect.html and if it returns anything other than "Success" it opens the browser for you to log in.
    – Majenko
    Aug 24, 2020 at 22:01
  • @Majenko♦ i understand that the phone does it on its own ... i misunderstood your first comment ... thanks for the useful apple.com link
    – jsotola
    Aug 24, 2020 at 22:17

2 Answers 2

5

Thanks to @Majenko I was able to find what I was looking for on the internet from this link. When I googled "captive portal" instead of the phrases that I was using I found a lot more examples.

This code opens a "captive portal" once I connect to the esp32 access point.

#include <WiFi.h>
#include <DNSServer.h>

const byte DNS_PORT = 53;
IPAddress apIP(192, 168, 1, 1);
DNSServer dnsServer;
WiFiServer server(80);

String responseHTML = ""
  "<!DOCTYPE html><html><head><title>CaptivePortal</title></head><body>"
  "<h1>Hello World!</h1><p>This is a captive portal example. All requests will "
  "be redirected here.</p></body></html>";

void setup() { 
  WiFi.disconnect();   //added to start with the wifi off, avoid crashing
  WiFi.mode(WIFI_OFF); //added to start with the wifi off, avoid crashing
  WiFi.mode(WIFI_AP);
  WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
  WiFi.softAP("DNSServer CaptivePortal example");

  // if DNSServer is started with "*" for domain name, it will reply with
  // provided IP to all DNS request
  dnsServer.start(DNS_PORT, "*", apIP);

  server.begin();
}

void loop() {
  dnsServer.processNextRequest();
  WiFiClient client = server.available();   // listen for incoming clients

  if (client) {
    String currentLine = "";
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (c == '\n') {
          if (currentLine.length() == 0) {
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println();
            client.print(responseHTML);
            break;
          } else {
            currentLine = "";
          }
        } else if (c != '\r') {
          currentLine += c;
        }
      }
    }
    client.stop();
  }
}
3

When providing HTTP server you generally have two options:

  1. Using WebServer class and set handlers for roots. The parsing and handling of HTTP header is done by the library.
  2. Use WifiServer and receive the HTTP message with header included and handler everything by your own.

If you are doing number 1 and pretend using by connecting with an Android device I suggest adding a handler for the error case showing the captive portal:

server.onNotFound(handleRoot);

I noticed that for Android 10, to properly detect the captive portal and make the phone to show "Touch to log in the network" message is necesary. If not you must navigate to any HTTP address and let the DNS do the job for you (not HTTPS).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.