ESP32-WIFI-WebUI控制LED
逻辑流程(A = ESP32,B = 客户端)
- A:将 ESP32 配置为 AP 模式,开启 Wi-Fi 热点并作为 HTTP 服务器运行。
- B:电脑或手机连接到 ESP32 热点,建立局域网通信。
- B → A:客户端在浏览器访问 192.168.4.1,向 ESP32 发送 HTTP GET 请求。
- A → B:ESP32 响应请求,返回 HTML 网页文件。
- B:浏览器接收并解析 HTML 文件,显示网页内容。
- B → A:用户在网页上点击按钮,浏览器向 ESP32 发送带有控制参数的 HTTP GET 请求(如 led_on / led_off)。
- A:ESP32 解析 URL 参数,根据指令触发对应的回调函数执行操作(如控制 LED 开关)。
Web界面
通过手机抓包软件分析
第一次进入192.168.4.1网址
可以看到响应内容格式为
text/html
对应代码段中处理根目录请求函数构造的数据响应格式(text/html)
按下按键(触发发送led_on事件)按下按键(触发发送led_off事件)可以分析看到请求路径为/led
分析代码可知触发路径为/led的请求格式后,处理函数为led_handler
后面源码中有详细解释led_handler()作用
在此简略说明处理过程:获取URL,查询键值对,判断值,做出处理
重要代码段分析
初始化NVS
- // 初始化NVS(非易失性存储)闪存,用于存储WiFi配置等数据
- ESP_ERROR_CHECK(nvs_flash_init());
复制代码 初始化 Wi-Fi AP 模式
- void wifi_init_softap(void)
- {
- // 初始化网络接口
- ESP_ERROR_CHECK(esp_netif_init());
- // 创建默认事件循环
- ESP_ERROR_CHECK(esp_event_loop_create_default());
- // 创建默认的Wi-Fi AP网络接口
- esp_netif_create_default_wifi_ap();
- // 初始化Wi-Fi配置
- wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
- ESP_ERROR_CHECK(esp_wifi_init(&cfg));
- // 配置Wi-Fi AP参数
- wifi_config_t wifi_config = {
- .ap = {
- .ssid = "ESP32_WEB", // 设置SSID名称
- .ssid_len = strlen("ESP32_WEB"), // SSID长度
- .password = "12345678", // 设置密码
- .max_connection = 2, // 最大连接数
- .authmode = WIFI_AUTH_WPA_WPA2_PSK // 设置认证模式为WPA/WPA2
- },
- };
- // 如果密码为空,则将认证模式设置为开放模式
- if (strlen((char *)wifi_config.ap.password) == 0)
- wifi_config.ap.authmode = WIFI_AUTH_OPEN;
- // 设置Wi-Fi模式为AP模式
- ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
- // 设置Wi-Fi配置
- ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
- // 启动Wi-Fi
- ESP_ERROR_CHECK(esp_wifi_start());
- // 打印日志,显示Wi-Fi AP已启动的信息
- ESP_LOGI(TAG, "Wi-Fi AP started. SSID:%s password:%s", "ESP32_WEB", "12345678");
- }
复制代码 初始化外设led(略)
启动HTTP服务器(注册服务器响应函数)
- // 启动 HTTP 服务器
- httpd_handle_t start_webserver(void)
- {
- httpd_config_t config = HTTPD_DEFAULT_CONFIG();
- httpd_handle_t server = NULL;
-
- if (httpd_start(&server, &config) == ESP_OK) {
- //注册根路径(/)的处理函数:
- httpd_uri_t index_uri = {
- .uri = "/",
- .method = HTTP_GET,
- .handler = index_handler,// 设置处理函数为index_handler
- .user_ctx = NULL //回传html
- };
- httpd_register_uri_handler(server, &index_uri);//注册到服务器中
- //注册 /led 路径的处理函数
- // 定义一个httpd_uri_t类型的变量led_uri// 设置uri为"/led"
- httpd_uri_t led_uri = {
- .uri = "/led",
- .method = HTTP_GET,
- .handler = led_handler,// 设置处理函数为led_handler
- .user_ctx = NULL //设置led
- };
- httpd_register_uri_handler(server, &led_uri);
- }
- return server;
- }
复制代码 处理/根目录请求,返回 HTML
- static esp_err_t index_handler(httpd_req_t *req)——
- {
- httpd_resp_set_type(req, "text/html");
- return httpd_resp_send(req, (const char *)_binary_index_html_start,
- _binary_index_html_end - _binary_index_html_start);
- }
复制代码 处理 /led 控制请求
- // 静态函数,用于处理LED控制请求
- static esp_err_t led_handler(httpd_req_t *req)
- {
- // 定义一个字符数组,用于存储URL查询字符串
- char buf[100];
- // 获取URL查询字符串的长度,并加1
- size_t len = httpd_req_get_url_query_len(req) + 1;
- // 如果URL查询字符串的长度大于1
- if (len > 1) {
- // 获取URL查询字符串
- httpd_req_get_url_query_str(req, buf, len);
- // 定义一个字符数组,用于存储查询参数
- char param[10];
- // 如果查询参数为"state"
- if (httpd_query_key_value(buf, "state", param, sizeof(param)) == ESP_OK) {
- // 打印查询参数
- ESP_LOGI(TAG, "LED state param: %s", param);
- // 如果查询参数为"on"
- if (strcmp(param, "on") == 0) {
- // 设置LED引脚为高电平
- gpio_set_level(LED_GPIO, 1);
- // 设置LED状态为打开
- led_on = true;
- // 发送响应,LED已打开
- httpd_resp_sendstr(req, "LED turned ON");
- // 如果查询参数为"off"
- } else if (strcmp(param, "off") == 0) {
- // 设置LED引脚为低电平
- gpio_set_level(LED_GPIO, 0);
- // 设置LED状态为关闭
- led_on = false;
- // 发送响应,LED已关闭
- httpd_resp_sendstr(req, "LED turned OFF");
- // 如果查询参数不为"on"或"off"
- } else {
- // 发送响应,LED状态无效
- httpd_resp_sendstr(req, "Invalid LED state");
- }
- // 如果查询参数不为"state"
- } else {
- // 发送响应,缺少"state"参数
- httpd_resp_sendstr(req, "Missing 'state' param");
- }
- // 如果URL查询字符串的长度不大于1
- } else {
- // 发送响应,未提供查询参数
- httpd_resp_sendstr(req, "No query provided");
- }
- // 返回ESP_OK
- return ESP_OK;
- }
复制代码 Web网页端(HTML)
触发部分
源码:
main.c
[code] #include #include "esp_event.h" #include "esp_log.h" #include "esp_netif.h" #include "nvs_flash.h" #include "esp_wifi.h" #include "esp_http_server.h" #include "driver/gpio.h" #define LED_GPIO GPIO_NUM_48 // 可根据板子修改,比如GPIO2或GPIO5 static const char *TAG = "WEB_LED"; // 嵌入的 HTML 网页内容 extern const uint8_t _binary_index_html_start[]; extern const uint8_t _binary_index_html_end[]; // LED 控制状态 static bool led_on = false; // 处理根目录请求,返回 HTML static esp_err_t index_handler(httpd_req_t *req) { httpd_resp_set_type(req, "text/html"); return httpd_resp_send(req, (const char *)_binary_index_html_start, _binary_index_html_end - _binary_index_html_start); } // 处理 /led 控制请求 // 静态函数,用于处理LED控制请求 static esp_err_t led_handler(httpd_req_t *req) { // 定义一个字符数组,用于存储URL查询字符串 char buf[100]; // 获取URL查询字符串的长度,并加1 size_t len = httpd_req_get_url_query_len(req) + 1; // 如果URL查询字符串的长度大于1 if (len > 1) { // 获取URL查询字符串 httpd_req_get_url_query_str(req, buf, len); // 定义一个字符数组,用于存储查询参数 char param[10]; // 如果查询参数为"state" if (httpd_query_key_value(buf, "state", param, sizeof(param)) == ESP_OK) { // 打印查询参数 ESP_LOGI(TAG, "LED state param: %s", param); // 如果查询参数为"on" if (strcmp(param, "on") == 0) { // 设置LED引脚为高电平 gpio_set_level(LED_GPIO, 1); // 设置LED状态为打开 led_on = true; // 发送响应,LED已打开 httpd_resp_sendstr(req, "LED turned ON"); // 如果查询参数为"off" } else if (strcmp(param, "off") == 0) { // 设置LED引脚为低电平 gpio_set_level(LED_GPIO, 0); // 设置LED状态为关闭 led_on = false; // 发送响应,LED已关闭 httpd_resp_sendstr(req, "LED turned OFF"); // 如果查询参数不为"on"或"off" } else { // 发送响应,LED状态无效 httpd_resp_sendstr(req, "Invalid LED state"); } // 如果查询参数不为"state" } else { // 发送响应,缺少"state"参数 httpd_resp_sendstr(req, "Missing 'state' param"); } // 如果URL查询字符串的长度不大于1 } else { // 发送响应,未提供查询参数 httpd_resp_sendstr(req, "No query provided"); } // 返回ESP_OK return ESP_OK; } // 初始化 GPIO void led_gpio_init(void) { gpio_config_t io_conf = { .pin_bit_mask = 1ULL |