雷鸟:调整ln_api.c文件中代码位置 2257/1 2257/head 2258/target/1
authorcheng <chengyf@zhihuishixun.com>
Tue, 16 Sep 2025 07:12:00 +0000 (15:12 +0800)
committercheng <chengyf@zhihuishixun.com>
Tue, 16 Sep 2025 07:12:00 +0000 (15:12 +0800)
code/sdk/zhihui/leiniao/imsl_ln/ln_api.c
code/sdk/zhihui/leiniao/imsl_ln/ln_api.h

index 5c8c941..20ffbf7 100644 (file)
@@ -453,753 +453,761 @@ void ln_ws_process_message(int cmd, const char *json_str)
     }
     cJSON_Delete(root);
 }
+/* ============================ WebSocket 业务消息 上层处理 End============================ */
 
-// 发送队列
-static void ln_http_server_send_task(void const *arg)
+
+
+
+/* ============================ 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)
 {
-    errcode_t ret;
+    if (!audio_url || !save_dir || !filename)
+    {
+        printf("[SSE] download_mp3_advanced: invalid parameters\n");
+        return ERRCODE_FAIL;
+    }
 
-    ln_http_data_mail_t mail = {0};
-    uint32_t msgsize = sizeof(ln_http_data_mail_t);
+    // 构建完整保存路径
+    char save_path[512];
+    snprintf(save_path, sizeof(save_path), "%s/%s", save_dir, filename);
 
-    while (1)
+    // 确保目录存在
+    if (access(save_dir, F_OK) == -1)
     {
-        ret = osal_msg_queue_read_copy(g_ln_send_queue, (void *)&mail, &msgsize,
-                                       OSAL_MSGQ_WAIT_FOREVER);
-        if (ret != OSAL_SUCCESS)
-        {
-            continue;
-        }
-        if (mail.cmd == LN_HTTP_SERVICE_CMD_GET_DEVICE_TOKEN)
-        {
-            if (mail.data != NULL && mail.len == sizeof(ln_device_token_req_t))
-            {
-                printf("LN_HTTP_SERVICE_CMD_GET_DEVICE_TOKEN:获取雷鸟设备Token\n");
-                ln_device_token_req_t req;
-                memcpy(&req, mail.data, sizeof(req));
-                ln_get_device_token_http(req.device_id, req.device_iccid, req.device_model, req.device_version);
-            }
-        }
-        else if (mail.cmd == LN_HTTP_SERVICE_CMD_SPEECH_CHAT_STREAM)
-        {
-            if (mail.data != NULL && mail.len == sizeof(ln_speech_chat_req_t))
-            {
-                printf("LN_HTTP_SERVICE_CMD_SPEECH_CHAT_STREAM\n");
-                ln_speech_chat_req_t req;
-                memcpy(&req, mail.data, sizeof(req));
-                ln_speech_chat_stream_http(req.device_id, req.device_token, req.audio_path);
-            }
-        }
-        else if (mail.cmd == LN_HTTP_SERVICE_CMD_STORY_CHOOSE)
-        {
-            if (mail.data && mail.len == sizeof(ln_story_choose_req_t)) {
-                printf("LN_HTTP_SERVICE_CMD_STORY_CHOOSE:选择故事\n");
-                ln_story_choose_req_t req; memcpy(&req, mail.data, sizeof(req));
-                ln_story_choose_http(uapi_ln_get_device_id(), uapi_ln_get_device_token(), req.audio_path);
-            }
-        }
-        else if (mail.cmd == LN_HTTP_SERVICE_CMD_STORY_RANDOM)
-        {
-            if (mail.data && mail.len == sizeof(ln_story_random_req_t)) {
-                printf("LN_HTTP_SERVICE_CMD_STORY_RANDOM:随机故事\n");
-                ln_story_random_req_t req; memcpy(&req, mail.data, sizeof(req));
-                ln_story_random_http(uapi_ln_get_device_id(), uapi_ln_get_device_token(), req.story_theme[0] ? req.story_theme : NULL);
-            }
-        }
-        else if (mail.cmd == LN_HTTP_SERVICE_CMD_STORY_EXIT_INQUIRY)
-        {
-            printf("LN_HTTP_SERVICE_CMD_STORY_EXIT_INQUIRY:获取退出哄睡询问\n");
-            ln_story_exit_inquiry_http(uapi_ln_get_device_id(), uapi_ln_get_device_token());
-        }
-        else if (mail.cmd == LN_HTTP_SERVICE_CMD_STORY_FINISH)
-        {
-            printf("LN_HTTP_SERVICE_CMD_STORY_FINISH:确认结束哄睡\n");
-            ln_story_finish_http(uapi_ln_get_device_id(), uapi_ln_get_device_token());
-        }
-        else if (mail.cmd == LN_HTTP_SERVICE_CMD_GET_CHARACTER)
-        {
-            printf("LN_HTTP_SERVICE_CMD_GET_CHARACTER:获取设备角色信息\n");
-            ln_device_get_character_http(uapi_ln_get_device_id(), uapi_ln_get_device_token());
-        }
-        else if (mail.cmd == LN_HTTP_SERVICE_CMD_GET_USER_ID)
-        {
-            printf("LN_HTTP_SERVICE_CMD_GET_USER_ID:获取设备绑定用户ID\n");
-            ln_device_get_user_id_http(uapi_ln_get_device_id(), uapi_ln_get_device_token());
-        }
-        else if (mail.cmd == LN_HTTP_SERVICE_CMD_OTA_GET_TASK)
-        {
-            printf("LN_HTTP_SERVICE_CMD_OTA_GET_TASK:获取OTA升级任务\n");
-            ln_ota_get_task_http(uapi_ln_get_device_id(), uapi_ln_get_device_token(), uapi_ln_get_device_version());
-        }
-        else if (mail.cmd == LN_HTTP_SERVICE_CMD_OTA_DOWNLOAD)
-        {
-            printf("LN_HTTP_SERVICE_CMD_OTA_DOWNLOAD:下载OTA升级包\n");
-            ln_ota_download_flow_http(uapi_ln_get_device_id(), uapi_ln_get_device_token(), uapi_ln_get_device_version());
-        }
-        else if (mail.cmd == LN_HTTP_SERVICE_CMD_AUDIO_PLAY)
-        {
-            printf("LN_HTTP_SERVICE_CMD_AUDIO_PLAY:播放音频\n");
-            #ifdef BOARD_N9
-            if (ln_story_player_simple_start("/user/leiniao/story/choose"))
-            {
-                printf("播放开始成功\n");
-            }
-            #endif
-        }
-        else if (mail.cmd == LN_HTTP_SERVICE_CMD_AUDIO_STOP)
-        {
-            printf("LN_HTTP_SERVICE_CMD_AUDIO_STOP:停止播放音频\n");
-            #ifdef BOARD_N9
-            ln_story_player_simple_stop();
-            #endif
-        }
-        else if (mail.cmd == LN_HTTP_SERVICE_CMD_AUDIO_PLAY_NEXT)
-        {
-            printf("LN_HTTP_SERVICE_CMD_AUDIO_PLAY_NEXT:播放下一首\n");
-            #ifdef BOARD_N9
-            ln_story_player_simple_handle_message(LN_HTTP_SERVICE_CMD_AUDIO_PLAY_NEXT, NULL, 0);
-            #endif
-        }
-        else if (mail.cmd == LN_HTTP_SERVICE_CMD_AUDIO_PLAY_FILE)
+        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_wakeup_cat1(1);
+    cat1_api_keep_wakeup(1);
+    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;
+
+    // 打开文件准备写入
+    FILE *fd = fopen(save_path, "wb");
+    if (!fd)
+    {
+        printf("[SSE] fopen failed for %s\n", save_path);
+        return ERRCODE_FAIL;
+    }
+
+    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);
+        fclose(fd);
+        return ERRCODE_FAIL;
+    }
+
+    // 建立连接
+    ret = HttpClientConn(&client, audio_url);
+    if (ret != 0)
+    {
+        printf("[SSE] connection failed, ret=0x%x\n", ret);
+        fclose(fd);
+        HttpClientUnprepare(&client_data);
+        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);
+        fclose(fd);
+        HttpClientClse(&client);
+        HttpClientUnprepare(&client_data);
+        return ERRCODE_FAIL;
+    }
+
+    // 接收响应数据
+    do
+    {
+        HTTPC_RESULT recv_res = HttpClientRecvResponse(&client, &client_data);
+        if (recv_res == HTTP_SUCCESS || recv_res == HTTP_EAGAIN)
         {
-            printf("LN_HTTP_SERVICE_CMD_AUDIO_PLAY_FILE:播放指定文件\n");
-            #ifdef BOARD_N9
-            if (mail.data != NULL)
+            if (client_data.contentBlockLen > 0)
             {
-                char *file_path = (char*)mail.data;
-                printf("Playing file: %s\n", file_path);
-                if (ln_story_player_simple_play_file(file_path))
-                {
-                    printf("File playback started successfully\n");
-                }
-                else
+                /* 一边下载到文件,一边推送到播放器队列,尝试边下边播 */
+                size_t written = fwrite(client_data.responseBuf, 1, client_data.contentBlockLen, fd);
+                if (written != client_data.contentBlockLen)
                 {
-                    printf("Failed to start file playback\n");
+                    printf("[SSE] write failed, written=%zu, expected=%d\n",
+                           written, client_data.contentBlockLen);
+                    fclose(fd);
+                    HttpClientClse(&client);
+                    HttpClientUnprepare(&client_data);
+                    return ERRCODE_FAIL;
                 }
+
+                /* 非阻塞入队,队列满则忽略该块 */
+                (void)ln_audio_player_write((const uint8_t*)client_data.responseBuf, (uint32_t)client_data.contentBlockLen);
+
+                total_written += written;
             }
-            else
-            {
-                printf("Error: No file path provided\n");
-            }
-            #endif
-        }
-        else if (mail.cmd == LN_HTTP_SERVICE_CMD_AUDIO_PAUSE)
-        {
-            printf("LN_HTTP_SERVICE_CMD_AUDIO_PAUSE:暂停播放\n");
-            #ifdef BOARD_N9
-            if (ln_story_player_simple_pause())
-            {
-                printf("Playback paused successfully\n");
-            }
-            else
-            {
-                printf("Failed to pause playback\n");
-            }
-            #endif
-        }
-        else if (mail.cmd == LN_HTTP_SERVICE_CMD_AUDIO_RESUME)
-        {
-            printf("LN_HTTP_SERVICE_CMD_AUDIO_RESUME:恢复播放\n");
-            #ifdef BOARD_N9
-            if (ln_story_player_simple_resume())
-            {
-                printf("Playback resumed successfully\n");
-            }
-            else
-            {
-                printf("Failed to resume playback\n");
-            }
-            #endif
         }
-        if (mail.data != NULL)
+        else
         {
-            printf("free(mail.data)\n");
-            free(mail.data);
+            printf("[SSE] receive ended (code: %d)\n", recv_res);
+            break;
         }
-    }
+    } while (client_data.isMore);
+
+    fclose(fd);
+    HttpClientUnprepare(&client_data);
+    HttpClientClse(&client);
+
+    printf("[SSE] download completed, total bytes: %zu\n", total_written);
+    return ERRCODE_SUCC;
 }
 
-// 接收队列
-static void ln_http_server_recv_task(void const *arg)
+/**
+ * 解析JSON数据,下载MP3并推送消息
+ * @param json_data JSON数据字符串
+ * @param interface_type 接口类型
+ * @param segment_index 片段索引
+ * @return ERRCODE_SUCC 成功,ERRCODE_FAIL 失败
+ */
+static uint32_t ln_parse_and_process_json_data(const char *json_data, int interface_type, int segment_index)
 {
-    errcode_t ret;
+    if (!json_data)
+    {
+        printf("[JSON_PARSE] invalid json_data\n");
+        return ERRCODE_FAIL;
+    }
 
-    ln_http_data_mail_t mail = {0};
-    uint32_t msgsize = sizeof(ln_http_data_mail_t);
+    printf("[JSON_PARSE] parsing JSON data (interface_type=%d, segment=%d): %s\n", 
+           interface_type, segment_index, json_data);
 
-    while (1)
+    // 解析JSON数据
+    cJSON *root = cJSON_Parse(json_data);
+    if (!root)
     {
-        ret = osal_msg_queue_read_copy(g_ln_recv_queue, (void *)&mail, &msgsize,
-                                       OSAL_MSGQ_WAIT_FOREVER);
-        if (ret != OSAL_SUCCESS)
-        {
-            continue;
-        }
+        printf("[JSON_PARSE] JSON parse failed: %s\n", json_data);
+        return ERRCODE_FAIL;
+    }
 
-        // 消息有效性检查
-        if (!mail.data || mail.len <= 0) 
-        { 
-            continue;
-        }
+    // 检查是否有错误
+    cJSON *errorCode = cJSON_GetObjectItem(root, "errorCode");
+    if (errorCode && !cJSON_IsNull(errorCode))
+    {
+        printf("[JSON_PARSE] server error: %s\n", 
+               cJSON_IsString(errorCode) ? errorCode->valuestring : "unknown");
+        cJSON_Delete(root);
+        return ERRCODE_FAIL;
+    }
 
-        // 分类处理消息
-        const char *tag = "UNKNOWN";
-        if (mail.cmd == LN_HTTP_SERVICE_CMD_SSE_RECV) {
-            tag = "SPEECH_CHAT";
-        } else if (mail.cmd == LN_HTTP_RECV_STORY_CHOOSE) {
-            tag = "STORY_CHOOSE";
-        } else if (mail.cmd == LN_HTTP_RECV_STORY_RANDOM) {
-            tag = "STORY_RANDOM";
-        } else if (mail.cmd == LN_HTTP_RECV_STORY_EXIT) {
-            tag = "STORY_EXIT";
-        } else if (mail.cmd == LN_HTTP_RECV_STORY_FINISH) {
-            tag = "STORY_FINISH";
-        } else if (mail.cmd == LN_HTTP_RECV_DEVICE_CHARACTER) {
-            tag = "DEVICE_CHARACTER";
-        } else if (mail.cmd == LN_HTTP_RECV_DEVICE_USER_ID) {
-            tag = "DEVICE_USER_ID";
-        } else if (mail.cmd == LN_HTTP_RECV_OTA_TASK) {
-            tag = "OTA_TASK";
-        } else if (mail.cmd == LN_HTTP_RECV_OTA_DOWNLOAD_MSG) {
-            tag = "OTA_DOWNLOAD_MSG";
-        }
+    // 获取data字段
+    cJSON *data = cJSON_GetObjectItem(root, "data");
+    if (!data || !cJSON_IsObject(data))
+    {
+        printf("[JSON_PARSE] no data field found\n");
+        cJSON_Delete(root);
+        return ERRCODE_FAIL;
+    }
 
-        printf("[%s] 数据长度: %u\n", tag, mail.len);
-        /* 确保可打印:追加\0 */
-        char *buf = (char *)malloc(mail.len + 1);
-        if (buf) {
-            memcpy(buf, mail.data, mail.len);
-            buf[mail.len] = '\0';
-            printf("[%s] 原始数据:%s\n", tag, buf);
-            /* 在收到 OTA_TASK 后,根据升级策略决定是否触发下载 */
-            if (mail.cmd == LN_HTTP_RECV_OTA_TASK) {
-                ln_handle_ota_task_response(buf, (int)mail.len);
-            }
-            /* 在收到 OTA_DOWNLOAD_MSG 后,解析状态并回调处理(进度/完成/失败) */
-            if (mail.cmd == LN_HTTP_RECV_OTA_DOWNLOAD_MSG) {
-                OtaDownloadMsg m = {0};
-                if (parse_ota_download_msg(buf, &m) == 0) {
-                    handle_ota_download_msg(&m);
-                }
-            }
-            free(buf);
+    // 根据接口类型获取音频URL
+    char *audio_url = NULL;
+    if (interface_type == LN_HTTP_SERVICE_CMD_SSE_RECV)
+    {
+        // 语音对话接口:使用 audioUrl 字段
+        cJSON *audioUrl = cJSON_GetObjectItem(data, "audioUrl");
+        if (audioUrl && cJSON_IsString(audioUrl))
+        {
+            audio_url = audioUrl->valuestring;
         }
     }
-}
-
-static void create_ln_http_send_queue(void)
-{
-    if (osal_msg_queue_create("ln_http_send_queue", 24, &g_ln_send_queue,
-                              0, sizeof(ln_http_data_mail_t)) != ERRCODE_SUCC)
+    else if (interface_type == LN_HTTP_RECV_STORY_CHOOSE || interface_type == LN_HTTP_RECV_STORY_RANDOM)
     {
-        printf("[ln][service] app create mail fail\n");
+        // 故事接口:使用 storyAudioUrl 字段
+        cJSON *storyAudioUrl = cJSON_GetObjectItem(data, "storyAudioUrl");
+        if (storyAudioUrl && cJSON_IsString(storyAudioUrl))
+        {
+            audio_url = storyAudioUrl->valuestring;
+        }
     }
-}
-
-static void create_ln_http_recv_queue(void)
-{
-    if (osal_msg_queue_create("ln_http_recv_queue", 24, &g_ln_recv_queue,
-                              0, sizeof(ln_http_data_mail_t)) != ERRCODE_SUCC)
+    else
     {
-        printf("[ln][service] app create mail fail\n");
+        // 默认尝试 audioUrl 字段
+        cJSON *audioUrl = cJSON_GetObjectItem(data, "audioUrl");
+        if (audioUrl && cJSON_IsString(audioUrl))
+        {
+            audio_url = audioUrl->valuestring;
+        }
     }
-}
 
-// 雷鸟http服务初始化
-errcode_t uapi_ln_http_server_init(void)
-{
-    printf("uapi_ln_http_server_init !\r\n");
-
-    ln_send_taskcfg.create_queue_handle = create_ln_http_send_queue;
-    ln_send_taskcfg.attr.name = "ln_http_server_send_task";
-    ln_send_taskcfg.attr.priority = osPriorityNormal;
-    ln_send_taskcfg.attr.stack_size = LN_HTTP_BOARD_TASK_SIZE;
-    ln_send_taskcfg.func = ln_http_server_send_task;
-    ln_send_taskcfg.use_mem = USE_EXTEND_MEM;
-
-    errcode_t ret = uapi_create_osThread_custom(&ln_send_taskcfg);
-    if (ret != ERRCODE_SUCC)
+    // 获取textContent
+    cJSON *textContent = cJSON_GetObjectItem(data, "textContent");
+    char *text_content = NULL;
+    if (textContent && cJSON_IsString(textContent))
     {
-        printf("create ln_send_service failed %d!\r\n", ret);
-        return ERRCODE_FAIL;
+        text_content = textContent->valuestring;
     }
 
-    ln_recv_taskcfg.create_queue_handle = create_ln_http_recv_queue;
-    ln_recv_taskcfg.attr.name = "ln_http_server_recv_task";
-    ln_recv_taskcfg.attr.priority = osPriorityNormal;
-    ln_recv_taskcfg.attr.stack_size = LN_HTTP_BOARD_TASK_SIZE;
-    ln_recv_taskcfg.func = ln_http_server_recv_task;
-    ln_recv_taskcfg.use_mem = USE_EXTEND_MEM;
-
-    ret = uapi_create_osThread_custom(&ln_recv_taskcfg);
-    if (ret != ERRCODE_SUCC)
+    // 获取intention
+    cJSON *intention = cJSON_GetObjectItem(data, "intention");
+    char *intention_str = NULL;
+    if (intention && cJSON_IsString(intention))
     {
-        printf("create gnss_recv_service failed %d!\r\n", ret);
-        return ERRCODE_FAIL;
+        intention_str = intention->valuestring;
     }
 
-    /* 初始化音频播放器(流式输出) */
-    if (ln_audio_player_init() != ERRCODE_SUCC)
+    // 获取storyTheme(故事接口特有)
+    cJSON *storyTheme = cJSON_GetObjectItem(data, "storyTheme");
+    char *story_theme = NULL;
+    if (storyTheme && cJSON_IsString(storyTheme))
     {
-        printf("[LN_AUDIO] init failed in http server init\n");
-        /* 不中断HTTP服务,按需可返回失败 */
+        story_theme = storyTheme->valuestring;
     }
 
-    return ERRCODE_SUCC;
-}
+    // 获取storyContent(故事接口特有)
+    cJSON *storyContent = cJSON_GetObjectItem(data, "storyContent");
+    char *story_content = NULL;
+    if (storyContent && cJSON_IsString(storyContent))
+    {
+        story_content = storyContent->valuestring;
+    }
 
-/* 通用发送接口:向 LN HTTP 发送队列投递消息 */
-void do_ln_http_server_send_data(int cmd, char *data, uint32_t len)
-{
-    errcode_t ret;
-    ln_http_data_mail_t send_data = {0};
-    send_data.cmd = cmd;
-    if (len && data)
+    // 创建推送数据
+    cJSON *push_data = cJSON_CreateObject();
+    
+    // 根据接口类型添加相应字段
+    if (text_content && strlen(text_content) > 0)
     {
-        send_data.len = len;
-        send_data.data = (char *)malloc(len);
-        if (send_data.data == NULL)
-        {
-            printf("malloc failed\n");
-            return;
-        }
-        memcpy(send_data.data, data, len);
+        cJSON_AddStringToObject(push_data, "textContent", text_content);
+    }
+    
+    if (story_content && strlen(story_content) > 0)
+    {
+        cJSON_AddStringToObject(push_data, "storyContent", story_content);
+    }
+    
+    if (intention_str && strlen(intention_str) > 0)
+    {
+        cJSON_AddStringToObject(push_data, "intention", intention_str);
+    }
+    
+    if (story_theme && strlen(story_theme) > 0)
+    {
+        cJSON_AddStringToObject(push_data, "storyTheme", story_theme);
     }
 
-    uint32_t send_len = sizeof(send_data);
-
-    ret = osal_msg_queue_write_copy(g_ln_send_queue, (void *)&send_data,
-                                    send_len, 0);
-    if (ret != OSAL_SUCCESS)
+    // 推送到相应的接收线程
+    char *json_string = cJSON_Print(push_data);
+    if (json_string)
     {
-        printf("Error ln http send failed! err=0x%x! \r\n", ret);
+        printf("[JSON_PARSE] pushing data to interface_type=%d: %s\n", interface_type, json_string);
+        do_ln_http_server_recv_data(interface_type, json_string, strlen(json_string));
+        free(json_string);
     }
-}
+    cJSON_Delete(push_data);
 
-/* 通用接收接口:向 LN HTTP 接收队列投递消息 */
-void do_ln_http_server_recv_data(int cmd, char *data, uint32_t len)
-{
-    errcode_t ret;
-    ln_http_data_mail_t recv_data = {0};
-    recv_data.cmd = cmd;
-    if (len && data)
+    // 下载音频文件
+    if (audio_url && strlen(audio_url) > 0)
     {
-        recv_data.len = len;
-        recv_data.data = (char *)malloc(len);
-        if (recv_data.data == NULL)
+        char save_dir[256];
+        char filename[128];
+        
+        // 根据接口类型确定保存目录和文件名
+        switch (interface_type)
         {
-            printf("malloc failed\n");
-            return;
+            case LN_HTTP_SERVICE_CMD_SSE_RECV:
+                snprintf(save_dir, sizeof(save_dir), "%s/speech", LN_DATA_PATH);
+                snprintf(filename, sizeof(filename), "%d.mp3", segment_index);
+                break;
+            case LN_HTTP_RECV_STORY_CHOOSE:
+                snprintf(save_dir, sizeof(save_dir), "%s/story/choose", LN_DATA_PATH);
+                snprintf(filename, sizeof(filename), "%d.mp3", segment_index);
+                break;
+            case LN_HTTP_RECV_STORY_RANDOM:
+                snprintf(save_dir, sizeof(save_dir), "%s/story/random", LN_DATA_PATH);
+                snprintf(filename, sizeof(filename), "%d.mp3", segment_index);
+                break;
+            default:
+                snprintf(save_dir, sizeof(save_dir), "%s", LN_DATA_PATH);
+                snprintf(filename, sizeof(filename), "%d.mp3", segment_index);
+                break;
         }
-        memcpy(recv_data.data, data, len);
-    }
-
-    uint32_t send_len = sizeof(recv_data);
 
-    ret = osal_msg_queue_write_copy(g_ln_recv_queue, (void *)&recv_data,
-                                    send_len, 0);
-    if (ret != OSAL_SUCCESS)
+        printf("[JSON_PARSE] found audio URL (interface_type=%d): %s\n", interface_type, audio_url);
+        printf("[JSON_PARSE] downloading audio to: %s/%s\n", save_dir, filename);
+        
+        uint32_t download_result = ln_download_mp3_file_advanced(audio_url, save_dir, filename);
+        if (download_result == ERRCODE_SUCC)
+        {
+            printf("[JSON_PARSE] audio downloaded successfully: %s/%s\n", save_dir, filename);
+        }
+        else
+        {
+            printf("[JSON_PARSE] audio download failed\n");
+        }
+    }
+    else
     {
-        printf("Error ln http recv send failed! err=0x%x! \r\n", ret);
-        if (recv_data.data) free(recv_data.data);
+        printf("[JSON_PARSE] no audio URL found for interface_type=%d, skipping download\n", interface_type);
     }
-}
 
+    cJSON_Delete(root);
+    return ERRCODE_SUCC;
+}
 
 /**
- * 高级MP3下载函数,支持自定义保存目录和文件名
- * @param audio_url 音频文件URL
- * @param save_dir 保存目录
- * @param filename 文件名(不包含路径)
+ * 从文件中解析data数据,下载MP3并推送消息
+ * @param file_path 文件路径
+ * @param interface_type 接口类型
  * @return ERRCODE_SUCC 成功,ERRCODE_FAIL 失败
  */
-static uint32_t ln_download_mp3_file_advanced(const char *audio_url, const char *save_dir, const char *filename)
+uint32_t ln_parse_file_and_process_data(const char *file_path, int interface_type)
 {
-    if (!audio_url || !save_dir || !filename)
+    if (!file_path)
     {
-        printf("[SSE] download_mp3_advanced: invalid parameters\n");
+        printf("[FILE_PARSE] invalid file path\n");
         return ERRCODE_FAIL;
     }
 
-    // 构建完整保存路径
-    char save_path[512];
-    snprintf(save_path, sizeof(save_path), "%s/%s", save_dir, filename);
+    printf("[FILE_PARSE] processing file: %s (interface_type=%d)\n", file_path, interface_type);
 
-    // 确保目录存在
-    if (access(save_dir, F_OK) == -1)
+    FILE *fp = fopen(file_path, "r");
+    if (!fp)
     {
-        uapi_create_folder(save_dir);
+        printf("[FILE_PARSE] failed to open file: %s\n", file_path);
+        return ERRCODE_FAIL;
     }
 
-    printf("[SSE] downloading MP3: %s -> %s\n", audio_url, save_path);
+    char line[2048];
+    int line_count = 0;
+    int success_count = 0;
+    int error_count = 0;
 
-    #ifdef SUPPORT_CAT1_SERVICE
-    /* CAT1 网络保活处理 */
-    cat1_api_add_cat1_vote();
-    cat1_api_wakeup_cat1(1);
-    cat1_api_keep_wakeup(1);
-    cat1_api_disable_cat1_cmd(0);
-    LOS_Msleep(300);
-    #endif
+    while (fgets(line, sizeof(line), 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--;
+        }
 
-    HttpClient client = {0};
-    HttpClientData client_data = {0};
-    int ret = -1;
-    size_t total_written = 0;
+        // 跳过空行
+        if (len == 0)
+        {
+            continue;
+        }
 
-    // 打开文件准备写入
-    FILE *fd = fopen(save_path, "wb");
-    if (!fd)
-    {
-        printf("[SSE] fopen failed for %s\n", save_path);
-        return ERRCODE_FAIL;
-    }
+        // 检查是否是SSE数据格式 (data: {...})
+        if (strncmp(line, "data:", 5) == 0)
+        {
+            char *json_start = line + 5;
+            // 跳过可能的空格
+            while (*json_start == ' ' || *json_start == '\t')
+            {
+                json_start++;
+            }
 
-    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);
-        fclose(fd);
-        return ERRCODE_FAIL;
+            printf("[FILE_PARSE] line %d: processing JSON: %s\n", line_count, 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
+        {
+            printf("[FILE_PARSE] line %d: invalid format (not SSE data): %s\n", line_count, line);
+            error_count++;
+        }
     }
 
-    // 建立连接
-    ret = HttpClientConn(&client, audio_url);
-    if (ret != 0)
-    {
-        printf("[SSE] connection failed, ret=0x%x\n", ret);
-        fclose(fd);
-        HttpClientUnprepare(&client_data);
-        return ERRCODE_FAIL;
-    }
+    fclose(fp);
 
-    // 发送GET请求
-    ret = HttpClientSend(&client, audio_url, HTTP_GET, &client_data);
-    if (ret != 0)
-    {
-        printf("[SSE] send request failed, ret=0x%x\n", ret);
-        fclose(fd);
-        HttpClientClse(&client);
-        HttpClientUnprepare(&client_data);
-        return ERRCODE_FAIL;
-    }
+    printf("[FILE_PARSE] processing completed: total lines=%d, success=%d, errors=%d\n", 
+           line_count, success_count, error_count);
 
-    // 接收响应数据
-    do
+    return (error_count == 0) ? ERRCODE_SUCC : ERRCODE_FAIL;
+}
+/* ============================ mp3下载功能 End ============================ */
+
+/* ============================ 队列相关代码  ============================ */
+// 发送队列
+static void ln_http_server_send_task(void const *arg)
+{
+    errcode_t ret;
+
+    ln_http_data_mail_t mail = {0};
+    uint32_t msgsize = sizeof(ln_http_data_mail_t);
+
+    while (1)
     {
-        HTTPC_RESULT recv_res = HttpClientRecvResponse(&client, &client_data);
-        if (recv_res == HTTP_SUCCESS || recv_res == HTTP_EAGAIN)
+        ret = osal_msg_queue_read_copy(g_ln_send_queue, (void *)&mail, &msgsize,
+                                       OSAL_MSGQ_WAIT_FOREVER);
+        if (ret != OSAL_SUCCESS)
+        {
+            continue;
+        }
+        if (mail.cmd == LN_HTTP_SERVICE_CMD_GET_DEVICE_TOKEN)
+        {
+            if (mail.data != NULL && mail.len == sizeof(ln_device_token_req_t))
+            {
+                printf("LN_HTTP_SERVICE_CMD_GET_DEVICE_TOKEN:获取雷鸟设备Token\n");
+                ln_device_token_req_t req;
+                memcpy(&req, mail.data, sizeof(req));
+                ln_get_device_token_http(req.device_id, req.device_iccid, req.device_model, req.device_version);
+            }
+        }
+        else if (mail.cmd == LN_HTTP_SERVICE_CMD_SPEECH_CHAT_STREAM)
+        {
+            if (mail.data != NULL && mail.len == sizeof(ln_speech_chat_req_t))
+            {
+                printf("LN_HTTP_SERVICE_CMD_SPEECH_CHAT_STREAM\n");
+                ln_speech_chat_req_t req;
+                memcpy(&req, mail.data, sizeof(req));
+                ln_speech_chat_stream_http(req.device_id, req.device_token, req.audio_path);
+            }
+        }
+        else if (mail.cmd == LN_HTTP_SERVICE_CMD_STORY_CHOOSE)
+        {
+            if (mail.data && mail.len == sizeof(ln_story_choose_req_t)) {
+                printf("LN_HTTP_SERVICE_CMD_STORY_CHOOSE:选择故事\n");
+                ln_story_choose_req_t req; memcpy(&req, mail.data, sizeof(req));
+                ln_story_choose_http(uapi_ln_get_device_id(), uapi_ln_get_device_token(), req.audio_path);
+            }
+        }
+        else if (mail.cmd == LN_HTTP_SERVICE_CMD_STORY_RANDOM)
         {
-            if (client_data.contentBlockLen > 0)
+            if (mail.data && mail.len == sizeof(ln_story_random_req_t)) {
+                printf("LN_HTTP_SERVICE_CMD_STORY_RANDOM:随机故事\n");
+                ln_story_random_req_t req; memcpy(&req, mail.data, sizeof(req));
+                ln_story_random_http(uapi_ln_get_device_id(), uapi_ln_get_device_token(), req.story_theme[0] ? req.story_theme : NULL);
+            }
+        }
+        else if (mail.cmd == LN_HTTP_SERVICE_CMD_STORY_EXIT_INQUIRY)
+        {
+            printf("LN_HTTP_SERVICE_CMD_STORY_EXIT_INQUIRY:获取退出哄睡询问\n");
+            ln_story_exit_inquiry_http(uapi_ln_get_device_id(), uapi_ln_get_device_token());
+        }
+        else if (mail.cmd == LN_HTTP_SERVICE_CMD_STORY_FINISH)
+        {
+            printf("LN_HTTP_SERVICE_CMD_STORY_FINISH:确认结束哄睡\n");
+            ln_story_finish_http(uapi_ln_get_device_id(), uapi_ln_get_device_token());
+        }
+        else if (mail.cmd == LN_HTTP_SERVICE_CMD_GET_CHARACTER)
+        {
+            printf("LN_HTTP_SERVICE_CMD_GET_CHARACTER:获取设备角色信息\n");
+            ln_device_get_character_http(uapi_ln_get_device_id(), uapi_ln_get_device_token());
+        }
+        else if (mail.cmd == LN_HTTP_SERVICE_CMD_GET_USER_ID)
+        {
+            printf("LN_HTTP_SERVICE_CMD_GET_USER_ID:获取设备绑定用户ID\n");
+            ln_device_get_user_id_http(uapi_ln_get_device_id(), uapi_ln_get_device_token());
+        }
+        else if (mail.cmd == LN_HTTP_SERVICE_CMD_OTA_GET_TASK)
+        {
+            printf("LN_HTTP_SERVICE_CMD_OTA_GET_TASK:获取OTA升级任务\n");
+            ln_ota_get_task_http(uapi_ln_get_device_id(), uapi_ln_get_device_token(), uapi_ln_get_device_version());
+        }
+        else if (mail.cmd == LN_HTTP_SERVICE_CMD_OTA_DOWNLOAD)
+        {
+            printf("LN_HTTP_SERVICE_CMD_OTA_DOWNLOAD:下载OTA升级包\n");
+            ln_ota_download_flow_http(uapi_ln_get_device_id(), uapi_ln_get_device_token(), uapi_ln_get_device_version());
+        }
+        else if (mail.cmd == LN_HTTP_SERVICE_CMD_AUDIO_PLAY)
+        {
+            printf("LN_HTTP_SERVICE_CMD_AUDIO_PLAY:播放音频\n");
+            #ifdef BOARD_N9
+            if (ln_story_player_simple_start("/user/leiniao/story/choose"))
             {
-                /* 一边下载到文件,一边推送到播放器队列,尝试边下边播 */
-                size_t written = fwrite(client_data.responseBuf, 1, client_data.contentBlockLen, fd);
-                if (written != client_data.contentBlockLen)
+                printf("播放开始成功\n");
+            }
+            #endif
+        }
+        else if (mail.cmd == LN_HTTP_SERVICE_CMD_AUDIO_STOP)
+        {
+            printf("LN_HTTP_SERVICE_CMD_AUDIO_STOP:停止播放音频\n");
+            #ifdef BOARD_N9
+            ln_story_player_simple_stop();
+            #endif
+        }
+        else if (mail.cmd == LN_HTTP_SERVICE_CMD_AUDIO_PLAY_NEXT)
+        {
+            printf("LN_HTTP_SERVICE_CMD_AUDIO_PLAY_NEXT:播放下一首\n");
+            #ifdef BOARD_N9
+            ln_story_player_simple_handle_message(LN_HTTP_SERVICE_CMD_AUDIO_PLAY_NEXT, NULL, 0);
+            #endif
+        }
+        else if (mail.cmd == LN_HTTP_SERVICE_CMD_AUDIO_PLAY_FILE)
+        {
+            printf("LN_HTTP_SERVICE_CMD_AUDIO_PLAY_FILE:播放指定文件\n");
+            #ifdef BOARD_N9
+            if (mail.data != NULL)
+            {
+                char *file_path = (char*)mail.data;
+                printf("Playing file: %s\n", file_path);
+                if (ln_story_player_simple_play_file(file_path))
                 {
-                    printf("[SSE] write failed, written=%zu, expected=%d\n",
-                           written, client_data.contentBlockLen);
-                    fclose(fd);
-                    HttpClientClse(&client);
-                    HttpClientUnprepare(&client_data);
-                    return ERRCODE_FAIL;
+                    printf("File playback started successfully\n");
                 }
-
-                /* 非阻塞入队,队列满则忽略该块 */
-                (void)ln_audio_player_write((const uint8_t*)client_data.responseBuf, (uint32_t)client_data.contentBlockLen);
-
-                total_written += written;
+                else
+                {
+                    printf("Failed to start file playback\n");
+                }
+            }
+            else
+            {
+                printf("Error: No file path provided\n");
             }
+            #endif
         }
-        else
+        else if (mail.cmd == LN_HTTP_SERVICE_CMD_AUDIO_PAUSE)
         {
-            printf("[SSE] receive ended (code: %d)\n", recv_res);
-            break;
+            printf("LN_HTTP_SERVICE_CMD_AUDIO_PAUSE:暂停播放\n");
+            #ifdef BOARD_N9
+            if (ln_story_player_simple_pause())
+            {
+                printf("Playback paused successfully\n");
+            }
+            else
+            {
+                printf("Failed to pause playback\n");
+            }
+            #endif
         }
-    } while (client_data.isMore);
-
-    fclose(fd);
-    HttpClientUnprepare(&client_data);
-    HttpClientClse(&client);
-
-    printf("[SSE] download completed, total bytes: %zu\n", total_written);
-    return ERRCODE_SUCC;
+        else if (mail.cmd == LN_HTTP_SERVICE_CMD_AUDIO_RESUME)
+        {
+            printf("LN_HTTP_SERVICE_CMD_AUDIO_RESUME:恢复播放\n");
+            #ifdef BOARD_N9
+            if (ln_story_player_simple_resume())
+            {
+                printf("Playback resumed successfully\n");
+            }
+            else
+            {
+                printf("Failed to resume playback\n");
+            }
+            #endif
+        }
+        if (mail.data != NULL)
+        {
+            printf("free(mail.data)\n");
+            free(mail.data);
+        }
+    }
 }
 
-/**
- * 解析JSON数据,下载MP3并推送消息
- * @param json_data JSON数据字符串
- * @param interface_type 接口类型
- * @param segment_index 片段索引
- * @return ERRCODE_SUCC 成功,ERRCODE_FAIL 失败
- */
-uint32_t ln_parse_and_process_json_data(const char *json_data, int interface_type, int segment_index)
+// 接收队列
+static void ln_http_server_recv_task(void const *arg)
 {
-    if (!json_data)
-    {
-        printf("[JSON_PARSE] invalid json_data\n");
-        return ERRCODE_FAIL;
-    }
-
-    printf("[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)
-    {
-        printf("[JSON_PARSE] JSON parse failed: %s\n", json_data);
-        return ERRCODE_FAIL;
-    }
-
-    // 检查是否有错误
-    cJSON *errorCode = cJSON_GetObjectItem(root, "errorCode");
-    if (errorCode && !cJSON_IsNull(errorCode))
-    {
-        printf("[JSON_PARSE] server error: %s\n", 
-               cJSON_IsString(errorCode) ? errorCode->valuestring : "unknown");
-        cJSON_Delete(root);
-        return ERRCODE_FAIL;
-    }
+    errcode_t ret;
 
-    // 获取data字段
-    cJSON *data = cJSON_GetObjectItem(root, "data");
-    if (!data || !cJSON_IsObject(data))
-    {
-        printf("[JSON_PARSE] no data field found\n");
-        cJSON_Delete(root);
-        return ERRCODE_FAIL;
-    }
+    ln_http_data_mail_t mail = {0};
+    uint32_t msgsize = sizeof(ln_http_data_mail_t);
 
-    // 根据接口类型获取音频URL
-    char *audio_url = NULL;
-    if (interface_type == LN_HTTP_SERVICE_CMD_SSE_RECV)
+    while (1)
     {
-        // 语音对话接口:使用 audioUrl 字段
-        cJSON *audioUrl = cJSON_GetObjectItem(data, "audioUrl");
-        if (audioUrl && cJSON_IsString(audioUrl))
+        ret = osal_msg_queue_read_copy(g_ln_recv_queue, (void *)&mail, &msgsize,
+                                       OSAL_MSGQ_WAIT_FOREVER);
+        if (ret != OSAL_SUCCESS)
         {
-            audio_url = audioUrl->valuestring;
+            continue;
         }
-    }
-    else if (interface_type == LN_HTTP_RECV_STORY_CHOOSE || interface_type == LN_HTTP_RECV_STORY_RANDOM)
-    {
-        // 故事接口:使用 storyAudioUrl 字段
-        cJSON *storyAudioUrl = cJSON_GetObjectItem(data, "storyAudioUrl");
-        if (storyAudioUrl && cJSON_IsString(storyAudioUrl))
-        {
-            audio_url = storyAudioUrl->valuestring;
+
+        // 消息有效性检查
+        if (!mail.data || mail.len <= 0) 
+        { 
+            continue;
         }
-    }
-    else
-    {
-        // 默认尝试 audioUrl 字段
-        cJSON *audioUrl = cJSON_GetObjectItem(data, "audioUrl");
-        if (audioUrl && cJSON_IsString(audioUrl))
-        {
-            audio_url = audioUrl->valuestring;
+
+        // 分类处理消息
+        const char *tag = "UNKNOWN";
+        if (mail.cmd == LN_HTTP_SERVICE_CMD_SSE_RECV) {
+            tag = "SPEECH_CHAT";
+        } else if (mail.cmd == LN_HTTP_RECV_STORY_CHOOSE) {
+            tag = "STORY_CHOOSE";
+        } else if (mail.cmd == LN_HTTP_RECV_STORY_RANDOM) {
+            tag = "STORY_RANDOM";
+        } else if (mail.cmd == LN_HTTP_RECV_STORY_EXIT) {
+            tag = "STORY_EXIT";
+        } else if (mail.cmd == LN_HTTP_RECV_STORY_FINISH) {
+            tag = "STORY_FINISH";
+        } else if (mail.cmd == LN_HTTP_RECV_DEVICE_CHARACTER) {
+            tag = "DEVICE_CHARACTER";
+        } else if (mail.cmd == LN_HTTP_RECV_DEVICE_USER_ID) {
+            tag = "DEVICE_USER_ID";
+        } else if (mail.cmd == LN_HTTP_RECV_OTA_TASK) {
+            tag = "OTA_TASK";
+        } else if (mail.cmd == LN_HTTP_RECV_OTA_DOWNLOAD_MSG) {
+            tag = "OTA_DOWNLOAD_MSG";
+        }
+
+        printf("[%s] 数据长度: %u\n", tag, mail.len);
+        /* 确保可打印:追加\0 */
+        char *buf = (char *)malloc(mail.len + 1);
+        if (buf) {
+            memcpy(buf, mail.data, mail.len);
+            buf[mail.len] = '\0';
+            printf("[%s] 原始数据:%s\n", tag, buf);
+            /* 在收到 OTA_TASK 后,根据升级策略决定是否触发下载 */
+            if (mail.cmd == LN_HTTP_RECV_OTA_TASK) {
+                ln_handle_ota_task_response(buf, (int)mail.len);
+            }
+            /* 在收到 OTA_DOWNLOAD_MSG 后,解析状态并回调处理(进度/完成/失败) */
+            if (mail.cmd == LN_HTTP_RECV_OTA_DOWNLOAD_MSG) {
+                OtaDownloadMsg m = {0};
+                if (parse_ota_download_msg(buf, &m) == 0) {
+                    handle_ota_download_msg(&m);
+                }
+            }
+            free(buf);
         }
     }
+}
 
-    // 获取textContent
-    cJSON *textContent = cJSON_GetObjectItem(data, "textContent");
-    char *text_content = NULL;
-    if (textContent && cJSON_IsString(textContent))
-    {
-        text_content = textContent->valuestring;
-    }
-
-    // 获取intention
-    cJSON *intention = cJSON_GetObjectItem(data, "intention");
-    char *intention_str = NULL;
-    if (intention && cJSON_IsString(intention))
+/* 创建雷鸟http发送队列 */
+static void create_ln_http_send_queue(void)
+{
+    if (osal_msg_queue_create("ln_http_send_queue", 24, &g_ln_send_queue,
+                              0, sizeof(ln_http_data_mail_t)) != ERRCODE_SUCC)
     {
-        intention_str = intention->valuestring;
+        printf("[ln][service] app create mail fail\n");
     }
+}
 
-    // 获取storyTheme(故事接口特有)
-    cJSON *storyTheme = cJSON_GetObjectItem(data, "storyTheme");
-    char *story_theme = NULL;
-    if (storyTheme && cJSON_IsString(storyTheme))
+/* 创建雷鸟http接收队列 */
+static void create_ln_http_recv_queue(void)
+{
+    if (osal_msg_queue_create("ln_http_recv_queue", 24, &g_ln_recv_queue,
+                              0, sizeof(ln_http_data_mail_t)) != ERRCODE_SUCC)
     {
-        story_theme = storyTheme->valuestring;
+        printf("[ln][service] app create mail fail\n");
     }
+}
 
-    // 获取storyContent(故事接口特有)
-    cJSON *storyContent = cJSON_GetObjectItem(data, "storyContent");
-    char *story_content = NULL;
-    if (storyContent && cJSON_IsString(storyContent))
+/* 通用发送接口:向 LN HTTP 发送队列投递消息 */
+void do_ln_http_server_send_data(int cmd, char *data, uint32_t len)
+{
+    errcode_t ret;
+    ln_http_data_mail_t send_data = {0};
+    send_data.cmd = cmd;
+    if (len && data)
     {
-        story_content = storyContent->valuestring;
+        send_data.len = len;
+        send_data.data = (char *)malloc(len);
+        if (send_data.data == NULL)
+        {
+            printf("malloc failed\n");
+            return;
+        }
+        memcpy(send_data.data, data, len);
     }
 
-    // 创建推送数据
-    cJSON *push_data = cJSON_CreateObject();
-    
-    // 根据接口类型添加相应字段
-    if (text_content && strlen(text_content) > 0)
-    {
-        cJSON_AddStringToObject(push_data, "textContent", text_content);
-    }
-    
-    if (story_content && strlen(story_content) > 0)
-    {
-        cJSON_AddStringToObject(push_data, "storyContent", story_content);
-    }
-    
-    if (intention_str && strlen(intention_str) > 0)
-    {
-        cJSON_AddStringToObject(push_data, "intention", intention_str);
-    }
-    
-    if (story_theme && strlen(story_theme) > 0)
-    {
-        cJSON_AddStringToObject(push_data, "storyTheme", story_theme);
-    }
+    uint32_t send_len = sizeof(send_data);
 
-    // 推送到相应的接收线程
-    char *json_string = cJSON_Print(push_data);
-    if (json_string)
+    ret = osal_msg_queue_write_copy(g_ln_send_queue, (void *)&send_data,
+                                    send_len, 0);
+    if (ret != OSAL_SUCCESS)
     {
-        printf("[JSON_PARSE] pushing data to interface_type=%d: %s\n", interface_type, json_string);
-        do_ln_http_server_recv_data(interface_type, json_string, strlen(json_string));
-        free(json_string);
+        printf("Error ln http send failed! err=0x%x! \r\n", ret);
     }
-    cJSON_Delete(push_data);
+}
 
-    // 下载音频文件
-    if (audio_url && strlen(audio_url) > 0)
+/* 通用接收接口:向 LN HTTP 接收队列投递消息 */
+void do_ln_http_server_recv_data(int cmd, char *data, uint32_t len)
+{
+    errcode_t ret;
+    ln_http_data_mail_t recv_data = {0};
+    recv_data.cmd = cmd;
+    if (len && data)
     {
-        char save_dir[256];
-        char filename[128];
-        
-        // 根据接口类型确定保存目录和文件名
-        switch (interface_type)
-        {
-            case LN_HTTP_SERVICE_CMD_SSE_RECV:
-                snprintf(save_dir, sizeof(save_dir), "%s/speech", LN_DATA_PATH);
-                snprintf(filename, sizeof(filename), "%d.mp3", segment_index);
-                break;
-            case LN_HTTP_RECV_STORY_CHOOSE:
-                snprintf(save_dir, sizeof(save_dir), "%s/story/choose", LN_DATA_PATH);
-                snprintf(filename, sizeof(filename), "%d.mp3", segment_index);
-                break;
-            case LN_HTTP_RECV_STORY_RANDOM:
-                snprintf(save_dir, sizeof(save_dir), "%s/story/random", LN_DATA_PATH);
-                snprintf(filename, sizeof(filename), "%d.mp3", segment_index);
-                break;
-            default:
-                snprintf(save_dir, sizeof(save_dir), "%s", LN_DATA_PATH);
-                snprintf(filename, sizeof(filename), "%d.mp3", segment_index);
-                break;
-        }
-
-        printf("[JSON_PARSE] found audio URL (interface_type=%d): %s\n", interface_type, audio_url);
-        printf("[JSON_PARSE] downloading audio to: %s/%s\n", save_dir, filename);
-        
-        uint32_t download_result = ln_download_mp3_file_advanced(audio_url, save_dir, filename);
-        if (download_result == ERRCODE_SUCC)
-        {
-            printf("[JSON_PARSE] audio downloaded successfully: %s/%s\n", save_dir, filename);
-        }
-        else
+        recv_data.len = len;
+        recv_data.data = (char *)malloc(len);
+        if (recv_data.data == NULL)
         {
-            printf("[JSON_PARSE] audio download failed\n");
+            printf("malloc failed\n");
+            return;
         }
+        memcpy(recv_data.data, data, len);
     }
-    else
+
+    uint32_t send_len = sizeof(recv_data);
+
+    ret = osal_msg_queue_write_copy(g_ln_recv_queue, (void *)&recv_data,
+                                    send_len, 0);
+    if (ret != OSAL_SUCCESS)
     {
-        printf("[JSON_PARSE] no audio URL found for interface_type=%d, skipping download\n", interface_type);
+        printf("Error ln http recv send failed! err=0x%x! \r\n", ret);
+        if (recv_data.data) free(recv_data.data);
     }
-
-    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)
+// 雷鸟http服务初始化
+errcode_t uapi_ln_http_server_init(void)
 {
-    if (!file_path)
+    printf("uapi_ln_http_server_init !\r\n");
+
+    ln_send_taskcfg.create_queue_handle = create_ln_http_send_queue;
+    ln_send_taskcfg.attr.name = "ln_http_server_send_task";
+    ln_send_taskcfg.attr.priority = osPriorityNormal;
+    ln_send_taskcfg.attr.stack_size = LN_HTTP_BOARD_TASK_SIZE;
+    ln_send_taskcfg.func = ln_http_server_send_task;
+    ln_send_taskcfg.use_mem = USE_EXTEND_MEM;
+
+    errcode_t ret = uapi_create_osThread_custom(&ln_send_taskcfg);
+    if (ret != ERRCODE_SUCC)
     {
-        printf("[FILE_PARSE] invalid file path\n");
+        printf("create ln_send_service failed %d!\r\n", ret);
         return ERRCODE_FAIL;
     }
 
-    printf("[FILE_PARSE] processing file: %s (interface_type=%d)\n", file_path, interface_type);
+    ln_recv_taskcfg.create_queue_handle = create_ln_http_recv_queue;
+    ln_recv_taskcfg.attr.name = "ln_http_server_recv_task";
+    ln_recv_taskcfg.attr.priority = osPriorityNormal;
+    ln_recv_taskcfg.attr.stack_size = LN_HTTP_BOARD_TASK_SIZE;
+    ln_recv_taskcfg.func = ln_http_server_recv_task;
+    ln_recv_taskcfg.use_mem = USE_EXTEND_MEM;
 
-    FILE *fp = fopen(file_path, "r");
-    if (!fp)
+    ret = uapi_create_osThread_custom(&ln_recv_taskcfg);
+    if (ret != ERRCODE_SUCC)
     {
-        printf("[FILE_PARSE] failed to open file: %s\n", file_path);
+        printf("create gnss_recv_service failed %d!\r\n", ret);
         return ERRCODE_FAIL;
     }
 
-    char line[2048];
-    int line_count = 0;
-    int success_count = 0;
-    int error_count = 0;
-
-    while (fgets(line, sizeof(line), fp))
+    /* 初始化音频播放器(流式输出) */
+    if (ln_audio_player_init() != ERRCODE_SUCC)
     {
-        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++;
-            }
-
-            printf("[FILE_PARSE] line %d: processing JSON: %s\n", line_count, 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
-        {
-            printf("[FILE_PARSE] line %d: invalid format (not SSE data): %s\n", line_count, line);
-            error_count++;
-        }
+        printf("[LN_AUDIO] init failed in http server init\n");
+        /* 不中断HTTP服务,按需可返回失败 */
     }
 
-    fclose(fp);
-
-    printf("[FILE_PARSE] processing completed: total lines=%d, success=%d, errors=%d\n", 
-           line_count, success_count, error_count);
-
-    return (error_count == 0) ? ERRCODE_SUCC : ERRCODE_FAIL;
+    return ERRCODE_SUCC;
 }
-
+/* ============================ 队列相关代码 End ============================ */
\ No newline at end of file
index 29fe607..0c1db7c 100644 (file)
@@ -13,6 +13,9 @@ extern "C"
 #include <unistd.h>
 #include "wearable_log.h"
 
+// 产品名称:Amby Box
+// 产品型号:AB101
+// 认证主体:深圳文阅数字科技有限公司
 typedef struct
 {
     int cmd;
@@ -175,7 +178,10 @@ extern char g_ln_last_package_md5[65];
 extern int g_ln_last_package_size;
 
 /* ============================== 公共工具函数(供拆分后的模块复用) ============================== */
+
 HTTPC_RESULT ln_http_prepare_auto(HttpClientData *clientData, int header_size, int resp_size);
+uint32_t ln_parse_file_and_process_data(const char *file_path, int interface_type);
+
 /* ============================== 各接口函数声明 ============================== */
 uint32_t ln_get_device_token_http(const char *device_id,
                                   const char *device_iccid,
@@ -219,9 +225,7 @@ int ln_ws_start(void);
 int ln_ws_send_text(const char *text);
 int ln_ws_stop(void);
 
-                                   /* 文件解析和数据处理函数 */
-uint32_t ln_parse_file_and_process_data(const char *file_path, int interface_type);
-uint32_t ln_parse_and_process_json_data(const char *json_data, int interface_type, int segment_index);
+
 #ifdef __cplusplus
 }
 #endif