#include "lvgl.h" #include "fatfs.h" #include "driver/ledc.h" #include "gpio.h" #include "wifi.h" #include "temp.h" #include "jpeg_decoder.h" #include "../ui/screens/ui_ScreenImg.h" #include #include #include #include #include #include char img_path[40]; char *img_filename; lv_obj_t *app_img; lv_obj_t *act_mainscreen; uint8_t *app_img_data = 0; esp_jpeg_image_output_t outdata; lv_img_dsc_t image; #define MAX_IMAGE_FILES 10 #define MAX_FILENAME_LEN 32 static char spiffs_image_files[MAX_IMAGE_FILES][MAX_FILENAME_LEN]; static int spiffs_image_count = 0; static int current_image_index = 0; static bool image_list_initialized = false; // 当前亮度值(用于休眠恢复) static uint8_t current_brightness = 50; // 获取当前亮度值 uint8_t pwm_get_brightness(void) { return current_brightness; } // 设置屏幕亮度,percent范围0-100 // 0=完全关闭背光,10~100为正常亮度范围 // 显示10%~100%映射到实际亮度20%~100%,背光低电平有效需反转占空比 void pwm_set_brightness(uint8_t percent) { if (percent == 0) { // 完全关闭背光(低电平有效,占空比100%=全高=关闭) ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 8191); ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0); return; } if (percent < 10) percent = 10; if (percent > 100) percent = 100; current_brightness = percent; uint32_t actual = 20 + (uint32_t)(percent - 10) * 80 / 90; uint32_t duty = 8191 - (8191 * actual) / 100; ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty); ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0); } // 初始化PWM void pwm_init(){ ledc_timer_config_t ledc_timer = { .speed_mode = LEDC_LOW_SPEED_MODE, .timer_num = LEDC_TIMER_0, .duty_resolution = LEDC_TIMER_13_BIT, .freq_hz = 5000, .clk_cfg = LEDC_AUTO_CLK }; ledc_timer_config(&ledc_timer);// 配置PWM定时器 ledc_channel_config_t ledc_channel = { .speed_mode = LEDC_LOW_SPEED_MODE, .channel = LEDC_CHANNEL_0, .timer_sel = LEDC_TIMER_0, .intr_type = LEDC_INTR_DISABLE, .gpio_num = PIN_LCD_BL, .duty = 0, .hpoint = 0 }; ledc_channel_config(&ledc_channel);// 配置PWM通道 pwm_set_brightness(50);// 初始亮度50% // ledc_timer_config_t motor_timer = { // .speed_mode = LEDC_LOW_SPEED_MODE, // .timer_num = LEDC_TIMER_1, // .duty_resolution = LEDC_TIMER_13_BIT, // .freq_hz = 5000, // .clk_cfg = LEDC_AUTO_CLK // }; // ledc_timer_config(&motor_timer); // ledc_channel_config_t motor_channel = { // .speed_mode = LEDC_LOW_SPEED_MODE, // .channel = LEDC_CHANNEL_1, // .timer_sel = LEDC_TIMER_0, // .intr_type = LEDC_INTR_DISABLE, // .gpio_num = PIN_MOTOR_EN, // .duty = 4095, // .hpoint = 0 // }; // ledc_channel_config(&motor_channel); // ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1, 0); // ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1); } // 测试扫描WiFi列表 void wifi_scan_list_test(){ wifi_ap_record_t* wifi_list = NULL;// 定义WiFi列表指针 uint16_t num = 0;// 定义WiFi数量变量 esp_err_t err = wifi_scan_list(&num,&wifi_list);// 扫描WiFi列表 if(err == ESP_OK){ ESP_LOGI("WIFI","列表获取成功,数量:%d",num);// 打印WiFi数量 for (int i = 0; i < num; i++) { ESP_LOGI("WIFI", "AP %d - SSID: %s, RSSI: %d", i + 1, wifi_list[i].ssid, wifi_list[i].rssi);// 打印每个WiFi的SSID和RSSI } } } // 测试连接WiFi void wifi_connect_test(){ wifi_config_t wifi_config = { .sta = { .password = "12345678", .ssid = "LDL的iPhone" } }; esp_wifi_set_config(ESP_IF_WIFI_STA,&wifi_config);// 设置WiFi配置 esp_err_t err = esp_wifi_connect();// 连接WiFi if(err == ESP_OK){ ESP_LOGI("WIFI","WIFI连接成功"); } } // 测试断开WiFi连接 void wifi_disconnect_test(){ esp_err_t err = esp_wifi_disconnect();// 断开WiFi连接 if(err == ESP_OK){ ESP_LOGI("WIFI","已断开WiFi连接"); } } // 测试开始扫描WiFi void wifi_scan_start_test(){ wifi_scan_start();// 开始扫描WiFi } // 测试获取可用堆内存 void free_heap_test(){ ESP_LOGI("HEAP","可用堆内存:%d",(int)heap_caps_get_total_size(MALLOC_CAP_SPIRAM)); } lv_obj_t *act_wifiscreen;// 当前WiFi屏幕对象 lv_obj_t *act_testscreen;// 当前测试屏幕对象 lv_obj_t *act_mainscreen;// 当前主屏幕对象 void app_wifi_display(){ } // 测试获取温度和湿度 void temp_test(){ float temp,humi;// 定义温度和湿度变量 get_temp(&temp);// 获取温度 get_humi(&humi);// 获取湿度 ESP_LOGI("TEMP","temp:%.2f humi:%.2f",temp,humi);// 打印温度和湿度 } // 从NVS中读取图片路径 esp_err_t nvs_read_img(void) { nvs_handle_t nvs_handle; // NVS 句柄 esp_err_t err; // NVS 错误码 err = nvs_open("config", NVS_READONLY, &nvs_handle);// 打开 NVS 句柄 if (err != ESP_OK) return err; // 如果打开失败,返回错误码 size_t imgname_len; err = nvs_get_str(nvs_handle, "img_filename", NULL, &imgname_len);// 获取图片路径长度 if (err == ESP_OK) { img_filename = malloc(imgname_len);// 分配内存 err = nvs_get_str(nvs_handle, "img_filename", img_filename, &imgname_len);// 获取图片路径 if (err != ESP_OK) { nvs_close(nvs_handle);// 关闭 NVS 句柄 return err; // 如果获取失败,返回错误码 } ESP_LOGI("NVS", "img_filename: %s", img_filename);// 打印图片路径 } nvs_close(nvs_handle);// 关闭 NVS 句柄 return err; } // 测试改变NVS中的图片路径 esp_err_t nvs_change_img(char *imgname) { nvs_handle_t nvs_handle;// NVS 句柄 esp_err_t err; err = nvs_open("config", NVS_READWRITE, &nvs_handle);// 打开 NVS 句柄 if (err != ESP_OK) goto close_handle; err = nvs_set_str(nvs_handle, "img_filename", imgname);// 设置图片路径 if (err != ESP_OK) goto close_handle; err = nvs_commit(nvs_handle);// 提交更改 if (err != ESP_OK) goto close_handle;// 如果提交失败,关闭句柄并返回错误码 close_handle: nvs_close(nvs_handle); // 关闭 NVS 句柄 return err; } // 仅更新现有图片,显示其他图片 // img_name: 图片文件名,为NULL时从NVS读取 void app_img_change(const char *img_name){ // 释放之前的图片数据 if(app_img_data){ free(app_img_data); app_img_data = NULL; ESP_LOGI("IMG", "释放之前显示的图片数据缓存"); } const char *current_img_name = img_name; // 如果没有指定图片名,从NVS读取 if(!current_img_name) { esp_err_t ret_nvs = nvs_read_img();// 从NVS中读取图片路径 if(ret_nvs != ESP_OK){ ESP_LOGE("NVS","图片路径获取失败2"); return; } current_img_name = img_filename; } // 构建图片路径 snprintf(img_path, sizeof(img_path), "/spiflash/%s", current_img_name);// 格式化图片路径 ESP_LOGI("IMG", "准备显示图片: %s, 路径: %s", current_img_name, img_path); // 检查文件是否存在 struct stat file_stat; if(stat(img_path, &file_stat) != 0) { ESP_LOGE("IMG", "文件不存在: %s", img_path); return; } ESP_LOGI("IMG", "文件大小: %ld 字节", file_stat.st_size); // 解码图片 esp_err_t ret = DecodeImg(img_path,&app_img_data,&outdata);// 解码图片 if(ret == ESP_OK){ ESP_LOGI("IMG", "图片解码成功,数据地址: %p, 宽度: %d, 高度: %d", app_img_data, outdata.width, outdata.height); // 检查解码后的数据 if(app_img_data == NULL) { ESP_LOGE("IMG", "解码数据为空"); return; } // 配置图片数据 image.header.cf = LV_IMG_CF_TRUE_COLOR; image.header.always_zero = 0; image.header.reserved = 0; image.header.w = outdata.width; image.header.h = outdata.height; image.data_size = outdata.output_len; image.data = app_img_data; // 获取屏幕对象 act_mainscreen = lv_scr_act(); if(act_mainscreen == NULL) { ESP_LOGE("IMG", "获取屏幕对象失败"); return; } // 如果图片对象不存在,创建它 if(app_img == NULL) { app_img = lv_img_create(act_mainscreen); if(app_img == NULL) { ESP_LOGE("IMG", "创建图片对象失败"); return; } lv_obj_center(app_img); ESP_LOGI("IMG", "创建图片对象成功"); } // 更新图片显示 lvgl_port_lock(0);// 锁定LVGL端口 lv_img_set_src(app_img, &image);// 设置图片源 lv_img_set_zoom(app_img, 512);// 2x缩放补偿(JPEG解码使用1:2缩放节省内存) lv_scr_load(act_mainscreen);// 加载主屏幕 lvgl_port_unlock();// 解锁LVGL端口 ESP_LOGI("IMG", "图片显示成功: %s", current_img_name); } else { ESP_LOGE("IMG", "图片解码失败,错误码: %d", ret); } } // 完整的图片显示初始化 void app_img_display(){ ESP_LOGI("IMG", "开始显示图片"); esp_err_t ret_nvs = nvs_read_img();// 从NVS中读取图片路径 if(ret_nvs != ESP_OK){ ESP_LOGE("NVS","图片路径获取失败1"); return; } ESP_LOGI("IMG", "图片路径: %s", img_filename); snprintf(img_path, sizeof(img_path), "/spiflash/%s",img_filename);// 格式化图片路径 ESP_LOGI("IMG", "完整路径: %s", img_path); // 检查文件是否存在 struct stat file_stat; if(stat(img_path, &file_stat) != 0){ ESP_LOGE("IMG", "文件不存在"); return; } ESP_LOGI("IMG", "文件大小: %ld 字节", file_stat.st_size); esp_err_t ret = DecodeImg(img_path,&app_img_data,&outdata);// 解码图片 if(ret == ESP_OK){ ESP_LOGI("IMG", "图片解码成功,数据地址: %p", app_img_data); // 检查解码后的数据 if(app_img_data == NULL){ ESP_LOGE("IMG", "解码数据为空"); return; } image.header.cf = LV_IMG_CF_TRUE_COLOR; image.header.always_zero = 0; image.header.reserved = 0; image.header.w = outdata.width; image.header.h = outdata.height; image.data_size = outdata.output_len; image.data = app_img_data; ESP_LOGI("IMG", "LV_IMG_CF_RGB565 值: %d", LV_IMG_CF_RGB565); ESP_LOGI("IMG", "设置图片数据: 宽度=%lu, 高度=%lu, 数据大小=%lu", (unsigned long)image.header.w, (unsigned long)image.header.h, (unsigned long)image.data_size); act_mainscreen = lv_scr_act();// 获取当前主屏幕对象 if(act_mainscreen == NULL){ ESP_LOGE("IMG", "获取屏幕对象失败"); return; } ESP_LOGI("IMG", "获取屏幕对象成功"); app_img = lv_img_create(act_mainscreen);// 创建图片对象 if(app_img == NULL){ ESP_LOGE("IMG", "创建图片对象失败"); return; } ESP_LOGI("IMG", "创建图片对象成功"); lvgl_port_lock(0);// 锁定LVGL端口 ESP_LOGI("IMG", "设置图片源前"); lv_img_set_src(app_img, &image);// 设置图片源 lv_img_set_zoom(app_img, 512);// 2x缩放补偿(JPEG解码使用1:2缩放节省内存) ESP_LOGI("IMG", "设置图片源后"); lv_obj_center(app_img);// 居中显示图片 ESP_LOGI("IMG", "居中显示图片后"); lv_scr_load(act_mainscreen);// 加载主屏幕 ESP_LOGI("IMG", "加载主屏幕后"); lvgl_port_unlock();// 解锁LVGL端口 vTaskDelay(50);// 延时50ms pwm_init();// 初始化PWM ESP_LOGI("IMG", "图片显示完成"); } else { ESP_LOGE("IMG", "图片解码失败,错误码: %d", ret); } } // // 图片切换任务 // void img_switch_task(void *pvParameters) { // char *image_files[] = {"default.jpg", "02.jpg"}; // int file_count = 2; // int current_index = 0; // while(1) { // // 释放之前的图片数据 // if(app_img_data) { // free(app_img_data); // app_img_data = NULL; // } // // 获取当前要显示的图片文件名 // const char *current_image = image_files[current_index]; // ESP_LOGI("IMG_SWITCH", "切换到图片: %s", current_image); // // 构建图片路径 // snprintf(img_path, sizeof(img_path), "/spiflash/%s", current_image); // ESP_LOGI("IMG_SWITCH", "图片路径: %s", img_path); // // 检查文件是否存在 // struct stat file_stat; // if(stat(img_path, &file_stat) != 0) { // ESP_LOGE("IMG_SWITCH", "文件不存在"); // vTaskDelay(pdMS_TO_TICKS(2000)); // continue; // } // ESP_LOGI("IMG_SWITCH", "文件大小: %ld 字节", file_stat.st_size); // // 解码图片 // esp_err_t ret = DecodeImg(img_path, &app_img_data, &outdata); // if(ret == ESP_OK) { // ESP_LOGI("IMG_SWITCH", "图片解码成功,数据地址: %p", app_img_data); // // 检查解码后的数据 // if(app_img_data == NULL) { // ESP_LOGE("IMG_SWITCH", "解码数据为空"); // vTaskDelay(pdMS_TO_TICKS(2000)); // continue; // } // // 配置图片数据 // image.header.cf = LV_IMG_CF_TRUE_COLOR; // image.header.always_zero = 0; // image.header.reserved = 0; // image.header.w = outdata.width; // image.header.h = outdata.height; // image.data_size = outdata.output_len; // image.data = app_img_data; // // 获取屏幕对象 // act_mainscreen = lv_scr_act(); // if(act_mainscreen == NULL) { // ESP_LOGE("IMG_SWITCH", "获取屏幕对象失败"); // vTaskDelay(pdMS_TO_TICKS(2000)); // continue; // } // // 如果图片对象不存在,创建它 // if(app_img == NULL) { // app_img = lv_img_create(act_mainscreen); // if(app_img == NULL) { // ESP_LOGE("IMG_SWITCH", "创建图片对象失败"); // vTaskDelay(pdMS_TO_TICKS(2000)); // continue; // } // lv_obj_center(app_img); // } // // 更新图片显示 // lvgl_port_lock(0); // lv_img_set_src(app_img, &image); // lv_scr_load(act_mainscreen); // lvgl_port_unlock(); // ESP_LOGI("IMG_SWITCH", "图片显示成功"); // } else { // ESP_LOGE("IMG_SWITCH", "图片解码失败,错误码: %d", ret); // } // // 切换到下一张图片 // current_index = (current_index + 1) % file_count; // // 等待2秒 // vTaskDelay(pdMS_TO_TICKS(2000)); // } // } // 新的显示测试屏幕函数 void app_test_display(){ lvgl_port_lock(0);// 锁定LVGL端口 // 获取或创建屏幕对象 lv_obj_t *screen = lv_scr_act(); if(screen == NULL) { screen = lv_obj_create(NULL);// 创建屏幕对象 if(screen == NULL) { ESP_LOGE("TEST", "Failed to create screen object");// 创建屏幕对象失败 lvgl_port_unlock();// 解锁LVGL端口 return; } } // 清空屏幕 lv_obj_clean(screen); // 创建标签 lv_obj_t *label = lv_label_create(screen); if(label) { lv_label_set_text(label, "Test Screen\nLCD is working!");// 设置标签文本 lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); // 创建基本样式 static lv_style_t style;// 基本样式 lv_style_init(&style);// 初始化基本样式 lv_style_set_text_font(&style, &lv_font_montserrat_14);// 设置字体 lv_style_set_text_color(&style, lv_color_hex(0xf9076a));// 设置文本颜色 lv_style_set_bg_color(&style, lv_color_hex(0x000000));// 设置背景颜色 lv_obj_add_style(label, &style, 0);// 添加样式到标签 } lv_scr_load(screen);// 加载屏幕 lvgl_port_unlock();// 解锁LVGL端口 } // 图片循环显示任务 - 显示spiffs中的所有图片 void img_loop_task(void *pvParameters) { // 存储SPIFFS中的图片文件名 char *image_files[10]; // 最多支持10张图片 int file_count = 0; int current_index = 0; static bool backlight_initialized = false; // 初始化背光(只执行一次) if(!backlight_initialized) { pwm_init(); backlight_initialized = true;// 初始化背光 ESP_LOGI("IMG_LOOP", "背光初始化完成"); } while(1) { // 重新扫描SPIFFS中的图片文件 ESP_LOGI("IMG_LOOP", "开始扫描SPIFFS中的图片文件"); // 打开SPIFFS目录 DIR *dir = opendir("/spiflash"); if(!dir) { ESP_LOGE("IMG_LOOP", "无法打开SPIFFS目录"); vTaskDelay(pdMS_TO_TICKS(3000)); continue; } // 重置文件计数 file_count = 0; // 遍历目录 struct dirent *entry; while((entry = readdir(dir)) != NULL && file_count < 10) { // 检查是否是图片文件(.jpg, .jpeg, .png等) const char *name = entry->d_name; int len = strlen(name); if(len > 4) { const char *ext = name + len - 4; if(strcasecmp(ext, ".jpg") == 0 || strcasecmp(ext, ".jpeg") == 0 || strcasecmp(ext, ".png") == 0 || strcasecmp(ext, ".bmp") == 0) { // 存储图片文件名 image_files[file_count] = strdup(name); ESP_LOGI("IMG_LOOP", "发现图片文件: %s", name); file_count++; } } } closedir(dir); // 检查是否找到图片 if(file_count == 0) { ESP_LOGE("IMG_LOOP", "未找到图片文件"); vTaskDelay(pdMS_TO_TICKS(3000)); continue; } ESP_LOGI("IMG_LOOP", "共发现 %d 张图片,开始循环显示", file_count); // 循环显示所有图片 for(current_index = 0; current_index < file_count; current_index++) { const char *current_image = image_files[current_index]; ESP_LOGI("IMG_LOOP", "显示图片 %d/%d: %s", current_index + 1, file_count, current_image); // 使用修改后的app_img_change函数显示图片 app_img_change(current_image); // 等待3秒 vTaskDelay(pdMS_TO_TICKS(3000)); } // 释放文件名内存 for(int i = 0; i < file_count; i++) { free(image_files[i]); } // 再次扫描前短暂延时 vTaskDelay(pdMS_TO_TICKS(500)); } } // 图片切换任务 - 显示指定的两张图片 void img_switch_task(void *pvParameters) { char *image_files[] = {"default.jpg", "02.jpg"}; int file_count = 2; int current_index = 0; while(1) { // 使用修改后的app_img_change函数显示图片 const char *current_image = image_files[current_index]; ESP_LOGI("IMG_SWITCH", "切换到图片: %s", current_image); app_img_change(current_image); // 切换到下一张图片 current_index = (current_index + 1) % file_count; // 等待2秒 vTaskDelay(pdMS_TO_TICKS(2000)); } } // 初始化SPIFFS图片列表 void init_spiffs_image_list(void) { if(image_list_initialized) { ESP_LOGI("IMG_LIST", "图片列表已初始化,跳过"); return; } ESP_LOGI("IMG_LIST", "开始扫描SPIFFS中的图片文件"); // 打开SPIFFS目录 DIR *dir = opendir("/spiflash"); if(!dir) { ESP_LOGE("IMG_LIST", "无法打开SPIFFS目录"); return; } // 重置文件计数 spiffs_image_count = 0; // 遍历目录 struct dirent *entry; while((entry = readdir(dir)) != NULL && spiffs_image_count < MAX_IMAGE_FILES) { // 检查是否是图片文件(.jpg, .jpeg, .png等) const char *name = entry->d_name; int len = strlen(name); if(len > 4 && len < MAX_FILENAME_LEN) { const char *ext = name + len - 4; if(strcasecmp(ext, ".jpg") == 0 || strcasecmp(ext, ".jpeg") == 0 || strcasecmp(ext, ".png") == 0 || strcasecmp(ext, ".bmp") == 0) { // 存储图片文件名到静态缓冲区 strncpy(spiffs_image_files[spiffs_image_count], name, MAX_FILENAME_LEN - 1); spiffs_image_files[spiffs_image_count][MAX_FILENAME_LEN - 1] = '\0'; ESP_LOGI("IMG_LIST", "发现图片文件: %s", name); spiffs_image_count++; } } } closedir(dir); // 检查是否找到图片 if(spiffs_image_count == 0) { ESP_LOGE("IMG_LIST", "未找到图片文件"); return; } image_list_initialized = true; ESP_LOGI("IMG_LIST", "图片列表初始化完成,共发现 %d 张图片", spiffs_image_count); // 查找default.jpg并设置为当前索引 for(int i = 0; i < spiffs_image_count; i++) { if(strcmp(spiffs_image_files[i], "default.jpg") == 0) { current_image_index = i; ESP_LOGI("IMG_LIST", "设置默认图片索引: %d", current_image_index); break; } } } // 获取下一张图片 const char* get_next_image(void) { if(!image_list_initialized || spiffs_image_count == 0) { ESP_LOGE("IMG_LIST", "图片列表未初始化或为空"); return NULL; } current_image_index = (current_image_index + 1) % spiffs_image_count; ESP_LOGI("IMG_LIST", "切换到下一张图片,索引: %d/%d", current_image_index + 1, spiffs_image_count); return spiffs_image_files[current_image_index]; } // 获取上一张图片 const char* get_prev_image(void) { if(!image_list_initialized || spiffs_image_count == 0) { ESP_LOGE("IMG_LIST", "图片列表未初始化或为空"); return NULL; } current_image_index = (current_image_index - 1 + spiffs_image_count) % spiffs_image_count; ESP_LOGI("IMG_LIST", "切换到上一张图片,索引: %d/%d", current_image_index + 1, spiffs_image_count); return spiffs_image_files[current_image_index]; } // 重置图片列表 void free_spiffs_image_list(void) { if(!image_list_initialized) { return; } spiffs_image_count = 0; current_image_index = 0; image_list_initialized = false; ESP_LOGI("IMG_LIST", "图片列表已重置"); } // 获取当前图片文件名 const char* get_current_image(void) { if(!image_list_initialized || spiffs_image_count == 0) { ESP_LOGE("IMG_LIST", "图片列表未初始化或为空"); return NULL; } return spiffs_image_files[current_image_index]; } // 删除当前图片并从列表中移除 bool delete_current_image(void) { if(!image_list_initialized || spiffs_image_count == 0) { ESP_LOGE("IMG_DEL", "图片列表未初始化或为空"); return false; } const char *current_img = spiffs_image_files[current_image_index]; // 构建完整路径 char full_path[64]; snprintf(full_path, sizeof(full_path), "/spiflash/%s", current_img); ESP_LOGI("IMG_DEL", "准备删除图片: %s", full_path); // 从SPIFFS文件系统中删除文件 if(unlink(full_path) != 0) { ESP_LOGE("IMG_DEL", "删除文件失败: %s", full_path); return false; } ESP_LOGI("IMG_DEL", "文件删除成功: %s", current_img); // 从列表中移除该图片 for(int i = current_image_index; i < spiffs_image_count - 1; i++) { strncpy(spiffs_image_files[i], spiffs_image_files[i + 1], MAX_FILENAME_LEN); } // 更新计数 spiffs_image_count--; // 如果列表为空,重置状态 if(spiffs_image_count == 0) { ESP_LOGI("IMG_DEL", "所有图片已删除"); image_list_initialized = false; current_image_index = 0; return true; } // 调整当前索引(如果删除的是最后一张,回到第一张) if(current_image_index >= spiffs_image_count) { current_image_index = 0; } ESP_LOGI("IMG_DEL", "图片列表已更新,剩余 %d 张图片,当前索引: %d", spiffs_image_count, current_image_index); return true; } // 更新ui_ImgBle控件的图片 void update_ui_ImgBle(const char *img_name) { if(!img_name) { ESP_LOGE("IMG_UI", "图片名为空"); return; } if(!ui_ImgBle) { ESP_LOGE("IMG_UI", "ui_ImgBle控件不存在"); return; } static uint8_t *ui_img_data = NULL; static lv_img_dsc_t ui_image; // 释放之前的图片数据 if(ui_img_data) { free(ui_img_data); ui_img_data = NULL; ESP_LOGI("IMG_UI", "释放之前的图片数据"); } // 构建图片路径 snprintf(img_path, sizeof(img_path), "/spiflash/%s", img_name); ESP_LOGI("IMG_UI", "准备显示图片: %s, 路径: %s", img_name, img_path); // 检查文件是否存在 struct stat file_stat; if(stat(img_path, &file_stat) != 0) { ESP_LOGE("IMG_UI", "文件不存在: %s", img_path); return; } ESP_LOGI("IMG_UI", "文件大小: %ld 字节", file_stat.st_size); // 解码图片 esp_jpeg_image_output_t ui_outdata; esp_err_t ret = DecodeImg(img_path, &ui_img_data, &ui_outdata); if(ret == ESP_OK) { ESP_LOGI("IMG_UI", "图片解码成功,宽度: %d, 高度: %d", ui_outdata.width, ui_outdata.height); // 检查解码后的数据 if(ui_img_data == NULL) { ESP_LOGE("IMG_UI", "解码数据为空"); return; } // 配置图片数据 ui_image.header.cf = LV_IMG_CF_TRUE_COLOR; ui_image.header.always_zero = 0; ui_image.header.reserved = 0; ui_image.header.w = ui_outdata.width; ui_image.header.h = ui_outdata.height; ui_image.data_size = ui_outdata.output_len; ui_image.data = ui_img_data; // 更新ui_ImgBle控件的图片 lvgl_port_lock(0); lv_img_set_src(ui_ImgBle, &ui_image); lv_img_set_zoom(ui_ImgBle, 512);// 2x缩放补偿(JPEG解码使用1:2缩放节省内存) lvgl_port_unlock(); ESP_LOGI("IMG_UI", "ui_ImgBle图片更新成功: %s", img_name); } else { ESP_LOGE("IMG_UI", "图片解码失败,错误码: %d", ret); } } // // 原本显示测试屏幕 代码 // void app_test_display(){ // lvgl_port_lock(0);// 锁定LVGL端口 // act_testscreen = lv_scr_act();// 获取当前测试屏幕对象 // // 创建列表样式 // static lv_style_t list_style; // lv_style_init(&list_style); // lv_style_set_bg_color(&list_style, lv_color_hex(0x1E1E1E)); // lv_style_set_border_width(&list_style, 0); // lv_style_set_radius(&list_style, 0); // lv_style_set_text_align(&list_style, LV_TEXT_ALIGN_CENTER); // // 创建列表项样式 // static lv_style_t list_item_style; // lv_style_init(&list_item_style); // lv_style_set_bg_color(&list_item_style, lv_color_hex(0x2E2E2E)); // lv_style_set_bg_opa(&list_item_style, LV_OPA_100); // lv_style_set_text_color(&list_item_style, lv_color_hex(0xFFFFFF)); // lv_style_set_pad_all(&list_item_style, 10); // lv_style_set_min_height(&list_item_style, 80); // 设置最小高度为60px // // 创建选中项样式 // static lv_style_t list_item_selected_style; // lv_style_init(&list_item_selected_style); // lv_style_set_bg_color(&list_item_selected_style, lv_color_hex(0x4A90E2)); // lv_style_set_text_color(&list_item_selected_style, lv_color_hex(0xFFFFFF)); // lv_obj_t* list = lv_list_create(act_testscreen); // lv_obj_add_style(list, &list_style, 0); // lv_obj_set_size(list, lv_pct(100), lv_pct(100)); // lv_obj_t* list_item1 = lv_list_add_btn(list, LV_SYMBOL_FILE, "FLASH TEST"); // lv_obj_t* list_item2 = lv_list_add_btn(list, LV_SYMBOL_FILE, "WIFI SCAN START TEST"); // lv_obj_t* list_item3 = lv_list_add_btn(list, LV_SYMBOL_FILE, "WIFI SCAN LIST TEST"); // lv_obj_t* list_item5 = lv_list_add_btn(list, LV_SYMBOL_FILE, "WIFI CONNECT TEST"); // lv_obj_t* list_item6 = lv_list_add_btn(list, LV_SYMBOL_FILE, "WIFI DISCONNECT TEST"); // lv_obj_t* list_item4 = lv_list_add_btn(list, LV_SYMBOL_FILE, "FREE HEAP"); // lv_obj_t* list_item7 = lv_list_add_btn(list, LV_SYMBOL_FILE, "TEMP TEST"); // lv_obj_add_event_cb(list_item1, fs_test, LV_EVENT_CLICKED, NULL); // lv_obj_add_event_cb(list_item2, wifi_scan_start_test, LV_EVENT_CLICKED, NULL); // lv_obj_add_event_cb(list_item3, wifi_scan_list_test, LV_EVENT_CLICKED, NULL); // lv_obj_add_event_cb(list_item4, free_heap_test, LV_EVENT_CLICKED, NULL); // lv_obj_add_event_cb(list_item5, wifi_connect_test, LV_EVENT_CLICKED, NULL); // lv_obj_add_event_cb(list_item6, wifi_disconnect_test, LV_EVENT_CLICKED, NULL); // lv_obj_add_event_cb(list_item7, temp_test, LV_EVENT_CLICKED, NULL); // lv_obj_t *parent = lv_obj_create(act_mainscreen); // lv_obj_set_size(parent, 150, 150); // lv_obj_center(parent); // 居中显示 // static lv_style_t style_bg_black; // lv_style_init(&style_bg_black); // lv_style_set_bg_color(&style_bg_black, lv_color_hex(0x000000)); // lv_obj_add_style(act_mainscreen, &style_bg_black, 0); // static lv_style_t style_img; // lv_style_init(&style_img); // lv_style_set_radius(&style_img,75); // lv_style_set_clip_corner(&style_img, true); // lv_style_set_border_width(&style_img,75); // lv_obj_add_style(parent,&style_img,0); // // lv_obj_t *img = lv_img_create(act_mainscreen); // // lv_img_set_src(img,"C:spiflash/face_1759919044875.jpg"); // lv_scr_load(act_testscreen); // lvgl_port_unlock(); // vTaskDelay(50); // pwm_init(); // }