ESP32 LED控制器

两个独立的文件:一个是 ESP32 运行的 Python 文件(main.py),另一个是独立的 HTML 文件(index.html)。这样结构更清晰,也方便你维护和修改前端页面。

import socket

import network

import machine

import time

from machine import Pin

全局变量

led = Pin(2, Pin.OUT) # 初始化GPIO2为输出模式

led.value(0) # 默认熄灭LED

def start_ap():

"""启动ESP32的AP模式"""

ap = network.WLAN(network.AP_IF)

ap.active(False)

time.sleep(0.5)

ap.active(True)

AP配置

ssid = 'ESP32_APTest'

password = '12345678'

ap.config(

essid=ssid,

password=password,

authmode=3, # WPA2-PSK

max_clients=10

)

等待AP启动完成

while not ap.active():

time.sleep(0.1)

print('='*20)

print('AP模式已启动')

print('SSID:', ssid)

print('密码:', password)

ip = ap.ifconfig()[0]

print('IP地址:', ip) # 通常是192.168.4.1

print('='*20)

return ip

def udp_server():

"""启动UDP服务,监听指令控制LED"""

udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

udp_socket.bind(("0.0.0.0", 7788))

udp_socket.settimeout(1) # 超时1秒,避免阻塞

while True:

try:

接收UDP数据

recv_data, sender_info = udp_socket.recvfrom(1024)

cmd = recv_data.decode("utf-8").strip()

执行指令

if cmd == "light on":

led.value(1)

print(f"来自{sender_info}的指令:点亮LED")

udp_socket.sendto(b"success: LED ON", sender_info)

elif cmd == "light off":

led.value(0)

print(f"来自{sender_info}的指令:熄灭LED")

udp_socket.sendto(b"success: LED OFF", sender_info)

else:

udp_socket.sendto(b"error: unknown command", sender_info)

兼容110和116两种超时错误码,不打印正常超时

except OSError as e:

err_code = e.args[0]

if err_code in (110, 116):

continue

else:

print(f"UDP服务异常: {e}")

continue

except Exception as e:

print(f"UDP服务其他错误: {e}")

continue

def read_html_file():

"""读取本地的HTML文件内容"""

try:

with open('index.html', 'r', encoding='utf-8') as f:

html_content = f.read()

return html_content

except Exception as e:

print(f"读取HTML文件失败: {e}")

返回备用简单页面,防止文件不存在导致服务异常

return "<html><body><h1>HTML文件加载失败</h1></body></html>

<!DOCTYPE html>

<html lang="zh-CN">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>ESP32 LED控制</title>

<style>

body {

font-family: Arial, sans-serif;

max-width: 400px;

margin: 50px auto;

text-align: center;

}

.control-btn {

width: 150px;

height: 60px;

font-size: 20px;

margin: 10px;

border: none;

border-radius: 8px;

cursor: pointer;

color: white;

}

#onBtn {

background-color: #4CAF50;

}

#offBtn {

background-color: #f44336;

}

#status {

margin-top: 20px;

font-size: 18px;

color: #333;

}

</style>

</head>

<body>

<h1>ESP32 LED控制器</h1>

<button id="onBtn" class="control-btn">点亮LED</button>

<button id="offBtn" class="control-btn">熄灭LED</button>

<div id="status">等待操作...</div>

<script>

// 使用HTTP请求控制LED,兼容所有浏览器

async function sendCommand(cmd) {

try {

const response = await fetch(`/light/${cmd}`);

const result = await response.text();

document.getElementById('status').textContent = `操作结果: ${result}`;

} catch (err) {

document.getElementById('status').textContent = `操作失败: ${err}`;

}

}

// 绑定按钮事件

document.getElementById('onBtn').addEventListener('click', () => {

sendCommand("on");

});

document.getElementById('offBtn').addEventListener('click', () => {

sendCommand("off");

});

</script>

</body>

</html>

使用说明

  1. 文件上传

    • main.pyindex.html两个文件都上传到 ESP32 的文件系统中(推荐使用 Thonny、uPyCraft 等工具)。
    • 确保两个文件在同一目录(ESP32 的根目录 /)。
  2. 关键修改说明

    • 新增了read_html_file()函数,专门负责读取本地的index.html文件。
    • Web 服务器不再内置 HTML 代码,而是读取外部文件,方便你单独修改前端样式。
    • 增加了 UTF-8 编码声明,避免中文乱码。

总结

  1. 文件拆分逻辑 :把前端 HTML 代码独立成index.html,后端控制逻辑保留在main.py中,通过文件读取的方式加载 HTML。
  2. 核心改动 :新增read_html_file()函数读取外部 HTML 文件,Web 服务器响应时返回该文件内容。
  3. 使用要求 :两个文件必须放在 ESP32 的同一目录下,上传完成后运行main.py即可正常使用。
相关推荐
observe1012 小时前
51单片机学习
嵌入式硬件·学习·51单片机
zkf01000073 小时前
uConsole RTL-SDR/LoRa/GPS/RTC/USB Hub多合一扩展板安装
单片机
惶了个恐4 小时前
嵌入式硬件第一弹——51单片机(1)
单片机·嵌入式硬件·51单片机
电子工程师成长日记-C514 小时前
51单片机语音实时采集系统
单片机·嵌入式硬件·51单片机
csaaa20054 小时前
STM32F103 开发USB设备端点超过ENDP4以上时崩溃问题的解决
stm32·单片机·嵌入式硬件
liefyuan5 小时前
【设备树】SDIO节点属性
单片机·嵌入式硬件
LCG元5 小时前
故障预测与健康管理:STM32G4监控自身参数,早期预警
stm32·单片机·嵌入式硬件
ipod7415 小时前
STM32 GPIO控制器及其应用
stm32·单片机·嵌入式硬件
逐步前行5 小时前
STM32_USART_串口通信
stm32·单片机·嵌入式硬件