// // Created by misaki on 2025/9/2. // #include "OTAClass.h" #include "esp_log.h" #include #include #include #include #include #include #include #include #include using namespace std::chrono; const auto sleep_time = seconds{ 5 }; #include "ThreadManager.h" #include "WifiConnectors.h" #include #include "LVGLRender.h" #include "SDFileManager.h" #include "AudioOutput.h" #include "CommClass.h" // JSON数据回调函数 void onJsonData(cJSON* json) { // 打印接收到的JSON数据 char* jsonStr = cJSON_Print(json); ESP_LOGI("JSON_CALLBACK", "收到JSON数据: %s", jsonStr); free(jsonStr); // 解析消息类型并处理 cJSON* type = cJSON_GetObjectItem(json, "type"); if (type && cJSON_IsString(type)) { if (strcmp(type->valuestring, "greeting") == 0) { ESP_LOGI("JSON_CALLBACK", "收到服务器问候消息"); } else if (strcmp(type->valuestring, "heartbeat") == 0) { ESP_LOGI("JSON_CALLBACK", "收到心跳响应"); } else if (strcmp(type->valuestring, "response") == 0) { ESP_LOGI("JSON_CALLBACK", "收到服务器响应"); } else if (strcmp(type->valuestring, "echo") == 0) { ESP_LOGI("JSON_CALLBACK", "收到回显消息"); } else if (strcmp(type->valuestring, "broadcast") == 0) { ESP_LOGI("JSON_CALLBACK", "收到广播消息"); } } // 记得删除cJSON对象 cJSON_Delete(json); } // WebSocket事件回调函数 void onWebSocketEvent(WebSocketEvent event, const std::string& message) { switch (event) { case WebSocketEvent::CONNECTED: ESP_LOGI("EVENT_CALLBACK", "WebSocket已连接: %s", message.c_str()); break; case WebSocketEvent::DISCONNECTED: ESP_LOGI("EVENT_CALLBACK", "WebSocket已断开: %s", message.c_str()); break; case WebSocketEvent::DATA_RECEIVED: ESP_LOGI("EVENT_CALLBACK", "收到原始数据: %s", message.c_str()); break; case WebSocketEvent::ERROR: ESP_LOGE("EVENT_CALLBACK", "WebSocket错误: %s", message.c_str()); break; } } // 发送状态信息函数 void sendStatus() { cJSON* status = cJSON_CreateObject(); cJSON_AddStringToObject(status, "type", "status"); cJSON* data = cJSON_CreateObject(); cJSON_AddNumberToObject(data, "free_heap", esp_get_free_heap_size()); cJSON_AddNumberToObject(data, "uptime", xTaskGetTickCount() * portTICK_PERIOD_MS / 1000); cJSON_AddItemToObject(status, "data", data); if (WebSocketManager::getInstance()->sendJson(status)) { ESP_LOGI("SEND", "已发送状态信息"); } else { ESP_LOGE("SEND", "发送状态信息失败"); } } // 发送问候消息函数 void sendGreeting() { cJSON* greeting = cJSON_CreateObject(); cJSON_AddStringToObject(greeting, "type", "greeting"); cJSON_AddStringToObject(greeting, "message", "Hello from ESP32-S3"); cJSON_AddNumberToObject(greeting, "timestamp", xTaskGetTickCount() * portTICK_PERIOD_MS / 1000); if (WebSocketManager::getInstance()->sendJson(greeting)) { ESP_LOGI("SEND", "已发送问候消息"); } else { ESP_LOGE("SEND", "发送问候消息失败"); } } void websocket_task() { TickType_t lastStatusTime = 0; TickType_t lastHeartbeatTime = 0; TickType_t lastGreetingTime = 0; while (true) { TickType_t currentTime = xTaskGetTickCount(); // 检查连接状态 if (!WebSocketManager::getInstance()->isConnected()) { ESP_LOGI("APP_TASK", "WebSocket未连接,尝试重新连接..."); // 确保WiFi已连接 if (!WifiConnectors::getInstance()->isWifiConnect()) { ESP_LOGI("APP_TASK", "WiFi未连接,等待WiFi连接..."); vTaskDelay(5000 / portTICK_PERIOD_MS); continue; } if (WebSocketManager::getInstance()->connect()) { ESP_LOGI("APP_TASK", "重新连接成功"); } else { ESP_LOGI("APP_TASK", "重新连接失败"); } vTaskDelay(5000 / portTICK_PERIOD_MS); continue; } // 每10秒发送状态信息 if (currentTime - lastStatusTime > (10000 / portTICK_PERIOD_MS)) { sendStatus(); lastStatusTime = currentTime; } // 每60秒发送问候 if (currentTime - lastGreetingTime > (60000 / portTICK_PERIOD_MS)) { sendGreeting(); lastGreetingTime = currentTime; } vTaskDelay(100 / portTICK_PERIOD_MS); } } void OTAClass::Init() { ESP_LOGI("OTA", "Init"); ESP_LOGI("OTAClass::Init", "当前固件版本 1.0.1"); // 列出当前目录内容 std::string listing = SDFileManager::getInstance()->lsCommand(".", false, true); ESP_LOGI("SD", "%s", listing.c_str()); // 切换到music目录 SDFileManager::getInstance()->cdCommand("music"); std::string pwdPath = SDFileManager::getInstance()->pwdCommand(); ESP_LOGI("SD", "%s", pwdPath.c_str()); // 列出当前目录内容 listing = SDFileManager::getInstance()->lsCommand(".", false, true); ESP_LOGI("SD", "%s", listing.c_str()); LVGLRender::getInstance()->RenderGif("sequence01m.gif"); // 设置音量 AudioOutput::getInstance()->setVolume(5); // 同步播放 AudioOutput::getInstance()->playSync("/sdcard/music", "Old_Memory.mp3"); // // 配置Wifi连接线程参数 // ThreadConfig wifi_config; // wifi_config.name = "WifiConnector"; // 线程名称 // wifi_config.core_id = 1; // 绑定到核心1(避免与主线程冲突) // wifi_config.stack_size = 4096; // 设置稍大的栈空间(Wifi连接可能需要) // wifi_config.priority = 6; // 设置较高优先级(确保连接及时) // // 使用单例方式创建线程,调用connectWifi成员函数 // std::thread wifi_thread = ThreadManager::createSingletonThread( // wifi_config, // &WifiConnectors::connectWifi, // "Misaki-2.4G", // SSID // "88888888", // 密码 // 5 // 最大重试次数 // ); // wifi_thread.detach(); WifiConnectors::getInstance()->connectWifi("Misaki-2.4G", "88888888", 5); // 等待WiFi连接成功后再连接WebSocket ESP_LOGI("APP_TASK", "等待WiFi连接..."); while (!WifiConnectors::getInstance()->isWifiConnect()) { ESP_LOGI("APP_TASK", "WiFi未连接,等待中..."); vTaskDelay(1000 / portTICK_PERIOD_MS); } // 配置WebSocket WebSocketConfig config; config.uri = "ws://" + std::string("192.168.1.11") + ":" + std::to_string(8080) + "/ws"; config.auto_reconnect = true; // 自动重连 config.reconnect_interval = 5000; // 重连间隔(毫秒) config.heartbeat_interval = 30000; // 心跳间隔(毫秒) config.max_reconnect_attempts = 10; // 最大重连尝试次数 // TODO: 此处通信类存在线程重复创建bug,似乎是来自esp-idf的bug,待查证 // 初始化WebSocket管理器 // if (!WebSocketManager::getInstance()->initialize(config)) { // ESP_LOGE("APP_TASK", "WebSocket管理器初始化失败"); // vTaskDelete(NULL); // return; // } // 设置回调函数 // WebSocketManager::getInstance()->setJsonCallback(onJsonData); // WebSocketManager::getInstance()->setEventCallback(onWebSocketEvent); // 连接WebSocket服务器 // ESP_LOGI("APP_TASK", "正在连接WebSocket服务器: %s", config.uri.c_str()); // if (!WebSocketManager::getInstance()->connect()) { // ESP_LOGE("APP_TASK", "WebSocket连接失败"); // } // 创建WebSocket任务 // ThreadConfig websocket_config; // websocket_config.core_id = 0; // websocket_config.inherit_cfg = true; // websocket_config.name = "websocket_task"; // websocket_config.priority = 5; // websocket_config.stack_size = 4096; // std::thread websocket_thread = ThreadManager::createThread(websocket_config, websocket_task); // websocket_thread.detach(); // ThreadConfig ota_config; // ota_config.name = "OTA"; // ota_config.stack_size = 4096; // ota_config.priority = 6; // ota_config.core_id = 0; // std::thread ota_thread = ThreadManager::createMemberThread( // ota_config, // this, // &OTAClass::Update // ); while (true) { // 主线程线程循环 ThreadManager::print_sys_memory(); // 打印系统内存使用情况 ThreadManager::stats_task(); // 打印任务统计信息 std::this_thread::sleep_for(sleep_time); // 休眠5秒 } } #include "ota_ws.h" // 启动OTA更新线程,前提是已经连接WiFi void OTAClass::Update() { // 测试OTA服务器192.168.1.11 while (true) { if (WifiConnectors::getInstance()->isWifiConnect()) { // 如果Wifi已连接 ota_ws_start("192.168.1.11", 8080); // 启动完就退出,删除自身 break; }else { std::this_thread::sleep_for(sleep_time); } } vTaskDelete(nullptr); }