[LVGL] 从0开始,学LVGL:进阶应用与项目实战(下)

LVGL智能家居控制面板实战
该文章已生成可运行项目,

第4部分:进阶应用与项目实战(下)

第13章:综合实战(一)- 设计一个智能家居控制面板UI

文章目录

  • **第4部分:进阶应用与项目实战(下)**
    • **第13章:综合实战(一)- 设计一个智能家居控制面板UI**
      • **13.1 项目需求分析与架构设计**
        • **13.1.1 功能需求分析**
        • **13.1.2 UI架构设计**
      • **13.2 创建主界面布局**
      • **13.3 创建环境监控页面**
    • **第14章:综合实战(二)- 为面板注入逻辑**
      • **14.1 设备控制页面与事件处理**
      • **14.2 场景管理与数据驱动**
      • **14.3 数据持久化与状态管理**
      • **14.4 应用初始化与主循环**
      • **项目总结与扩展**

13.1 项目需求分析与架构设计

在本章中,我们将创建一个完整的智能家居控制面板。这个项目将综合运用我们之前学到的所有知识:布局、样式、事件处理、动画、图表和高级控件。

13.1.1 功能需求分析

我们的智能家居控制面板需要包含以下核心功能:

智能家居控制面板
环境监控
设备控制
场景管理
能源管理
系统设置
温度湿度显示
空气质量监测
实时数据图表
灯光控制
窗帘控制
空调控制
安防系统
场景快速切换
自定义场景
定时任务
用电统计
节能模式
费用估算
设备管理
用户设置
系统信息
13.1.2 UI架构设计

基于功能需求,我们设计以下UI架构:

// 应用状态数据结构
typedef struct {
    // 环境数据
    float temperature;
    float humidity;
    float air_quality;
    
    // 设备状态
    struct {
        bool living_room_light;
        bool bedroom_light;
        bool kitchen_light;
        int light_brightness;
        bool curtains_open;
        int ac_temperature;
        bool security_armed;
    } devices;
    
    // 场景状态
    const char * current_scene;
    
    // 能源数据
    float power_consumption;
    float energy_cost;
} smart_home_state_t;

static smart_home_state_t app_state = {
    .temperature = 24.5f,
    .humidity = 65.0f,
    .air_quality = 85.0f,
    .devices = {
        .living_room_light = true,
        .bedroom_light = false,
        .kitchen_light = true,
        .light_brightness = 75,
        .curtains_open = true,
        .ac_temperature = 24,
        .security_armed = false
    },
    .current_scene = "居家模式",
    .power_consumption = 2.3f,
    .energy_cost = 1.2f
};

13.2 创建主界面布局

我们将使用Grid布局创建响应式的主界面:

#include <lvgl.h>

// 全局UI组件引用
typedef struct {
    lv_obj_t * main_container;
    lv_obj_t * header;
    lv_obj_t * content_area;
    lv_obj_t * sidebar;
    lv_obj_t * status_bar;
} ui_components_t;

static ui_components_t ui;

/**
 * 创建智能家居主界面
 */
void create_smart_home_ui() {
    lv_obj_t * parent = lv_scr_act();
    
    // 设置屏幕背景
    lv_obj_set_style_bg_color(parent, lv_color_hex(0x1A2530), 0);
    
    /********************
     * 1. 定义主网格布局
     ********************/
    
    // 列定义:侧边栏 | 主要内容区域
    static lv_coord_t col_dsc[] = {
        280,    // 侧边栏固定宽度
        LV_GRID_FR(1),  // 主要内容区域占据剩余空间
        LV_GRID_TEMPLATE_LAST
    };
    
    // 行定义:头部 | 内容区域 | 状态栏
    static lv_coord_t row_dsc[] = {
        80,     // 头部高度
        LV_GRID_FR(1),  // 内容区域
        60,     // 状态栏高度
        LV_GRID_TEMPLATE_LAST
    };
    
    // 创建主容器
    ui.main_container = lv_obj_create(parent);
    lv_obj_set_size(ui.main_container, LV_PCT(100), LV_PCT(100));
    lv_obj_set_style_bg_opa(ui.main_container, LV_OPA_0, 0);
    lv_obj_set_style_border_width(ui.main_container, 0, 0);
    lv_obj_set_style_pad_all(ui.main_container, 0, 0);
    lv_obj_set_grid_dsc_array(ui.main_container, col_dsc, row_dsc);
    
    /********************
     * 2. 创建头部区域
     ********************/
    create_header_area();
    
    /********************
     * 3. 创建侧边栏
     ********************/
    create_sidebar();
    
    /********************
     * 4. 创建内容区域
     ********************/
    create_content_area();
    
    /********************
     * 5. 创建状态栏
     ********************/
    create_status_bar();
}

/**
 * 创建头部区域
 */
void create_header_area() {
    // 头部占据第一行,跨越两列
    ui.header = lv_obj_create(ui.main_container);
    lv_obj_set_style_bg_color(ui.header, lv_color_hex(0x2C3E50), 0);
    lv_obj_set_style_border_width(ui.header, 0, 0);
    lv_obj_set_style_radius(ui.header, 0, 0);
    lv_obj_set_grid_cell(ui.header,
        LV_GRID_ALIGN_STRETCH, 0, 2,
        LV_GRID_ALIGN_STRETCH, 0, 1
    );
    
    // 头部内容使用Flex布局
    lv_obj_set_flex_flow(ui.header, LV_FLEX_FLOW_ROW);
    lv_obj_set_flex_align(ui.header, LV_FLEX_ALIGN_SPACE_BETWEEN,
                         LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    lv_obj_set_style_pad_hor(ui.header, 30, 0);
    
    // 左侧:Logo和标题
    lv_obj_t * title_container = lv_obj_create(ui.header);
    lv_obj_set_size(title_container, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
    lv_obj_set_style_bg_opa(title_container, LV_OPA_0, 0);
    lv_obj_set_style_border_width(title_container, 0, 0);
    lv_obj_set_flex_flow(title_container, LV_FLEX_FLOW_ROW);
    lv_obj_set_flex_align(title_container, LV_FLEX_ALIGN_START,
                         LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    
    lv_obj_t * logo = lv_label_create(title_container);
    lv_label_set_text(logo, "🏠");
    lv_obj_set_style_text_font(logo, &lv_font_montserrat_24, 0);
    
    lv_obj_t * title = lv_label_create(title_container);
    lv_label_set_text(title, "智能家居控制中心");
    lv_obj_set_style_text_color(title, lv_color_white(), 0);
    lv_obj_set_style_text_font(title, &lv_font_montserrat_20, 0);
    lv_obj_set_style_pad_left(title, 10, 0);
    
    // 右侧:用户信息和通知
    lv_obj_t * user_container = lv_obj_create(ui.header);
    lv_obj_set_size(user_container, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
    lv_obj_set_style_bg_opa(user_container, LV_OPA_0, 0);
    lv_obj_set_style_border_width(user_container, 0, 0);
    lv_obj_set_flex_flow(user_container, LV_FLEX_FLOW_ROW);
    lv_obj_set_flex_align(user_container, LV_FLEX_ALIGN_END,
                         LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    
    // 通知图标
    lv_obj_t * notification_btn = lv_btn_create(user_container);
    lv_obj_set_size(notification_btn, 40, 40);
    lv_obj_set_style_bg_opa(notification_btn, LV_OPA_0, 0);
    lv_obj_set_style_border_width(notification_btn, 0, 0);
    
    lv_obj_t * notification_icon = lv_label_create(notification_btn);
    lv_label_set_text(notification_icon, LV_SYMBOL_BELL);
    lv_obj_set_style_text_color(notification_icon, lv_color_white(), 0);
    lv_obj_set_style_text_font(notification_icon, &lv_font_montserrat_18, 0);
    lv_obj_center(notification_icon);
    
    // 用户头像
    lv_obj_t * user_avatar = lv_obj_create(user_container);
    lv_obj_set_size(user_avatar, 45, 45);
    lv_obj_set_style_bg_color(user_avatar, lv_color_hex(0x3498DB), 0);
    lv_obj_set_style_radius(user_avatar, 22, 0);
    lv_obj_set_style_pad_left(user_avatar, 15, 0);
    
    lv_obj_t * avatar_text = lv_label_create(user_avatar);
    lv_label_set_text(avatar_text, "用户");
    lv_obj_set_style_text_color(avatar_text, lv_color_white(), 0);
    lv_obj_set_style_text_font(avatar_text, &lv_font_montserrat_14, 0);
    lv_obj_center(avatar_text);
}

/**
 * 创建侧边栏导航
 */
void create_sidebar() {
    // 侧边栏占据第二行第一列
    ui.sidebar = lv_obj_create(ui.main_container);
    lv_obj_set_style_bg_color(ui.sidebar, lv_color_hex(0x34495E), 0);
    lv_obj_set_style_border_width(ui.sidebar, 0, 0);
    lv_obj_set_style_radius(ui.sidebar, 0, 0);
    lv_obj_set_grid_cell(ui.sidebar,
        LV_GRID_ALIGN_STRETCH, 0, 1,
        LV_GRID_ALIGN_STRETCH, 1, 1
    );
    
    // 侧边栏使用垂直Flex布局
    lv_obj_set_flex_flow(ui.sidebar, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_flex_align(ui.sidebar, LV_FLEX_ALIGN_START,
                         LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
    lv_obj_set_style_pad_all(ui.sidebar, 20, 0);
    lv_obj_set_style_pad_gap(ui.sidebar, 10, 0);
    
    // 导航菜单项
    struct {
        const char * icon;
        const char * text;
        const char * id;
    } menu_items[] = {
        {"📊", "环境监控", "environment"},
        {"💡", "设备控制", "devices"},
        {"🎭", "场景模式", "scenes"},
        {"🔋", "能源管理", "energy"},
        {"⚙️", "系统设置", "settings"},
    };
    
    for(int i = 0; i < sizeof(menu_items) / sizeof(menu_items[0]); i++) {
        create_nav_item(ui.sidebar, menu_items[i].icon, menu_items[i].text, menu_items[i].id);
    }
    
    // 底部信息区域
    create_sidebar_footer();
}

/**
 * 创建导航菜单项
 */
void create_nav_item(lv_obj_t * parent, const char * icon, const char * text, const char * id) {
    lv_obj_t * nav_btn = lv_btn_create(parent);
    lv_obj_set_size(nav_btn, LV_PCT(100), 55);
    lv_obj_set_style_bg_color(nav_btn, lv_color_hex(0x2C3E50), 0);
    lv_obj_set_style_bg_color(nav_btn, lv_color_hex(0x3498DB), LV_STATE_CHECKED);
    lv_obj_set_style_radius(nav_btn, 10, 0);
    lv_obj_set_style_border_width(nav_btn, 0, 0);
    lv_obj_add_flag(nav_btn, LV_OBJ_FLAG_CHECKABLE);
    
    // 默认选中第一个菜单项
    if(strcmp(id, "environment") == 0) {
        lv_obj_add_state(nav_btn, LV_STATE_CHECKED);
    }
    
    // 内容容器
    lv_obj_t * content = lv_obj_create(nav_btn);
    lv_obj_set_size(content, LV_PCT(100), LV_PCT(100));
    lv_obj_set_style_bg_opa(content, LV_OPA_0, 0);
    lv_obj_set_style_border_width(content, 0, 0);
    lv_obj_set_flex_flow(content, LV_FLEX_FLOW_ROW);
    lv_obj_set_flex_align(content, LV_FLEX_ALIGN_START,
                         LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    lv_obj_set_style_pad_all(content, 15, 0);
    
    // 图标
    lv_obj_t * icon_label = lv_label_create(content);
    lv_label_set_text(icon_label, icon);
    lv_obj_set_style_text_color(icon_label, lv_color_white(), 0);
    lv_obj_set_style_text_font(icon_label, &lv_font_montserrat_18, 0);
    
    // 文本
    lv_obj_t * text_label = lv_label_create(content);
    lv_label_set_text(text_label, text);
    lv_obj_set_style_text_color(text_label, lv_color_white(), 0);
    lv_obj_set_style_text_font(text_label, &lv_font_montserrat_16, 0);
    lv_obj_set_style_pad_left(text_label, 15, 0);
    
    // 存储菜单ID用于事件处理
    lv_obj_set_user_data(nav_btn, (void*)id);
    
    // 添加点击事件
    lv_obj_add_event_cb(nav_btn, nav_item_click_handler, LV_EVENT_CLICKED, NULL);
}

/**
 * 创建侧边栏底部信息
 */
void create_sidebar_footer() {
    // 底部容器
    lv_obj_t * footer = lv_obj_create(ui.sidebar);
    lv_obj_set_size(footer, LV_PCT(100), LV_SIZE_CONTENT);
    lv_obj_set_style_bg_opa(footer, LV_OPA_0, 0);
    lv_obj_set_style_border_width(footer, 0, 0);
    lv_obj_set_flex_flow(footer, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_flex_align(footer, LV_FLEX_ALIGN_START,
                         LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
    lv_obj_set_style_pad_top(footer, 20, 0);
    
    // 系统状态
    lv_obj_t * status_title = lv_label_create(footer);
    lv_label_set_text(status_title, "系统状态");
    lv_obj_set_style_text_color(status_title, lv_color_hex(0xBDC3C7), 0);
    lv_obj_set_style_text_font(status_title, &lv_font_montserrat_14, 0);
    
    lv_obj_t * status_info = lv_label_create(footer);
    lv_label_set_text(status_info, "✅ 所有系统正常");
    lv_obj_set_style_text_color(status_info, lv_color_hex(0x2ECC71), 0);
    lv_obj_set_style_text_font(status_info, &lv_font_montserrat_12, 0);
    lv_obj_set_style_pad_top(status_info, 5, 0);
    
    // 版本信息
    lv_obj_t * version = lv_label_create(footer);
    lv_label_set_text(version, "v2.1.0");
    lv_obj_set_style_text_color(version, lv_color_hex(0x7F8C8D), 0);
    lv_obj_set_style_text_font(version, &lv_font_montserrat_10, 0);
    lv_obj_set_style_pad_top(version, 15, 0);
}

/**
 * 创建内容区域
 */
void create_content_area() {
    // 内容区域占据第二行第二列
    ui.content_area = lv_obj_create(ui.main_container);
    lv_obj_set_style_bg_color(ui.content_area, lv_color_hex(0x1A2530), 0);
    lv_obj_set_style_border_width(ui.content_area, 0, 0);
    lv_obj_set_style_radius(ui.content_area, 0, 0);
    lv_obj_set_grid_cell(ui.content_area,
        LV_GRID_ALIGN_STRETCH, 1, 1,
        LV_GRID_ALIGN_STRETCH, 1, 1
    );
    
    // 初始化显示环境监控页面
    create_environment_page();
}

/**
 * 创建状态栏
 */
void create_status_bar() {
    // 状态栏占据第三行,跨越两列
    ui.status_bar = lv_obj_create(ui.main_container);
    lv_obj_set_style_bg_color(ui.status_bar, lv_color_hex(0x2C3E50), 0);
    lv_obj_set_style_border_width(ui.status_bar, 0, 0);
    lv_obj_set_style_radius(ui.status_bar, 0, 0);
    lv_obj_set_grid_cell(ui.status_bar,
        LV_GRID_ALIGN_STRETCH, 0, 2,
        LV_GRID_ALIGN_STRETCH, 2, 1
    );
    
    // 状态栏使用Flex布局
    lv_obj_set_flex_flow(ui.status_bar, LV_FLEX_FLOW_ROW);
    lv_obj_set_flex_align(ui.status_bar, LV_FLEX_ALIGN_SPACE_BETWEEN,
                         LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    lv_obj_set_style_pad_hor(ui.status_bar, 30, 0);
    
    // 左侧:当前场景和连接状态
    lv_obj_t * left_info = lv_obj_create(ui.status_bar);
    lv_obj_set_size(left_info, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
    lv_obj_set_style_bg_opa(left_info, LV_OPA_0, 0);
    lv_obj_set_style_border_width(left_info, 0, 0);
    lv_obj_set_flex_flow(left_info, LV_FLEX_FLOW_ROW);
    lv_obj_set_flex_align(left_info, LV_FLEX_ALIGN_START,
                         LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    
    lv_obj_t * scene_label = lv_label_create(left_info);
    lv_label_set_text_fmt(scene_label, "当前场景: %s", app_state.current_scene);
    lv_obj_set_style_text_color(scene_label, lv_color_white(), 0);
    lv_obj_set_style_text_font(scene_label, &lv_font_montserrat_14, 0);
    
    lv_obj_t * conn_status = lv_label_create(left_info);
    lv_label_set_text(conn_status, " 🌐 已连接");
    lv_obj_set_style_text_color(conn_status, lv_color_hex(0x2ECC71), 0);
    lv_obj_set_style_text_font(conn_status, &lv_font_montserrat_12, 0);
    lv_obj_set_style_pad_left(conn_status, 20, 0);
    
    // 右侧:时间和日期
    lv_obj_t * time_label = lv_label_create(ui.status_bar);
    lv_label_set_text(time_label, "2024-06-15 14:30:25");
    lv_obj_set_style_text_color(time_label, lv_color_white(), 0);
    lv_obj_set_style_text_font(time_label, &lv_font_montserrat_14, 0);
    
    // 更新时间显示
    lv_timer_t * timer = lv_timer_create(update_time_display, 1000, time_label);
}

/**
 * 导航菜单点击事件处理
 */
static void nav_item_click_handler(lv_event_t * e) {
    lv_obj_t * target = lv_event_get_target(e);
    const char * page_id = (const char *)lv_obj_get_user_data(target);
    
    // 清除其他菜单项的选中状态
    lv_obj_t * sibling = lv_obj_get_child(ui.sidebar, 0);
    while(sibling) {
        if(sibling != target && lv_obj_has_flag(sibling, LV_OBJ_FLAG_CHECKABLE)) {
            lv_obj_clear_state(sibling, LV_STATE_CHECKED);
        }
        sibling = lv_obj_get_child(ui.sidebar, lv_obj_get_index(sibling) + 1);
    }
    
    // 设置当前菜单项为选中状态
    lv_obj_add_state(target, LV_STATE_CHECKED);
    
    // 根据ID切换到对应页面
    if(strcmp(page_id, "environment") == 0) {
        create_environment_page();
    } else if(strcmp(page_id, "devices") == 0) {
        create_devices_page();
    } else if(strcmp(page_id, "scenes") == 0) {
        create_scenes_page();
    } else if(strcmp(page_id, "energy") == 0) {
        create_energy_page();
    } else if(strcmp(page_id, "settings") == 0) {
        create_settings_page();
    }
}

/**
 * 更新时间显示
 */
static void update_time_display(lv_timer_t * timer) {
    // 这里应该获取系统时间,这里使用静态变量模拟
    static int seconds = 0;
    seconds++;
    
    int hours = (14 + seconds / 3600) % 24;
    int minutes = (30 + (seconds % 3600) / 60) % 60;
    int secs = seconds % 60;
    
    char time_str[32];
    snprintf(time_str, sizeof(time_str), "2024-06-15 %02d:%02d:%02d", hours, minutes, secs);
    
    lv_label_set_text((lv_obj_t *)timer->user_data, time_str);
}

13.3 创建环境监控页面

现在让我们创建第一个功能页面 - 环境监控:

/**
 * 创建环境监控页面
 */
void create_environment_page() {
    // 清除之前的内容
    lv_obj_clean(ui.content_area);
    
    // 设置内容区域为垂直Flex布局
    lv_obj_set_flex_flow(ui.content_area, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_flex_align(ui.content_area, LV_FLEX_ALIGN_START,
                         LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
    lv_obj_set_style_pad_all(ui.content_area, 25, 0);
    lv_obj_set_style_pad_gap(ui.content_area, 20, 0);
    
    // 页面标题
    lv_obj_t * page_title = lv_label_create(ui.content_area);
    lv_label_set_text(page_title, "环境监控");
    lv_obj_set_style_text_color(page_title, lv_color_white(), 0);
    lv_obj_set_style_text_font(page_title, &lv_font_montserrat_24, 0);
    
    // 环境数据卡片容器
    lv_obj_t * cards_container = lv_obj_create(ui.content_area);
    lv_obj_set_size(cards_container, LV_PCT(100), LV_SIZE_CONTENT);
    lv_obj_set_style_bg_opa(cards_container, LV_OPA_0, 0);
    lv_obj_set_style_border_width(cards_container, 0, 0);
    lv_obj_set_flex_flow(cards_container, LV_FLEX_FLOW_ROW_WRAP);
    lv_obj_set_flex_align(cards_container, LV_FLEX_ALIGN_SPACE_EVENLY,
                         LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
    lv_obj_set_style_pad_gap(cards_container, 20, 0);
    
    // 创建环境数据卡片
    create_environment_card(cards_container, "🌡️", "温度", "24.5°C", "舒适", lv_color_hex(0xE74C3C));
    create_environment_card(cards_container, "💧", "湿度", "65%", "正常", lv_color_hex(0x3498DB));
    create_environment_card(cards_container, "🍃", "空气质量", "85", "良好", lv_color_hex(0x2ECC71));
    create_environment_card(cards_container, "🔊", "噪音", "42dB", "安静", lv_color_hex(0x9B59B6));
    
    // 创建图表区域
    create_environment_charts();
}

/**
 * 创建环境数据卡片
 */
void create_environment_card(lv_obj_t * parent, const char * icon, const char * title, 
                            const char * value, const char * status, lv_color_t color) {
    lv_obj_t * card = lv_obj_create(parent);
    lv_obj_set_size(card, 180, 140);
    lv_obj_set_style_bg_color(card, lv_color_hex(0x2C3E50), 0);
    lv_obj_set_style_radius(card, 15, 0);
    lv_obj_set_style_shadow_width(card, 10, 0);
    lv_obj_set_style_shadow_color(card, lv_color_hex(0x1A2530), 0);
    lv_obj_set_flex_flow(card, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_flex_align(card, LV_FLEX_ALIGN_SPACE_AROUND,
                         LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    lv_obj_set_style_pad_all(card, 20, 0);
    
    // 图标
    lv_obj_t * icon_label = lv_label_create(card);
    lv_label_set_text(icon_label, icon);
    lv_obj_set_style_text_color(icon_label, color, 0);
    lv_obj_set_style_text_font(icon_label, &lv_font_montserrat_24, 0);
    
    // 标题
    lv_obj_t * title_label = lv_label_create(card);
    lv_label_set_text(title_label, title);
    lv_obj_set_style_text_color(title_label, lv_color_hex(0xBDC3C7), 0);
    lv_obj_set_style_text_font(title_label, &lv_font_montserrat_14, 0);
    
    // 数值
    lv_obj_t * value_label = lv_label_create(card);
    lv_label_set_text(value_label, value);
    lv_obj_set_style_text_color(value_label, lv_color_white(), 0);
    lv_obj_set_style_text_font(value_label, &lv_font_montserrat_20, 0);
    
    // 状态
    lv_obj_t * status_label = lv_label_create(card);
    lv_label_set_text(status_label, status);
    lv_obj_set_style_text_color(status_label, color, 0);
    lv_obj_set_style_text_font(status_label, &lv_font_montserrat_12, 0);
}

/**
 * 创建环境数据图表
 */
void create_environment_charts() {
    lv_obj_t * charts_container = lv_obj_create(ui.content_area);
    lv_obj_set_size(charts_container, LV_PCT(100), 300);
    lv_obj_set_style_bg_opa(charts_container, LV_OPA_0, 0);
    lv_obj_set_style_border_width(charts_container, 0, 0);
    lv_obj_set_flex_flow(charts_container, LV_FLEX_FLOW_ROW);
    lv_obj_set_flex_align(charts_container, LV_FLEX_ALIGN_SPACE_BETWEEN,
                         LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
    
    // 温度图表
    lv_obj_t * temp_chart = lv_chart_create(charts_container);
    lv_obj_set_size(temp_chart, LV_PCT(48), LV_PCT(100));
    lv_obj_set_style_bg_color(temp_chart, lv_color_hex(0x2C3E50), 0);
    lv_obj_set_style_radius(temp_chart, 15, 0);
    
    lv_chart_set_type(temp_chart, LV_CHART_TYPE_LINE);
    lv_chart_set_range(temp_chart, LV_CHART_AXIS_PRIMARY_Y, 15, 35);
    lv_chart_set_point_count(temp_chart, 24);
    lv_chart_set_div_line_count(temp_chart, 4, 6);
    
    lv_chart_series_t * temp_series = lv_chart_add_series(temp_chart, lv_color_hex(0xE74C3C), LV_CHART_AXIS_PRIMARY_Y);
    
    // 湿度图表
    lv_obj_t * humi_chart = lv_chart_create(charts_container);
    lv_obj_set_size(humi_chart, LV_PCT(48), LV_PCT(100));
    lv_obj_set_style_bg_color(humi_chart, lv_color_hex(0x2C3E50), 0);
    lv_obj_set_style_radius(humi_chart, 15, 0);
    
    lv_chart_set_type(humi_chart, LV_CHART_TYPE_LINE);
    lv_chart_set_range(humi_chart, LV_CHART_AXIS_PRIMARY_Y, 30, 90);
    lv_chart_set_point_count(humi_chart, 24);
    lv_chart_set_div_line_count(humi_chart, 4, 6);
    
    lv_chart_series_t * humi_series = lv_chart_add_series(humi_chart, lv_color_hex(0x3498DB), LV_CHART_AXIS_PRIMARY_Y);
    
    // 模拟历史数据
    for(int i = 0; i < 24; i++) {
        lv_chart_set_next_value(temp_chart, temp_series, 20 + rand() % 10);
        lv_chart_set_next_value(humi_chart, humi_series, 40 + rand() % 40);
    }
    
    // 图表标题
    lv_obj_t * temp_title = lv_label_create(temp_chart);
    lv_label_set_text(temp_title, "温度趋势");
    lv_obj_set_style_text_color(temp_title, lv_color_white(), 0);
    lv_obj_align(temp_title, LV_ALIGN_TOP_LEFT, 10, 10);
    
    lv_obj_t * humi_title = lv_label_create(humi_chart);
    lv_label_set_text(humi_title, "湿度趋势");
    lv_obj_set_style_text_color(humi_title, lv_color_white(), 0);
    lv_obj_align(humi_title, LV_ALIGN_TOP_LEFT, 10, 10);
}

第14章:综合实战(二)- 为面板注入逻辑

14.1 设备控制页面与事件处理

现在让我们创建设备控制页面并实现完整的交互逻辑:

/**
 * 创建设备控制页面
 */
void create_devices_page() {
    // 清除之前的内容
    lv_obj_clean(ui.content_area);
    
    // 设置内容区域布局
    lv_obj_set_flex_flow(ui.content_area, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_flex_align(ui.content_area, LV_FLEX_ALIGN_START,
                         LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
    lv_obj_set_style_pad_all(ui.content_area, 25, 0);
    lv_obj_set_style_pad_gap(ui.content_area, 20, 0);
    
    // 页面标题
    lv_obj_t * page_title = lv_label_create(ui.content_area);
    lv_label_set_text(page_title, "设备控制");
    lv_obj_set_style_text_color(page_title, lv_color_white(), 0);
    lv_obj_set_style_text_font(page_title, &lv_font_montserrat_24, 0);
    
    // 创建设备控制卡片
    create_device_control_section("💡 灯光控制", create_lighting_controls);
    create_device_control_section("🌡️ 空调控制", create_ac_controls);
    create_device_control_section("🪟 窗帘控制", create_curtain_controls);
    create_device_control_section("🔒 安防系统", create_security_controls);
}

/**
 * 创建设备控制区域
 */
void create_device_control_section(const char * title, void (*create_controls_func)(lv_obj_t*)) {
    lv_obj_t * section = lv_obj_create(ui.content_area);
    lv_obj_set_size(section, LV_PCT(100), LV_SIZE_CONTENT);
    lv_obj_set_style_bg_color(section, lv_color_hex(0x2C3E50), 0);
    lv_obj_set_style_radius(section, 15, 0);
    lv_obj_set_flex_flow(section, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_flex_align(section, LV_FLEX_ALIGN_START,
                         LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
    lv_obj_set_style_pad_all(section, 20, 0);
    lv_obj_set_style_pad_gap(section, 15, 0);
    
    // 区域标题
    lv_obj_t * section_title = lv_label_create(section);
    lv_label_set_text(section_title, title);
    lv_obj_set_style_text_color(section_title, lv_color_white(), 0);
    lv_obj_set_style_text_font(section_title, &lv_font_montserrat_18, 0);
    
    // 创建设备控制
    create_controls_func(section);
}

/**
 * 创建灯光控制
 */
void create_lighting_controls(lv_obj_t * parent) {
    lv_obj_t * controls_container = lv_obj_create(parent);
    lv_obj_set_size(controls_container, LV_PCT(100), LV_SIZE_CONTENT);
    lv_obj_set_style_bg_opa(controls_container, LV_OPA_0, 0);
    lv_obj_set_style_border_width(controls_container, 0, 0);
    lv_obj_set_flex_flow(controls_container, LV_FLEX_FLOW_ROW_WRAP);
    lv_obj_set_flex_align(controls_container, LV_FLEX_ALIGN_SPACE_EVENLY,
                         LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
    
    // 客厅灯光
    create_light_switch(controls_container, "客厅主灯", &app_state.devices.living_room_light, 
                       lv_color_hex(0xF39C12));
    // 卧室灯光
    create_light_switch(controls_container, "卧室灯光", &app_state.devices.bedroom_light, 
                       lv_color_hex(0x3498DB));
    // 厨房灯光
    create_light_switch(controls_container, "厨房灯光", &app_state.devices.kitchen_light, 
                       lv_color_hex(0x2ECC71));
    
    // 亮度调节
    create_brightness_control(parent);
}

/**
 * 创建灯光开关
 */
void create_light_switch(lv_obj_t * parent, const char * room, bool * state, lv_color_t color) {
    lv_obj_t * switch_container = lv_obj_create(parent);
    lv_obj_set_size(switch_container, 150, 100);
    lv_obj_set_style_bg_opa(switch_container, LV_OPA_0, 0);
    lv_obj_set_style_border_width(switch_container, 0, 0);
    lv_obj_set_flex_flow(switch_container, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_flex_align(switch_container, LV_FLEX_ALIGN_SPACE_AROUND,
                         LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    
    // 房间名称
    lv_obj_t * room_label = lv_label_create(switch_container);
    lv_label_set_text(room_label, room);
    lv_obj_set_style_text_color(room_label, lv_color_white(), 0);
    lv_obj_set_style_text_font(room_label, &lv_font_montserrat_14, 0);
    
    // 开关
    lv_obj_t * sw = lv_switch_create(switch_container);
    lv_obj_set_style_bg_color(sw, lv_color_hex(0x7F8C8D), LV_PART_MAIN);
    lv_obj_set_style_bg_color(sw, color, LV_PART_INDICATOR);
    
    // 设置初始状态
    if(*state) {
        lv_obj_add_state(sw, LV_STATE_CHECKED);
    }
    
    // 事件处理
    lv_obj_add_event_cb(sw, [](lv_event_t * e) {
        lv_obj_t * sw = lv_event_get_target(e);
        bool * device_state = (bool *)lv_event_get_user_data(e);
        *device_state = lv_obj_has_state(sw, LV_STATE_CHECKED);
        
        const char * room_name = (const char *)lv_obj_get_user_data(sw);
        printf("%s %s\n", room_name, *device_state ? "开启" : "关闭");
        
        // 这里可以添加实际的设备控制逻辑
        // control_light_device(room_name, *device_state);
    }, LV_EVENT_VALUE_CHANGED, state);
    
    lv_obj_set_user_data(sw, (void*)room);
}

/**
 * 创建亮度调节
 */
void create_brightness_control(lv_obj_t * parent) {
    lv_obj_t * brightness_container = lv_obj_create(parent);
    lv_obj_set_size(brightness_container, LV_PCT(100), 80);
    lv_obj_set_style_bg_opa(brightness_container, LV_OPA_0, 0);
    lv_obj_set_style_border_width(brightness_container, 0, 0);
    lv_obj_set_flex_flow(brightness_container, LV_FLEX_FLOW_ROW);
    lv_obj_set_flex_align(brightness_container, LV_FLEX_ALIGN_SPACE_BETWEEN,
                         LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    
    // 亮度标签
    lv_obj_t * brightness_label = lv_label_create(brightness_container);
    lv_label_set_text(brightness_label, "整体亮度");
    lv_obj_set_style_text_color(brightness_label, lv_color_white(), 0);
    lv_obj_set_style_text_font(brightness_label, &lv_font_montserrat_14, 0);
    
    // 亮度值显示
    lv_obj_t * value_label = lv_label_create(brightness_container);
    lv_label_set_text_fmt(value_label, "%d%%", app_state.devices.light_brightness);
    lv_obj_set_style_text_color(value_label, lv_color_hex(0xF39C12), 0);
    lv_obj_set_style_text_font(value_label, &lv_font_montserrat_16, 0);
    
    // 亮度滑块
    lv_obj_t * slider = lv_slider_create(brightness_container);
    lv_obj_set_size(slider, LV_PCT(60), 20);
    lv_slider_set_range(slider, 0, 100);
    lv_slider_set_value(slider, app_state.devices.light_brightness, LV_ANIM_OFF);
    lv_obj_set_style_bg_color(slider, lv_color_hex(0xF39C12), LV_PART_INDICATOR);
    lv_obj_set_style_bg_color(slider, lv_color_hex(0xF39C12), LV_PART_KNOB);
    
    // 事件处理
    lv_obj_add_event_cb(slider, [](lv_event_t * e) {
        lv_obj_t * slider = lv_event_get_target(e);
        int brightness = lv_slider_get_value(slider);
        app_state.devices.light_brightness = brightness;
        
        lv_obj_t * value_label = (lv_obj_t *)lv_event_get_user_data(e);
        lv_label_set_text_fmt(value_label, "%d%%", brightness);
        
        printf("调整亮度到: %d%%\n", brightness);
        
        // 这里可以添加实际的亮度控制逻辑
        // set_light_brightness(brightness);
    }, LV_EVENT_VALUE_CHANGED, value_label);
}

/**
 * 创建空调控制
 */
void create_ac_controls(lv_obj_t * parent) {
    lv_obj_t * controls_container = lv_obj_create(parent);
    lv_obj_set_size(controls_container, LV_PCT(100), LV_SIZE_CONTENT);
    lv_obj_set_style_bg_opa(controls_container, LV_OPA_0, 0);
    lv_obj_set_style_border_width(controls_container, 0, 0);
    lv_obj_set_flex_flow(controls_container, LV_FLEX_FLOW_ROW);
    lv_obj_set_flex_align(controls_container, LV_FLEX_ALIGN_SPACE_AROUND,
                         LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    
    // 温度显示和调节
    lv_obj_t * temp_control = lv_obj_create(controls_container);
    lv_obj_set_size(temp_control, 200, 120);
    lv_obj_set_style_bg_opa(temp_control, LV_OPA_0, 0);
    lv_obj_set_style_border_width(temp_control, 0, 0);
    lv_obj_set_flex_flow(temp_control, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_flex_align(temp_control, LV_FLEX_ALIGN_SPACE_AROUND,
                         LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    
    lv_obj_t * temp_label = lv_label_create(temp_control);
    lv_label_set_text(temp_label, "设定温度");
    lv_obj_set_style_text_color(temp_label, lv_color_white(), 0);
    
    lv_obj_t * temp_value = lv_label_create(temp_control);
    lv_label_set_text_fmt(temp_value, "%d°C", app_state.devices.ac_temperature);
    lv_obj_set_style_text_color(temp_value, lv_color_hex(0x3498DB), 0);
    lv_obj_set_style_text_font(temp_value, &lv_font_montserrat_24, 0);
    
    // 温度调节按钮
    lv_obj_t * temp_buttons = lv_obj_create(temp_control);
    lv_obj_set_size(temp_buttons, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
    lv_obj_set_style_bg_opa(temp_buttons, LV_OPA_0, 0);
    lv_obj_set_style_border_width(temp_buttons, 0, 0);
    lv_obj_set_flex_flow(temp_buttons, LV_FLEX_FLOW_ROW);
    lv_obj_set_flex_align(temp_buttons, LV_FLEX_ALIGN_SPACE_AROUND,
                         LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    
    lv_obj_t * temp_down = lv_btn_create(temp_buttons);
    lv_obj_set_size(temp_down, 40, 40);
    lv_obj_set_style_bg_color(temp_down, lv_color_hex(0xE74C3C), 0);
    lv_obj_t * down_label = lv_label_create(temp_down);
    lv_label_set_text(down_label, "-");
    lv_obj_center(down_label);
    
    lv_obj_t * temp_up = lv_btn_create(temp_buttons);
    lv_obj_set_size(temp_up, 40, 40);
    lv_obj_set_style_bg_color(temp_up, lv_color_hex(0x2ECC71), 0);
    lv_obj_t * up_label = lv_label_create(temp_up);
    lv_label_set_text(up_label, "+");
    lv_obj_center(up_label);
    
    // 温度调节事件
    lv_obj_add_event_cb(temp_down, [](lv_event_t * e) {
        if(app_state.devices.ac_temperature > 16) {
            app_state.devices.ac_temperature--;
            update_ac_temperature_display();
        }
    }, LV_EVENT_CLICKED, NULL);
    
    lv_obj_add_event_cb(temp_up, [](lv_event_t * e) {
        if(app_state.devices.ac_temperature < 30) {
            app_state.devices.ac_temperature++;
            update_ac_temperature_display();
        }
    }, LV_EVENT_CLICKED, NULL);
    
    // 存储温度显示标签的引用
    lv_obj_set_user_data(temp_control, temp_value);
}

/**
 * 更新空调温度显示
 */
void update_ac_temperature_display() {
    // 这里需要遍历UI找到温度显示标签并更新
    // 在实际项目中,应该维护UI组件的引用
    printf("空调温度设置为: %d°C\n", app_state.devices.ac_temperature);
}

14.2 场景管理与数据驱动

现在让我们实现场景管理功能和数据驱动的UI更新:

/**
 * 创建场景模式页面
 */
void create_scenes_page() {
    // 清除之前的内容
    lv_obj_clean(ui.content_area);
    
    // 设置内容区域布局
    lv_obj_set_flex_flow(ui.content_area, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_flex_align(ui.content_area, LV_FLEX_ALIGN_START,
                         LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
    lv_obj_set_style_pad_all(ui.content_area, 25, 0);
    lv_obj_set_style_pad_gap(ui.content_area, 20, 0);
    
    // 页面标题
    lv_obj_t * page_title = lv_label_create(ui.content_area);
    lv_label_set_text(page_title, "场景模式");
    lv_obj_set_style_text_color(page_title, lv_color_white(), 0);
    lv_obj_set_style_text_font(page_title, &lv_font_montserrat_24, 0);
    
    // 当前场景显示
    lv_obj_t * current_scene_container = lv_obj_create(ui.content_area);
    lv_obj_set_size(current_scene_container, LV_PCT(100), 80);
    lv_obj_set_style_bg_color(current_scene_container, lv_color_hex(0x2C3E50), 0);
    lv_obj_set_style_radius(current_scene_container, 15, 0);
    lv_obj_set_flex_flow(current_scene_container, LV_FLEX_FLOW_ROW);
    lv_obj_set_flex_align(current_scene_container, LV_FLEX_ALIGN_SPACE_BETWEEN,
                         LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    lv_obj_set_style_pad_hor(current_scene_container, 20, 0);
    
    lv_obj_t * current_label = lv_label_create(current_scene_container);
    lv_label_set_text(current_label, "当前场景");
    lv_obj_set_style_text_color(current_label, lv_color_hex(0xBDC3C7), 0);
    
    lv_obj_t * scene_name = lv_label_create(current_scene_container);
    lv_label_set_text_fmt(scene_name, "🏠 %s", app_state.current_scene);
    lv_obj_set_style_text_color(scene_name, lv_color_hex(0x2ECC71), 0);
    lv_obj_set_style_text_font(scene_name, &lv_font_montserrat_18, 0);
    
    // 场景网格
    lv_obj_t * scenes_grid = lv_obj_create(ui.content_area);
    lv_obj_set_size(scenes_grid, LV_PCT(100), LV_PCT(100));
    lv_obj_set_style_bg_opa(scenes_grid, LV_OPA_0, 0);
    lv_obj_set_style_border_width(scenes_grid, 0, 0);
    lv_obj_set_flex_flow(scenes_grid, LV_FLEX_FLOW_ROW_WRAP);
    lv_obj_set_flex_align(scenes_grid, LV_FLEX_ALIGN_SPACE_EVENLY,
                         LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START);
    lv_obj_set_style_pad_gap(scenes_grid, 20, 0);
    
    // 定义场景
    struct {
        const char * name;
        const char * icon;
        const char * description;
        lv_color_t color;
    } scenes[] = {
        {"居家模式", "🏠", "舒适的居家环境", lv_color_hex(0x3498DB)},
        {"影院模式", "🎬", "沉浸式观影体验", lv_color_hex(0x9B59B6)},
        {"睡眠模式", "😴", "安静舒适的睡眠", lv_color_hex(0x2C3E50)},
        {"阅读模式", "📖", "专注的阅读光线", lv_color_hex(0xF39C12)},
        {"聚会模式", "🎉", "欢乐的聚会氛围", lv_color_hex(0xE74C3C)},
        {"离家模式", "🚪", "节能安全模式", lv_color_hex(0x7F8C8D)},
    };
    
    for(int i = 0; i < sizeof(scenes) / sizeof(scenes[0]); i++) {
        create_scene_card(scenes_grid, &scenes[i]);
    }
}

/**
 * 创建场景卡片
 */
void create_scene_card(lv_obj_t * parent, void * scene_data) {
    typedef struct {
        const char * name;
        const char * icon;
        const char * description;
        lv_color_t color;
    } scene_info_t;
    
    scene_info_t * scene = (scene_info_t *)scene_data;
    
    lv_obj_t * card = lv_btn_create(parent);
    lv_obj_set_size(card, 170, 150);
    lv_obj_set_style_bg_color(card, scene->color, 0);
    lv_obj_set_style_bg_color(card, lv_color_lighten(scene->color, 50), LV_STATE_PRESSED);
    lv_obj_set_style_radius(card, 15, 0);
    lv_obj_set_style_shadow_width(card, 15, 0);
    lv_obj_set_style_shadow_color(card, lv_color_darken(scene->color, 100), 0);
    lv_obj_set_flex_flow(card, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_flex_align(card, LV_FLEX_ALIGN_SPACE_AROUND,
                         LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
    
    // 场景图标
    lv_obj_t * icon = lv_label_create(card);
    lv_label_set_text(icon, scene->icon);
    lv_obj_set_style_text_color(icon, lv_color_white(), 0);
    lv_obj_set_style_text_font(icon, &lv_font_montserrat_24, 0);
    
    // 场景名称
    lv_obj_t * name = lv_label_create(card);
    lv_label_set_text(name, scene->name);
    lv_obj_set_style_text_color(name, lv_color_white(), 0);
    lv_obj_set_style_text_font(name, &lv_font_montserrat_16, 0);
    
    // 场景描述
    lv_obj_t * desc = lv_label_create(card);
    lv_label_set_text(desc, scene->description);
    lv_obj_set_style_text_color(desc, lv_color_white(), 0);
    lv_obj_set_style_text_font(desc, &lv_font_montserrat_12, 0);
    lv_obj_set_style_text_align(desc, LV_TEXT_ALIGN_CENTER, 0);
    lv_obj_set_width(desc, LV_PCT(90));
    
    // 事件处理
    lv_obj_add_event_cb(card, [](lv_event_t * e) {
        scene_info_t * scene = (scene_info_t *)lv_event_get_user_data(e);
        
        // 更新当前场景
        app_state.current_scene = scene->name;
        
        printf("切换到场景: %s\n", scene->name);
        printf("场景描述: %s\n", scene->description);
        
        // 这里可以添加实际的场景切换逻辑
        // apply_scene_configuration(scene->name);
        
        // 更新状态栏显示
        update_status_bar_scene();
        
        // 添加切换动画
        lv_obj_t * card = lv_event_get_target(e);
        lv_anim_t a;
        lv_anim_init(&a);
        lv_anim_set_var(&a, card);
        lv_anim_set_values(&a, 255, 150, 255);
        lv_anim_set_time(&a, 300);
        lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_style_opa);
        lv_anim_start(&a);
    }, LV_EVENT_CLICKED, scene);
}

/**
 * 更新状态栏场景显示
 */
void update_status_bar_scene() {
    // 在实际项目中,应该维护状态栏组件的引用
    printf("状态栏更新: 当前场景 = %s\n", app_state.current_scene);
}

14.3 数据持久化与状态管理

为了实现完整的数据驱动,我们需要添加状态管理和数据持久化:

/**
 * 应用状态管理器
 */
typedef struct {
    smart_home_state_t current_state;
    void (*state_change_callback)(smart_home_state_t new_state);
} state_manager_t;

static state_manager_t state_mgr;

/**
 * 初始化状态管理器
 */
void init_state_manager() {
    state_mgr.current_state = app_state;
    state_mgr.state_change_callback = NULL;
}

/**
 * 更新应用状态
 */
void update_application_state(smart_home_state_t new_state) {
    state_mgr.current_state = new_state;
    app_state = new_state; // 更新全局状态
    
    // 通知状态变化
    if(state_mgr.state_change_callback) {
        state_mgr.state_change_callback(new_state);
    }
    
    // 更新UI
    update_ui_for_new_state();
}

/**
 * 注册状态变化回调
 */
void register_state_change_callback(void (*callback)(smart_home_state_t)) {
    state_mgr.state_change_callback = callback;
}

/**
 * 根据新状态更新UI
 */
void update_ui_for_new_state() {
    // 更新环境监控页面
    update_environment_display();
    
    // 更新设备控制页面
    update_device_controls();
    
    // 更新场景页面
    update_scene_display();
    
    // 更新状态栏
    update_status_bar();
}

/**
 * 模拟数据更新
 */
void simulate_sensor_data() {
    lv_timer_t * sensor_timer = lv_timer_create([](lv_timer_t * timer) {
        // 模拟传感器数据变化
        app_state.temperature += (rand() % 10 - 5) * 0.1f;
        app_state.humidity += (rand() % 10 - 5) * 0.1f;
        app_state.air_quality += (rand() % 20 - 10) * 0.1f;
        
        // 限制数值范围
        app_state.temperature = LV_CLAMP(18.0f, app_state.temperature, 32.0f);
        app_state.humidity = LV_CLAMP(30.0f, app_state.humidity, 80.0f);
        app_state.air_quality = LV_CLAMP(0.0f, app_state.air_quality, 100.0f);
        
        // 模拟用电量变化
        float base_power = 1.5f;
        if(app_state.devices.living_room_light) base_power += 0.2f;
        if(app_state.devices.bedroom_light) base_power += 0.2f;
        if(app_state.devices.kitchen_light) base_power += 0.3f;
        
        app_state.power_consumption = base_power + (rand() % 10) * 0.1f;
        app_state.energy_cost = app_state.power_consumption * 0.52f; // 假设电价0.52元/度
        
        printf("传感器数据更新: 温度=%.1f°C, 湿度=%.1f%%, 用电量=%.1fkW\n", 
               app_state.temperature, app_state.humidity, app_state.power_consumption);
        
        // 触发UI更新
        update_ui_for_new_state();
        
    }, 5000, NULL); // 每5秒更新一次
}

/**
 * 保存配置到持久化存储
 */
void save_configuration() {
    // 这里应该实现实际的存储逻辑
    printf("保存配置到持久化存储...\n");
    printf(" - 灯光状态: 客厅=%d, 卧室=%d, 厨房=%d\n", 
           app_state.devices.living_room_light,
           app_state.devices.bedroom_light, 
           app_state.devices.kitchen_light);
    printf(" - 亮度: %d%%\n", app_state.devices.light_brightness);
    printf(" - 空调温度: %d°C\n", app_state.devices.ac_temperature);
    printf(" - 当前场景: %s\n", app_state.current_scene);
}

/**
 * 从持久化存储加载配置
 */
void load_configuration() {
    // 这里应该实现实际的加载逻辑
    printf("从持久化存储加载配置...\n");
    
    // 模拟加载的配置
    app_state.devices.living_room_light = true;
    app_state.devices.bedroom_light = false;
    app_state.devices.kitchen_light = true;
    app_state.devices.light_brightness = 75;
    app_state.devices.ac_temperature = 24;
    app_state.current_scene = "居家模式";
}

14.4 应用初始化与主循环

最后,让我们完成应用的初始化和主循环:

/**
 * 应用初始化
 */
void app_init() {
    // 初始化状态管理器
    init_state_manager();
    
    // 加载保存的配置
    load_configuration();
    
    // 创建用户界面
    create_smart_home_ui();
    
    // 注册状态变化回调
    register_state_change_callback([](smart_home_state_t new_state) {
        printf("应用状态发生变化,更新UI...\n");
    });
    
    // 启动传感器数据模拟
    simulate_sensor_data();
    
    // 创建自动保存定时器
    lv_timer_t * save_timer = lv_timer_create([](lv_timer_t * timer) {
        save_configuration();
    }, 30000, NULL); // 每30秒自动保存
}

/**
 * 主函数
 */
int main(void) {
    // LVGL初始化(参考第一部分)
    lv_init();
    // ... 显示和输入设备初始化
    
    // 应用初始化
    app_init();
    
    // 主循环
    while(1) {
        lv_timer_handler();
        SDL_Delay(5);
    }
    
    return 0;
}

项目总结与扩展

恭喜!你已经完成了一个功能完整的智能家居控制面板。这个项目综合运用了:

  1. 高级布局技术:Grid和Flex布局创建复杂界面
  2. 事件处理系统:完整的用户交互逻辑
  3. 数据驱动架构:状态管理和UI更新机制
  4. 动画效果:提升用户体验的视觉反馈
  5. 多页面管理:模块化的页面切换系统

项目扩展建议:

  1. 网络通信:添加MQTT或WebSocket支持,连接真实的智能家居设备
  2. 数据持久化:实现真正的配置保存和加载
  3. 用户认证:添加登录系统和多用户支持
  4. 语音控制:集成语音识别功能
  5. 移动端适配:创建响应式设计,支持手机和平板

性能优化提示:

  1. 虚拟列表:对于大量数据,使用虚拟列表优化内存使用
  2. 图片缓存:对频繁使用的图片进行缓存
  3. 事件去抖:对频繁触发的事件进行去抖处理
  4. 内存管理:合理使用静态分配,避免内存碎片

这个项目展示了LVGL在真实世界应用中的强大能力。通过这个完整的示例,你已经掌握了创建复杂、专业的嵌入式GUI应用所需的所有技能。

在接下来的第五部分中,我们将深入LVGL的原理和优化技术,帮助你从使用者成长为LVGL专家!


研究学习不易,点赞易。
工作生活不易,收藏易,点收藏不迷茫 :)


本文章已经生成可运行项目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极客不孤独

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值