/** * @file bluetooth_provisioning_test.cc * @brief 蓝牙配网功能测试文件 * @author AI Assistant * @date 2024-01-01 */ #include "bluetooth_provisioning.h" #include "bluetooth_provisioning_config.h" #include #include #include #include #include // 为了避免IDE环境中的头文件错误,使用条件编译 #ifdef ESP_PLATFORM #include "esp_wifi.h" #include "esp_netif.h" #include "esp_event.h" #include "nvs_flash.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" #include "esp_log.h" #else // 在非ESP环境中定义必要的宏和类型 #define ESP_LOGI(tag, format, ...) printf("[INFO][%s] " format "\n", tag, ##__VA_ARGS__) #define ESP_LOGE(tag, format, ...) printf("[ERROR][%s] " format "\n", tag, ##__VA_ARGS__) #define ESP_LOGW(tag, format, ...) printf("[WARN][%s] " format "\n", tag, ##__VA_ARGS__) #define pdMS_TO_TICKS(ms) (ms) typedef void* TaskHandle_t; void vTaskDelay(int ticks) { std::this_thread::sleep_for(std::chrono::milliseconds(ticks)); } void vTaskDelete(TaskHandle_t task) { (void)task; } int xTaskCreate(void (*task_func)(void*), const char* name, int stack_size, void* params, int priority, TaskHandle_t* handle) { (void)task_func; (void)name; (void)stack_size; (void)params; (void)priority; (void)handle; return 1; // 模拟成功 } #endif #define TAG "BluetoothProvisioningTest" // 测试事件组 static EventGroupHandle_t test_event_group = nullptr; #define TEST_WIFI_CONNECTED_BIT BIT0 #define TEST_WIFI_FAILED_BIT BIT1 #define TEST_BT_CONNECTED_BIT BIT2 #define TEST_TIMEOUT_BIT BIT3 // 测试结果统计 static struct { int total_tests; int passed_tests; int failed_tests; } test_stats = {0, 0, 0}; /** * @brief 测试事件回调函数 */ void test_provisioning_callback(BluetoothProvisioningEvent event, void* data) { switch (event) { case BluetoothProvisioningEvent::STATE_CHANGED: ESP_LOGI(TAG, "[测试] 配网状态变更"); break; case BluetoothProvisioningEvent::CLIENT_CONNECTED: ESP_LOGI(TAG, "[测试] 蓝牙客户端已连接"); xEventGroupSetBits(test_event_group, TEST_BT_CONNECTED_BIT); break; case BluetoothProvisioningEvent::CLIENT_DISCONNECTED: ESP_LOGI(TAG, "[测试] 蓝牙客户端已断开"); xEventGroupClearBits(test_event_group, TEST_BT_CONNECTED_BIT); break; case BluetoothProvisioningEvent::WIFI_CREDENTIALS: { WiFiCredentials* credentials = static_cast(data); ESP_LOGI(TAG, "[测试] 收到WiFi凭据: SSID=%s", credentials->ssid.c_str()); break; } case BluetoothProvisioningEvent::WIFI_CONNECTED: { esp_ip4_addr_t* ip = static_cast(data); ESP_LOGI(TAG, "[测试] WiFi连接成功: IP=" IPSTR, IP2STR(ip)); xEventGroupSetBits(test_event_group, TEST_WIFI_CONNECTED_BIT); break; } case BluetoothProvisioningEvent::WIFI_FAILED: { uint8_t* reason = static_cast(data); ESP_LOGE(TAG, "[测试] WiFi连接失败: 原因=%d", *reason); xEventGroupSetBits(test_event_group, TEST_WIFI_FAILED_BIT); break; } default: ESP_LOGD(TAG, "[测试] 未处理的事件: %d", static_cast(event)); break; } } /** * @brief 测试辅助函数 - 记录测试结果 */ void record_test_result(const char* test_name, bool passed) { test_stats.total_tests++; if (passed) { test_stats.passed_tests++; ESP_LOGI(TAG, "✅ [测试通过] %s", test_name); } else { test_stats.failed_tests++; ESP_LOGE(TAG, "❌ [测试失败] %s", test_name); } } /** * @brief 测试1:基本初始化和反初始化 */ bool test_basic_initialization() { ESP_LOGI(TAG, "开始测试:基本初始化和反初始化"); BluetoothProvisioning* prov = new BluetoothProvisioning(); if (!prov) { return false; } // 测试初始化 bool init_result = prov->Initialize(); if (!init_result) { delete prov; return false; } // 检查初始状态 BluetoothProvisioningState state = prov->GetState(); if (state != BluetoothProvisioningState::IDLE) { prov->Deinitialize(); delete prov; return false; } // 测试反初始化 bool deinit_result = prov->Deinitialize(); delete prov; return init_result && deinit_result; } /** * @brief 测试2:配网服务启动和停止 */ bool test_provisioning_start_stop() { ESP_LOGI(TAG, "开始测试:配网服务启动和停止"); BluetoothProvisioning* prov = new BluetoothProvisioning(); if (!prov || !prov->Initialize()) { delete prov; return false; } // 测试启动配网 bool start_result = prov->StartProvisioning("测试设备"); if (!start_result) { prov->Deinitialize(); delete prov; return false; } // 检查状态 BluetoothProvisioningState state = prov->GetState(); if (state != BluetoothProvisioningState::ADVERTISING) { prov->Deinitialize(); delete prov; return false; } // 等待一段时间 vTaskDelay(pdMS_TO_TICKS(2000)); // 测试停止配网 bool stop_result = prov->StopProvisioning(); // 检查状态 state = prov->GetState(); bool state_ok = (state == BluetoothProvisioningState::IDLE); prov->Deinitialize(); delete prov; return start_result && stop_result && state_ok; } /** * @brief 测试3:回调函数设置和触发 */ bool test_callback_functionality() { ESP_LOGI(TAG, "开始测试:回调函数设置和触发"); BluetoothProvisioning* prov = new BluetoothProvisioning(); if (!prov || !prov->Initialize()) { delete prov; return false; } // 设置回调函数 prov->SetCallback(test_provisioning_callback); // 启动配网(这会触发状态变更回调) bool start_result = prov->StartProvisioning("回调测试设备"); // 等待回调触发 vTaskDelay(pdMS_TO_TICKS(1000)); // 停止配网 prov->StopProvisioning(); prov->Deinitialize(); delete prov; return start_result; } /** * @brief 测试4:状态管理 */ bool test_state_management() { ESP_LOGI(TAG, "开始测试:状态管理"); BluetoothProvisioning* prov = new BluetoothProvisioning(); if (!prov) { return false; } // 检查初始状态 BluetoothProvisioningState state = prov->GetState(); if (state != BluetoothProvisioningState::IDLE) { delete prov; return false; } // 初始化后检查状态 if (!prov->Initialize()) { delete prov; return false; } state = prov->GetState(); if (state != BluetoothProvisioningState::IDLE) { prov->Deinitialize(); delete prov; return false; } // 启动配网后检查状态 prov->StartProvisioning("状态测试设备"); state = prov->GetState(); bool advertising_state_ok = (state == BluetoothProvisioningState::ADVERTISING); // 停止配网后检查状态 prov->StopProvisioning(); state = prov->GetState(); bool idle_state_ok = (state == BluetoothProvisioningState::IDLE); prov->Deinitialize(); delete prov; return advertising_state_ok && idle_state_ok; } /** * @brief 测试5:错误处理 */ bool test_error_handling() { ESP_LOGI(TAG, "开始测试:错误处理"); BluetoothProvisioning* prov = new BluetoothProvisioning(); if (!prov) { return false; } // 测试未初始化时启动配网 bool should_fail = prov->StartProvisioning("错误测试设备"); if (should_fail) { // 这应该失败 delete prov; return false; } // 正常初始化 if (!prov->Initialize()) { delete prov; return false; } // 测试重复初始化 bool repeat_init = prov->Initialize(); if (!repeat_init) { // 重复初始化应该返回true(已经初始化) prov->Deinitialize(); delete prov; return false; } // 测试重复启动配网 prov->StartProvisioning("错误测试设备1"); bool repeat_start = prov->StartProvisioning("错误测试设备2"); if (!repeat_start) { // 重复启动应该返回true(已经在运行) prov->Deinitialize(); delete prov; return false; } prov->StopProvisioning(); prov->Deinitialize(); delete prov; return true; } /** * @brief 测试6:内存管理 */ bool test_memory_management() { ESP_LOGI(TAG, "开始测试:内存管理"); size_t free_heap_before = esp_get_free_heap_size(); ESP_LOGI(TAG, "测试前可用内存: %d 字节", free_heap_before); // 创建和销毁多个实例 for (int i = 0; i < 3; i++) { BluetoothProvisioning* prov = new BluetoothProvisioning(); if (!prov) { return false; } if (prov->Initialize()) { prov->StartProvisioning("内存测试设备"); vTaskDelay(pdMS_TO_TICKS(500)); prov->StopProvisioning(); prov->Deinitialize(); } delete prov; vTaskDelay(pdMS_TO_TICKS(100)); } size_t free_heap_after = esp_get_free_heap_size(); ESP_LOGI(TAG, "测试后可用内存: %d 字节", free_heap_after); // 检查内存泄漏(允许一定的误差) int memory_diff = free_heap_before - free_heap_after; bool memory_ok = (memory_diff < 1024); // 允许1KB的误差 if (!memory_ok) { ESP_LOGW(TAG, "可能存在内存泄漏: %d 字节", memory_diff); } return memory_ok; } /** * @brief 运行所有测试 */ void run_all_tests() { ESP_LOGI(TAG, "=== 开始蓝牙配网功能测试 ==="); // 创建测试事件组 test_event_group = xEventGroupCreate(); if (!test_event_group) { ESP_LOGE(TAG, "测试事件组创建失败"); return; } // 运行各项测试 record_test_result("基本初始化和反初始化", test_basic_initialization()); record_test_result("配网服务启动和停止", test_provisioning_start_stop()); record_test_result("回调函数设置和触发", test_callback_functionality()); record_test_result("状态管理", test_state_management()); record_test_result("错误处理", test_error_handling()); record_test_result("内存管理", test_memory_management()); // 输出测试结果 ESP_LOGI(TAG, "=== 测试结果统计 ==="); ESP_LOGI(TAG, "总测试数: %d", test_stats.total_tests); ESP_LOGI(TAG, "通过测试: %d", test_stats.passed_tests); ESP_LOGI(TAG, "失败测试: %d", test_stats.failed_tests); if (test_stats.failed_tests == 0) { ESP_LOGI(TAG, "🎉 所有测试通过!蓝牙配网功能正常"); } else { ESP_LOGE(TAG, "⚠️ 有 %d 个测试失败,请检查实现", test_stats.failed_tests); } // 清理资源 vEventGroupDelete(test_event_group); test_event_group = nullptr; } /** * @brief 蓝牙配网测试任务 */ void bluetooth_provisioning_test_task(void* pvParameters) { ESP_LOGI(TAG, "蓝牙配网测试任务启动"); // 等待系统稳定 vTaskDelay(pdMS_TO_TICKS(2000)); // 运行测试 run_all_tests(); ESP_LOGI(TAG, "蓝牙配网测试任务完成"); vTaskDelete(nullptr); } /** * @brief 启动蓝牙配网测试 * * 在主程序中调用此函数来启动测试 */ void start_bluetooth_provisioning_test() { BaseType_t ret = xTaskCreate( bluetooth_provisioning_test_task, "bt_prov_test", 8192, nullptr, 3, // 较低优先级 nullptr ); if (ret != pdPASS) { ESP_LOGE(TAG, "蓝牙配网测试任务创建失败"); } else { ESP_LOGI(TAG, "蓝牙配网测试任务已创建"); } } /** * @brief 简单的配网功能演示 * * 演示如何使用蓝牙配网功能 */ void bluetooth_provisioning_demo() { ESP_LOGI(TAG, "=== 蓝牙配网功能演示 ==="); BluetoothProvisioning* prov = new BluetoothProvisioning(); if (!prov) { ESP_LOGE(TAG, "配网对象创建失败"); return; } // 设置回调 prov->SetCallback(test_provisioning_callback); // 初始化 if (!prov->Initialize()) { ESP_LOGE(TAG, "配网初始化失败"); delete prov; return; } // 启动配网 if (!prov->StartProvisioning("小智AI-演示")) { ESP_LOGE(TAG, "配网启动失败"); prov->Deinitialize(); delete prov; return; } ESP_LOGI(TAG, "配网服务已启动,请使用配网APP连接设备"); ESP_LOGI(TAG, "设备名称: 小智AI-演示"); ESP_LOGI(TAG, "等待客户端连接..."); // 运行30秒演示 for (int i = 0; i < 30; i++) { BluetoothProvisioningState state = prov->GetState(); const char* state_names[] = { "空闲", "初始化中", "广播中", "已连接", "配网中", "成功", "失败", "已停止" }; ESP_LOGI(TAG, "当前状态: %s, 客户端连接: %s", state_names[static_cast(state)], prov->IsClientConnected() ? "是" : "否"); if (state == BluetoothProvisioningState::SUCCESS) { ESP_LOGI(TAG, "配网成功!演示结束"); break; } vTaskDelay(pdMS_TO_TICKS(1000)); } // 清理资源 prov->StopProvisioning(); prov->Deinitialize(); delete prov; ESP_LOGI(TAG, "演示结束"); }