// // Created by kindring on 2025/12/26. // #include "esp_log.h" #include "app_io.h" #include "app_manager.h" #include #include "app_ble.h" #include "ble_nvs.h" #include "esp_timer.h" #include "portmacro.h" #include "freertos/task.h" #include "esp_bt_defs.h" #include "esp_bt_device.h" #include "esp_gap_bt_api.h" #define TAG "app_manager" audio_mode_t m_current_audio_mode = AUDIO_MODE_AUX; static bool is_reconnecting = false; static int current_reconnect_attempt = 0; static uint64_t last_reconnect_time = 0; const char* mode_names[] = { "NORMAL", "BASS_BOOST", }; yun_config_t g_device_config = { .device_name = "YunTune", .auto_reconnect = true, .audio_mode = AUDIO_MODE_AUX, .wifi_mode = WIFI_MODE_AP, .reconnect_wait_time = 2, .reconnect_max_attempts = 10, .wifi_ssid = '\0', .wifi_password = '\0', .ap_ssid = "YunTune", .ap_password = "YunTune", }; static void start_reconnection_process(bt_device_list_t *device_list); // 切换为下一个播放模式 audio_mode_t next_audio_mode() { const audio_mode_t next_audio_mode = (m_current_audio_mode + 1) % AUDIO_MODE_MAX; ESP_LOGI(TAG, "Audio mode switched to: %s", mode_names[next_audio_mode]); update_output_mode(next_audio_mode); return next_audio_mode; } // 保存连接的蓝牙信息 esp_err_t save_bt_info(uint8_t *bda, char *device_name) { if (!bda || !device_name) { ESP_LOGE(TAG, "Invalid input parameters"); return ESP_ERR_INVALID_ARG; } // 创建蓝牙设备信息结构体 bt_device_info_t bt_info = {0}; // 复制蓝牙设备地址 memcpy(bt_info.bda, bda, 6); // 复制设备名称 strncpy(bt_info.device_name, device_name, sizeof(bt_info.device_name) - 1); bt_info.device_name[sizeof(bt_info.device_name) - 1] = '\0'; // 设置其他属性 bt_info.is_paired = true; bt_info.connect_count++; bt_info.last_connect_time = esp_timer_get_time(); // 获取当前时间戳 bt_info.is_valid = true; // 使用公共函数保存蓝牙设备信息 esp_err_t err = bt_device_add_or_update(&bt_info); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to save bluetooth device info: %s", esp_err_to_name(err)); return err; } ESP_LOGI(TAG, "Bluetooth device info saved successfully: %s", device_name); return ESP_OK; } esp_err_t reconnect_ble() { // 获取最新的蓝牙设备信息 // 尝试连接蓝牙 if (!g_device_config.auto_reconnect) { ESP_LOGI(TAG, "Auto-reconnect is disabled, skipping reconnection"); return ESP_OK; } if (is_reconnecting) { ESP_LOGI(TAG, "Already in reconnection process"); return ESP_OK; } is_reconnecting = true; current_reconnect_attempt = 0; // 获取保存的蓝牙设备列表 bt_device_list_t device_list; esp_err_t err = bt_device_get_list(&device_list); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to get bluetooth device list: %s", esp_err_to_name(err)); is_reconnecting = false; return err; } // 按最后连接时间排序,优先尝试最近连接过的设备 bt_device_info_t *most_recent_device = NULL; uint64_t latest_time = 0; for (int i = 0; i < MAX_BT_DEVICES; i++) { if (device_list.devices[i].is_valid && device_list.devices[i].last_connect_time > latest_time) { latest_time = device_list.devices[i].last_connect_time; most_recent_device = &device_list.devices[i]; } } if (most_recent_device != NULL) { ESP_LOGI(TAG, "Attempting to reconnect to: %s", most_recent_device->device_name); // 调用蓝牙连接函数 err = connect_to_bt_device(most_recent_device->bda, most_recent_device->device_name); if (err != ESP_OK) { ESP_LOGW(TAG, "Initial reconnection attempt failed: %s", esp_err_to_name(err)); // 如果初始连接失败,启动重试机制 start_reconnection_process(&device_list); } } else { ESP_LOGI(TAG, "No saved bluetooth devices to reconnect"); is_reconnecting = false; } return ESP_OK; } // 查找下一个候选连接设备 static bt_device_info_t* find_next_candidate_device(bt_device_list_t *device_list, int attempt_order) { // 创建一个临时数组来存储有效的设备信息 bt_device_info_t valid_devices[MAX_BT_DEVICES]; int valid_count = 0; // 收集所有有效设备 for (int i = 0; i < MAX_BT_DEVICES; i++) { if (device_list->devices[i].is_valid) { memcpy(&valid_devices[valid_count], &device_list->devices[i], sizeof(bt_device_info_t)); valid_count++; } } if (valid_count == 0) { return NULL; } // 简单的排序:根据连接次数和最后连接时间 // 这里使用简单的冒泡排序,实际应用中可能需要更高效的算法 for (int i = 0; i < valid_count - 1; i++) { for (int j = 0; j < valid_count - i - 1; j++) { // 按照连接次数降序排列,然后按最后连接时间降序排列 if ((valid_devices[j].connect_count < valid_devices[j+1].connect_count) || (valid_devices[j].connect_count == valid_devices[j+1].connect_count && valid_devices[j].last_connect_time < valid_devices[j+1].last_connect_time)) { bt_device_info_t temp = valid_devices[j]; valid_devices[j] = valid_devices[j+1]; valid_devices[j+1] = temp; } } } // 返回指定顺序的设备 if (attempt_order < valid_count) { // 找到原始设备列表中的索引并返回指针 for (int i = 0; i < MAX_BT_DEVICES; i++) { if (device_list->devices[i].is_valid && memcmp(&device_list->devices[i], &valid_devices[attempt_order], sizeof(bt_device_info_t)) == 0) { return &device_list->devices[i]; } } } return NULL; } // 启动重连过程 static void start_reconnection_process(bt_device_list_t *device_list) { // 按连接次数和最后连接时间排序,尝试其他设备 for (int attempt = 0; attempt < g_device_config.reconnect_max_attempts; attempt++) { bt_device_info_t *candidate_device = find_next_candidate_device(device_list, attempt); if (candidate_device != NULL) { ESP_LOGI(TAG, "Attempting reconnection to candidate device: %s (attempt %d/%d)", candidate_device->device_name, attempt + 1, g_device_config.reconnect_max_attempts); esp_err_t err = connect_to_bt_device(candidate_device->bda, candidate_device->device_name); if (err == ESP_OK) { ESP_LOGI(TAG, "Successfully connected to %s", candidate_device->device_name); is_reconnecting = false; return; } // 等待一段时间再尝试下一个设备 vTaskDelay(g_device_config.reconnect_wait_time * 1000 / portTICK_PERIOD_MS); } } ESP_LOGW(TAG, "All reconnection attempts failed"); is_reconnecting = false; } // 当蓝牙连接成功时调用此函数更新设备信息 void on_bt_connection_success(uint8_t *bda, char *device_name) { if (bda && device_name) { // 更新设备连接计数和时间 bt_device_info_t bt_info = {0}; memcpy(bt_info.bda, bda, 6); strncpy(bt_info.device_name, device_name, sizeof(bt_info.device_name) - 1); bt_info.device_name[sizeof(bt_info.device_name) - 1] = '\0'; bt_info.is_paired = true; bt_info.connect_count++; // 增加连接计数 bt_info.last_connect_time = esp_timer_get_time(); bt_info.is_valid = true; // 保存更新后的设备信息 esp_err_t err = bt_device_add_or_update(&bt_info); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to update bluetooth device info after connection: %s", esp_err_to_name(err)); } else { ESP_LOGI(TAG, "Bluetooth device info updated after successful connection: %s", device_name); } } // 重置重连状态 is_reconnecting = false; current_reconnect_attempt = 0; } // 当蓝牙断开连接时调用此函数,如果启用自动重连则开始重连 void on_bt_disconnection() { ESP_LOGI(TAG, "Bluetooth disconnected, checking for auto-reconnect"); if (g_device_config.auto_reconnect && !is_reconnecting) { ESP_LOGI(TAG, "Starting auto-reconnect process..."); // 延迟一点时间再开始重连,避免立即重连导致的问题 vTaskDelay(g_device_config.reconnect_wait_time * 1000 / portTICK_PERIOD_MS); reconnect_ble(); } } esp_err_t init_app() { esp_err_t err = ESP_OK; err = ble_nvs_init(&g_device_config); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize NVS"); return err; } init_io(g_device_config.audio_mode); // 初始化蓝牙 init_ble(g_device_config.device_name); // 根据逻辑调整蓝牙的运行模式 if (g_device_config.audio_mode == AUDIO_MODE_BLE) { // todo 重连 蓝牙设备 reconnect_ble(); } return ESP_OK; }