From 23613e1cd3ef3990451af5a0e5e47c4ef59a4f56 Mon Sep 17 00:00:00 2001 From: Rdzleo Date: Thu, 5 Mar 2026 15:44:47 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E6=96=B0=E5=A2=9Eobtain=5Fmusic=20Fu?= =?UTF-8?q?nction=20Calling=E9=9F=B3=E4=B9=90=E6=92=AD=E6=94=BE=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=8C4=E5=A4=84=E5=8D=8F=E8=AE=AE=E5=88=86?= =?UTF-8?q?=E6=94=AF=E5=9D=87=E6=94=AF=E6=8C=81URL=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E5=92=8C=E9=9F=B3=E4=B9=90API=E4=B8=A4=E7=A7=8DHTTPS=E6=96=B9?= =?UTF-8?q?=E5=BC=8F=EF=BC=9B=202=E3=80=81Kconfig=E6=96=B0=E5=A2=9EMUSIC?= =?UTF-8?q?=5FAPI=5FURL=E9=9F=B3=E4=B9=90=E6=92=AD=E6=94=BEAPI=E5=9C=B0?= =?UTF-8?q?=E5=9D=80=E9=85=8D=E7=BD=AE=EF=BC=9B=203=E3=80=81=E9=87=8D?= =?UTF-8?q?=E6=9E=84SendStoryRequest=E5=92=8CSendMusicRequest=E4=B8=BAHttp?= =?UTF-8?q?sApiPlayback=E9=80=9A=E7=94=A8=E6=96=B9=E6=B3=95=EF=BC=8C?= =?UTF-8?q?=E6=B6=88=E9=99=A4=E6=95=85=E4=BA=8B/=E9=9F=B3=E4=B9=90?= =?UTF-8?q?=E6=92=AD=E6=94=BE~440=E8=A1=8C=E9=87=8D=E5=A4=8D=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=EF=BC=9B=204=E3=80=81=E4=BF=AE=E6=AD=A34=E5=A4=84obta?= =?UTF-8?q?in=5Fstory=E6=B3=A8=E9=87=8A=E5=92=8C=E6=97=A5=E5=BF=97?= =?UTF-8?q?=EF=BC=9AWebSocket=E6=8F=8F=E8=BF=B0=E6=94=B9=E4=B8=BAHTTPS=20A?= =?UTF-8?q?PI=EF=BC=88=E4=B8=8E=E5=AE=9E=E9=99=85=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E4=B8=80=E8=87=B4=EF=BC=89=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/Kconfig.projbuild | 6 ++ main/application.cc | 150 ++++++++++++++++++++++++++++++----------- main/application.h | 4 +- sdkconfig | 22 +++++- 4 files changed, 138 insertions(+), 44 deletions(-) diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index 005c3aa..e3e8f69 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -18,6 +18,12 @@ config STORY_API_URL help 故事播放API接口地址,设备会附加 ?mac_address=XX:XX:XX:XX:XX:XX 参数请求 +config MUSIC_API_URL + string "Music API URL" + default "http://192.168.124.8:8000/api/v1/devices/music/" + help + 音乐播放API接口地址,设备会附加 ?mac_address=XX:XX:XX:XX:XX:XX 参数请求 + choice prompt "语言选择" default LANGUAGE_ZH_CN diff --git a/main/application.cc b/main/application.cc index 9d522d6..d40ec37 100644 --- a/main/application.cc +++ b/main/application.cc @@ -944,9 +944,9 @@ void Application::Start() { } } } - // 讲故事功能:通过WebSocket发送故事请求 + // 讲故事功能:通过HTTPS API请求故事 else if (strcmp(name->valuestring, "obtain_story") == 0) { - ESP_LOGI(TAG, "收到obtain_story工具调用,通过WebSocket请求故事"); + ESP_LOGI(TAG, "收到obtain_story工具调用,通过HTTPS API请求故事"); cJSON* sn = cJSON_GetObjectItem(args_obj, "story_name"); const char* story = (sn && cJSON_IsString(sn) && sn->valuestring) ? sn->valuestring : "random"; ESP_LOGI(TAG, "故事名称: %s", story); @@ -962,6 +962,18 @@ void Application::Start() { protocol_->SendFunctionResult(call_id, msg); } } + // 播放音乐功能:通过HTTPS API请求音乐 + else if (strcmp(name->valuestring, "obtain_music") == 0) { + ESP_LOGI(TAG, "收到obtain_music工具调用,通过HTTPS API请求音乐"); + AbortSpeaking(kAbortReasonNone); + SendMusicRequest(); + std::string msg = "正在为你获取音乐"; + cJSON* call_id_item = cJSON_GetObjectItem(call, "id"); + const char* call_id = (call_id_item && cJSON_IsString(call_id_item) && call_id_item->valuestring) ? call_id_item->valuestring : ""; + if (protocol_ && call_id && call_id[0] != '\0') { + protocol_->SendFunctionResult(call_id, msg); + } + } // // 添加天气查询功能处理 get_weather_aihub // else if (strcmp(name->valuestring, "get_weather_aihub") == 0) { // ESP_LOGI(TAG, "[WeatherAPI] ===== 收到get_weather_aihub工具调用 ====="); @@ -1157,9 +1169,9 @@ void Application::Start() { } } } - // 讲故事功能:通过WebSocket发送故事请求 + // 讲故事功能:通过HTTPS API请求故事 else if (strcmp(name->valuestring, "obtain_story") == 0) { - ESP_LOGI(TAG, "收到obtain_story工具调用,通过WebSocket请求故事"); + ESP_LOGI(TAG, "收到obtain_story工具调用,通过HTTPS API请求故事"); AbortSpeaking(kAbortReasonNone); SendStoryRequest(); std::string msg = "正在为你获取故事"; @@ -1169,6 +1181,18 @@ void Application::Start() { protocol_->SendFunctionResult(call_id, msg); } } + // 播放音乐功能:通过HTTPS API请求音乐 + else if (strcmp(name->valuestring, "obtain_music") == 0) { + ESP_LOGI(TAG, "收到obtain_music工具调用,通过HTTPS API请求音乐"); + AbortSpeaking(kAbortReasonNone); + SendMusicRequest(); + std::string msg = "正在为你获取音乐"; + cJSON* call_id_item = cJSON_GetObjectItem(call, "id"); + const char* call_id = (call_id_item && cJSON_IsString(call_id_item) && call_id_item->valuestring) ? call_id_item->valuestring : ""; + if (protocol_ && call_id && call_id[0] != '\0') { + protocol_->SendFunctionResult(call_id, msg); + } + } } } } @@ -1410,9 +1434,9 @@ void Application::Start() { } } } - // 讲故事功能:通过WebSocket发送故事请求 + // 讲故事功能:通过HTTPS API请求故事 else if (strcmp(name->valuestring, "obtain_story") == 0) { - ESP_LOGI(TAG, "收到obtain_story工具调用,通过WebSocket请求故事"); + ESP_LOGI(TAG, "收到obtain_story工具调用,通过HTTPS API请求故事"); AbortSpeaking(kAbortReasonNone); SendStoryRequest(); std::string msg = "正在为你获取故事"; @@ -1422,6 +1446,18 @@ void Application::Start() { protocol_->SendFunctionResult(call_id, msg); } } + // 播放音乐功能:通过HTTPS API请求音乐 + else if (strcmp(name->valuestring, "obtain_music") == 0) { + ESP_LOGI(TAG, "收到obtain_music工具调用,通过HTTPS API请求音乐"); + AbortSpeaking(kAbortReasonNone); + SendMusicRequest(); + std::string msg = "正在为你获取音乐"; + cJSON* call_id_item = cJSON_GetObjectItem(root, "call_id"); + const char* call_id = (call_id_item && cJSON_IsString(call_id_item) && call_id_item->valuestring) ? call_id_item->valuestring : ""; + if (protocol_ && call_id && call_id[0] != '\0') { + protocol_->SendFunctionResult(call_id, msg); + } + } cJSON_Delete(args_obj); } else { ESP_LOGI(TAG, "工具调用: name=%s arguments=%s", name->valuestring, args_str); @@ -1474,9 +1510,9 @@ void Application::Start() { } } } - // 讲故事功能:通过WebSocket发送故事请求 + // 讲故事功能:通过HTTPS API请求故事 else if (strcmp(name->valuestring, "obtain_story") == 0) { - ESP_LOGI(TAG, "收到obtain_story工具调用,通过WebSocket请求故事"); + ESP_LOGI(TAG, "收到obtain_story工具调用,通过HTTPS API请求故事"); AbortSpeaking(kAbortReasonNone); SendStoryRequest(); std::string msg = "正在为你获取故事"; @@ -1486,6 +1522,18 @@ void Application::Start() { protocol_->SendFunctionResult(call_id, msg); } } + // 播放音乐功能:通过HTTPS API请求音乐 + else if (strcmp(name->valuestring, "obtain_music") == 0) { + ESP_LOGI(TAG, "收到obtain_music工具调用,通过HTTPS API请求音乐"); + AbortSpeaking(kAbortReasonNone); + SendMusicRequest(); + std::string msg = "正在为你获取音乐"; + cJSON* call_id_item = cJSON_GetObjectItem(root, "call_id"); + const char* call_id = (call_id_item && cJSON_IsString(call_id_item) && call_id_item->valuestring) ? call_id_item->valuestring : ""; + if (protocol_ && call_id && call_id[0] != '\0') { + protocol_->SendFunctionResult(call_id, msg); + } + } } } // 新增代码(小程序控制 暂停/继续播放 音频) @@ -2683,14 +2731,35 @@ void Application::HttpsPlaybackFromUrl(const std::string& url) { } // 通过故事API请求并播放故事(intro标题 + body正文无缝衔接) +// 通过HTTPS故事API请求并播放故事 void Application::SendStoryRequest() { - // 防止重复启动 + HttpsApiPlayback(CONFIG_STORY_API_URL, "故事API", "story_play"); +} + +// 通过HTTPS音乐API请求并播放音乐 +void Application::SendMusicRequest() { + HttpsApiPlayback(CONFIG_MUSIC_API_URL, "音乐API", "music_play"); +} + +// HTTPS API音频播放通用实现(intro标题 + body正文无缝衔接) +struct HttpsApiParams { + const char* api_url; + const char* tag; +}; + +void Application::HttpsApiPlayback(const char* api_url_base, const char* tag, const char* task_name) { if (https_playback_active_.load() || https_playback_abort_.load() || opus_playback_active_.load()) { - ESP_LOGW(TAG, "[故事API] 已有音频正在播放或退出中,忽略本次请求"); + ESP_LOGW(TAG, "[%s] 已有音频正在播放或退出中,忽略本次请求", tag); return; } + auto* params = new HttpsApiParams{api_url_base, tag}; xTaskCreate([](void* arg) { + auto* p = static_cast(arg); + const char* api_url_base = p->api_url; + const char* tag = p->tag; + delete p; + auto& app = Application::GetInstance(); // 先设置opus和abort标志(覆盖HTTP请求阶段,阻断RTC PCM) app.opus_playback_active_.store(true); @@ -2707,19 +2776,18 @@ void Application::SendStoryRequest() { b64_inited = true; } - // ========== 步骤1: 请求故事API ========== + // ========== 步骤1: 请求API ========== std::string mac = SystemInfo::GetBleMacAddress(); - // 转大写 for (auto& c : mac) { if (c >= 'a' && c <= 'f') c -= 32; } char api_url[256]; snprintf(api_url, sizeof(api_url), "%s?mac_address=%s", - CONFIG_STORY_API_URL, mac.c_str()); + api_url_base, mac.c_str()); - ESP_LOGI(TAG, "[故事API] 请求: %s", api_url); - ESP_LOGI(TAG, "[故事API] 空闲堆: %lu", (unsigned long)esp_get_free_heap_size()); + ESP_LOGI(TAG, "[%s] 请求: %s", tag, api_url); + ESP_LOGI(TAG, "[%s] 空闲堆: %lu", tag, (unsigned long)esp_get_free_heap_size()); esp_http_client_config_t api_config = {}; api_config.url = api_url; @@ -2730,7 +2798,7 @@ void Application::SendStoryRequest() { esp_http_client_handle_t api_client = esp_http_client_init(&api_config); if (!api_client) { - ESP_LOGE(TAG, "[故事API] HTTP客户端初始化失败"); + ESP_LOGE(TAG, "[%s] HTTP客户端初始化失败", tag); app.https_playback_active_.store(false); app.opus_playback_active_.store(false); vTaskDelete(NULL); @@ -2739,7 +2807,7 @@ void Application::SendStoryRequest() { esp_err_t err = esp_http_client_open(api_client, 0); if (err != ESP_OK) { - ESP_LOGE(TAG, "[故事API] 连接失败: %s", esp_err_to_name(err)); + ESP_LOGE(TAG, "[%s] 连接失败: %s", tag, esp_err_to_name(err)); esp_http_client_cleanup(api_client); app.https_playback_active_.store(false); app.opus_playback_active_.store(false); @@ -2750,7 +2818,7 @@ void Application::SendStoryRequest() { esp_http_client_fetch_headers(api_client); int api_status = esp_http_client_get_status_code(api_client); if (api_status != 200) { - ESP_LOGE(TAG, "[故事API] 请求失败,状态码: %d", api_status); + ESP_LOGE(TAG, "[%s] 请求失败,状态码: %d", tag, api_status); esp_http_client_close(api_client); esp_http_client_cleanup(api_client); app.https_playback_active_.store(false); @@ -2769,7 +2837,7 @@ void Application::SendStoryRequest() { esp_http_client_close(api_client); esp_http_client_cleanup(api_client); - ESP_LOGI(TAG, "[故事API] 响应: %d 字节", (int)api_response.size()); + ESP_LOGI(TAG, "[%s] 响应: %d 字节", tag, (int)api_response.size()); if (app.https_playback_abort_.load()) { app.https_playback_active_.store(false); @@ -2785,7 +2853,7 @@ void Application::SendStoryRequest() { api_response.shrink_to_fit(); if (!root) { - ESP_LOGE(TAG, "[故事API] JSON解析失败"); + ESP_LOGE(TAG, "[%s] JSON解析失败", tag); app.https_playback_active_.store(false); app.opus_playback_active_.store(false); vTaskDelete(NULL); @@ -2795,7 +2863,7 @@ void Application::SendStoryRequest() { cJSON* code_item = cJSON_GetObjectItem(root, "code"); if (!code_item || code_item->valueint != 0) { cJSON* msg_item = cJSON_GetObjectItem(root, "message"); - ESP_LOGE(TAG, "[故事API] 服务端错误: %s", + ESP_LOGE(TAG, "[%s] 服务端错误: %s", tag, (msg_item && msg_item->valuestring) ? msg_item->valuestring : "unknown"); cJSON_Delete(root); app.https_playback_active_.store(false); @@ -2811,7 +2879,7 @@ void Application::SendStoryRequest() { if (!intro_str || !cJSON_IsString(intro_str) || !intro_str->valuestring || !opus_url_item || !cJSON_IsString(opus_url_item) || !opus_url_item->valuestring) { - ESP_LOGE(TAG, "[故事API] 缺少intro_opus_data或opus_url字段"); + ESP_LOGE(TAG, "[%s] 缺少intro_opus_data或opus_url字段", tag); cJSON_Delete(root); app.https_playback_active_.store(false); app.opus_playback_active_.store(false); @@ -2819,7 +2887,7 @@ void Application::SendStoryRequest() { return; } - ESP_LOGI(TAG, "[故事API] 标题: %s", + ESP_LOGI(TAG, "[%s] 标题: %s", tag, (title_item && title_item->valuestring) ? title_item->valuestring : "未知"); // 提取字符串后释放外层JSON @@ -2833,7 +2901,7 @@ void Application::SendStoryRequest() { intro_json_str.shrink_to_fit(); if (!intro_root) { - ESP_LOGE(TAG, "[故事API] intro JSON解析失败"); + ESP_LOGE(TAG, "[%s] intro JSON解析失败", tag); app.https_playback_active_.store(false); app.opus_playback_active_.store(false); vTaskDelete(NULL); @@ -2845,7 +2913,7 @@ void Application::SendStoryRequest() { cJSON* intro_frames = cJSON_GetObjectItem(intro_root, "frames"); if (!intro_frames || !cJSON_IsArray(intro_frames)) { - ESP_LOGE(TAG, "[故事API] intro缺少frames数组"); + ESP_LOGE(TAG, "[%s] intro缺少frames数组", tag); cJSON_Delete(intro_root); app.https_playback_active_.store(false); app.opus_playback_active_.store(false); @@ -2857,7 +2925,7 @@ void Application::SendStoryRequest() { int frame_duration = (intro_fd && cJSON_IsNumber(intro_fd)) ? intro_fd->valueint : 60; int intro_count = cJSON_GetArraySize(intro_frames); - ESP_LOGI(TAG, "[故事API] intro: 采样率=%d, 帧时长=%dms, 帧数=%d (%.1f秒)", + ESP_LOGI(TAG, "[%s] intro: 采样率=%d, 帧时长=%dms, 帧数=%d (%.1f秒)", tag, sample_rate, frame_duration, intro_count, intro_count * frame_duration / 1000.0f); @@ -2911,7 +2979,7 @@ void Application::SendStoryRequest() { } cJSON_Delete(intro_root); - ESP_LOGI(TAG, "[故事API] intro入队完成: %d帧, 错误: %d", enqueued, errors); + ESP_LOGI(TAG, "[%s] intro入队完成: %d帧, 错误: %d", tag, enqueued, errors); if (app.https_playback_abort_.load()) { app.https_playback_active_.store(false); @@ -2922,7 +2990,7 @@ void Application::SendStoryRequest() { } // ========== 步骤4: 下载 opus_url 正文 ========== - ESP_LOGI(TAG, "[故事API] 开始下载正文: %s", opus_url.c_str()); + ESP_LOGI(TAG, "[%s] 开始下载正文: %s", tag, opus_url.c_str()); esp_http_client_config_t opus_config = {}; opus_config.url = opus_url.c_str(); @@ -2937,7 +3005,7 @@ void Application::SendStoryRequest() { esp_http_client_handle_t opus_client = esp_http_client_init(&opus_config); if (!opus_client) { - ESP_LOGE(TAG, "[故事API] opus HTTP初始化失败"); + ESP_LOGE(TAG, "[%s] opus HTTP初始化失败", tag); app.https_playback_active_.store(false); app.https_playback_abort_.store(false); app.opus_playback_active_.store(false); @@ -2947,7 +3015,7 @@ void Application::SendStoryRequest() { err = esp_http_client_open(opus_client, 0); if (err != ESP_OK) { - ESP_LOGE(TAG, "[故事API] opus连接失败: %s", esp_err_to_name(err)); + ESP_LOGE(TAG, "[%s] opus连接失败: %s", tag, esp_err_to_name(err)); esp_http_client_cleanup(opus_client); app.https_playback_active_.store(false); app.https_playback_abort_.store(false); @@ -2958,10 +3026,10 @@ void Application::SendStoryRequest() { int64_t opus_content_len = esp_http_client_fetch_headers(opus_client); int opus_status = esp_http_client_get_status_code(opus_client); - ESP_LOGI(TAG, "[故事API] opus状态码: %d, 长度: %lld", opus_status, (long long)opus_content_len); + ESP_LOGI(TAG, "[%s] opus状态码: %d, 长度: %lld", tag, opus_status, (long long)opus_content_len); if (opus_status != 200) { - ESP_LOGE(TAG, "[故事API] opus请求失败,状态码: %d", opus_status); + ESP_LOGE(TAG, "[%s] opus请求失败,状态码: %d", tag, opus_status); esp_http_client_close(opus_client); esp_http_client_cleanup(opus_client); app.https_playback_active_.store(false); @@ -2982,7 +3050,7 @@ void Application::SendStoryRequest() { esp_http_client_close(opus_client); esp_http_client_cleanup(opus_client); - ESP_LOGI(TAG, "[故事API] opus下载完成: %d 字节, 堆: %lu", + ESP_LOGI(TAG, "[%s] opus下载完成: %d 字节, 堆: %lu", tag, total_read, (unsigned long)esp_get_free_heap_size()); if (app.https_playback_abort_.load()) { @@ -2999,7 +3067,7 @@ void Application::SendStoryRequest() { opus_json.shrink_to_fit(); if (!opus_root) { - ESP_LOGE(TAG, "[故事API] opus JSON解析失败"); + ESP_LOGE(TAG, "[%s] opus JSON解析失败", tag); app.https_playback_active_.store(false); app.https_playback_abort_.store(false); app.opus_playback_active_.store(false); @@ -3009,7 +3077,7 @@ void Application::SendStoryRequest() { cJSON* body_frames = cJSON_GetObjectItem(opus_root, "frames"); if (!body_frames || !cJSON_IsArray(body_frames)) { - ESP_LOGE(TAG, "[故事API] opus缺少frames数组"); + ESP_LOGE(TAG, "[%s] opus缺少frames数组", tag); cJSON_Delete(opus_root); app.https_playback_active_.store(false); app.https_playback_abort_.store(false); @@ -3024,7 +3092,7 @@ void Application::SendStoryRequest() { int body_frame_duration = (body_fd && cJSON_IsNumber(body_fd)) ? body_fd->valueint : frame_duration; int body_count = cJSON_GetArraySize(body_frames); - ESP_LOGI(TAG, "[故事API] body: 采样率=%d, 帧时长=%dms, 帧数=%d (%.1f秒)", + ESP_LOGI(TAG, "[%s] body: 采样率=%d, 帧时长=%dms, 帧数=%d (%.1f秒)", tag, body_sample_rate, body_frame_duration, body_count, body_count * body_frame_duration / 1000.0f); @@ -3035,7 +3103,7 @@ void Application::SendStoryRequest() { int body_enqueued = 0; for (int i = 0; i < body_count; i++) { if (app.https_playback_abort_.load()) { - ESP_LOGI(TAG, "[故事API] body入队中止: %d/%d", body_enqueued, body_count); + ESP_LOGI(TAG, "[%s] body入队中止: %d/%d", tag, body_enqueued, body_count); break; } @@ -3078,14 +3146,14 @@ void Application::SendStoryRequest() { } if (body_enqueued % 100 == 0) { - ESP_LOGI(TAG, "[故事API] body进度: %d/%d (%.0f%%)", + ESP_LOGI(TAG, "[%s] body进度: %d/%d (%.0f%%)", tag, body_enqueued, body_count, body_enqueued * 100.0f / body_count); } } cJSON_Delete(opus_root); - ESP_LOGI(TAG, "[故事API] body入队完成: %d帧", body_enqueued); + ESP_LOGI(TAG, "[%s] body入队完成: %d帧", tag, body_enqueued); // ========== 步骤6: 等待播放完毕 ========== if (!app.https_playback_abort_.load()) { @@ -3100,11 +3168,11 @@ void Application::SendStoryRequest() { app.https_playback_active_.store(false); app.https_playback_abort_.store(false); app.opus_playback_active_.store(false); - ESP_LOGI(TAG, "[故事API] 播放结束, 堆: %lu", + ESP_LOGI(TAG, "[%s] 播放结束, 堆: %lu", tag, (unsigned long)esp_get_free_heap_size()); vTaskDelete(NULL); - }, "story_play", 10240, NULL, 5, NULL); + }, task_name, 10240, params, 5, NULL); } // 设置监听模式 diff --git a/main/application.h b/main/application.h index cd2c79c..34c0d0c 100644 --- a/main/application.h +++ b/main/application.h @@ -72,7 +72,8 @@ public: void AbortSpeaking(AbortReason reason);// 打断语音播报 void AbortHttpsPlayback(const char* reason);// 中止HTTPS音频播放并清空DMA void HttpsPlaybackFromUrl(const std::string& url); // 通过HTTPS下载JSON并播放音频(故事/歌曲等) - void SendStoryRequest(); // 发送讲故事 请求 + void SendStoryRequest(); // 通过HTTPS故事API请求并播放故事 + void SendMusicRequest(); // 通过HTTPS音乐API请求并播放音乐 void ToggleChatState();// 切换聊天状态 void ToggleListeningState();// 切换监听状态 void StartListening();// 开始监听 @@ -202,6 +203,7 @@ private: void StartDialogWatchdog();// 启动对话看门狗 void StopDialogWatchdog(); // 停止对话看门狗 + void HttpsApiPlayback(const char* api_url_base, const char* tag, const char* task_name); // HTTPS API音频播放通用实现 const char* DeviceStateToString(DeviceState state); // 状态枚举转字符串 }; diff --git a/sdkconfig b/sdkconfig index 056906b..f9310f1 100644 --- a/sdkconfig +++ b/sdkconfig @@ -14,6 +14,7 @@ CONFIG_SOC_GDMA_SUPPORTED=y CONFIG_SOC_AHB_GDMA_SUPPORTED=y CONFIG_SOC_GPTIMER_SUPPORTED=y CONFIG_SOC_LCDCAM_SUPPORTED=y +CONFIG_SOC_LCDCAM_CAM_SUPPORTED=y CONFIG_SOC_LCDCAM_I80_LCD_SUPPORTED=y CONFIG_SOC_LCDCAM_RGB_LCD_SUPPORTED=y CONFIG_SOC_MCPWM_SUPPORTED=y @@ -101,7 +102,7 @@ CONFIG_SOC_CPU_HAS_FPU=y CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES=y CONFIG_SOC_CPU_BREAKPOINTS_NUM=2 CONFIG_SOC_CPU_WATCHPOINTS_NUM=2 -CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=64 +CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=0x40 CONFIG_SOC_SIMD_PREFERRED_DATA_ALIGNMENT=16 CONFIG_SOC_DS_SIGNATURE_MAX_BIT_LEN=4096 CONFIG_SOC_DS_KEY_PARAM_MD_IV_LENGTH=16 @@ -208,7 +209,7 @@ CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y CONFIG_SOC_LP_IO_CLOCK_IS_INDEPENDENT=y -CONFIG_SOC_SDM_GROUPS=y +CONFIG_SOC_SDM_GROUPS=1 CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8 CONFIG_SOC_SDM_CLK_SUPPORT_APB=y CONFIG_SOC_SPI_PERIPH_NUM=3 @@ -369,6 +370,9 @@ CONFIG_SOC_BLE_DEVICE_PRIVACY_SUPPORTED=y CONFIG_SOC_BLUFI_SUPPORTED=y CONFIG_SOC_ULP_HAS_ADC=y CONFIG_SOC_PHY_COMBO_MODULE=y +CONFIG_SOC_LCDCAM_CAM_SUPPORT_RGB_YUV_CONV=y +CONFIG_SOC_LCDCAM_CAM_PERIPH_NUM=1 +CONFIG_SOC_LCDCAM_CAM_DATA_WIDTH_MAX=16 CONFIG_IDF_CMAKE=y CONFIG_IDF_TOOLCHAIN="gcc" CONFIG_IDF_TOOLCHAIN_GCC=y @@ -566,6 +570,7 @@ CONFIG_PARTITION_TABLE_MD5=y CONFIG_OTA_VERSION_URL="https://xiaozhi-dev-web.goods.fun/xiaozhi/ota/" CONFIG_DEVICE_STATUS_REPORT_URL="http://192.168.124.8:8000/api/v1/devices/report-status" CONFIG_STORY_API_URL="http://192.168.124.8:8000/api/v1/devices/stories/" +CONFIG_MUSIC_API_URL="http://192.168.124.8:8000/api/v1/devices/music/" CONFIG_LANGUAGE_ZH_CN=y # CONFIG_LANGUAGE_ZH_TW is not set # CONFIG_LANGUAGE_EN_US is not set @@ -1032,6 +1037,7 @@ CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y CONFIG_BT_BLE_42_DTM_TEST_EN=y CONFIG_BT_BLE_42_ADV_EN=y CONFIG_BT_BLE_42_SCAN_EN=y +CONFIG_BT_BLE_VENDOR_HCI_EN=y # CONFIG_BT_BLE_HIGH_DUTY_ADV_INTERVAL is not set # CONFIG_BT_ABORT_WHEN_ALLOCATION_FAILS is not set # end of Bluedroid Options @@ -1253,6 +1259,7 @@ CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y # CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set # CONFIG_ESP_TLS_PSK_VERIFICATION is not set # CONFIG_ESP_TLS_INSECURE is not set +CONFIG_ESP_TLS_DYN_BUF_STRATEGY_SUPPORTED=y # end of ESP-TLS # @@ -1280,6 +1287,12 @@ CONFIG_ESP_ERR_TO_NAME_LOOKUP=y CONFIG_ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y # end of Common ESP-related +# +# ESP-Driver:Camera Controller Configurations +# +# CONFIG_CAM_CTLR_DVP_CAM_ISR_CACHE_SAFE is not set +# end of ESP-Driver:Camera Controller Configurations + # # ESP-Driver:GPIO Configurations # @@ -1597,8 +1610,11 @@ CONFIG_ESP_PHY_RF_CAL_PARTIAL=y # CONFIG_ESP_PHY_RF_CAL_NONE is not set # CONFIG_ESP_PHY_RF_CAL_FULL is not set CONFIG_ESP_PHY_CALIBRATION_MODE=0 +CONFIG_ESP_PHY_PLL_TRACK_PERIOD_MS=1000 # CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set # CONFIG_ESP_PHY_RECORD_USED_TIME is not set +CONFIG_ESP_PHY_IRAM_OPT=y +# CONFIG_ESP_PHY_DEBUG is not set # end of PHY # @@ -2269,6 +2285,7 @@ CONFIG_MBEDTLS_DYNAMIC_BUFFER=y # CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set # CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set # CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE is not set +# CONFIG_MBEDTLS_SSL_KEYING_MATERIAL_EXPORT is not set CONFIG_MBEDTLS_PKCS7_C=y # end of mbedTLS v3.x related @@ -3299,6 +3316,7 @@ CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_DIS=y CONFIG_SW_COEXIST_ENABLE=y CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y CONFIG_ESP_WIFI_SW_COEXIST_ENABLE=y +# CONFIG_CAM_CTLR_DVP_CAM_ISR_IRAM_SAFE is not set # CONFIG_MCPWM_ISR_IN_IRAM is not set # CONFIG_EVENT_LOOP_PROFILING is not set CONFIG_POST_EVENTS_FROM_ISR=y