- 新增 wifi-connect 组件(AP 配网、DNS 劫持、Captive Portal) - 支持长按按键进入配网,网页配置路由器 SSID/密码 - 增加清除已保存 Wi-Fi 参数能力(API + 页面按钮) - 增加中文状态日志与中文注释,优化配网交互 - 补充组件文档:README、USER_GUIDE、QUICK_POSTER、BLOG
220 lines
6.4 KiB
Markdown
220 lines
6.4 KiB
Markdown
# 从 0 到 1:我在 ESP32-C3 上做了一个可落地的 Wi-Fi 配网组件(含中文日志与一键清除配置)
|
||
|
||
> 项目:BotanicalBuddy
|
||
> 平台:ESP-IDF v5.5.2(ESP32-C3)
|
||
|
||
---
|
||
|
||
## 一、为什么要自己做一个配网组件?
|
||
|
||
很多物联网项目都会遇到同一个问题:
|
||
|
||
- 设备第一次上电,怎么让用户把它连进家里 Wi-Fi?
|
||
- 配网失败时,怎么给用户清晰反馈?
|
||
- 现场调试时,日志如何快速看懂?
|
||
|
||
我这次的目标很明确:
|
||
|
||
1. **用户侧简单**:长按按键 → 连接热点 → 打开网页 → 输入密码;
|
||
2. **开发侧可维护**:接口清晰、状态可追踪、日志可读;
|
||
3. **现场可排障**:失败能看到原因,支持“一键清除历史配置”。
|
||
|
||
最终我把这些能力收敛成一个组件:`wifi-connect`。
|
||
|
||
---
|
||
|
||
## 二、组件能力概览
|
||
|
||
`wifi-connect` 目前实现了这些核心能力:
|
||
|
||
- 长按按键进入配网模式;
|
||
- 设备开启 SoftAP(`ESP32-xxxxxx`);
|
||
- 内置 HTTP 配网页面(扫描、提交、状态轮询);
|
||
- DNS 劫持 + Captive Portal 路径兼容(提升手机弹窗成功率);
|
||
- 配网成功后保存凭据到 NVS;
|
||
- 上电自动重连已保存网络;
|
||
- 中文状态日志(便于现场阅读);
|
||
- **清除已保存配置**(网页按钮 + API + SDK 接口)。
|
||
|
||
---
|
||
|
||
## 三、整体架构(简化)
|
||
|
||
```text
|
||
[按键任务] --长按--> [进入配网]
|
||
|
|
||
+--> APSTA 模式
|
||
+--> HTTP Server(网页)
|
||
+--> DNS 劫持服务
|
||
|
||
[网页] --POST /api/connect--> [设置 STA 参数并连接]
|
||
[网页] --GET /api/status --> [轮询状态]
|
||
[网页] --POST /api/clear --> [清除 NVS 凭据]
|
||
|
||
[Wi-Fi/IP 事件] --> [更新状态机 + 打印中文日志 + 保存凭据]
|
||
```
|
||
|
||
核心状态枚举:
|
||
|
||
- `idle`
|
||
- `provisioning`
|
||
- `connecting`
|
||
- `connected`
|
||
- `failed`
|
||
- `timeout`
|
||
|
||
---
|
||
|
||
## 四、最关键的实现点
|
||
|
||
### 1)配网页面的“够用即好”设计
|
||
|
||
我没有引入前端框架,而是把 HTML/JS 直接内嵌在 C 字符串里,避免增加构建复杂度。页面只保留 3 个动作:
|
||
|
||
- 扫描网络
|
||
- 提交连接
|
||
- 清除已保存配置
|
||
|
||
这种做法的好处是:**部署轻、调试快、资源占用低**。
|
||
|
||
---
|
||
|
||
### 2)手机“连上热点但不弹页面”的处理
|
||
|
||
这是配网常见痛点。为了提高兼容性,我做了两件事:
|
||
|
||
1. 注册常见探测路径(如 `/generate_204`、`/hotspot-detect.html` 等);
|
||
2. 对探测/未知 GET 请求统一返回 `302` 到 `http://192.168.4.1/`。
|
||
|
||
这样很多手机系统会更容易触发门户页面。
|
||
|
||
---
|
||
|
||
### 3)连接超时问题的根因与修复
|
||
|
||
我遇到过这样一条典型日志:
|
||
|
||
- `sta is connected, disconnect before connecting to new ap`
|
||
|
||
说明设备当时还连着旧网络,却直接尝试切到新网络,最终走到连接超时。修复方案很直接:
|
||
|
||
- 在 `esp_wifi_set_config + esp_wifi_connect` 前,先 `esp_wifi_disconnect()`;
|
||
- 若断开失败(非 `NOT_CONNECT`),记录告警日志。
|
||
|
||
这一步对稳定性提升很明显。
|
||
|
||
---
|
||
|
||
### 4)新增“清除已保存配置”能力
|
||
|
||
为了提升可恢复性,我新增了完整链路:
|
||
|
||
- SDK API:`wifi_connect_clear_config()`
|
||
- HTTP API:`POST /api/clear`
|
||
- 页面按钮:“清除已保存”
|
||
|
||
执行逻辑:
|
||
|
||
1. 清除 NVS 的 `ssid`/`pass`;
|
||
2. 清空运行时 pending 参数;
|
||
3. 若正在连接中,取消当前连接流程;
|
||
4. 在配网模式下把状态恢复为 `provisioning`,并清空旧错误文案。
|
||
|
||
这让“失败后重试”路径变得非常顺畅。
|
||
|
||
---
|
||
|
||
## 五、中文日志:现场效率提升非常大
|
||
|
||
为了让非固件同学也能看懂串口,我统一了状态日志风格:
|
||
|
||
- `【状态】配网已启动:配网热点已开启,SSID=...`
|
||
- `【状态】开始连接路由器:收到配网请求,目标网络:...`
|
||
- `【状态】联网成功:已连接 ...,获取 IP=...`
|
||
- `【状态】连接路由器超时:请确认密码和路由器信号`
|
||
|
||
这类日志在现场排障时比纯英文驱动日志直观很多。
|
||
|
||
> 注:`wifi:`、`esp_netif_lwip:` 前缀日志依然是 ESP-IDF 框架默认输出。
|
||
|
||
---
|
||
|
||
## 六、前端交互做了哪些“小而有效”的优化?
|
||
|
||
在配网页面里,我加了几项很实用的小优化:
|
||
|
||
- 连接/清除时禁用按钮,防止连点并发请求;
|
||
- 清除成功后自动清空密码框;
|
||
- 清除后自动刷新状态和扫描结果;
|
||
- 状态枚举映射成中文显示(`connecting -> 连接中`)。
|
||
|
||
这些改动代码不多,但用户体验差异非常明显。
|
||
|
||
---
|
||
|
||
## 七、对外 API(当前版本)
|
||
|
||
```c
|
||
esp_err_t wifi_connect_init(void);
|
||
esp_err_t wifi_connect_start(void);
|
||
esp_err_t wifi_connect_stop(void);
|
||
wifi_connect_status_t wifi_connect_get_status(void);
|
||
esp_err_t wifi_connect_get_config(wifi_connect_config_t *config);
|
||
esp_err_t wifi_connect_clear_config(void);
|
||
```
|
||
|
||
建议调用顺序:
|
||
|
||
1. 启动时调用 `wifi_connect_init()`;
|
||
2. 用户长按或业务触发时调用 `wifi_connect_start()`;
|
||
3. 成功后由组件自动收口,必要时可手动 `wifi_connect_stop()`;
|
||
4. 需要重置时调用 `wifi_connect_clear_config()`。
|
||
|
||
---
|
||
|
||
## 八、测试与验证建议
|
||
|
||
建议至少覆盖以下场景:
|
||
|
||
1. 首次配网成功;
|
||
2. 密码错误后重试成功;
|
||
3. 已连接旧网时切换到新网;
|
||
4. 清除配置后重新配网;
|
||
5. 空闲超时自动退出;
|
||
6. 断电重启后自动重连。
|
||
|
||
如果这 6 条都稳定通过,组件可用性通常已经比较高。
|
||
|
||
---
|
||
|
||
## 九、我这次的经验总结
|
||
|
||
如果你也在做 ESP32 配网,我建议优先做好三件事:
|
||
|
||
1. **状态机清晰**:每个阶段可见、可回退;
|
||
2. **日志可读**:现场的人不一定是固件开发;
|
||
3. **失败可恢复**:必须有“清除历史配置”的入口。
|
||
|
||
很多时候,不是“功能没做出来”,而是“异常路径没兜住”。把恢复路径做顺,产品体验会提升一大截。
|
||
|
||
---
|
||
|
||
## 十、后续可继续优化的方向
|
||
|
||
- 增加多语言页面(中/英切换);
|
||
- 增加 AP 密码与会话保护;
|
||
- 支持 BLE 辅助配网;
|
||
- 接入云端激活与设备绑定流程;
|
||
- 做更细粒度的连接错误码映射(前端可读提示)。
|
||
|
||
---
|
||
|
||
## 参考(项目内文档)
|
||
|
||
- `components/wifi-connect/README.md`
|
||
- `components/wifi-connect/USER_GUIDE.md`
|
||
- `components/wifi-connect/QUICK_POSTER.md`
|
||
|
||
---
|
||
|
||
如果你正在做类似项目,希望这篇实践记录能帮你少踩一些坑。 |