feat(display): 添加蓝牙连接状态显示功能
- 引入ble_common_event头文件支持蓝牙事件处理 - 在UI模型中添加蓝牙连接状态字段,包括隐藏、搜索中、已连接三种状态 - 实现蓝牙事件处理器,响应蓝牙对等设备搜索和连接事件 - 当切换到非BLE模式时自动隐藏蓝牙连接状态 - 在主界面UI中添加蓝牙连接状态显示组件(包装器、旋转动画、蓝牙图标) - 根据蓝牙连接状态动态更新UI显示:搜索时显示旋转动画,连接时显示蓝色蓝牙图标,其他情况隐藏 - 订阅蓝牙对等设备相关事件以实时更新连接状态
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
#define MODULE display_module
|
||||
#include <caf/events/module_state_event.h>
|
||||
#include <caf/events/ble_common_event.h>
|
||||
#include <caf/events/power_event.h>
|
||||
|
||||
#include <lvgl_zephyr.h>
|
||||
@@ -76,6 +77,7 @@ static struct display_module_ctx ctx = {
|
||||
BLINKY_THEME_DEFAULT_B),
|
||||
.inactive_border_color = LV_COLOR_MAKE(0x3A, 0x44, 0x52),
|
||||
.mode = MODE_SWITCH_BLE,
|
||||
.ble_link_state = UI_BLE_LINK_HIDDEN,
|
||||
},
|
||||
.date_text = "1970/01/01",
|
||||
.time_text = "00:00:00",
|
||||
@@ -210,6 +212,9 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
||||
const struct mode_switch_event *event = cast_mode_switch_event(aeh);
|
||||
|
||||
ctx.ui_model.mode = event->mode;
|
||||
if (ctx.ui_model.mode != MODE_SWITCH_BLE) {
|
||||
ctx.ui_model.ble_link_state = UI_BLE_LINK_HIDDEN;
|
||||
}
|
||||
refresh_ui();
|
||||
return false;
|
||||
}
|
||||
@@ -219,6 +224,45 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_ble_peer_search_event(aeh)) {
|
||||
const struct ble_peer_search_event *event =
|
||||
cast_ble_peer_search_event(aeh);
|
||||
|
||||
if (ctx.ui_model.mode == MODE_SWITCH_BLE) {
|
||||
ctx.ui_model.ble_link_state = event->active ?
|
||||
UI_BLE_LINK_SEARCHING : UI_BLE_LINK_HIDDEN;
|
||||
refresh_ui();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_ble_peer_event(aeh)) {
|
||||
const struct ble_peer_event *event = cast_ble_peer_event(aeh);
|
||||
|
||||
if (ctx.ui_model.mode != MODE_SWITCH_BLE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (event->state) {
|
||||
case PEER_STATE_CONNECTED:
|
||||
case PEER_STATE_SECURED:
|
||||
ctx.ui_model.ble_link_state = UI_BLE_LINK_CONNECTED;
|
||||
break;
|
||||
|
||||
case PEER_STATE_DISCONNECTED:
|
||||
case PEER_STATE_CONN_FAILED:
|
||||
ctx.ui_model.ble_link_state = UI_BLE_LINK_SEARCHING;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
refresh_ui();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_hid_led_event(aeh)) {
|
||||
const struct hid_led_event *event = cast_hid_led_event(aeh);
|
||||
|
||||
@@ -323,6 +367,8 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
||||
APP_EVENT_LISTENER(MODULE, app_event_handler);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, bat_state_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, ble_bond_multi_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, ble_peer_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, ble_peer_search_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, datetime_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, hid_led_event);
|
||||
APP_EVENT_SUBSCRIBE(MODULE, module_state_event);
|
||||
|
||||
@@ -25,6 +25,9 @@ struct ui_main_ctx {
|
||||
lv_obj_t *battery_icon;
|
||||
lv_obj_t *battery_label;
|
||||
lv_obj_t *battery_state_label;
|
||||
lv_obj_t *ble_link_wrap;
|
||||
lv_obj_t *ble_link_spinner;
|
||||
lv_obj_t *ble_link_icon;
|
||||
lv_obj_t *date_label;
|
||||
lv_obj_t *time_label;
|
||||
};
|
||||
@@ -42,6 +45,8 @@ static const char *const status_texts[UI_STATUS_COUNT] = {
|
||||
"A",
|
||||
};
|
||||
|
||||
#define UI_BLE_LINK_BLUE lv_color_hex(0x0082FC)
|
||||
|
||||
static lv_color_t ui_main_get_battery_color(uint8_t battery_level)
|
||||
{
|
||||
if (battery_level > 70U) {
|
||||
@@ -176,6 +181,31 @@ void ui_main_refresh_battery(const struct ui_main_model *model)
|
||||
lv_label_set_text(g_ui.battery_label, battery_text);
|
||||
lv_label_set_text(g_ui.battery_state_label, state_symbol);
|
||||
lv_obj_set_style_text_color(g_ui.battery_state_label, state_color, 0);
|
||||
|
||||
if ((g_ui.ble_link_wrap == NULL) || (g_ui.ble_link_spinner == NULL) ||
|
||||
(g_ui.ble_link_icon == NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (model->ble_link_state) {
|
||||
case UI_BLE_LINK_SEARCHING:
|
||||
lv_obj_clear_flag(g_ui.ble_link_wrap, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_clear_flag(g_ui.ble_link_spinner, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_add_flag(g_ui.ble_link_icon, LV_OBJ_FLAG_HIDDEN);
|
||||
break;
|
||||
|
||||
case UI_BLE_LINK_CONNECTED:
|
||||
lv_obj_clear_flag(g_ui.ble_link_wrap, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_add_flag(g_ui.ble_link_spinner, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_clear_flag(g_ui.ble_link_icon, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_set_style_text_color(g_ui.ble_link_icon, UI_BLE_LINK_BLUE, 0);
|
||||
break;
|
||||
|
||||
case UI_BLE_LINK_HIDDEN:
|
||||
default:
|
||||
lv_obj_add_flag(g_ui.ble_link_wrap, LV_OBJ_FLAG_HIDDEN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ui_main_refresh_datetime(const char *date_text, const char *time_text)
|
||||
@@ -270,6 +300,31 @@ void ui_main_init(const struct ui_main_model *model,
|
||||
g_ui.battery_state_label = lv_label_create(battery_wrap);
|
||||
lv_obj_set_style_text_font(g_ui.battery_state_label, &lv_font_montserrat_14, 0);
|
||||
|
||||
g_ui.ble_link_wrap = lv_obj_create(battery_wrap);
|
||||
lv_obj_remove_style_all(g_ui.ble_link_wrap);
|
||||
lv_obj_set_size(g_ui.ble_link_wrap, 18, 18);
|
||||
lv_obj_add_flag(g_ui.ble_link_wrap, LV_OBJ_FLAG_HIDDEN);
|
||||
|
||||
g_ui.ble_link_spinner = lv_spinner_create(g_ui.ble_link_wrap);
|
||||
lv_obj_center(g_ui.ble_link_spinner);
|
||||
lv_obj_set_size(g_ui.ble_link_spinner, 16, 16);
|
||||
lv_spinner_set_anim_params(g_ui.ble_link_spinner, 2000, 200);
|
||||
lv_obj_set_style_arc_width(g_ui.ble_link_spinner, 2, LV_PART_MAIN);
|
||||
lv_obj_set_style_arc_width(g_ui.ble_link_spinner, 2, LV_PART_INDICATOR);
|
||||
lv_obj_set_style_arc_color(g_ui.ble_link_spinner, lv_color_hex(0x2A3442),
|
||||
LV_PART_MAIN);
|
||||
lv_obj_set_style_arc_color(g_ui.ble_link_spinner, model->theme_color,
|
||||
LV_PART_INDICATOR);
|
||||
lv_obj_remove_style(g_ui.ble_link_spinner, NULL, LV_PART_KNOB);
|
||||
lv_obj_clear_flag(g_ui.ble_link_spinner, LV_OBJ_FLAG_CLICKABLE);
|
||||
|
||||
g_ui.ble_link_icon = lv_label_create(g_ui.ble_link_wrap);
|
||||
lv_label_set_text(g_ui.ble_link_icon, LV_SYMBOL_BLUETOOTH);
|
||||
lv_obj_center(g_ui.ble_link_icon);
|
||||
lv_obj_set_style_text_font(g_ui.ble_link_icon, &lv_font_montserrat_14, 0);
|
||||
lv_obj_set_style_text_color(g_ui.ble_link_icon, UI_BLE_LINK_BLUE, 0);
|
||||
lv_obj_add_flag(g_ui.ble_link_icon, LV_OBJ_FLAG_HIDDEN);
|
||||
|
||||
middle_row = lv_obj_create(content);
|
||||
lv_obj_remove_style_all(middle_row);
|
||||
lv_obj_set_width(middle_row, LV_PCT(100));
|
||||
|
||||
@@ -13,11 +13,18 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum ui_ble_link_state {
|
||||
UI_BLE_LINK_HIDDEN = 0,
|
||||
UI_BLE_LINK_SEARCHING,
|
||||
UI_BLE_LINK_CONNECTED,
|
||||
};
|
||||
|
||||
struct ui_main_model {
|
||||
lv_color_t theme_color;
|
||||
lv_color_t inactive_border_color;
|
||||
uint8_t battery_level;
|
||||
enum mode_switch_mode mode;
|
||||
enum ui_ble_link_state ble_link_state;
|
||||
uint8_t led_mask;
|
||||
bool charging;
|
||||
bool full;
|
||||
|
||||
Reference in New Issue
Block a user