diff --git a/main/ble/ble.c b/main/ble/ble.c index 858f342..1a9df8c 100644 --- a/main/ble/ble.c +++ b/main/ble/ble.c @@ -258,6 +258,13 @@ static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *par param->update_conn_params.latency, param->update_conn_params.timeout); break; + case ESP_GAP_BLE_PHY_UPDATE_COMPLETE_EVT: + ESP_LOGI(CONN_TAG, "PHY update, status %d, tx_phy %d, rx_phy %d", + param->phy_update.status, + param->phy_update.tx_phy, + param->phy_update.rx_phy); + // tx_phy/rx_phy: 1=1M, 2=2M, 3=Coded + break; default: break; } @@ -388,10 +395,26 @@ static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_ ESP_LOGI(CONN_TAG, "Connected, conn_id %u, remote "ESP_BD_ADDR_STR"", param->connect.conn_id, ESP_BD_ADDR_HEX(param->connect.remote_bda)); esp_ble_gap_update_conn_params(&conn_params); + // 请求 2M PHY 提升传输速度(对端不支持时自动回退 1M,不影响兼容性) + esp_ble_gap_set_preferred_phy(param->connect.remote_bda, + ESP_BLE_GAP_NO_PREFER_TRANSMIT_PHY | ESP_BLE_GAP_NO_PREFER_RECEIVE_PHY, + ESP_BLE_GAP_PHY_2M_PREF_MASK, + ESP_BLE_GAP_PHY_2M_PREF_MASK, + ESP_BLE_GAP_PHY_OPTIONS_NO_PREF); break; case ESP_GATTS_DISCONNECT_EVT: ESP_LOGI(CONN_TAG, "Disconnected, remote "ESP_BD_ADDR_STR", reason 0x%02x", ESP_BD_ADDR_HEX(param->disconnect.remote_bda), param->disconnect.reason); + // 清理未完成的传输,防止内存泄漏 + if (SendStatus.isSend) { + ESP_LOGW(CONN_TAG, "传输中断,已接收 %d/%d 字节", + (int)SendStatus.port, (int)firstMeg.len); + SendStatus.isSend = false; + SendStatus.port = 0; + if (img_data) { free(img_data); img_data = NULL; } + if (filepath) { free(filepath); filepath = NULL; } + if (file_img) { fclose(file_img); file_img = NULL; } + } esp_ble_gap_start_advertising(&adv_params); break; default: diff --git a/main/pages/pages.c b/main/pages/pages.c index 121eb38..475746f 100644 --- a/main/pages/pages.c +++ b/main/pages/pages.c @@ -1124,15 +1124,15 @@ void pages_cleanup_gif(void) { #endif // LV_USE_GIF // 更新ui_ImgBle控件的图片(支持 JPEG) -void update_ui_ImgBle(const char *img_name) { +bool update_ui_ImgBle(const char *img_name) { if(!img_name) { ESP_LOGE("IMG_UI", "图片名为空"); - return; + return false; } if(!ui_ImgBle) { ESP_LOGE("IMG_UI", "ui_ImgBle控件不存在"); - return; + return false; } static uint8_t *ui_img_data = NULL; @@ -1146,7 +1146,7 @@ void update_ui_ImgBle(const char *img_name) { struct stat file_stat; if(stat(img_path, &file_stat) != 0) { ESP_LOGE("IMG_UI", "文件不存在: %s", img_path); - return; + return false; } ESP_LOGI("IMG_UI", "文件大小: %ld 字节", file_stat.st_size); @@ -1170,13 +1170,13 @@ void update_ui_ImgBle(const char *img_name) { FILE *gif_file = fopen(img_path, "rb"); if (!gif_file) { ESP_LOGE("IMG_UI", "GIF文件打开失败: %s", img_path); - return; + return false; } gif_psram_buf = heap_caps_malloc(file_stat.st_size, MALLOC_CAP_SPIRAM); if (!gif_psram_buf) { ESP_LOGE("IMG_UI", "PSRAM分配失败: %ld 字节", file_stat.st_size); fclose(gif_file); - return; + return false; } fread(gif_psram_buf, 1, file_stat.st_size, gif_file); fclose(gif_file); @@ -1187,13 +1187,14 @@ void update_ui_ImgBle(const char *img_name) { ESP_LOGE("IMG_UI", "gifdec 打开失败: %s", img_name); free(gif_psram_buf); gif_psram_buf = NULL; - return; + return false; } // 启动自定义 GIF 播放器(Palette LUT + 双缓冲流水线) gif_player_start(); ESP_LOGI("IMG_UI", "GIF显示启动(优化): %s", img_name); + return true; } else #endif // LV_USE_GIF { @@ -1226,7 +1227,7 @@ void update_ui_ImgBle(const char *img_name) { if(ui_img_data == NULL) { ESP_LOGE("IMG_UI", "解码数据为空"); - return; + return false; } // 配置图片数据 @@ -1243,11 +1244,14 @@ void update_ui_ImgBle(const char *img_name) { lvgl_port_unlock(); ESP_LOGI("IMG_UI", "JPEG图片更新成功: %s", img_name); + return true; } else { ESP_LOGE("IMG_UI", "图片解码失败,错误码: %d", ret); ui_img_data = NULL; + return false; } } + return false; } diff --git a/main/ui/screens/ui_ScreenImg.c b/main/ui/screens/ui_ScreenImg.c index 226ff82..f64d30b 100644 --- a/main/ui/screens/ui_ScreenImg.c +++ b/main/ui/screens/ui_ScreenImg.c @@ -9,7 +9,7 @@ #include "esp_log.h" // 用于日志输出 extern void init_spiffs_image_list(void); -extern void update_ui_ImgBle(const char *img_name); +extern bool update_ui_ImgBle(const char *img_name); extern void free_spiffs_image_list(void); extern const char* get_next_image(void); extern const char* get_prev_image(void); @@ -127,16 +127,22 @@ lv_indev_wait_release(lv_indev_get_act()); } if ( event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_get_act()) == LV_DIR_LEFT ) { lv_indev_wait_release(lv_indev_get_act()); - const char *next_img = get_next_image(); - if(next_img) { - update_ui_ImgBle(next_img); + // 解码失败时自动跳过,最多尝试全部图片避免死循环 + for(int try = 0; try < 10; try++) { + const char *next_img = get_next_image(); + if(!next_img) break; + if(update_ui_ImgBle(next_img)) break; + ESP_LOGW("ScreenImg", "跳过无效图片,继续下一张"); } } if ( event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_get_act()) == LV_DIR_RIGHT ) { lv_indev_wait_release(lv_indev_get_act()); - const char *prev_img = get_prev_image(); - if(prev_img) { - update_ui_ImgBle(prev_img); + // 解码失败时自动跳过,最多尝试全部图片避免死循环 + for(int try = 0; try < 10; try++) { + const char *prev_img = get_prev_image(); + if(!prev_img) break; + if(update_ui_ImgBle(prev_img)) break; + ESP_LOGW("ScreenImg", "跳过无效图片,继续上一张"); } } } diff --git a/main/ui/screens/ui_ScreenImg.h b/main/ui/screens/ui_ScreenImg.h index f2383b4..7db5a07 100644 --- a/main/ui/screens/ui_ScreenImg.h +++ b/main/ui/screens/ui_ScreenImg.h @@ -21,7 +21,7 @@ extern lv_obj_t *ui_ImageDel; extern lv_obj_t *ui_ImageReturn; extern void init_spiffs_image_list(void); -extern void update_ui_ImgBle(const char *img_name); +extern bool update_ui_ImgBle(const char *img_name); extern void free_spiffs_image_list(void); extern const char* get_next_image(void); extern const char* get_prev_image(void); diff --git a/sdkconfig b/sdkconfig index fc356d0..fac0c61 100644 --- a/sdkconfig +++ b/sdkconfig @@ -835,7 +835,12 @@ CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST=y # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set CONFIG_BT_MAX_DEVICE_NAME_LEN=32 CONFIG_BT_BLE_RPA_TIMEOUT=900 -# CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set +CONFIG_BT_BLE_50_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_50_EXTEND_ADV_EN=y +CONFIG_BT_BLE_50_PERIODIC_ADV_EN=y +CONFIG_BT_BLE_50_EXTEND_SCAN_EN=y +CONFIG_BT_BLE_50_EXTEND_SYNC_EN=y +CONFIG_BT_BLE_50_DTM_TEST_EN=y CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y CONFIG_BT_BLE_42_DTM_TEST_EN=y CONFIG_BT_BLE_42_ADV_EN=y