ESP32 Query String Web Server Tham Số URL Động

Ví Dụ WebServerQueryStrings - Server Đa Trang Động

Tổng Quan

Ví dụ này minh họa cách tạo một web server đa trang động sử dụng tham số query URL để cung cấp nội dung tương tác và chức năng điều khiển với điều hướng trang liền mạch.

Tính Năng

  • Điều hướng đa trang với nội dung động dựa trên tham số URL
  • Chuyển đổi đơn vị nhiệt độ (Celsius/Fahrenheit) thông qua tham số query
  • Điều khiển LED với tham số query string
  • Tạo nội dung động dựa trên đầu vào người dùng
  • Bố cục đa trang chuyên nghiệp với điều hướng nhất quán
  • Phân tích và xác thực tham số URL

Phần Cứng Cần Thiết

1×mô-đun phát triển ESP-WROOM-32
1×Alternatively, ESP32 Uno-form board
1×Alternatively, ESP32 S3 Uno-form board
1×Cáp USB Type-C
1×(Khuyến nghị) Screw Terminal Expansion Board for ESP32
1×(Khuyến nghị) Breakout Expansion Board for ESP32
1×(Khuyến nghị) 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)

Cài Đặt Thư Viện

Thực hiện theo các hướng dẫn sau từng bước:

  • Nếu đây là lần đầu tiên bạn sử dụng ESP32, hãy tham khảo hướng dẫn về thiết lập môi trường cho ESP32 trong Arduino IDE.
  • Kết nối board ESP32 với máy tính của bạn bằng cáp USB.
  • Khởi động Arduino IDE trên máy tính của bạn.
  • Chọn board ESP32 thích hợp (ví dụ: ESP32) và cổng COM.
  • Mở Library Manager bằng cách nhấp vào biểu tượng Library Manager ở phía bên trái của Arduino IDE.
  • Tìm kiếm Web Server for ESP32 và định vị thư viện mWebSockets của DIYables.
  • Nhấp vào nút Install để thêm thư viện mWebSockets.
ESP32 web server thư viện

Ví Dụ Web Server Query Strings

  • Trong Arduino IDE, đi tới File Examples Web Server for ESP32 WebServerQueryStrings để mở mã ví dụ

Cấu Trúc Code

  1. home.h: Template HTML trang chủ
  2. temperature.h: Template trang giám sát nhiệt độ
  3. led.h: Template trang điều khiển LED
  4. WebServerQueryStrings.ino: Logic server chính

Kết Nối Mạch

Không cần linh kiện ngoài - ví dụ này sử dụng LED tích hợp trên pin 13.

Tính Năng Tham Số Query

Tham Số Trang Nhiệt Độ

  • unit=c hoặc unit=celsius - Hiển thị nhiệt độ theo Celsius
  • unit=f hoặc unit=fahrenheit - Hiển thị nhiệt độ theo Fahrenheit
  • Không có tham số - Mặc định là Celsius

Tham Số Điều Khiển LED

  • state=on - Bật LED
  • state=off - Tắt LED

Hướng Dẫn Thiết Lập

1. Cấu Hình Mạng

Chỉnh sửa thông tin WiFi trực tiếp trong file WebServerQueryStrings.ino:

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

2. Upload Code và Theo Dõi Đầu Ra

  1. Kết nối ESP32 với máy tính của bạn
  2. Chọn board và port đúng trong Arduino IDE
  3. Upload sketch WebServerQueryStrings.ino
  4. Mở Serial Monitor (9600 baud)
  5. Đợi kết nối WiFi
  6. Ghi chú địa chỉ IP được hiển thị
  7. Nếu bạn không thấy địa chỉ IP trong Serial monitor, nhấn nút reset trên board ESP32

Ví Dụ Sử Dụng

Mở trình duyệt web của bạn và nhập địa chỉ IP hiển thị trong Serial Monitor để truy cập web server.

ESP32 web server query strings

Kiểm Tra Chức Năng Giám Sát Nhiệt Độ:

  • Nhấp vào menu "Temperature".
  • Xem hiển thị nhiệt độ. Nhấp vào từng nút để thay đổi đơn vị nhiệt độ
ESP32 web server temperature query strings

Kiểm Tra Chức Năng Điều Khiển LED:

  • Nhấp vào menu "LED Control". Bạn sẽ thấy giao diện web như bên dưới:
LED control page query strings
  • Bật và tắt LED bằng các nút được cung cấp.
  • Quan sát trạng thái LED tích hợp trên board ESP32 cập nhật ngay lập tức.

Truy Cập Các Trang Khác Nhau

Trang Chủ
  • URL: http://your-esp32-ip/
  • Tính Năng: Trang chào mừng với menu điều hướng
Trang Nhiệt Độ (Mặc Định - Celsius)
  • URL: http://your-esp32-ip/temperature
  • Hiển Thị: Nhiệt độ theo Celsius với bộ chọn đơn vị
Nhiệt Độ Theo Fahrenheit
  • URL: http://your-esp32-ip/temperature?unit=f
  • URL: http://your-esp32-ip/temperature?unit=fahrenheit
  • Hiển Thị: Nhiệt độ được chuyển đổi sang Fahrenheit
Điều Khiển LED
  • Bật: http://your-esp32-ip/led?state=on
  • Tắt: http://your-esp32-ip/led?state=off

Giải Thích Code

Xử Lý Tham Số Query

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()); }

Điều Khiển LED với Tham Số Query

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()); }

Xác Thực Tham Số

// 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 == ""); }

Template HTML với Nội Dung Động

Template Trang Nhiệt Độ

<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>

Template Điều Khiển LED

<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>

Tính Năng Nâng Cao

Cấu Hình Route

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); }

Hàm Hỗ Trợ Tham Số Query

// 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; }

Hàm Hỗ Trợ Xây Dựng URL

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

Ghi Chú Triển Khai Thực Tế

Hạn Chế Hiện Tại

Triển khai thực tế được đơn giản hóa so với web server đầy đủ tính năng:

  • Chỉ hỗ trợ trích xuất tham số đơn lẻ cho mỗi handler
  • Mô phỏng nhiệt độ đơn giản dựa trên chuỗi (không có chuyển đổi đơn vị)
  • Điều khiển LED cơ bản chỉ với trạng thái bật/tắt
  • Sử dụng pin 9 thay vì pin 13 tiêu chuẩn

Khắc Phục Sự Cố

Vấn Đề Phổ Biến

Tham Số Không Hoạt Động

  • Kiểm tra định dạng URL: page?param=value
  • Xác minh tên tham số khớp chính xác (phân biệt chữ hoa chữ thường)
  • Triển khai hiện tại sử dụng state cho LED, không phải action

Vấn Đề Pin LED

  • Ví dụ này sử dụng pin 9, không phải pin 13
  • Xác minh hằng số LED_PIN khớp với phần cứng của bạn

Truy Cập Tham Số Query

  • Sử dụng cấu trúc QueryParams, không phải server.arg()
  • Lặp qua params.params[i] để tìm các tham số cụ thể

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("========================"); }

Tùy Chỉnh

Thêm Handler Mới với Tham Số

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);

Cải Tiến Hệ Thống Template

Triển khai thực tế sử dụng thay thế placeholder đơn giản:

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

Bước Tiếp Theo

  • Khám phá WebServerJson.ino để phát triển REST API
  • Thử WebServerWithWebSocket.ino cho giao tiếp thời gian thực
  • Triển khai xử lý form với tham số POST

Tài Nguyên Học Tập