{
g_ln_is_device_bound = bound;
}
-
-/* 下载文件
-@param url 文件URL
-@param save_path 保存路径
-@return ERRCODE_SUCC 成功,ERRCODE_FAIL 失败
-*/
-int uapi_ln_download_file(const char *url, const char *save_path)
+void uapi_ln_remove_vote(void)
{
- if (!url || !save_path)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] url or save_path is NULL");
- return ERRCODE_FAIL;
- }
-
- if (g_ln_is_file_downloading == 1)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] 已有文件正在下载中");
- return ERRCODE_FAIL;
- }
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] 开始下载: %s -> %s", url, save_path);
- g_ln_is_file_downloading = 1;
-
-
- HttpClient client = {0};
- HttpClientData client_data = {0};
- int ret = -1;
- size_t total_written = 0;
- // 打开文件准备写入
- FILE *fd = fopen(save_path, "wb+");
- if (!fd)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] fopen failed for %s", save_path);
- g_ln_is_file_downloading = 0;
- return ERRCODE_FAIL;
- }
-
- HTTPC_RESULT prep = ln_http_prepare_auto(&client_data, 2048, LN_CLIENT_PREPARE_SIZE * 2);
- if (prep != HTTP_SUCCESS)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] prepare failed: %d", prep);
- fclose(fd);
- g_ln_is_file_downloading = 0;
- return ERRCODE_FAIL;
- }
-
- // 建立连接
- ret = HttpClientConn(&client, url);
- if (ret != 0)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] connection failed, ret=0x%x", ret);
- fclose(fd);
- HttpClientUnprepare(&client_data);
- g_ln_is_file_downloading = 0;
- return ERRCODE_FAIL;
- }
-
- // 发送GET请求
- ret = HttpClientSend(&client, url, HTTP_GET, &client_data);
- if (ret != 0)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] send request failed, ret=0x%x", ret);
- fclose(fd);
- HttpClientClse(&client);
- HttpClientUnprepare(&client_data);
- g_ln_is_file_downloading = 0;
- return ERRCODE_FAIL;
- }
-
- // 接收响应数据
- do
- {
- HTTPC_RESULT recv_res = HttpClientRecvResponse(&client, &client_data);
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] recv_res = %d", recv_res);
- if (recv_res == HTTP_SUCCESS || recv_res == HTTP_EAGAIN)
- {
- if (client_data.contentBlockLen > 0)
- {
- size_t written = fwrite(client_data.responseBuf, 1, client_data.contentBlockLen, fd);
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] written = %zu", written);
- if (written != client_data.contentBlockLen)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] write failed, written=%zu, expected=%d",
- written, client_data.contentBlockLen);
- fclose(fd);
- HttpClientClse(&client);
- HttpClientUnprepare(&client_data);
- return ERRCODE_FAIL;
- }
- total_written += written;
- }
- }
- else
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] 接收响应失败, break, recv_res = %d", recv_res);
- break;
- }
- } while (client_data.isMore);
-
- if (client_data.responseContentLen == 0)
+ uint8_t cnt = pm_veto_get_id_cnt(PM_ID_DEBUG);
+ if (cnt == 1)
{
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] 接收长度为0");
+ uapi_ln_remove_vote();
}
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] responsecode = %d", client.responseCode);
- if (total_written == client_data.responseContentLen && client.responseCode == 200 && total_written > 0)
- {
- ret = ERRCODE_SUCC;
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] 文件下载成功");
- }
- else
- {
- ret = ERRCODE_FAIL;
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] 文件下载失败删除不完整文件,save_path = %s", save_path);
- int ret = 0;
- ret = unlink(save_path);
- if (ret < 0)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "删除不完整文件失败\r\n");
- }
- else
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "删除不完整文件成功\r\n");
- }
- }
-
- HttpClientUnprepare(&client_data);
- HttpClientClse(&client);
- fclose(fd);
- g_ln_is_file_downloading = 0;
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] 下载过程结束,ret=%d", ret);
- return ret;
}
-
-/* 下载函数封装:带重试,不做UI通知与资源释放 */
-int uapi_ln_download_with_retry(const char *url, const char *save_path, int max_retries)
+void uapi_ln_add_vote(void)
{
- if (url == NULL || save_path == NULL || (max_retries <= 0 || max_retries > 10 ))
+ uint8_t cnt = pm_veto_get_id_cnt(PM_ID_DEBUG);
+ if (cnt == 0)
{
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] 参数无效");
- return ERRCODE_FAIL;
+ uapi_ln_add_vote();
}
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] 开始下载: %s -> %s", url, save_path);
- uapi_pm_add_sleep_veto(PM_ID_DEBUG);
- int ret = uapi_ln_download_file(url, save_path);
- if (ERRCODE_SUCC != ret)
- {
- for (int i = 1; i <= max_retries; i++)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] 重试 %d/%d", i, max_retries);
- ret = uapi_ln_download_file(url, save_path);
- if (ERRCODE_SUCC == ret)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD] 重试成功 %d", i);
- break;
- }
- }
- }
- uapi_pm_remove_sleep_veto(PM_ID_DEBUG);
- return ret;
}
/* 下载文件(支持断点续传)
g_ln_is_file_downloading = 1;
//添加睡眠投票
- uapi_pm_add_sleep_veto(PM_ID_DEBUG);
+ uapi_ln_add_vote();
int ret = uapi_ln_download_file_resume(url, save_path);
if (ERRCODE_SUCC != ret)
}
g_ln_is_file_downloading = 0;
//移除睡眠投票
- uapi_pm_remove_sleep_veto(PM_ID_DEBUG);
+ uapi_ln_remove_vote();
return ret;
}
// 断点续传下载函数封装:带重试,不做UI通知与资源释放,文件写入发送到队列
g_ln_is_file_downloading = 1;
//添加睡眠投票
- uapi_pm_add_sleep_veto(PM_ID_DEBUG);
+ uapi_ln_add_vote();
int ret = uapi_ln_download_file_resume_queue(url, save_path);
if (ERRCODE_SUCC != ret)
}
g_ln_is_file_downloading = 0;
//移除睡眠投票
- uapi_pm_remove_sleep_veto(PM_ID_DEBUG);
+ uapi_ln_remove_vote();
return ret;
}
/* 自适应申请HttpClient缓冲(保证header>=2048),失败则逐步扩容重试 */
}
}
/* ============================ WebSocket 业务消息 上层处理 End============================ */
-
-/* ============================ mp3下载功能 ============================ */
-
-/**
- * 高级MP3下载函数,支持自定义保存目录和文件名
- * @param audio_url 音频文件URL
- * @param save_dir 保存目录
- * @param filename 文件名(不包含路径)
- * @return ERRCODE_SUCC 成功,ERRCODE_FAIL 失败
- */
-static uint32_t ln_download_mp3_file_advanced(const char *audio_url, const char *save_dir, const char *filename)
-{
- if (!audio_url || !save_dir || !filename)
- {
- printf("[SSE] download_mp3_advanced: invalid parameters\n");
- return ERRCODE_FAIL;
- }
-
- // 构建完整保存路径
- size_t sp_cap = strlen(save_dir) + 1 + strlen(filename) + 1;
- char *save_path = (char *)malloc(sp_cap);
- if (!save_path)
- {
- printf("[SSE] malloc save_path failed\n");
- return ERRCODE_FAIL;
- }
- snprintf(save_path, sp_cap, "%s/%s", save_dir, filename);
-
- // 确保目录存在
- if (access(save_dir, F_OK) == -1)
- {
- uapi_create_folder(save_dir);
- }
-
- printf("[SSE] downloading MP3: %s -> %s\n", audio_url, save_path);
-
-#ifdef SUPPORT_CAT1_SERVICE
- /* CAT1 网络保活处理 */
- cat1_api_add_cat1_vote();
- cat1_api_disable_cat1_cmd(0);
- LOS_Msleep(300);
-#endif
-
- HttpClient client = {0};
- HttpClientData client_data = {0};
- int ret = -1;
- size_t total_written = 0;
-
-#if TEST_MP3_DOWNLOAD
- // 打开文件准备写入
- FILE *fd = fopen(save_path, "wb");
- if (!fd)
- {
- printf("[SSE] fopen failed for %s\n", save_path);
- return ERRCODE_FAIL;
- }
-#endif
-
- HTTPC_RESULT prep = ln_http_prepare_auto(&client_data, 2048, LN_CLIENT_PREPARE_SIZE * 2);
- if (prep != HTTP_SUCCESS)
- {
- printf("[SSE] prepare failed: %d\n", prep);
-#if TEST_MP3_DOWNLOAD
- fclose(fd);
-#endif
- free(save_path);
- return ERRCODE_FAIL;
- }
-
- // 建立连接
- ret = HttpClientConn(&client, audio_url);
- if (ret != 0)
- {
- printf("[SSE] connection failed, ret=0x%x\n", ret);
-#if TEST_MP3_DOWNLOAD
- fclose(fd);
-#endif
- HttpClientUnprepare(&client_data);
- free(save_path);
- return ERRCODE_FAIL;
- }
-
- // 发送GET请求
- ret = HttpClientSend(&client, audio_url, HTTP_GET, &client_data);
- if (ret != 0)
- {
- printf("[SSE] send request failed, ret=0x%x\n", ret);
-#if TEST_MP3_DOWNLOAD
- fclose(fd);
-#endif
- HttpClientClse(&client);
- HttpClientUnprepare(&client_data);
- free(save_path);
- return ERRCODE_FAIL;
- }
-
- // 接收响应数据(支持取消)
- do
- {
- HTTPC_RESULT recv_res = HttpClientRecvResponse(&client, &client_data);
- if (recv_res == HTTP_SUCCESS || recv_res == HTTP_EAGAIN)
- {
- if (client_data.contentBlockLen > 0)
- {
- printf("download mp3 file advanced: contentBlockLen=%d\n", client_data.contentBlockLen);
-#if TEST_MP3_DOWNLOAD
- /* 一边下载到文件,一边推送到播放器队列,尝试边下边播 */
- size_t written = fwrite(client_data.responseBuf, 1, client_data.contentBlockLen, fd);
- if (written != client_data.contentBlockLen)
- {
- printf("[SSE] write failed, written=%zu, expected=%d\n",
- written, client_data.contentBlockLen);
- fclose(fd);
- HttpClientClse(&client);
- HttpClientUnprepare(&client_data);
- return ERRCODE_FAIL;
- }
- total_written += written;
-#endif
- ret = AI_SendAudioDataToQueue((const uint8_t *)client_data.responseBuf, client_data.contentBlockLen);
- if (ret != 0)
- {
- printf("download mp3 file advanced: write failed1, ret=%d\n", ret);
- // 写失败重新写
- LOS_Msleep(100);
- ret = AI_SendAudioDataToQueue((const uint8_t *)client_data.responseBuf, (uint32_t)client_data.contentBlockLen);
- if (ret != 0)
- {
- printf("download mp3 file advanced: write failed2, ret=%d\n", ret);
- LOS_Msleep(100);
- ret = AI_SendAudioDataToQueue((const uint8_t *)client_data.responseBuf, (uint32_t)client_data.contentBlockLen);
- if (ret != 0)
- {
- printf("download mp3 file advanced: write failed3, ret=%d\n", ret);
- }
- }
- }
- }
- else
- {
- /* EAGAIN 或 chunk 分界但无数据时,让出CPU避免忙等 */
- LOS_Msleep(10);
- }
- }
- else
- {
- printf("[SSE] receive ended (code: %d)\n", recv_res);
- break;
- }
- } while (client_data.isMore);
-
-#if TEST_MP3_DOWNLOAD
- fclose(fd);
-#endif
- HttpClientUnprepare(&client_data);
- HttpClientClse(&client);
- free(save_path);
- return ERRCODE_SUCC;
-}
-
-/**
- * 解析JSON数据,下载MP3并推送消息
- * @param json_data JSON数据字符串
- * @param interface_type 接口类型
- * @param segment_index 片段索引
- * @return ERRCODE_SUCC 成功,ERRCODE_FAIL 失败
- */
-/* 辅助函数:根据接口类型生成保存目录与文件名 */
-static void ln_build_audio_save_path(int interface_type, int segment_index, int is_error,
- char *save_dir, size_t save_dir_len,
- char *filename, size_t filename_len)
-{
- if (!save_dir || !filename)
- return;
- if (interface_type == LN_HTTP_SERVICE_CMD_SSE_RECV)
- {
- (void)snprintf(save_dir, save_dir_len, "%s/speech", LN_DATA_PATH);
- }
- else if (interface_type == LN_HTTP_RECV_STORY_CHOOSE)
- {
- (void)snprintf(save_dir, save_dir_len, "%s/story/choose", LN_DATA_PATH);
- }
- else if (interface_type == LN_HTTP_RECV_STORY_RANDOM)
- {
- (void)snprintf(save_dir, save_dir_len, "%s/story/random", LN_DATA_PATH);
- }
- else
- {
- (void)snprintf(save_dir, save_dir_len, "%s", LN_DATA_PATH);
- }
-
- if (is_error)
- {
- (void)snprintf(filename, filename_len, "%d_err.mp3", segment_index);
- }
- else
- {
- (void)snprintf(filename, filename_len, "%d.mp3", segment_index);
- }
-}
-
-/* 辅助函数:提取音频URL */
-static const char *ln_get_audio_url_for_interface(cJSON *data, int interface_type)
-{
- if (!data)
- return NULL;
- if (interface_type == LN_HTTP_SERVICE_CMD_SSE_RECV)
- {
- cJSON *audioUrl = cJSON_GetObjectItem(data, "audioUrl");
- if (audioUrl && cJSON_IsString(audioUrl))
- return audioUrl->valuestring;
- return NULL;
- }
- if (interface_type == LN_HTTP_RECV_STORY_CHOOSE || interface_type == LN_HTTP_RECV_STORY_RANDOM)
- {
- cJSON *storyAudioUrl = cJSON_GetObjectItem(data, "storyAudioUrl");
- if (storyAudioUrl && cJSON_IsString(storyAudioUrl))
- return storyAudioUrl->valuestring;
- return NULL;
- }
- cJSON *audioUrl = cJSON_GetObjectItem(data, "audioUrl");
- if (audioUrl && cJSON_IsString(audioUrl))
- return audioUrl->valuestring;
- return NULL;
-}
-
-/* 辅助函数:若存在音频URL则执行下载 */
-static void ln_download_audio_if_present(const char *audio_url, int interface_type, int segment_index, int is_error)
-{
- if (!audio_url || strlen(audio_url) == 0)
- return;
- char save_dir[256];
- char filename[128];
- ln_build_audio_save_path(interface_type, segment_index, is_error, save_dir, sizeof(save_dir), filename, sizeof(filename));
- printf("[JSON_PARSE] downloading audio to: %s/%s\n", save_dir, filename);
- (void)ln_download_mp3_file_advanced(audio_url, save_dir, filename);
-}
-
-// 解析JSON数据并处理
-static uint32_t ln_parse_and_process_json_data(const char *json_data, int interface_type, int segment_index)
-{
- if (!json_data)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[JSON_PARSE] invalid json_data\n");
- return ERRCODE_FAIL;
- }
-
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[JSON_PARSE] parsing JSON data (interface_type=%d, segment=%d): %s\n",
- interface_type, segment_index, json_data);
-
- // 解析JSON数据
- cJSON *root = cJSON_Parse(json_data);
- if (!root)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[JSON_PARSE] JSON parse failed: %s\n", json_data);
- return ERRCODE_FAIL;
- }
-
- // 检查是否有错误
- cJSON *errorCode = cJSON_GetObjectItem(root, "errorCode");
- if (errorCode && !cJSON_IsNull(errorCode))
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[JSON_PARSE] 失败响应,开始处理数据\n");
- const char *err = cJSON_IsString(errorCode) ? errorCode->valuestring : "unknown";
- cJSON *message = cJSON_GetObjectItem(root, "message");
- const char *msg_str = (message && cJSON_IsString(message)) ? message->valuestring : "";
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[JSON_PARSE] server error: %s, message=%s\n", err, msg_str);
-
- const char *audio_url_err = NULL;
- const char *text_content_err = NULL;
- cJSON *data_err = cJSON_GetObjectItem(root, "data");
- if (data_err && cJSON_IsObject(data_err))
- {
- cJSON *audioUrl = cJSON_GetObjectItem(data_err, "audioUrl");
- if (audioUrl && cJSON_IsString(audioUrl))
- audio_url_err = audioUrl->valuestring;
- cJSON *textContent = cJSON_GetObjectItem(data_err, "textContent");
- if (textContent && cJSON_IsString(textContent))
- text_content_err = textContent->valuestring;
- }
-
- if (text_content_err && strlen(text_content_err) > 0)
- {
- // 推送文本到UI
- }
-
- // 下载音频,并播放
- ln_download_audio_if_present(audio_url_err, interface_type, segment_index, 1);
-
- if (err)
- {
- if (strcmp(err, "AUTH_FAILURE") == 0 || strcmp(err, "DEVICE_NOT_FOUND") == 0)
- {
- // 获取设备Token
- do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_GET_DEVICE_TOKEN, NULL, 0);
- }
- else if (strcmp(err, "MODEL_NOT_FOUND") == 0 || strcmp(err, "VOICE_NOT_FOUND") == 0)
- {
- // 获取角色配置
- do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_GET_CHARACTER, NULL, 0);
- }
- }
-
- cJSON_Delete(root);
- return ERRCODE_FAIL;
- }
-
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[JSON_PARSE] 成功响应,开始处理数据\n");
-
- /* -------------------------------- 获取data字段 -------------------------------- */
- cJSON *data = cJSON_GetObjectItem(root, "data");
- if (!data || !cJSON_IsObject(data))
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[JSON_PARSE] no data field found\n");
- cJSON_Delete(root);
- return ERRCODE_FAIL;
- }
-
- // 获取音频URL
- const char *audio_url = ln_get_audio_url_for_interface(data, interface_type);
-
- // 获取文本内容
- cJSON *textContent = cJSON_GetObjectItem(data, "textContent");
- if (textContent && cJSON_IsString(textContent) && strlen(textContent->valuestring) > 0)
- {
- // 推送文本到UI
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[JSON_PARSE] textContent: %s\n", textContent->valuestring);
- }
- else
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[JSON_PARSE] no textContent found\n");
- }
-
- // 识别意图并触发相应业务
- cJSON *intention = cJSON_GetObjectItem(data, "intention");
- if (intention && cJSON_IsString(intention) && intention->valuestring && intention->valuestring[0])
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[JSON_PARSE] intention: %s\n", intention->valuestring);
- if (strcmp(intention->valuestring, "StartSleepMode") == 0)
- {
- // 触发故事接口(默认随机故事,无主题)
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[JSON_PARSE] intention: StartSleepMode\n");
- ln_story_random_req_t req;
- memset(&req, 0, sizeof(req));
- do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_STORY_RANDOM, (char *)&req, sizeof(req));
- }
- }
-
- // 下载音频,并播放
- if (audio_url && strlen(audio_url) > 0)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[JSON_PARSE] found audio URL (interface_type=%d): %s\n", interface_type, audio_url);
- ln_download_audio_if_present(audio_url, interface_type, segment_index, 0);
- }
- else
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[JSON_PARSE] no audio URL found for interface_type=%d, skipping download\n", interface_type);
- }
-
- cJSON_Delete(root);
- return ERRCODE_SUCC;
-}
-
-/**
- * 从文件中解析data数据,下载MP3并推送消息
- * @param file_path 文件路径
- * @param interface_type 接口类型
- * @return ERRCODE_SUCC 成功,ERRCODE_FAIL 失败
- */
-uint32_t ln_parse_file_and_process_data(const char *file_path, int interface_type)
-{
- if (!file_path)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[FILE_PARSE] invalid file path\n");
- return ERRCODE_FAIL;
- }
-
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[FILE_PARSE] processing file: %s (interface_type=%d)\n", file_path, interface_type);
-
- FILE *fp = fopen(file_path, "r");
- if (!fp)
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[FILE_PARSE] failed to open file: %s\n", file_path);
- return ERRCODE_FAIL;
- }
-
- char *line = (char *)malloc(2048);
- if (!line)
- {
- fclose(fp);
- return ERRCODE_FAIL;
- }
- int line_count = 0;
- int success_count = 0;
- int error_count = 0;
-
- /* 向UI上报开始状态 */
- if (interface_type == LN_HTTP_SERVICE_CMD_SSE_RECV)
- {
- set_start_conversation_flag(START_CONVERSATION_FLAG_START);
- }
- else if (interface_type == LN_HTTP_RECV_STORY_CHOOSE || interface_type == LN_HTTP_RECV_STORY_RANDOM)
- {
- set_start_conversation_flag(START_CONVERSATION_FLAG_STORY_START);
- }
-
- while (fgets(line, 2048, fp))
- {
- line_count++;
-
- // 去除行尾的换行符
- size_t len = strlen(line);
- if (len > 0 && line[len - 1] == '\n')
- {
- line[len - 1] = '\0';
- len--;
- }
- if (len > 0 && line[len - 1] == '\r')
- {
- line[len - 1] = '\0';
- len--;
- }
-
- // 跳过空行
- if (len == 0)
- {
- continue;
- }
-
- // 检查是否是SSE数据格式 (data: {...})
- if (strncmp(line, "data:", 5) == 0)
- {
- char *json_start = line + 5;
- // 跳过可能的空格
- while (*json_start == ' ' || *json_start == '\t')
- {
- json_start++;
- }
-
- uint32_t result = ln_parse_and_process_json_data(json_start, interface_type, line_count);
- if (result == ERRCODE_SUCC)
- {
- success_count++;
- }
- else
- {
- error_count++;
- }
- }
- else
- {
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[FILE_PARSE] line %d: invalid format (not SSE data): %s\n", line_count, line);
- error_count++;
- }
- }
-
- fclose(fp);
- free(line);
-
- WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[FILE_PARSE] processing completed: total lines=%d, success=%d, errors=%d\n",
- line_count, success_count, error_count);
-
- /* 向UI上报结束状态 */
- if (interface_type == LN_HTTP_SERVICE_CMD_SSE_RECV)
- {
- set_start_conversation_flag(START_CONVERSATION_FLAG_END);
- }
- else if (interface_type == LN_HTTP_RECV_STORY_CHOOSE || interface_type == LN_HTTP_RECV_STORY_RANDOM)
- {
- set_start_conversation_flag(START_CONVERSATION_FLAG_STORY_END);
- }
-
- return (error_count == 0) ? ERRCODE_SUCC : ERRCODE_FAIL;
-}
-/* ============================ mp3下载功能 End ============================ */
-
/* ============================ 打断当前ai回答 ============================ */
void ln_voice_chat_interrupt(const char *reason)
{