在ESP32的Asyncio Web服务器中获取HTML下拉框选项值并存储到Python变量
在ESP32的Asyncio Web服务器中获取HTML下拉框选项值并存储到Python变量
嘿,我来帮你解决这个问题!你现在遇到的问题主要有两个关键点需要调整:一是HTML表单的结构问题,二是在ESP32的Web服务器代码里正确解析请求参数。
第一步:修正你的HTML代码
你现在的下拉框<select>是放在<form>标签外面的,这会导致点击提交按钮时,浏览器根本不会把下拉框的参数传递给服务器!得把<select>整个包裹在<form>标签内部,同时明确指定请求方法(默认是GET,写上更清晰),调整后的代码如下:
<form action="./sendToESP" method="GET"> <select name="dropdown" id="dropdown"> <option value="649">McMiller</option> <!-- 可以根据需求添加更多选项 --> <option value="750">Another Option</option> </select> <br> <input type="submit" value="Send!"> </form>
第二步:在ESP32的Python代码中解析参数并存储值
接下来你需要在服务器端解析请求的查询参数,这里给你两种常见的实现方案,根据你的项目需求选择:
方案一:原生Asyncio服务器实现(不依赖第三方框架)
如果是用MicroPython自带的uasyncio搭建服务器,可以借助urllib.parse.parse_qs来解析URL中的查询参数,示例代码如下:
import uasyncio as asyncio from urllib.parse import parse_qs # 定义全局变量存储选中的值(也可以根据你的项目结构用类变量、局部变量等) selected_value = None async def handle_request(reader, writer): # 读取请求行,格式类似 b'GET /sendToESP?dropdown=649 HTTP/1.1\r\n' request_line = await reader.readline() request_path = request_line.decode().split(' ')[1] # 处理sendToESP的请求 if '/sendToESP' in request_path: global selected_value # 拆分路径和查询参数部分 if '?' in request_path: _, query_string = request_path.split('?', 1) # 解析查询参数,返回字典格式,键是参数名,值是参数值的列表 query_params = parse_qs(query_string) # 提取dropdown的参数值 if 'dropdown' in query_params: selected_value = query_params['dropdown'][0] print(f"成功获取下拉框值: {selected_value}") # 返回成功响应给客户端 response = ( "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n" f"<h1>值已接收: {selected_value}</h1><a href='/'>返回首页</a>" ) else: # 处理缺少参数的情况 response = ( "HTTP/1.1 400 Bad Request\r\nContent-Type: text/html\r\n\r\n" "<h1>缺少dropdown参数,请先选择选项</h1>" ) else: # 没有带参数的情况 response = ( "HTTP/1.1 400 Bad Request\r\nContent-Type: text/html\r\n\r\n" "<h1>请先选择下拉框选项再提交</h1>" ) writer.write(response.encode()) await writer.drain() # 处理首页请求,返回带下拉框的页面 elif request_path == '/' or request_path == '/index.html': html = """ <html> <body> <form action="./sendToESP" method="GET"> <select name="dropdown" id="dropdown"> <option value="649">McMiller</option> <option value="750">Another Option</option> </select> <br> <input type="submit" value="Send!"> </form> </body> </html> """ response = f"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: {len(html)}\r\n\r\n{html}" writer.write(response.encode()) await writer.drain() # 处理其他无效请求 else: response = "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n\r\n<h1>页面不存在</h1>" writer.write(response.encode()) await writer.drain() await writer.wait_closed() # 启动服务器 async def main(): server = await asyncio.start_server(handle_request, '0.0.0.0', 80) await server.serve_forever() asyncio.run(main())
方案二:用Microdot轻量框架实现(更简洁)
如果你的ESP32已经安装了microdot框架(这是ESP32上非常流行的轻量级Web框架),代码会简洁很多,框架会自动帮你解析请求参数:
from microdot import Microdot app = Microdot() # 存储选中值的变量 selected_value = None # 首页路由,返回带下拉框的页面 @app.route('/') def index(request): return """ <html> <body> <form action="/sendToESP" method="GET"> <select name="dropdown" id="dropdown"> <option value="649">McMiller</option> <option value="750">Another Option</option> </select> <br> <input type="submit" value="Send!"> </form> </body> </html> """ # 处理提交请求的路由 @app.route('/sendToESP') def handle_submit(request): global selected_value # 直接从request.args获取解析好的参数字典 if 'dropdown' in request.args: selected_value = request.args['dropdown'] return f"<h1>值已接收: {selected_value}</h1><a href='/'>返回首页</a>" # 参数缺失的情况 return "<h1>请先选择下拉框选项再提交</h1>", 400 # 启动服务器 app.run(host='0.0.0.0', port=80)
几个容易踩的坑要注意
- 千万别忘了把select放在form标签内部,不然参数根本传不到服务器
- 解析参数时一定要处理参数不存在的情况,避免出现KeyError报错
- 如果是多并发请求场景,全局变量可能会有覆盖问题,这种情况建议用类或者局部作用域的变量来存储值
备注:内容来源于stack exchange,提问作者DanniDeleto




