如何为家用ESP32 HTTP服务器搭建本地圣诞灯控制UI
可行的UI搭建方案
方案1:在ESP32中嵌入Web UI(最简便)
直接把控制UI的HTML+JS代码嵌入到ESP32的HTTP服务器中,用户通过浏览器访问10.0.0.22即可打开控制界面,完全规避跨域和安全限制:
- 在ESP32代码中,添加根路由(比如
/),返回包含UI的HTML内容,页面内的JS直接向你的控制接口(比如/control)发送POST请求——因为是同一IP下的请求,不存在跨域问题。 - 示例ESP32代码片段(Arduino框架):
#include <WiFi.h> #include <WebServer.h> WebServer server(80); void handleRoot() { String html = "<!DOCTYPE html>" "<html>" "<body>" "<h1>圣诞灯控制</h1>" "<textarea id='requestBody' placeholder='输入自定义请求体' rows='4' cols='30'></textarea>" "<br>" "<button onclick='sendControl()'>发送控制请求</button>" "<script>" "async function sendControl() {" " const body = document.getElementById('requestBody').value;" " try {" " const res = await fetch('/control', {" " method: 'POST'," " body: body" " });" " alert('请求成功:' + await res.text());" " } catch (err) {" " alert('请求失败:' + err.message);" " }" "}" "</script>" "</body>" "</html>"; server.send(200, "text/html", html); } void handleControl() { // 读取POST请求体并执行控制逻辑 String reqBody = server.arg("plain"); // 你的圣诞灯控制代码 server.send(200, "text/plain", "控制指令已接收"); } void setup() { // WiFi连接代码... server.on("/", handleRoot); server.on("/control", HTTP_POST, handleControl); server.begin(); } void loop() { server.handleClient(); } - 优势:无需额外APP或本地文件,所有逻辑都在ESP32上,同一WiFi下直接用浏览器访问即可,无安全限制。
方案2:修复Flutter APP打包后的HTTP请求问题
你调试时可用但打包后失效,核心原因是Android 9+默认禁止明文HTTP请求,只需配置安卓项目允许对目标IP的明文访问:
- 快速解决:在Flutter项目的
android/app/src/main/AndroidManifest.xml中,给application标签添加:android:usesCleartextTraffic="true" - 精细配置(推荐,仅允许指定IP):
- 创建
android/app/src/main/res/xml/network_security_config.xml文件,内容:<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="false">10.0.0.22</domain> </domain-config> </network-security-config> - 在
AndroidManifest.xml的application标签中引用该配置:android:networkSecurityConfig="@xml/network_security_config"
- 创建
- 重新打包APK,安装后即可正常向
10.0.0.22发送POST请求。
方案3:本地HTML+JS文件(无需APP)
将UI做成独立的HTML文件,存在手机或电脑本地,通过浏览器打开,同时解决跨域问题:
- 给ESP32的HTTP服务器添加CORS响应头,在处理所有请求时返回:
(注:如果用浏览器打开本地server.sendHeader("Access-Control-Allow-Origin", "*"); server.sendHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS"); server.sendHeader("Access-Control-Allow-Headers", "Content-Type");file://协议的HTML,部分浏览器可能不认可*,可临时关闭浏览器跨域安全限制,比如Chrome用--disable-web-security --user-data-dir=/tmp/chrome-test参数启动) - HTML文件示例:
<!DOCTYPE html> <html> <body> <h1>圣诞灯控制</h1> <textarea id="bodyInput" rows="4" cols="30">{"brightness": 80, "mode": "blink"}</textarea> <br> <button onclick="sendPost()">发送</button> <script> async function sendPost() { const url = "http://10.0.0.22/control"; const body = document.getElementById("bodyInput").value; try { const response = await fetch(url, { method: "POST", headers: {"Content-Type": "application/json"}, body: body }); const result = await response.text(); alert("请求成功:" + result); } catch (err) { alert("请求失败:" + err.message); } } </script> </body> </html> - 将这个文件保存到手机,用浏览器打开(确保手机和ESP32在同一WiFi下)即可使用。
方案4:React Native本地APP
类似Flutter,构建移动端APP,只需解决安卓明文HTTP限制:
- 配置安卓项目的
AndroidManifest.xml或network_security_config.xml(同方案2的配置)。 - 使用
fetch或axios库发送POST请求到10.0.0.22,同时构建自定义输入请求体的UI即可。
内容的提问来源于stack exchange,提问作者Gwinter
相关产品推荐
相关产品推荐

