跳到主要内容

网页服务器

ESP32 内置了 Wi-Fi 功能,能够作为网页服务器(Web Server)向网络中的其他设备提供服务。通过在 ESP32 上运行网页服务器,可以创建基于浏览器的用户界面,用于监控传感器数据或控制设备状态,是实现物联网(IoT)应用的基础功能之一。

1. WebServer 库简介

Arduino-ESP32 核心库内置了 WebServer.h,它提供了一套简洁的 API 来快速构建 Web Server。通过注册路由(URL 路径)及回调函数,实现请求分发与应答。适用于绝大多数典型 IOT 项目的本地网页交互。本教程将使用此库。

  • 简洁易用,适合入门和资源受限场景。
  • 需在主循环 (loop() ) 中定期调用 server.handleClient() 以处理客户端请求。
  • 对大流量/高并发等复杂场景建议选用异步库(如 ESPAsyncWebServer)。

2. 示例 1:基础网页服务(STA 模式)

在 STA 模式下创建一个基础的网页服务器,用于显示一个包含"Hello World!"的静态页面。

2.1 代码

#include <WiFi.h>
#include <WebServer.h>

const char *ssid = "Maker";
const char *password = "12345678";

WebServer server(80);

void setup() {
Serial.begin(115200);
delay(10);

// 连接 WiFi 网络
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.begin(ssid, password);

// 等待连接成功
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

Serial.println();
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

// 配置路由和启动服务器
server.on("/", handleRoot);
server.begin();
}

void loop() {
server.handleClient();
}

// 处理根路径请求
void handleRoot() {
server.send(200, "text/html", generateHTML());
}

// 生成 HTML 页面内容
String generateHTML() {
String htmlContent = "<!DOCTYPE html> <html>\n";
htmlContent += "<head><meta name=\"viewport\" content=\"width=device-width\">\n";
htmlContent += "<title>ESP32S3 Test</title>\n";
htmlContent += "</head><body>\n";
htmlContent += "<h1>Hello World!</h1>\n";
htmlContent += "</body>\n";
htmlContent += "</html>\n";
return htmlContent;
}

2. 代码解释

  • #include <WebServer.h>:引入 Web Server 库,用以在 ESP32 上创建 HTTP 服务器。
  • WebServer server(80);:创建一个服务器对象,监听标准的 HTTP 端口 80。80 是 HTTP 协议的默认端口。
  • server.on("/", handleRoot);:注册路由处理函数。当客户端访问根路径"/"时,调用handleRoot()函数。
  • server.begin();:启动服务器,开始监听客户端的连接请求。
  • server.handleClient();:在loop()中持续调用,处理传入的客户端请求。
  • handleRoot():这是一个自定义的回调函数,用于处理特定路径的请求。
  • server.send(statusCode, contentType, content);:向客户端发送一个 HTTP 响应。向客户端浏览器返回包含 "Hello World" 的简单 HTML 页面。
    • 200:HTTP 状态码,200 OK 表示请求成功。
    • "text/html":MIME 类型,告知浏览器响应内容是 HTML 文本。
    • generateHTML():函数返回的字符串,即网页的实际内容。
  • generateHTML():一个辅助函数,将 HTML 代码拼接成一个 String 对象,返回包含完整 HTML 结构的字符串。

3. 运行结果

将代码中的 ssidpassword 修改为目标 Wi-Fi 网络的名称和密码后上传。串口监视器将显示连接过程和获取到的 IP 地址。在同一局域网的设备上打开浏览器,输入显示的 IP 地址,即可看到"Hello World!"页面。

3. 示例 2:通过网页控制 LED (STA 模式)

在 STA 模式下,开启网页服务器。同局域网下的设备,通过网页控制 ESP32 连接的 LED 状态。

3.1 搭建电路

需要使用的器件有:

  • LED * 1
  • 330Ω 电阻 * 1
  • 面包板 * 1
  • 导线
  • ESP32 开发板

按照下面接线图连接电路:

ESP32-S3-Zero 引脚图

ESP32-S3-Zero-Pinout

接线图

3.2 代码

#include <WiFi.h>
#include <WebServer.h>

const int ledPin = 7;

const char *ssid = "Maker";
const char *password = "12345678";

WebServer server(80);

String generateHTML(bool ledState = false);

void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(115200);

// 连接 WiFi 网络
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.begin(ssid, password);

// 等待连接成功
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

Serial.println();
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

// 配置路由和启动服务器
server.on("/", handleRoot);
server.on("/ledon", handleLedOn);
server.on("/ledoff", handleLedOff);
server.begin();
}

void loop() {
server.handleClient();
}

// 处理根路径请求
void handleRoot() {
server.send(200, "text/html", generateHTML(digitalRead(ledPin)));
}

// 开启 LED
void handleLedOn() {
digitalWrite(ledPin, HIGH);
server.send(200, "text/html", generateHTML(true));
}

// 关闭 LED
void handleLedOff() {
digitalWrite(ledPin, LOW);
server.send(200, "text/html", generateHTML(false));
}

// 生成 HTML 页面内容
String generateHTML(bool ledState) {
String htmlContent = "<!DOCTYPE html> <html>\n";
htmlContent += "<head><meta name=\"viewport\" content=\"width=device-width\">\n";
htmlContent += "<title>ESP32S3 Test</title>\n";
htmlContent += "</head><body>\n";

htmlContent += "<h1>Hello World!</h1>\n";

if (ledState) {
htmlContent += "<p>LED Status: ON</p>";
htmlContent += "<a href=\"/ledoff\">LED OFF</a>\n";
} else {
htmlContent += "<p>LED Status: OFF</p>";
htmlContent += "<a href=\"/ledon\">LED ON</a>\n";
}

htmlContent += "</body>\n";
htmlContent += "</html>\n";
return htmlContent;
}

3.3 代码解析

  • 新增路由

    • server.on("/ledon", handleLedOn);

      /ledon 路径的请求绑定到 handleLedOn 函数。当浏览器访问 http://<IP 地址>/ledon 时,服务器将调用 handleLedOn 函数。

    • server.on("/ledoff", handleLedOff);

      同理,将 /ledoff 路径绑定到 handleLedOff 函数。当浏览器访问 http://<IP 地址>/ledoff 时,服务器将调用 handleLedOff 函数。

  • LED 控制

    • 使用 HTML 的 <a> 标签创建链接按钮,点击时会向相应的路径发送 GET 请求,实现 LED 的控制。

      当用户点击“LED ON”链接时,浏览器会向服务器的 /ledon 路径发起一个 HTTP GET 请求。

      服务器收到后,server.handleClient() 会匹配到 server.on("/ledon", handleLedOn); ,进而执行 handleLedOn 函数。

    • handleLedOnhandleLedOff 函数中,首先通过 digitalWrite() 控制 LED 状态。执行硬件操作后,它们会再次调用 generateHTML() 生成新的页面并发送给客户端,以更新页面状态。

  • 动态 HTML

    • generateHTML(bool ledState) 函数现在接受一个布尔参数,代表 LED 的当前状态。
    • 函数内部使用 if-else 语句,根据 ledState 的值,动态地生成不同的 HTML 内容。如果灯是亮的,就显示 "OFF" 按钮;如果灯是灭的,就显示 "ON" 按钮。

3.4 运行结果

上传代码后,打开串口监视器查看 IP 地址。然后在浏览器中访问该 IP 地址,页面会显示当前 LED 状态和控制按钮。点击"LED ON"或"LED OFF"按钮可以控制 LED 的开关状态,页面会实时更新显示当前状态。

信息

以上网页未做页面美化,仅用作功能演示,可自行扩展 HTML/CSS 实现更友好的用户界面。

4. 示例 3:通过网页控制 LED (AP 模式)

在 AP 模式下,开启网页服务器。其他设备连接 ESP32 创建的 Wi-Fi 热点后,可直接通过网页访问 ESP32 提供的服务器,实现对 LED 状态的控制。

4.1 搭建电路

需要使用的器件有:

  • LED * 1
  • 330Ω 电阻 * 1
  • 面包板 * 1
  • 导线
  • ESP32 开发板

按照下面接线图连接电路:

ESP32-S3-Zero 引脚图

ESP32-S3-Zero-Pinout

接线图

4.2 代码

#include <WiFi.h>
#include <WebServer.h>

const int ledPin = 7;

const char *ssid = "ESP32S3-TEST"; // 设置热点名称
const char *password = "12345678"; // 设置热点密码(至少 8 位)

WebServer server(80);

String generateHTML(bool ledState = false);

void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(115200);

// 创建 Wi-Fi 热点
Serial.println("Configuring access point...");
if (!WiFi.softAP(ssid, password)) {
Serial.println("Soft AP creation failed.");
while (1)
;
}
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);

// 配置路由和启动服务器
server.on("/", handleRoot);
server.on("/ledon", handleLedOn);
server.on("/ledoff", handleLedOff);
server.begin();
}

void loop() {
server.handleClient();
}

// 处理根路径请求
void handleRoot() {
server.send(200, "text/html", generateHTML(digitalRead(ledPin)));
}

// 开启 LED
void handleLedOn() {
digitalWrite(ledPin, HIGH);
server.send(200, "text/html", generateHTML(true));
}

// 关闭 LED
void handleLedOff() {
digitalWrite(ledPin, LOW);
server.send(200, "text/html", generateHTML(false));
}

// 生成 HTML 页面内容
String generateHTML(bool ledState) {
String htmlContent = "<!DOCTYPE html> <html>\n";
htmlContent += "<head><meta name=\"viewport\" content=\"width=device-width\">\n";
htmlContent += "<title>ESP32S3 Test</title>\n";
htmlContent += "</head><body>\n";

htmlContent += "<h1>Hello World!</h1>\n";

if (ledState) {
htmlContent += "<p>LED Status: ON</p>";
htmlContent += "<a href=\"/ledoff\">LED OFF</a>\n";
} else {
htmlContent += "<p>LED Status: OFF</p>";
htmlContent += "<a href=\"/ledon\">LED ON</a>\n";
}

htmlContent += "</body>\n";
htmlContent += "</html>\n";
return htmlContent;
}

4.3 代码解析

  • AP 模式配置:使用 WiFi.softAP(ssid, password) 创建 Wi-Fi 热点,而不是连接到现有网络。
  • WiFi.softAPIP():获取 ESP32 作为热点时的 IP 地址,通常默认为 192.168.4.1。
  • 独立网络:ESP32 创建自己的局域网,其他设备需要先连接到这个热点才能访问网页服务器。
  • 网页服务器逻辑:处理 HTTP 请求的逻辑与 STA 模式下的示例基本一致,主要区别在于网络连接的初始化方式。

4.4 运行结果

上传代码后,ESP32 会创建一个名为"ESP32S3-TEST"的 Wi-Fi 热点。使用电脑或手机连接此热点(密码:12345678),然后在浏览器中访问 192.168.4.1,即可看到 LED 控制页面。点击按钮可以控制 LED 的开关状态。

5. 相关链接