1. LVGL 与 MQTT 基础连接状态显示
任务目标
创建一个LVGL图形界面,包含一个MQTT连接状态指示标签。界面启动时显示“DISCONNECTED”,当收到MQTT消息(例如发布到主题status的内容为connected)时,标签更新为“CONNECTED”并改变颜色。本案例聚焦于LVGL标签控件的基本使用与MQTT回调到UI更新的最小闭环。
环境依赖
需要LVGL v8.x库及MQTT客户端库(如paho.mqtt.c)。以下代码假设LVGL已初始化且显示器/触摸驱动已就绪,MQTT客户端已连接至Broker。UI更新需在LVGL的线程上下文中执行,因此MQTT回调中仅记录状态,通过lv_timer周期性检查并更新UI。
关键完整代码
#include "lvgl.h"
#include "MQTTClient.h"
// MQTT配置
#define BROKER_ADDR "tcp://broker.emqx.io:1883"
#define CLIENT_ID "lvgl_demo_client"
#define TOPIC_STATUS "demo/status"
// 全局状态
static volatile int mqtt_connected_flag = 0; // 0=断开, 1=已连接
static lv_obj_t *status_label;
// MQTT消息到达回调(在MQTT线程中执行)
static void msg_arrived(void *context, char *topicName, int topicLen,
MQTTClient_message *message) {
if (strcmp(topicName, TOPIC_STATUS) == 0) {
if (strncmp(message->payload, "connected", 9) == 0) {
mqtt_connected_flag = 1;
} else {
mqtt_connected_flag = 0;
}
}
MQTTClient_freeMessage(&message);
MQTTClient_free(topicName);
}
// LVGL定时器:周期性检查MQTT状态并更新UI
static void ui_update_timer_cb(lv_timer_t *timer) {
if (mqtt_connected_flag) {
lv_label_set_text(status_label, "CONNECTED");
lv_obj_set_style_text_color(status_label, lv_color_hex(0x00FF00), 0);
} else {
lv_label_set_text(status_label, "DISCONNECTED");
lv_obj_set_style_text_color(status_label, lv_color_hex(0xFF0000), 0);
}
}
// 创建UI界面
static void ui_create(void) {
status_label = lv_label_create(lv_scr_act());
lv_obj_center(status_label);
lv_label_set_text(status_label, "DISCONNECTED");
lv_obj_set_style_text_color(status_label, lv_color_hex(0xFF0000), 0);
lv_obj_set_style_text_font(status_label, &lv_font_montserrat_24, 0);
}
// MQTT初始化与连接
static void mqtt_init(void) {
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_willOptions will_opts = MQTTClient_willOptions_initializer;
int rc;
MQTTClient_create(&client, BROKER_ADDR, CLIENT_ID,
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
MQTTClient_setCallbacks(client, NULL, NULL, msg_arrived, NULL);
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) {
printf("MQTT连接失败,错误码: %d\n", rc);
return;
}
MQTTClient_subscribe(client, TOPIC_STATUS, 1);
}
// 主函数
int main(void) {
lv_init();
// ... 显示器/触摸初始化代码 ...
ui_create();
mqtt_init();
// 创建LVGL定时器,每200ms检查一次状态
lv_timer_create(ui_update_timer_cb, 200, NULL);
while (1) {
lv_timer_handler();
lv_delay_ms(5);
}
}
运行与验证
- 编译:链接LVGL、MQTT库及必要的系统库,例如:
gcc -o mqtt_ui_demo main.c -llvgl -lpaho-mqtt3c -lm -lpthread - 运行:执行
./mqtt_ui_demo,屏幕中央应显示红色“DISCONNECTED”。 - 验证步骤:
- 使用MQTT客户端(如MQTTX)连接同一Broker,向主题
demo/status发布消息connected。 - 观察屏幕标签应在200ms内变为绿色“CONNECTED”。
- 发布任意其他内容(如
disconnected),标签应恢复为红色“DISCONNECTED”。
- 使用MQTT客户端(如MQTTX)连接同一Broker,向主题
- 通过条件:标签颜色与文本能随MQTT消息正确切换,且程序无崩溃或内存泄漏。
关键说明
- MQTT回调运行在MQTT客户端线程,不能直接调用LVGL API,因此使用
volatile标志位传递状态,由LVGL定时器轮询更新。 - 若需实时性更高的响应,可使用
lv_async_call,但定时器方案更简单且足以满足状态指示场景。 - 本案例仅演示状态文本更新,实际项目中可扩展为图标、动画等更丰富的视觉反馈。