ESP32 LVGL 天气 UI 界面开发与多日天气 + 网络时间展示实现
本次开发基于前期 ESP32-LVGL 界面开发、WiFi 网络接入、心知天气数据请求解析、时钟模块适配的基础,完成南宁今明后 3 天天气(温湿度) 与网络同步北京时间的 LVGL 天气 UI 界面开发,整合 WiFi、时钟、天气数据、图标资源全模块,实现软硬件协同运行与界面可视化展示,以下为完整开发流程、代码实现与实操要点。
一、开发前置准备
1.1 环境与资源确认
- 开发环境:ESP-IDF、LVGL 9.4.0、GUI-Guider
- 已完成基础模块:WiFi STA 模式接入(wifi.c/.h)、心知天气接口对接(南宁城市编号 / 名称配置)、cJSON 解析组件整合、网络时间同步基础、天气现象图标(bin/png 格式)转换与工程导入
- 硬件:ESP32 开发板、LCD 显示屏(适配 LVGL 驱动)
- 核心配置:心知天气 API Key、南宁城市参数(建议用城市编号101300101,避免中文编码问题)、2.4G WiFi(SSID/PWD)、静态 DNS(8.8.8.8/114.114.114.114)
1.2 工程文件结构确认
在原有工程基础上,确保main目录下文件完整,新增天气 UI 相关控件定义,核心结构如下:
main/
├── CMakeLists.txt // 已添加wifi、cjson、lvgl编译项
├── main.c // 主函数:整合所有模块,实现界面刷新与数据联动
├── LCD.c/LCD.h // LCD硬件驱动
├── gui_guider.c/gui_guider.h // GUI-Guider导出天气UI界面代码
├── lvgl_ui.c/lvgl_ui.h // 天气UI控件定义(时间、温湿度、天气图标等)
├── font_zh.c/font_zh.h // 中文字体(支持“南宁”“今天”等中文显示)
├── wifi.c/wifi.h // WiFi+心知天气数据请求/解析核心
├── cJSON.c/cJSON.h // JSON解析组件
├── icon/ // 天气图标资源目录(已配置CMake编译)
├── Timer.h/Timer.c // 定时器(界面刷新、数据定时更新)
二、核心开发步骤
2.1 GUI-Guider 制作天气 UI 界面(可视化设计)
基于 LVGL 9.4.0 在 GUI-Guider 中设计适配 LCD 的天气界面,核心控件按功能分区布局,需支持中文字体显示,控件命名与代码调用一致,具体布局如下:
|
区域 |
控件类型 |
控件名称 |
显示内容 |
|
网络时间区 |
标签(label) |
screen_label_time |
北京时间:HH:MM:SS 年 - 月 - 日 |
|
城市与日期区 |
标签(label) |
screen_label_city |
南宁 今天 / 明天 / 后天 |
|
温度展示区 |
标签(label) |
screen_label_temp |
温度:XX℃ 最低 / 最高:XX℃/XX℃ |
|
湿度展示区 |
标签(label) |
screen_label_hum |
湿度:XX% |
|
天气图标区 |
图片(img) |
screen_img_weather |
对应天气现象图标(晴 / 多云 / 雨等) |
设计完成后导出gui_guider.c/.h和lvgl_ui.c/.h文件,替换工程原有文件,确保控件可被主函数调用。
2.2 心知天气数据适配:南宁今明后 3 天数据解析
在原有wifi.c的天气数据解析函数中,优化心知天气 3 天预报接口(WEATHER_3D_URL) 解析逻辑,提取南宁今天、明天、后天的实时温湿度、最高 / 最低温、天气现象,定义专属天气数据结构体存储,适配 3 天数据的独立调用。
2.2.1 天气数据结构体定义(wifi.h 中添加)
// 单天天气数据结构体
typedef struct {
char date[20]; // 日期:年-月-日
char weather[20]; // 天气现象:晴/多云/小雨等
int temp; // 实时温度
int temp_min; // 最低温度
int temp_max; // 最高温度
int humidity; // 湿度
} Weather_Day_t;
// 3天天气数据结构体(今明后)
typedef struct {
Weather_Day_t today;
Weather_Day_t tomorrow;
Weather_Day_t day_after;
} Weather_3D_t;
extern Weather_3D_t nanning_weather; // 南宁3天天气全局变量,供主函数调用
// 函数声明
void weather_get_3d_nanning(Weather_3D_t *weather); // 南宁3天天气获取与解析
void weather_icon_match(char *weather, lv_img_dsc_t *img); // 天气现象与图标匹配
2.2.2 南宁 3 天天气解析实现(wifi.c 中添加)
基于 cJSON 解析心知天气 3 天预报接口返回数据,城市参数固定为南宁 101300101,接口请求参数days=3,核心解析逻辑如下(关键代码):
Weather_3D_t nanning_weather; // 定义全局变量
void weather_get_3d_nanning(Weather_3D_t *weather) {
char req_url[512] = {0};
// 拼接心知天气3天预报请求地址(南宁编号101300101)
sprintf(req_url, "%s?key=%s&location=101300101&language=zh-CN&unit=c&days=3",
WEATHER_3D_URL, WEATHER_KEY);
// 发送HTTP GET请求,获取返回JSON数据(原有esp_http_client实现)
char *json_data = esp_http_client_get_data(req_url);
if (json_data == NULL) {
ESP_LOGE("WEATHER", "获取南宁天气数据失败");
return;
}
// cJSON解析
cJSON *root = cJSON_Parse(json_data);
cJSON *results = cJSON_GetObjectItem(root, "results");
cJSON *daily = cJSON_GetObjectItem(cJSON_GetArrayItem(results, 0), "daily");
// 解析今天(数组第0项)、明天(第1项)、后天(第2项)
cJSON *today = cJSON_GetArrayItem(daily, 0);
cJSON *tomorrow = cJSON_GetArrayItem(daily, 1);
cJSON *day_after = cJSON_GetArrayItem(daily, 2);
// 解析今天数据
strcpy(weather->today.date, cJSON_GetObjectItem(today, "date")->valuestring);
strcpy(weather->today.weather, cJSON_GetObjectItem(today, "text_day")->valuestring);
weather->today.temp = atoi(cJSON_GetObjectItem(today, "temp")->valuestring);
weather->today.temp_min = atoi(cJSON_GetObjectItem(today, "low")->valuestring);
weather->today.temp_max = atoi(cJSON_GetObjectItem(today, "high")->valuestring);
weather->today.humidity = atoi(cJSON_GetObjectItem(today, "humidity")->valuestring);
// 解析明天、后天数据(与今天一致,替换为tomorrow/day_after)
// ... 省略重复解析代码
// 释放内存
cJSON_Delete(root);
free(json_data);
ESP_LOGI("WEATHER", "南宁3天天气数据解析成功");
}
2.2.3 天气图标匹配实现(wifi.c 中添加)
关联心知天气现象与工程中导入的 LVGL 图标资源,通过if-else建立映射关系,核心代码:
void weather_icon_match(char *weather, lv_img_dsc_t *img) {
if (strcmp(weather, "晴") == 0) {
*img = &img_sunny; // 晴图标资源(lvgl_ui中定义)
} else if (strcmp(weather, "多云") == 0) {
*img = &img_cloudy;
} else if (strcmp(weather, "小雨") == 0 || strcmp(weather, "中雨") == 0) {
*img = &img_rain;
} else if (strcmp(weather, "阴") == 0) {
*img = &img_overcast;
} else {
*img = &img_unknown; // 未知天气默认图标
}
}
2.3 网络时间精准同步:北京时间实现
优化原有时钟模块,基于NTP 网络时间同步(替代简易网络请求)实现北京时间(东八区) 获取,解决本地计时误差,在Timer.c中实现时间校准,输出年-月-日 时:分:秒格式,供 LVGL 界面调用。
2.3.1 NTP 时间同步配置(main.c 中添加)
2.4 全模块整合:main.c 主函数编写
主函数为核心调度入口,实现WiFi 初始化→NTP 时间同步→南宁 3 天天气获取→LVGL 界面初始化→定时器实时刷新界面的全流程,确保网络接入后自动调取数据并在 LCD 屏幕展示
2.5 编译配置与工程检查
打开CMakeLists.txt,确认已添加cjson、lvgl、wifi相关编译项,天气图标资源已配置EMBED_FILES;
检查wifi.h中核心配置:WiFi SSID/PWD、心知天气 API Key、南宁城市编号101300101、3 天预报接口地址;
确认中文字体font_zh.c/.h已正确导入,LVGL 控件支持中文显示;
在 ESP-IDF 终端执行idf.py reconfigure重新加载配置,解决文件依赖问题。
三、烧录与运行测试
3.1 烧录操作
连接 ESP32 开发板与电脑,确认串口号(COMx);
执行idf.py -p COMx flash monitor,完成代码烧录并打开串口监视器;
观察串口打印信息,确认WiFi 连接成功(获取 IP)、NTP 时间同步成功、南宁 3 天天气数据解析成功。
3.2 屏幕显示预期效果
开发板上电后,LCD 屏幕正常加载天气 UI 界面,无白屏、乱码、卡顿,核心显示效果:
顶部网络时间区:实时刷新北京时间,格式为北京时间:2026-XX-XX XX:XX:XX;
中部城市天气区:显示南宁 今天 晴(随实际天气现象变化);
温湿度区:显示温度:25℃ 最低/最高:20℃/28℃、湿度:60%(南宁实时数据);
图标区:显示与天气现象匹配的图标(如晴天显示太阳图标);
数据刷新:天气数据每 5 分钟自动刷新,时间每秒实时刷新,WiFi 断连后本地计时续跑,重连后自动校准时间与天气数据。
3.3 拓展:明天 / 后天天气展示
若需实现点击 / 滑动切换今明后 3 天天气,可在 GUI-Guider 中添加按钮控件,在custom.c中编写按钮点击回调函数,通过修改ui_data_refresh中的数据解析对象(today→tomorrow→day_after)实现切换。
四、常见问题排查
屏幕无中文显示:检查中文字体是否正确导入、LVGL 控件字体是否设置为自定义中文字体、编码是否为 UTF-8;
天气数据获取失败:核对心知天气 API Key 是否有效、南宁城市编号是否正确、接口地址拼接是否缺少参数(key/location);
图标不显示:检查图标资源格式是否为 LVGL 支持的 bin/png、CMake 是否配置资源编译、图标映射函数是否匹配天气现象;
时间与北京时差 8 小时:确认 NTP 配置中TZ_INFO "CST-8"已添加,tzset()函数已执行;
WiFi 连接成功但无网络:配置静态 DNS(8.8.8.8)、检查网络是否为 2.4G、避免 IP 地址冲突。
五、开发成果总结
本次开发完成了 ESP32 全模块整合与天气 UI 界面的落地实现,核心成果:
实现ESP32 WiFi 接入后自动调取南宁今明后 3 天天气数据,包含温湿度、天气现象、最高 / 最低温;
完成NTP 精准同步北京时间,并在 LVGL 界面实时刷新,解决本地计时误差;
实现天气现象与图标自动关联,完成可视化展示;
达成软硬件协同运行:网络、时钟、天气、UI 模块联动,添加数据定时刷新、临界区保护,提升程序鲁棒性;
实现中文友好显示,适配 LCD 屏幕的天气 UI 布局,满足实际使用需求。
后续可基于此实现界面交互优化(滑动 / 点击切换)、温湿度数据可视化(折线图)、网络状态界面提示等功能,进一步提升产品体验。
更多推荐
所有评论(0)