DIYables ESP32 Web Server Query String Example

WebServerQueryStrings Example - Dynamic Multi-Page Server

Overview

This example demonstrates how to create a dynamic multi-page web server that uses URL query parameters to provide interactive content and control functionality with seamless page navigation.

Features

  • Multi-page navigation with dynamic content based on URL parameters
  • Temperature unit conversion (Celsius/Fahrenheit) via query parameters
  • LED control with query string parameters
  • Dynamic content generation based on user input
  • Professional multi-page layout with consistent navigation
  • URL parameter parsing and validation

Hardware Used In This Tutorial

1×ESP-WROOM-32 Dev Module
1×USB Cable Type-A to Type-C (for USB-A PC)
1×USB Cable Type-C to Type-C (for USB-C PC)
1×Recommended: Screw Terminal Expansion Board for ESP32
1×Recommended: Breakout Expansion Board for ESP32
1×Recommended: Power Splitter for ESP32

Or you can buy the following kits:

1×DIYables ESP32 Starter Kit (ESP32 included)
1×DIYables Sensor Kit (30 sensors/displays)
1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links in this section are Amazon affiliate links, meaning we may earn a commission at no additional cost to you if you make a purchase through them. Additionally, some links direct you to products from our own brand, DIYables .

Library Installation

Follow these instructions step by step:

  • If this is your first time using the ESP32, refer to the tutorial on setting up the environment for ESP32 in the Arduino IDE.
  • Connect the ESP32 board to your computer using a USB cable.
  • Launch the Arduino IDE on your computer.
  • Select the appropriate ESP32 board (e.g., ESP32) and COM port.
  • Open the Library Manager by clicking on the Library Manager icon on the left side of the Arduino IDE.
  • Search for Web Server for ESP32 and locate the mWebSockets by DIYables.
  • Click on the Install button to add the mWebSockets library.
ESP32 Web Server library

Web Server Query Strings Example

  • On Arduino IDE, Go to File Examples Web Server for ESP32 WebServerQueryStrings example to open the example code

Code Structure

  1. home.h: Home page HTML template
  2. temperature.h: Temperature monitoring page template
  3. led.h: LED control page template
  4. WebServerQueryStrings.ino: Main server logic

Circuit Connection

No external components required - this example uses the built-in LED on pin 13.

Query Parameter Features

Temperature Page Parameters

  • unit=c or unit=celsius - Display temperature in Celsius
  • unit=f or unit=fahrenheit - Display temperature in Fahrenheit
  • No parameter - Defaults to Celsius

LED Control Parameters

  • state=on - Turn LED on
  • state=off - Turn LED off

Setup Instructions

1. Network Configuration

Edit the WiFi credentials directly in the WebServerQueryStrings.ino file:

const char WIFI_SSID[] = "YOUR_WIFI_SSID"; const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";

2. Upload Code and Monitor Output

  1. Connect your ESP32 to your computer
  2. Select the correct board and port in Arduino IDE
  3. Upload the WebServerQueryStrings.ino sketch
  4. Open Serial Monitor (9600 baud)
  5. Wait for WiFi connection
  6. Note the IP address displayed
  7. If you do not see IP address in Serial monitor, press the reset button on the ESP32 board

Usage Examples

Open your web browser and enter the IP address displayed in the Serial Monitor to access the web server.

ESP32 Web Server Query Strings

Test the Temperature Monitoring Function:

  • Click on the "Temperature" menu.
  • View the temperature display. Click each button to change the temperature unit
ESP32 Web Server Temperature Query Strings

Test the LED Control Function:

  • Click on the "LED Control" menu. You will see the web interface like the below:
LED Control Page Query Strings
  • Toggle the LED ON and OFF using the provided buttons.
  • Observe the built-in LED status on the ESP32 board update instantly.

Accessing Different Pages

Home Page
  • URL: http://your-esp32-ip/
  • Features: Welcome page with navigation menu
Temperature Page (Default - Celsius)
  • URL: http://your-esp32-ip/temperature
  • Display: Temperature in Celsius with unit selector
Temperature in Fahrenheit
  • URL: http://your-esp32-ip/temperature?unit=f
  • URL: http://your-esp32-ip/temperature?unit=fahrenheit
  • Display: Temperature converted to Fahrenheit
LED Control
  • Turn ON: http://your-esp32-ip/led?state=on
  • Turn OFF: http://your-esp32-ip/led?state=off

Code Explanation

Query Parameter Processing

void handleTemperature(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { // Check for query parameter "unit" String unit = "C"; for (int i = 0; i < params.count; i++) { if (String(params.params[i].key) == "unit") { unit = params.params[i].value; } } // Generate temperature display based on unit String temperatureDisplay = "Simulated temperature: 25°" + unit; // Use the TEMPERATURE_PAGE template and replace placeholder String response = TEMPERATURE_PAGE; response.replace("%TEMPERATURE_VALUE%", temperatureDisplay); server.sendResponse(client, response.c_str()); }

LED Control with Query Parameters

void handleLed(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { // Check for query parameter "state" String state = ""; for (int i = 0; i < params.count; i++) { if (String(params.params[i].key) == "state") { state = params.params[i].value; break; } } // Control LED based on state if (state == "on") { ledState = HIGH; digitalWrite(LED_PIN, ledState); } else if (state == "off") { ledState = LOW; digitalWrite(LED_PIN, ledState); } else if (state == "") { // No state parameter provided, just show current status } else { // Invalid state parameter client.println("HTTP/1.1 400 Bad Request"); client.println("Connection: close"); client.println(); client.print("Invalid state parameter. Use ?state=on or ?state=off"); return; } // Get current LED state String ledStatus = (ledState == HIGH) ? "ON" : "OFF"; // Use the LED_PAGE template and replace placeholders String response = LED_PAGE; response.replace("%LED_STATUS%", ledStatus); server.sendResponse(client, response.c_str()); }

Parameter Validation

// Helper function to find query parameter value String getQueryParam(const QueryParams& params, const String& key) { for (int i = 0; i < params.count; i++) { if (String(params.params[i].key) == key) { return params.params[i].value; } } return ""; } // Validation functions bool isValidTemperatureUnit(String unit) { unit.toLowerCase(); return (unit == "c" || unit == "celsius" || unit == "f" || unit == "fahrenheit" || unit == ""); } bool isValidLedState(String state) { return (state == "on" || state == "off" || state == ""); }

HTML Templates with Dynamic Content

Temperature Page Template

<div class="temperature-display"> <h2>Current Temperature</h2> <div class="temp-value">%TEMPERATURE% %UNIT%</div> <div class="unit-selector"> <p>Display in:</p> <a href="/temperature?unit=c" class="unit-btn">Celsius</a> <a href="/temperature?unit=f" class="unit-btn">Fahrenheit</a> </div> </div>

LED Control Template

<div class="led-control"> <h2>LED Control</h2> <div class="status">Status: <span>%LED_STATUS%</span></div> <div class="controls"> <a href="/led?state=on" class="btn btn-on">Turn ON</a> <a href="/led?state=off" class="btn btn-off">Turn OFF</a> </div> </div>

Advanced Features

Route Configuration

void setup() { Serial.begin(9600); pinMode(LED_PIN, OUTPUT); ledState = LOW; digitalWrite(LED_PIN, ledState); // Initialize web server with credentials server.begin(WIFI_SSID, WIFI_PASSWORD); server.printWifiStatus(); // Add routes server.addRoute("/", handleHome); server.addRoute("/temperature", handleTemperature); server.addRoute("/led", handleLed); // Set custom 404 handler server.setNotFoundHandler(handleNotFound); }

Query Parameter Helper Functions

// Extract parameter from QueryParams structure String getParam(const QueryParams& params, const String& key, const String& defaultValue = "") { for (int i = 0; i < params.count; i++) { if (String(params.params[i].key) == key) { return params.params[i].value; } } return defaultValue; } // Check if parameter exists bool hasParam(const QueryParams& params, const String& key) { for (int i = 0; i < params.count; i++) { if (String(params.params[i].key) == key) { return true; } } return false; }

URL Building Helpers

// Helper to build URLs with parameters String buildLedUrl(String state) { return "/led?state=" + state; } String buildTempUrl(String unit) { return "/temperature?unit=" + unit; }

Real Implementation Notes

Current Limitations

The actual implementation is simplified compared to a full-featured web server:

  • Only supports single parameter extraction per handler
  • Simple string-based temperature simulation (no unit conversion)
  • Basic LED control with on/off states only
  • Uses pin 9 instead of the standard pin 13

Troubleshooting

Common Issues

Parameters Not Working

  • Check URL format: page?param=value
  • Verify parameter names match exactly (case-sensitive)
  • Current implementation uses state for LED, not action

LED Pin Issues

  • This example uses pin 9, not pin 13
  • Verify LED_PIN constant matches your hardware

Query Parameter Access

  • Use QueryParams structure, not server.arg()
  • Loop through params.params[i] to find specific parameters

Debug Output

void debugParameters(const QueryParams& params) { Serial.println("=== Request Parameters ==="); Serial.println("Params count: " + String(params.count)); for (int i = 0; i < params.count; i++) { Serial.print(" "); Serial.print(params.params[i].key); Serial.print(" = "); Serial.println(params.params[i].value); } Serial.println("========================"); }

Customization

Adding New Handler with Parameters

void handleCustomPage(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { String theme = getParam(params, "theme", "light"); String lang = getParam(params, "lang", "en"); // Process parameters and generate response String response = "<html><body>"; response += "<h1>Custom Page</h1>"; response += "<p>Theme: " + theme + "</p>"; response += "<p>Language: " + lang + "</p>"; response += "</body></html>"; server.sendResponse(client, response.c_str()); } // Register the new route in setup() server.addRoute("/custom", handleCustomPage);

Template System Enhancement

The actual implementation uses simple placeholder replacement:

String response = TEMPERATURE_PAGE; response.replace("%TEMPERATURE_VALUE%", temperatureDisplay); // Add more replacements as needed response.replace("%UNIT%", unit); response.replace("%TIMESTAMP%", String(millis()));

Next Steps

  • Explore WebServerJson.ino for REST API development
  • Try WebServerWithWebSocket.ino for real-time communication
  • Implement form handling with POST parameters

Learning Resources

※ OUR MESSAGES