ESP32 Captive Portal Search Engine Code

 #include <WiFi.h>

#include <DNSServer.h>

#include <WebServer.h>

#include <HTTPClient.h>

#include <WiFiClientSecure.h>

#include <ArduinoJson.h>


// ---------------- USER CONFIGURATION ----------------

// Backend Router (Internet connection for ESP32)

const char* sta_ssid = "Airtel_X";       // Aapka router ka naam

const char* sta_pass = "Gau@0369";    // Aapka router ka password


// ESP32 Access Point (Network name for users)

const char* ap_ssid = "ESP32 SEARCH ENGINE";        // AP Name jo mobile mein show hoga

// ----------------------------------------------------


const byte DNS_PORT = 53;

DNSServer dnsServer;

WebServer server(80);


// Function to safely encode search queries for URL (e.g. "Elon Musk" -> "Elon%20Musk")

String urlEncode(String str) {

  String encodedString = "";

  char c;

  char code0;

  char code1;

  for (int i = 0; i < str.length(); i++) {

    c = str.charAt(i);

    if (c == ' ') {

      encodedString += "%20";

    } else if (isalnum(c)) {

      encodedString += c;

    } else {

      code1 = (c & 0xf) + '0';

      if ((c & 0xf) > 9) code1 = (c & 0xf) - 10 + 'A';

      c = (c >> 4) & 0xf;

      code0 = c + '0';

      if (c > 9) code0 = c - 10 + 'A';

      encodedString += '%';

      encodedString += code0;

      encodedString += code1;

    }

  }

  return encodedString;

}


// 🌐 HTML: The Home Page (Search Engine UI)

void handleRoot() {

  String html = "<!DOCTYPE html><html><head><meta name='viewport' content='width=device-width, initial-scale=1'>";

  html += "<title>ESR369 Search</title>";

  html += "<style>";

  html += "body { font-family: Arial, sans-serif; text-align: center; margin-top: 20%; background-color: #f2f2f2; }";

  html += "h1 { font-size: 50px; color: #4285F4; margin-bottom: 10px; }";

  html += "input[type=text] { width: 80%; max-width: 400px; padding: 12px; border: 1px solid #dfe1e5; border-radius: 24px; outline: none; font-size: 16px; }";

  html += "input[type=submit] { margin-top: 20px; padding: 10px 20px; background-color: #f8f9fa; border: 1px solid #f8f9fa; border-radius: 4px; cursor: pointer; color: #3c4043; }";

  html += "</style></head><body>";

  html += "<h1>ESR369</h1>";

  html += "<form action='/search' method='GET'>";

  html += "<input type='text' name='q' placeholder='Search the web...' required><br>";

  html += "<input type='submit' value='ESR369 Search'>";

  html += "</form>";

  html += "</body></html>";

  server.send(200, "text/html", html);

}


// 🌐 HTML & Backend Logic: The Search Results Page

void handleSearch() {

  if (!server.hasArg("q")) {

    server.sendHeader("Location", "/");

    server.send(302, "text/plain", "");

    return;

  }


  String query = server.arg("q");

  String resultTitle = "No exact match found.";

  String resultText = "Sorry, we couldn't find a summary for your search via our backend API. Please try a different keyword (e.g., 'India', 'Internet', 'Computer').";


  // Check if ESP32 is connected to the Internet (AIRTEL)

  if (WiFi.status() == WL_CONNECTED) {

    WiFiClientSecure *client = new WiFiClientSecure;

    client->setInsecure(); // Bypass SSL certificate check for simplicity

    HTTPClient https;

   

    // Wikipedia API call for a clean summary

    String apiUrl = "https://en.wikipedia.org/w/api.php?action=query&prop=extracts&exsentences=3&exlimit=1&titles=" + urlEncode(query) + "&explaintext=1&formatversion=2&format=json";

   

    Serial.println("Fetching: " + apiUrl);

    if (https.begin(*client, apiUrl)) {

      int httpCode = https.GET();

      if (httpCode == HTTP_CODE_OK) {

        String payload = https.getString();

       

        // Parse the JSON data

        DynamicJsonDocument doc(4096);

        DeserializationError error = deserializeJson(doc, payload);

       

        if (!error) {

          String extract = doc["query"]["pages"][0]["extract"].as<String>();

          if (extract != "null" && extract.length() > 0) {

            resultTitle = doc["query"]["pages"][0]["title"].as<String>();

            resultText = extract;

          }

        }

      }

      https.end();

    }

    delete client;

  } else {

    resultText = "Backend Error: ESP32 is not connected to AIRTEL WiFi. Cannot fetch internet results.";

  }


  // Generate Results HTML Page

  String html = "<!DOCTYPE html><html><head><meta name='viewport' content='width=device-width, initial-scale=1'>";

  html += "<title>ESR369 - Results</title>";

  html += "<style>";

  html += "body { font-family: Arial, sans-serif; padding: 20px; background-color: #fff; }";

  html += ".header { display: flex; align-items: center; border-bottom: 1px solid #ebebeb; padding-bottom: 15px; margin-bottom: 20px; }";

  html += ".header h2 { color: #4285F4; margin: 0; margin-right: 20px; cursor: pointer; }";

  html += "input[type=text] { padding: 10px; width: 60%; max-width: 300px; border: 1px solid #dfe1e5; border-radius: 20px; outline: none; }";

  html += ".result-box { max-width: 600px; }";

  html += ".title { color: #1a0dab; font-size: 20px; text-decoration: none; font-weight: normal; margin-bottom: 5px; }";

  html += ".url { color: #202124; font-size: 14px; margin-bottom: 5px; }";

  html += ".desc { color: #4d5156; font-size: 14px; line-height: 1.58; }";

  html += "</style></head><body>";

 

  html += "<div class='header'>";

  html += "<h2 onclick=\"window.location.href='/'\">ESR369</h2>";

  html += "<form action='/search' method='GET' style='margin:0; width:100%;'>";

  html += "<input type='text' name='q' value='" + query + "' required>";

  html += "</form></div>";

 

  html += "<div class='result-box'>";

  html += "<div class='url'>Source: Wikipedia API </div>";

  html += "<div class='title'>" + resultTitle + "</div>";

  html += "<div class='desc'>" + resultText + "</div>";

  html += "</div>";

 

  html += "</body></html>";

  server.send(200, "text/html", html);

}


// Captive Portal Redirect

void handleNotFound() {

  server.sendHeader("Location", "/", true);

  server.send(302, "text/plain", "");

}


void setup() {

  Serial.begin(115200);

  delay(1000);

  Serial.println("\nStarting ESP32 Search Engine...");


  // Set mode to Both Station (Connect to Router) and AP (Host Network)

  WiFi.mode(WIFI_AP_STA);


  // 1. Connect to Internet (STA Mode)

  Serial.print("Connecting to Backend WiFi: ");

  Serial.println(sta_ssid);

  WiFi.begin(sta_ssid, sta_pass);


  // 2. Start Access Point (AP Mode)

  Serial.print("Starting AP: ");

  Serial.println(ap_ssid);

  WiFi.softAP(ap_ssid);

 

  Serial.print("AP IP Address: ");

  Serial.println(WiFi.softAPIP());


  // 3. Start Captive Portal (Redirect all DNS requests to ESP32 IP)

  dnsServer.start(DNS_PORT, "*", WiFi.softAPIP());


  // 4. Setup Web Server Routes

  server.on("/", handleRoot);

  server.on("/search", handleSearch);

  server.on("/generate_204", handleRoot);  // Android Captive Portal

  server.on("/hotspot-detect.html", handleRoot); // Apple Captive Portal

  server.onNotFound(handleNotFound);       // Catch-all redirect


  server.begin();

  Serial.println("ESR369 Server is UP & RUNNING!");

}


void loop() {

  // Handle DNS requests for Captive Portal

  dnsServer.processNextRequest();

  // Handle HTTP client requests

  server.handleClient();

}

Comments

Popular posts from this blog

ESP32 Wi-Fi Extender Code

WiFi Remote Control RC Car Code For ESP32