当前位置: 首页 > news >正文

ESP32开发入门(九):HTTP服务器开发实践

一、HTTP服务器基础

1.1 什么是HTTP服务器?

HTTP服务器是能够处理HTTP请求并返回响应的网络服务程序。在物联网应用中,ESP32可以作为轻量级HTTP服务器,直接接收来自客户端(如浏览器、手机APP)的请求。

1.2 ESP32作为HTTP服务器的特点

  1. 轻量级:适合资源有限的嵌入式设备

  2. 低功耗:可作为电池供电设备的控制接口

  3. 本地网络服务:无需云端即可提供Web服务

  4. 实时交互:直接控制硬件设备

  5. 配置简单:无需复杂网络配置

1.3 典型应用场景

  1. 设备控制面板:通过网页控制LED、继电器等

  2. 传感器数据展示:实时显示温湿度等数据

  3. 设备配置界面:WiFi配置、参数设置

  4. OTA升级服务:本地固件更新

  5. 局域网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 代码说明

  1. WebServer初始化

    • 使用WebServer类创建服务器实例

    • 默认监听80端口(HTTP标准端口)

  2. 路由处理

    • server.on()注册路径处理函数

    • 支持静态页面和API接口

    • 处理GET/POST请求

  3. HTML生成

    • 动态生成响应页面

    • 包含CSS内联样式

    • 响应式设计适配移动设备

  4. JSON API

    • 使用ArduinoJson库生成JSON数据

    • 返回设备状态和传感器数据

  5. 多任务处理

    • 使用FreeRTOS单独处理Web请求

    • 避免阻塞主循环

2.2 使用说明

  1. 修改WiFi配置(ssidpassword)

  2. 根据需求添加更多路由处理

  3. 集成实际传感器读取代码

  4. 如需HTTPS支持需额外配置

2.3 所需库

  • WiFi.h (Arduino ESP32核心自带)

  • WebServer.h (Arduino ESP32核心自带)

  • ArduinoJson.h (需单独安装)

三、功能验证与测试

3.1 基础功能测试

  1. 上传代码后,查看串口输出的IP地址

  2. 在浏览器中输入http://[ESP32-IP]

  3. 应显示包含传感器数据和控制按钮的页面

  4. 点击LED控制按钮测试功能

  5. 访问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 性能优化技巧

  1. 使用SPIFFS存储静态文件

    #include <SPIFFS.h>
    ​
    void setup() {if(!SPIFFS.begin(true)){Serial.println("SPIFFS Mount Failed");return;}server.serveStatic("/", SPIFFS, "/index.html");
    }

  2. 启用Gzip压缩

    server.enableCORS(true);
    server.enableGzip();
  3. 连接复用

    server.setReusePort(true);

5.2 安全增强措施

  1. 基本认证

    server.requireAuthentication("admin", "password");
  2. HTTPS支持

    #include <HTTPSServer.hpp>
    using namespace httpsserver;
    ​
    // 需要加载证书和私钥
    HTTPSServer secureServer = HTTPSServer(443);
  3. 请求限制

    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 学习路径

  1. 进阶Web开发

    • 学习使用SPIFFS文件系统

    • 实现更复杂的前端界面

    • 添加WebSocket实时通信

  2. 安全增强

    • 实现HTTPS安全连接

    • 添加用户认证系统

    • 防止CSRF攻击

  3. 性能优化

    • 学习异步Web服务器

    • 实现缓存策略

    • 优化内存使用

7.2 相关资源推荐

  1. ESP32开发入门(七):HTTP客户端开发实践

  2. ESP32官方WebServer示例

  3. ArduinoJson文档

  4. ESP32 HTTPS服务器指南

http://www.xdnf.cn/news/404965.html

相关文章:

  • Day22打卡-复习
  • 【K8S学习之探针】详细了解就绪探针 readinessProbe 和存活探针 livenessProbe 的配置
  • Kotlin 异步初始化值
  • JVM类加载
  • 生产环境怎么移除console
  • WebSocket集成方案对比
  • 中华春节符号全球推广委员会——“金文形意书《易经》成果展”研学之旅
  • 【Spark】使用Spark集群搭建Yarn模式
  • Docker-配置私有仓库(Harbor)
  • mapreduce-wordcount程序2
  • PostgreSQL 中的序列(Sequence)
  • 力扣HOT100之二叉树:226. 翻转二叉树
  • WSL-Ubuntu 中安装 Git LFS 记录
  • 网络编程epoll和udp
  • 华为防火墙配置与网络协议实战指南:从基础到高阶排查
  • 破局智算瓶颈:400G光模块如何重构AI时代的网络神经脉络
  • 大模型的实践应用41-天气预测与分析决策系统:Qwen3(32B)+langchain框架+MCP(大模型上下文协议)+RAG+传统算法
  • RabbitMQ高并发秒杀、抢购系统、预约系统底层实现逻辑
  • ArcGIS+InVEST+RUSLE:水土流失模拟与流域管理的高效解决方案;水土保持专题地图制作
  • 《Python星球日记》 第63天:文本方向综合项目(新闻分类)
  • 危化品安全员职业发展方向的优劣对比
  • 人工智能时代:解锁职业新身份,从“认证师”到“工程师”的进阶之路
  • 图灵爬虫练习平台第九题js逆向
  • 电力系统静态安全因素与动态安全因素的区别及具体分类
  • matlab计算天线的近场和远场
  • ThreadLocal原理分析--结合Spring事务
  • 产品设计基石--用户体验要素--实战4
  • 【课题推荐】基于改进遗传算法的公交车调度排班优化研究与实现方案
  • PID与模糊PID系统设计——基于模糊PID的水下航行器运动控制研究Simulink仿真(包含设计报告)
  • 在Web应用中集成Google AI NLP服务的完整指南:从Dialogflow配置到高并发优化