开始前适用开发板:ESP32-P4 + ESP32-C5 · 开发框架:ESP-IDF
适用开发板:P4C5 · 工程
04.application.weather_clock· targetesp32p4
前置:Wi-Fi Station · MIPI 屏
学习时长:约 40 分钟 · 难度:★★★★☆
P4C5 独有:Korvo 无此例程
学习目标
完成本节后,你将能够:
- 理解一个产品级嵌入式 UI 应用的完整架构(55 个源文件,7 大模块)
- 掌握心知天气 HTTPS API 的对接方法和 cJSON 解析
- 了解 SNTP 网络对时、农历算法、AP/Web 配网的实现
- 理解 ESP-SR 离线语音(WakeNet + MultiNet)的集成方式
- 学会用 LVGL 9 构建多页面导航 + 状态栏 UI
1. 这个例子在干嘛
一个 桌面智能时钟站——横屏 800×480 MIPI 大屏,集时钟、农历节气、心知天气预报、待办事项、离线语音控制于一体。
生活类比:你家桌上的智能闹钟,但它是你亲手写的代码。
┌──────────────────────────────────────────────────┐ y=0
│ 状态栏 800×32 城市 | 日期·农历 | WiFi信号 | 时间 │
├──────────────────────────────────────────────────┤ y=32
│ │
│ 内容区 800×388(page_manager) │
│ │
│ ┌─────────────────┬──────────────────────┐ │
│ │ 14:23:56 │ 今天 32°C ☀ 晴 │ │
│ │ 农历·五月廿一 │ 明天 30°C ⛅ 多云 │ │
│ │ 小暑 │ 后天 28°C 🌧 阵雨 │ │
│ └─────────────────┴──────────────────────┘ │
│ │
├──────────────────────────────────────────────────┤ y=420
│ 导航栏 800×60 [时钟] [预报] [待办] [设置] │
└──────────────────────────────────────────────────┘ y=480
技术栈全景
P4 主控 ─── LVGL 9(4 页面 + 状态栏 + 导航栏)
│
├── 网络层 ─── C5(SDIO/esp_hosted) → Wi-Fi STA / AP 配网
│ ├── SNTP 对时(阿里云/Apple/Pool NTP)
│ └── HTTPS → 心知天气 API → cJSON 解析
│
├── 本地计算 ── 农历算法 1900-2099 + 二十四节气(寿星公式)
│ └── NVS 持久化(设置 + 待办事项)
│
└── 语音 ────── ES7210 麦克风 → ESP-SR AFE
├── WakeNet 9「嗨,乐鑫」
└── MultiNet 7 中文命令(12 条)
2. 编译烧录
cd P4_C5_4.3_Firmware\04.application.weather_clock
idf.py set-target esp32p4
idf.py menuconfig # 配置天气 API Key、Wi-Fi(可选)
idf.py build flash monitor
menuconfig 关键配置
| 菜单路径 | 选项 | 默认值 | 说明 |
|---|---|---|---|
| Weather Clock 配置 | WCLOCK_SENIVERSE_KEY | 空 | 心知天气 API Key(必填) |
WCLOCK_SENIVERSE_LOCATION | beijing | 城市代码 | |
WCLOCK_SENIVERSE_REFRESH_MIN | 30 | 天气刷新周期(10~240 分钟) | |
WCLOCK_AP_SSID | KSDIY-WClock-Setup | 配网热点前缀 | |
WCLOCK_AP_PASSWORD | 空 | AP 密码(空=开放) | |
WCLOCK_TTS_FEEDBACK | y | 语音提示音开关 | |
| Component → ESP-SR | WakeNet 模型 | wn9_hilexin | 唤醒词 |
| MultiNet 模型 | mn7_cn_quant | 中文命令识别 |
3. 首次使用流程
3.1 无 Wi-Fi 凭据启动
- 上电后进入 AP 配网模式
- 手机搜索热点
KSDIY-WClock-Setup-XXXX - 浏览器自动弹出配网页(Captive Portal),或访问
192.168.4.1 - 输入 Wi-Fi SSID/密码 + 心知天气 API Key + 城市
- 保存后自动重启,进入正常工作模式
3.2 正常工作
- 连接 Wi-Fi → SNTP 对时 → 时钟显示准确时间
- 拉取心知天气 → 显示实时温度 + 3 日预报
- 语音唤醒:说「嗨,乐鑫」→ 6 秒命令窗口 → 说命令
4. 运行现象
| 阶段 | 屏幕 | 串口 |
|---|---|---|
| 启动 | LVGL UI 加载,时钟显示 00:00 | NVS 初始化、LVGL init |
| 配网中 | 显示 AP 热点信息 | httpd: Started |
| Wi-Fi 连接 | 状态栏 WiFi 图标 | GOT_IP: 192.168.x.x |
| SNTP 同步 | 时钟跳为准确时间 | SNTP: Time synced |
| 天气拉取 | 温度/天气文字显示 | Weather: 晴 32°C |
| 语音唤醒 | — | WakeNet: detected |
| 语音命令 | 页面跳转/亮度调节 | MultiNet: cmd_id=X |
5. 工程文件架构(55 个源文件)
main/
├── app_main.c ← 启动编排:NVS→设置→LVGL→WiFi→天气→语音
├── Kconfig.projbuild ← menuconfig 选项定义
│
├── config/ ← 配置与事件总线
│ ├── app_settings.c/h ← NVS 持久化设置(namespace="wclock")
│ └── app_events.c/h ← esp_event 跨模块事件
│
├── lunar/ ← 农历算法
│ └── lunar.c/h ← 公历↔农历、节气、节日查表
│
├── weather/ ← 心知天气
│ ├── weather_model.h ← weather_now_t / weather_day_t 数据模型
│ ├── weather_api.c/h ← HTTPS GET + cJSON 解析 + 互斥锁
│ ├── weather_task.c/h ← FreeRTOS 任务:周期拉取 + 失败退避
│ └── weather_icons.c/h ← 天气 code → 中文文字
│
├── network/ ← 网络与配网
│ ├── net_wifi.c/h ← Wi-Fi STA(重试 5 次,15s 超时)
│ ├── net_sntp.c/h ← SNTP 校时 CST-8
│ ├── net_provision.c/h ← APSTA 配网模式
│ └── net_httpd.c/h ← 内嵌 HTML 配网页 + Captive Portal
│
├── todo/ ← 待办事项
│ ├── todo_model.h ← 最多 24 条,每条 48 字符
│ └── todo_store.c/h ← NVS blob 持久化
│
├── voice/ ← 离线语音
│ ├── voice_afe.c/h ← ESP-SR AFE + WakeNet + MultiNet(双任务)
│ ├── voice_commands.c/h ← 拼音命令注册 + 分发
│ └── voice_tts.c/h ← TTS 提示音(占位)
│
└── ui/ ← LVGL 界面
├── ui_main.c/h ← 主题/字体/状态栏/导航栏/页面注册
├── ui_theme.c/h ← 深色主题色板
├── ui_status_bar.c/h ← 顶栏:城市/日期/WiFi/时间
├── ui_nav_bar.c/h ← 底栏:4 页导航按钮
├── page_manager.c/h ← 页面切换管理
└── pages/
├── page_clock.c/h ← 主页:大时钟 + 农历 + 天气卡
├── page_forecast.c/h ← 3 日预报横排
├── page_todo.c/h ← 待办列表 + 键盘输入
└── page_settings.c/h ← 亮度/24h/刷新/重置WiFi
6. 核心数据流
6.1 天气数据流
app_settings(key/location)
↓
weather_task (Core1, 8KB 栈)
↓ 等待 Wi-Fi 获取 IP
↓
HTTPS GET → api.seniverse.com
├── /v3/weather/now.json → 实时天气
└── /v3/weather/daily.json → 3 日预报
↓
cJSON 解析 → weather_snapshot_t(互斥锁保护)
↓
page_clock / page_forecast 的 lv_timer (1s/5s) 读取快照 → 更新 UI
6.2 语音命令流
ES7210 麦克风 → feed_task (Core0) → AFE 处理
↓
detect_task (Core1) → WakeNet 检测「嗨乐鑫」
↓ 唤醒
MultiNet 6 秒命令窗口 → 识别 command_id
↓
voice_commands_dispatch() → LVGL 锁内执行动作
12 条语音命令
| 命令 | 拼音 | 动作 |
|---|---|---|
| 今天天气 | jin1 tian1 tian1 qi4 | 跳预报页 |
| 现在几点 | xian4 zai4 ji3 dian3 | 播报时间 |
| 添加待办 | tian1 jia1 dai4 ban4 | 跳待办 + 弹输入 |
| 返回主页 | fan3 hui2 zhu3 ye4 | 跳主页 |
| 打开设置 | da3 kai1 she4 zhi4 | 跳设置页 |
| 调亮/暗一点 | tiao2 liang4/an4 | 亮度 ±50 |
| 关闭屏幕 | guan1 bi4 ping2 mu4 | 背光关闭 |
7. 心知天气 API 对接
7.1 注册获取 Key
- 访问 seniverse.com 注册免费账号
- 创建产品 → 获取 API Key
- 在 menuconfig 或配网页面中填入
7.2 API 请求详解
GET https://api.seniverse.com/v3/weather/now.json
?key=YOUR_KEY
&location=shenzhen
&language=zh-Hans
&unit=c
响应:
{
"results": [{
"location": {"name": "深圳"},
"now": {"text": "晴", "code": "0", "temperature": "32"},
"last_update": "2026-07-04T09:00:00+08:00"
}]
}
7.3 刷新策略
- 默认 30 分钟拉取一次
- 失败自动退避:5→10→20→30 分钟
- 使用
esp_crt_bundle_attach内置 CA 证书验证 HTTPS
8. 常见问题与排查
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 天气不显示 | API Key 为空或错误 | menuconfig 或配网页填入正确 Key |
| 天气不显示 | 免费版 API 限制 | 心知免费版每天 100 次调用 |
| 时间不准 | SNTP 服务器不可达 | 检查网络;默认已配 3 个 NTP |
| 时间显示 00:00 | Wi-Fi 未连接 | 检查路由器和凭据 |
| 配网页面打不开 | 手机未连接 AP | 确认连上 KSDIY-WClock-Setup-XXX |
| 配网页面打不开 | Captive Portal 被手机拦截 | 手动浏览器输入 192.168.4.1 |
| C5 未就绪 | SDIO 通信延迟 | 等待 10~20 秒 |
| 语音无反应 | codec 与触摸共用 I2C | 确保语音在 LVGL 之后初始化 |
| 语音无反应 | 麦克风硬件 | 先跑 board_test 验证 ES7210 |
| 农历/节气错误 | 算法范围 1900-2099 | 理论上不会出现 |
9. 动手改造建议
- 换天气 API:改用 OpenWeatherMap(修改
weather_api.c的 URL 和 JSON 路径) - 添加闹钟:
todo_store扩展时间字段 + lv_timer 触发提醒 - MQTT 远程推送:订阅 Topic 接收待办事项
- 天气图标:替换
weather_icons.c的 NULL 返回为 LVGL 图标字体 - 自定义唤醒词:ESP-SR menuconfig 中更换 WakeNet 模型
10. 知识延伸
- SNTP 与 RTC:ESP32-P4 没有外部 RTC,依赖 SNTP 网络对时。系统时间存在内部 RTC 中,掉电归零
- Captive Portal:配网时 HTTP Server 对所有 DNS 请求返回自身 IP,手机自动弹出配网页——和酒店 Wi-Fi 登录原理相同
- esp_hosted:C5 作为 SDIO 从机提供 WiFi 能力,应用层使用标准
esp_wifiAPI,无需关心底层通信细节 - FreeRTOS 任务分布:天气/语音 feed 在 Core0,语音检测在 Core1,避免语音推理阻塞网络
11. Flash 分区
| 分区 | 大小 | 用途 |
|---|---|---|
nvs | 24 KB | 设置 + 待办事项 |
model | 3 MB | ESP-SR WakeNet/MultiNet 模型 |
factory | 3 MB | 应用固件 |
storage | 6 MB | 可选 SPIFFS(TTF/背景/提示音) |
12. 下一步
| 方向 | 推荐例程 | 说明 |
|---|---|---|
| 智能家居 | Smart Panel | 另一个产品级应用 |
| Wi-Fi 基础 | Wi-Fi Station | 理解 C5 联网流程 |
| HTTP 基础 | HTTP Server | HTTP 处理入门 |
| MQTT | MQTT | IoT 通信 |
酷世DIY · Kevincoooool