3. MQTT 消息接收计数器
任务目标
本案例实现一个LVGL图表控件,通过MQTT订阅主题接收传感器数值,并将数据实时绘制为曲线。完成本案例后,你将得到一个可在嵌入式设备或模拟器上运行的独立演示程序,能够动态更新曲线数据。
环境依赖
- LVGL v8.x(已初始化,显示器与触摸驱动可用)
- MQTT客户端库(如paho.mqtt.embedded-c或ESP-MQTT),需提供连接、订阅、回调接口
- 开发板具备网络连接能力(如ESP32、STM32+W5500)
核心实现
以下代码创建了一个包含60个数据点的折线图,通过MQTT回调函数接收sensor/temp主题的数值,将新数据移入图表并刷新显示。代码中mqtt_client_connect()和mqtt_subscribe()为MQTT库的接入函数,实际使用时需根据所选库进行适配。
#include "lvgl.h"
#include "mqtt_client.h" // 根据实际MQTT库调整头文件
#define DATA_POINTS 60
#define CHART_RANGE 100 // Y轴范围0-100
static lv_obj_t *chart;
static lv_chart_series_t *series_temp;
// MQTT消息回调:解析温度值并更新曲线
static void mqtt_data_callback(const char *topic, const uint8_t *payload, uint32_t len)
{
if (strcmp(topic, "sensor/temp") != 0) return;
// 将payload转为整数(假设数据格式为纯数字字符串)
char buf[16];
uint32_t copy_len = len < 15 ? len : 15;
memcpy(buf, payload, copy_len);
buf[copy_len] = '\0';
int temp = atoi(buf);
// 将新值加入图表,自动移除最旧数据点
lv_chart_set_next_value(chart, series_temp, temp);
lv_chart_refresh(chart); // 触发重绘
}
void chart_mqtt_demo_create(void)
{
// 创建图表控件
chart = lv_chart_create(lv_scr_act());
lv_obj_set_size(chart, 400, 200);
lv_obj_center(chart);
// 配置Y轴范围与数据点数
lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 0, CHART_RANGE);
lv_chart_set_point_count(chart, DATA_POINTS);
// 不显示数据点标记,仅连线
lv_obj_set_style_size(chart, 0, LV_PART_INDICATOR);
// 添加数据系列
series_temp = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_BLUE),
LV_CHART_AXIS_PRIMARY_Y);
// 初始化数据为0
lv_chart_set_all_value(chart, series_temp, 0);
// 连接MQTT并订阅主题(需根据实际MQTT库实现)
mqtt_client_connect("192.168.1.100", 1883);
mqtt_subscribe("sensor/temp", mqtt_data_callback);
}
运行与验证
- 将上述代码集成到你的LVGL项目中,确保
chart_mqtt_demo_create()在UI初始化后被调用。 - 配置MQTT服务器地址与端口,确保设备能访问该服务器。
- 使用MQTT客户端工具(如MQTT.fx)向
sensor/temp主题发布0~100之间的整数值。 - 观察屏幕上的图表:每次发布新值,曲线应向右移动并显示最新数据点。
通过条件:连续发布10个以上不同数值,图表曲线能实时更新且无卡顿或崩溃,旧数据点被正确移出显示区域。
关键说明
- 本示例假设MQTT消息为纯数字字符串,若实际为JSON或二进制格式,需在回调中增加相应解析逻辑。
- 图表Y轴范围固定为0~100,若传感器数据超出此范围,需调整
CHART_RANGE或改为动态范围。 - LVGL图表默认在数据点达到
point_count后自动左移,无需手动管理环形缓冲。