一、HTTP服務器基礎
1.1 什么是HTTP服務器?
HTTP服務器是能夠處理HTTP請求并返回響應的網絡服務程序。在物聯網應用中,ESP32可以作為輕量級HTTP服務器,直接接收來自客戶端(如瀏覽器、手機APP)的請求。
1.2 ESP32作為HTTP服務器的特點
-
輕量級:適合資源有限的嵌入式設備
-
低功耗:可作為電池供電設備的控制接口
-
本地網絡服務:無需云端即可提供Web服務
-
實時交互:直接控制硬件設備
-
配置簡單:無需復雜網絡配置
1.3 典型應用場景
-
設備控制面板:通過網頁控制LED、繼電器等
-
傳感器數據展示:實時顯示溫濕度等數據
-
設備配置界面:WiFi配置、參數設置
-
OTA升級服務:本地固件更新
-
局域網IoT中心:聚合多個設備數據
二、ESP32-S3 HTTP服務器實現 (FreeRTOS + Arduino框架)
#include <WiFi.h>
#include <WebServer.h>
#include <ArduinoJson.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
?
// WiFi配置
const char* ssid = "Your_WiFi_SSID";
const char* password = "Your_WiFi_Password";
?
// 創建WebServer實例,監聽80端口
WebServer server(80);
?
// FreeRTOS任務句柄
TaskHandle_t webServerTaskHandle = NULL;
?
// 傳感器數據示例
float temperature = 25.0;
float humidity = 60.0;
?
// 處理根路徑請求
void handleRoot() {String html = "<!DOCTYPE html><html><head>";html += "<title>ESP32 Web Server</title>";html += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">";html += "<style>body{font-family:Arial;text-align:center;margin-top:50px;}";html += ".card{display:inline-block;width:150px;border-radius:10px;";html += "box-shadow:0 4px 8px 0 rgba(0,0,0,0.2);padding:20px;margin:10px;}";html += ".button{padding:10px 20px;background-color:#4CAF50;color:white;";html += "border:none;border-radius:5px;text-decoration:none;}</style></head>";html += "<body><h1>ESP32 Web Server</h1>";// 顯示傳感器數據html += "<div class=\"card\"><h3>Temperature</h3><p>" + String(temperature) + " °C</p></div>";html += "<div class=\"card\"><h3>Humidity</h3><p>" + String(humidity) + " %</p></div>";// 控制按鈕html += "<div style=\"margin-top:30px;\">";html += "<a href=\"/led_on\" class=\"button\">LED ON</a> ";html += "<a href=\"/led_off\" class=\"button\">LED OFF</a>";html += "</div></body></html>";server.send(200, "text/html", html);
}
?
// 處理LED控制請求
void handleLEDOn() {digitalWrite(LED_BUILTIN, HIGH);server.send(200, "text/plain", "LED is ON");
}
?
void handleLEDOff() {digitalWrite(LED_BUILTIN, LOW);server.send(200, "text/plain", "LED is OFF");
}
?
// 處理API數據請求
void handleAPI() {StaticJsonDocument<200> jsonDoc;jsonDoc["device"] = "ESP32-S3";jsonDoc["temperature"] = temperature;jsonDoc["humidity"] = humidity;jsonDoc["uptime"] = millis() / 1000;String response;serializeJson(jsonDoc, response);server.send(200, "application/json", response);
}
?
// 處理未找到的路徑
void handleNotFound() {String message = "File Not Found\n\n";message += "URI: ";message += server.uri();message += "\nMethod: ";message += (server.method() == HTTP_GET) ? "GET" : "POST";message += "\nArguments: ";message += server.args();message += "\n";for (uint8_t i = 0; i < server.args(); i++) {message += " " + server.argName(i) + ": " + server.arg(i) + "\n";}server.send(404, "text/plain", message);
}
?
// Web服務器任務
void webServerTask(void *pvParameters) {while (1) {server.handleClient();vTaskDelay(10 / portTICK_PERIOD_MS);}
}
?
void setup() {Serial.begin(115200);pinMode(LED_BUILTIN, OUTPUT);// 連接WiFiWiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED) {delay(500);Serial.print(".");}Serial.println("");Serial.println("WiFi connected");Serial.print("IP address: ");Serial.println(WiFi.localIP());// 配置路由server.on("/", handleRoot);server.on("/led_on", handleLEDOn);server.on("/led_off", handleLEDOff);server.on("/api", handleAPI);server.onNotFound(handleNotFound);// 啟動Web服務器server.begin();Serial.println("HTTP server started");// 創建Web服務器任務xTaskCreatePinnedToCore(webServerTask, ? ? ?// 任務函數"WebServer Task", ? // 任務名稱8192, ? ? ? ? ? ? ? // 堆棧大小NULL, ? ? ? ? ? ? ? // 參數1, ? ? ? ? ? ? ? ? ?// 優先級&webServerTaskHandle, // 任務句柄1 ? ? ? ? ? ? ? ? ? // 運行在核心1上);
}
?
void loop() {// 模擬更新傳感器數據temperature = 25.0 + (millis() % 200) * 0.1;humidity = 60.0 + (millis() % 150) * 0.1;vTaskDelay(10000 / portTICK_PERIOD_MS); // 每10秒更新一次
}
2.1 代碼說明
-
WebServer初始化:
-
使用
WebServer
類創建服務器實例 -
默認監聽80端口(HTTP標準端口)
-
-
路由處理:
-
server.on()
注冊路徑處理函數 -
支持靜態頁面和API接口
-
處理GET/POST請求
-
-
HTML生成:
-
動態生成響應頁面
-
包含CSS內聯樣式
-
響應式設計適配移動設備
-
-
JSON API:
-
使用ArduinoJson庫生成JSON數據
-
返回設備狀態和傳感器數據
-
-
多任務處理:
-
使用FreeRTOS單獨處理Web請求
-
避免阻塞主循環
-
2.2 使用說明
-
修改WiFi配置(
ssid
和password
) -
根據需求添加更多路由處理
-
集成實際傳感器讀取代碼
-
如需HTTPS支持需額外配置
2.3 所需庫
-
WiFi.h (Arduino ESP32核心自帶)
-
WebServer.h (Arduino ESP32核心自帶)
-
ArduinoJson.h (需單獨安裝)
三、功能驗證與測試
3.1 基礎功能測試
-
上傳代碼后,查看串口輸出的IP地址
-
在瀏覽器中輸入
http://[ESP32-IP]
-
應顯示包含傳感器數據和控制按鈕的頁面
-
點擊LED控制按鈕測試功能
-
訪問
http://[ESP32-IP]/api
測試JSON API
3.2 高級測試場景
3.2.1 使用cURL測試API
# 獲取設備信息
curl http://[ESP32-IP]/api
?
# 控制LED
curl http://[ESP32-IP]/led_on
curl http://[ESP32-IP]/led_off
3.2.2 POST請求測試
添加表單處理路由:
void handleForm() {if (server.method() != HTTP_POST) {server.send(405, "text/plain", "Method Not Allowed");return;}String message = "Received:\n";for (uint8_t i = 0; i < server.args(); i++) {message += server.argName(i) + ": " + server.arg(i) + "\n";}server.send(200, "text/plain", message);
}
?
// 在setup()中添加
server.on("/submit", HTTP_POST, handleForm);
測試命令:
curl -X POST -d "name=ESP32&value=100" http://[ESP32-IP]/submit
四、實際項目應用
4.1 智能家居控制面板
// 控制多個設備的HTML頁面
void handleControlPanel() {String html = "<html><body><h1>Home Control</h1>";html += "<form action='/control' method='post'>";html += "Light: <input type='radio' name='light' value='1'>ON ";html += "<input type='radio' name='light' value='0' checked>OFF<br>";html += "Fan Speed: <input type='range' name='fan' min='0' max='3'><br>";html += "<input type='submit' value='Apply'>";html += "</form></body></html>";server.send(200, "text/html", html);
}
?
// 處理控制請求
void handleControl() {if (server.hasArg("light")) {int lightState = server.arg("light").toInt();digitalWrite(LIGHT_PIN, lightState);}if (server.hasArg("fan")) {int fanSpeed = server.arg("fan").toInt();analogWrite(FAN_PIN, fanSpeed * 85);}server.send(200, "text/plain", "Settings applied");
}
4.2 OTA升級服務
#include <Update.h>
?
void handleOTAUpdate() {server.sendHeader("Connection", "close");server.send(200, "text/html", "<form method='POST' action='/do_update' enctype='multipart/form-data'>""<input type='file' name='update'>""<input type='submit' value='Update'>""</form>");
}
?
void handleDoUpdate() {HTTPUpload& upload = server.upload();if (upload.status == UPLOAD_FILE_START) {Serial.printf("Update: %s\n", upload.filename.c_str());if (!Update.begin(UPDATE_SIZE_UNKNOWN)) {Update.printError(Serial);}} else if (upload.status == UPLOAD_FILE_WRITE) {if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {Update.printError(Serial);}} else if (upload.status == UPLOAD_FILE_END) {if (Update.end(true)) {Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);server.sendHeader("Location", "/");server.send(303);} else {Update.printError(Serial);}}
}
?
// 在setup()中添加
server.on("/update", handleOTAUpdate);
server.on("/do_update", HTTP_POST, []() {server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");ESP.restart();
}, handleDoUpdate);
五、性能優化與安全
5.1 性能優化技巧
-
使用SPIFFS存儲靜態文件
#include <SPIFFS.h> ? void setup() {if(!SPIFFS.begin(true)){Serial.println("SPIFFS Mount Failed");return;}server.serveStatic("/", SPIFFS, "/index.html"); }
-
啟用Gzip壓縮
server.enableCORS(true); server.enableGzip();
-
連接復用
server.setReusePort(true);
5.2 安全增強措施
-
基本認證
server.requireAuthentication("admin", "password");
-
HTTPS支持
#include <HTTPSServer.hpp> using namespace httpsserver; ? // 需要加載證書和私鑰 HTTPSServer secureServer = HTTPSServer(443);
-
請求限制
void handleRequest() {static unsigned long lastRequest = 0;if (millis() - lastRequest < 1000) {server.send(429, "text/plain", "Too Many Requests");return;}lastRequest = millis();// 正常處理 }
六、擴展功能
6.1 WebSocket實時通信
#include <WebSocketsServer.h>
?
WebSocketsServer webSocket = WebSocketsServer(81);
?
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {switch(type) {case WStype_DISCONNECTED:Serial.printf("[%u] Disconnected!\n", num);break;case WStype_CONNECTED:Serial.printf("[%u] Connected!\n", num);break;case WStype_TEXT:Serial.printf("[%u] Received: %s\n", num, payload);webSocket.broadcastTXT(payload, length);break;}
}
?
void setup() {webSocket.begin();webSocket.onEvent(webSocketEvent);
}
6.2 mDNS服務發現
#include <ESPmDNS.h>
?
void setup() {if (MDNS.begin("esp32")) {Serial.println("mDNS responder started");MDNS.addService("http", "tcp", 80);}
}
七、總結與擴展學習
7.1 學習路徑
-
進階Web開發
-
學習使用SPIFFS文件系統
-
實現更復雜的前端界面
-
添加WebSocket實時通信
-
-
安全增強
-
實現HTTPS安全連接
-
添加用戶認證系統
-
防止CSRF攻擊
-
-
性能優化
-
學習異步Web服務器
-
實現緩存策略
-
優化內存使用
-
7.2 相關資源推薦
-
ESP32開發入門(七):HTTP客戶端開發實踐
-
ESP32官方WebServer示例
-
ArduinoJson文檔
-
ESP32 HTTPS服務器指南