static app_task_definition_t ln_send_taskcfg = {0};
static app_task_definition_t ln_recv_taskcfg = {0};
-#define LN_HTTP_BOARD_TASK_SIZE 0x2000
+#define LN_HTTP_BOARD_TASK_SIZE 0x3000
static unsigned long g_ln_send_queue = 0xFFFFFFFF;
static unsigned long g_ln_recv_queue = 0xFFFFFFFF;
#define LN_FULL_URL LN_BASE_URL LN_INTERFACE_PATH
#define LN_CHAT_PATH "/v1/speechChat/chatStream"
#define LN_CHAT_URL LN_BASE_URL LN_CHAT_PATH
+/* 故事接口路径 */
+#define LN_STORY_CHOOSE_PATH "/v1/story/chooseStory"
+#define LN_STORY_RANDOM_PATH "/v1/story/randomStory"
+#define LN_STORY_EXIT_INQUIRY_PATH "/v1/story/getExitSleepInquiry"
+#define LN_STORY_FINISH_PATH "/v1/story/finishSleepMode"
+#define LN_STORY_CHOOSE_URL LN_BASE_URL LN_STORY_CHOOSE_PATH
+#define LN_STORY_RANDOM_URL LN_BASE_URL LN_STORY_RANDOM_PATH
+#define LN_STORY_EXIT_INQUIRY_URL LN_BASE_URL LN_STORY_EXIT_INQUIRY_PATH
+#define LN_STORY_FINISH_URL LN_BASE_URL LN_STORY_FINISH_PATH
#define LN_SIGN_SECRET "vDdXVXgPUEUM6_piUjz5AEhMvYTSFzQdPaN-ogKnSus="
/* 生成[a-zA-Z0-9]随机串 */
g_device_token = strdup("<null>");
}
/* -------------------------------------------------------------------------- */
- printf("LN Device Token: %s,len=%d\n", g_device_token, (int)strlen(g_device_token));
// 打印完整的json字符串
printf("\njson=%s\n",json_text);
if (expire && cJSON_IsNumber(expire))
return buf;
}
+/* 自适应申请HttpClient缓冲(保证header>=2048),失败则逐步扩容重试 */
+static HTTPC_RESULT ln_http_prepare_auto(HttpClientData *clientData, int header_size, int resp_size)
+{
+ if (header_size < 2048) header_size = 2048;
+ if (resp_size < 2048) resp_size = 2048;
+ HTTPC_RESULT ret = HttpClientPrepare(clientData, header_size, resp_size);
+ if (ret == HTTP_SUCCESS) return ret;
+ int tries = 0;
+ while (ret != HTTP_SUCCESS && tries < 3) {
+ header_size = header_size < 4096 ? 4096 : header_size * 2;
+ resp_size = resp_size < (16 * 1024) ? (16 * 1024) : resp_size * 2;
+ if (resp_size > (256 * 1024)) resp_size = (256 * 1024);
+ ret = HttpClientPrepare(clientData, header_size, resp_size);
+ tries++;
+ }
+ return ret;
+}
+
/* 简单 multipart/form-data 组包(单文件字段 file) */
static int ln_build_multipart_form(const char *boundary,
const char *filename,
"deviceId: %s\r\n"
"deviceToken: %s\r\n"
"Accept: text/event-stream\r\n"
- "Cache-Control: no-cache\r\n"
- "Connection: keep-alive\r\n",
+ "Cache-Control: no-cache\r\n",
device_id, device_token);
if (hdr <= 0 || hdr >= (int)sizeof(header_buf)) { free(body); return ERRCODE_FAIL; }
HttpClientSetCustomHeader(&client, header_buf);
- /* 准备缓冲区 */
- HTTPC_RESULT prep = HttpClientPrepare(&clientData, 2048, 64 * 1024);
+ /* 准备缓冲区(自适应) */
+ HTTPC_RESULT prep = ln_http_prepare_auto(&clientData, 2048, 64 * 1024);
if (prep != HTTP_SUCCESS) { free(body); return ERRCODE_FAIL; }
/* 设置POST数据与Content-Type(放在Prepare之后,避免被重置) */
/* ============================ 雷鸟语音对话流 End ============================ */
+/* ============================ 故事相关接口 Start ============================ */
+
+// 累积并解析SSE数据(补充实现)
+static void ln_sse_accumulate_and_dispatch(int cmd, const char *data, int data_len,
+ char *acc, int *acc_len, int acc_size) {
+ if (!data || data_len <= 0 || !acc || !acc_len || *acc_len >= acc_size) return;
+
+ // 累积数据
+ int copy_len = (acc_size - *acc_len - 1) < data_len ? (acc_size - *acc_len - 1) : data_len;
+ memcpy(acc + *acc_len, data, copy_len);
+ *acc_len += copy_len;
+ acc[*acc_len] = '\0';
+
+ // 分割SSE事件(按"\n\n"分割)
+ char *ptr = acc;
+ while ((ptr = strstr(ptr, "\n\n")) != NULL) {
+ int event_len = ptr - acc;
+ if (event_len > 0) {
+ // 提取data字段(去掉"date: "前缀)
+ char *data_start = strstr(acc, "data: ");
+ if (data_start) {
+ data_start += 6; // 跳过"data: "
+ int json_len = (acc + event_len) - data_start;
+ char *json = (char *)malloc(json_len + 1);
+ if (json) {
+ memcpy(json, data_start, json_len);
+ json[json_len] = '\0';
+ // 投递解析后的JSON数据
+ do_ln_http_server_recv_data(cmd, json, json_len);
+ free(json);
+ }
+ }
+ }
+ // 移动指针处理剩余数据
+ *acc_len -= (ptr - acc + 2);
+ memmove(acc, ptr + 2, *acc_len);
+ acc[*acc_len] = '\0';
+ ptr = acc;
+ }
+}
+
+/* 通用:设置SSE头(deviceId/deviceToken/Accept) */
+static int ln_set_sse_header(HttpClient *client, const char *device_id, const char *device_token)
+{
+ char header_buf[512];
+ int hdr = snprintf(header_buf, sizeof(header_buf),
+ "deviceId: %s\r\n"
+ "deviceToken: %s\r\n"
+ "Accept: text/event-stream\r\n"
+ "Cache-Control: no-cache\r\n",
+ device_id, device_token);
+ if (hdr <= 0 || hdr >= (int)sizeof(header_buf)) return -1;
+ HttpClientSetCustomHeader(client, header_buf);
+ return 0;
+}
+
+/* 故事-选择故事(SSE,multipart)*/
+static uint32_t ln_story_choose_http(const char *device_id,
+ const char *device_token,
+ const char *audio_path)
+{
+ if (!device_id || !device_token || !audio_path) {
+ printf("story choose: invalid parameters\n");
+ return ERRCODE_FAIL;
+ }
+
+ /* 读取音频文件 */
+ int audio_len = 0;
+ uint8_t *audio_buf = ln_read_file_all(audio_path, &audio_len);
+ if (!audio_buf || audio_len <= 0) {
+ printf("story choose: read audio file failed (path: %s)\n", audio_path);
+ return ERRCODE_FAIL;
+ }
+
+ /* 生成 boundary 并构建 multipart 表单数据 */
+ char boundary[64] = {0};
+ int boundary_len = snprintf(boundary, sizeof(boundary), "----LNBOUNDARY-%u",
+ (unsigned)uapi_tcxo_get_ms());
+ if (boundary_len <= 0 || boundary_len >= (int)sizeof(boundary)) {
+ printf("story choose: create boundary failed\n");
+ free(audio_buf);
+ return ERRCODE_FAIL;
+ }
+
+ char *body = NULL;
+ int body_len = 0;
+ char content_type[96] = {0};
+ if (ln_build_multipart_form(boundary, "story_request.mp3", audio_buf, audio_len,
+ &body, &body_len, content_type, sizeof(content_type)) != 0) {
+ printf("story choose: build multipart form failed\n");
+ free(audio_buf);
+ return ERRCODE_FAIL;
+ }
+ free(audio_buf); // 音频数据已复制到 body,释放原始缓冲区
+
+ /* 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);
+
+ HttpClient client = {0};
+ HttpClientData clientData = {0};
+ client.isHttp = false; // 使用 HTTPS
+ client.remotePort = 443;
+
+ /* 设置请求头(包含Content-Type,保持与Python一致) */
+ {
+ char header_buf[1024];
+ int hdr = snprintf(header_buf, sizeof(header_buf),
+ "deviceId: %s\r\n"
+ "deviceToken: %s\r\n"
+ "Accept: text/event-stream\r\n"
+ "Cache-Control: no-cache\r\n"
+ "Content-Type: %s\r\n",
+ device_id, device_token, content_type);
+ if (hdr <= 0 || hdr >= (int)sizeof(header_buf)) {
+ printf("story choose: build header failed\n");
+ free(body);
+ return ERRCODE_FAIL;
+ }
+ HttpClientSetCustomHeader(&client, header_buf);
+ }
+
+ /* 自适应准备 HTTP 缓冲区 */
+ HTTPC_RESULT prep = ln_http_prepare_auto(&clientData, 2048, 8 * 1024);
+ if (prep != HTTP_SUCCESS) {
+ printf("story choose: prepare HTTP buffer failed (code: %d)\n", prep);
+ free(body);
+ return ERRCODE_FAIL;
+ }
+
+ /* 设置 POST 数据 */
+ clientData.postBuf = body;
+ clientData.postBufLen = body_len;
+ clientData.postContentType = content_type;
+
+ /* 发送 POST 请求 */
+ HTTPC_RESULT res = HttpClientPostRequest(&client, LN_STORY_CHOOSE_URL, &clientData);
+ if (res != HTTP_SUCCESS) {
+ if (res == HTTP_EAGAIN) {
+ /* 驱动状态机直到成功或失败 */
+ while (1) {
+ HTTPC_RESULT rrp = HttpClientRecvResponse(&client, &clientData);
+ if (rrp == HTTP_SUCCESS) { break; }
+ if (rrp == HTTP_EAGAIN) { continue; }
+ printf("story choose post failed %d\n", rrp);
+ free(body);
+ HttpClientUnprepare(&clientData);
+ HttpClientClse(&client);
+ return ERRCODE_FAIL;
+ }
+ } else {
+ printf("story choose: send POST request failed (code: %d)\n", res);
+ free(body);
+ HttpClientUnprepare(&clientData);
+ HttpClientClse(&client);
+ return ERRCODE_FAIL;
+ }
+ }
+
+ /* 检查 HTTP 响应码 */
+ int http_code = HttpClientGetResponseCode(&client);
+ if (http_code != 200) {
+ printf("story choose: invalid HTTP response code (%d)\n", http_code);
+ // 新增:打印响应体内容
+ if (clientData.responseBuf && clientData.responseBufLen > 0) {
+ char *resp = (char *)malloc(clientData.responseBufLen + 1);
+ if (resp) {
+ memcpy(resp, clientData.responseBuf, clientData.responseBufLen);
+ resp[clientData.responseBufLen] = '\0';
+ printf("story choose: server response: %s\n", resp);
+ free(resp);
+ }
+ }
+ free(body);
+ HttpClientUnprepare(&clientData);
+ HttpClientClse(&client);
+ return ERRCODE_FAIL;
+ }
+
+ /* 循环接收 SSE 分块数据(带累积处理)*/
+ int loop_guard = 0;
+ char sse_acc[4096] = {0}; // SSE 数据累积缓冲区
+ int sse_acc_len = 0;
+ const int MAX_LOOP = 2000; // 约 40 秒超时(20ms * 2000)
+ while (loop_guard++ < MAX_LOOP) {
+ HTTPC_RESULT recv_res = HttpClientRecvResponse(&client, &clientData);
+ if (recv_res == HTTP_SUCCESS || recv_res == HTTP_EAGAIN) {
+ if (clientData.responseBuf && clientData.responseBufLen > 0) {
+ // 累积并分发 SSE 数据
+ ln_sse_accumulate_and_dispatch(LN_HTTP_RECV_STORY_CHOOSE,
+ clientData.responseBuf,
+ clientData.responseBufLen,
+ sse_acc, &sse_acc_len, sizeof(sse_acc));
+ HttpClientReset(&clientData); // 重置缓冲区继续接收
+ } else {
+ LOS_Msleep(20); // 无数据时短暂休眠
+ }
+ continue;
+ } else {
+ printf("story choose: SSE receive ended (code: %d)\n", recv_res);
+ break;
+ }
+ }
+
+ /* 释放资源 */
+ free(body);
+ HttpClientUnprepare(&clientData);
+ HttpClientClse(&client);
+ return ERRCODE_SUCC;
+}
+
+/* 故事-随机故事(SSE,JSON)*/
+static uint32_t ln_story_random_http(const char *device_id,
+ const char *device_token,
+ const char *story_theme /* 可为NULL */)
+{
+ if (!device_id || !device_token) {
+ printf("story random: invalid parameters\n");
+ return ERRCODE_FAIL;
+ }
+
+ /* CAT1 网络保活处理 */
+ cat1_api_add_cat1_vote();cat1_api_wakeup_cat1(1);cat1_api_keep_wakeup(1);cat1_api_disable_cat1_cmd(0);
+ LOS_Msleep(200);
+
+ HttpClient client = {0};
+ HttpClientData clientData = {0};
+ client.isHttp = false; // 使用 HTTPS
+ client.remotePort = 443;
+
+ /* 设置请求头(包含Content-Type,保持与Python一致) */
+ {
+ char header_buf[1024];
+ int hdr = snprintf(header_buf, sizeof(header_buf),
+ "deviceId: %s\r\n"
+ "deviceToken: %s\r\n"
+ "Accept: text/event-stream\r\n"
+ "Cache-Control: no-cache\r\n"
+ "Content-Type: application/json\r\n",
+ device_id, device_token);
+ if (hdr <= 0 || hdr >= (int)sizeof(header_buf)) {
+ printf("story random: build header failed\n");
+ return ERRCODE_FAIL;
+ }
+ HttpClientSetCustomHeader(&client, header_buf);
+ }
+
+ /* 自适应准备 HTTP 缓冲区 */
+ HTTPC_RESULT prep = ln_http_prepare_auto(&clientData, 2048, 8 * 1024);
+ if (prep != HTTP_SUCCESS) {
+ printf("story random: prepare HTTP buffer failed (code: %d)\n", prep);
+ return ERRCODE_FAIL;
+ }
+
+ /* 构建 JSON 请求体(增加转义处理,避免格式错误)*/
+ char json_body[256] = {0};
+ char escaped_theme[256] = {0};
+ int json_len = 0;
+
+ // 对故事主题进行JSON转义(处理双引号和反斜杠)
+ if (story_theme && story_theme[0]) {
+ int i = 0, j = 0;
+ while (story_theme[i] && j < sizeof(escaped_theme) - 1) {
+ if (story_theme[i] == '"') {
+ escaped_theme[j++] = '\\';
+ escaped_theme[j++] = '"';
+ } else if (story_theme[i] == '\\') {
+ escaped_theme[j++] = '\\';
+ escaped_theme[j++] = '\\';
+ } else {
+ escaped_theme[j++] = story_theme[i];
+ }
+ i++;
+ }
+ escaped_theme[j] = '\0';
+ json_len = snprintf(json_body, sizeof(json_body),
+ "{\"storyTheme\":\"%s\"}", escaped_theme);
+ } else {
+ json_len = snprintf(json_body, sizeof(json_body), "{}");
+ }
+ if (json_len <= 0 || json_len >= (int)sizeof(json_body)) {
+ printf("story random: build JSON body failed\n");
+ HttpClientUnprepare(&clientData);
+ return ERRCODE_FAIL;
+ }
+
+ /* 设置 POST 数据 */
+ clientData.postBuf = json_body;
+ clientData.postBufLen = json_len;
+ clientData.postContentType = (char *)"application/json";
+
+
+ /* 打印发送给服务端的请求数据(关键调试信息)*/
+ printf("story random: request details:\n");
+ printf(" URL:%s\n", LN_STORY_RANDOM_URL); // 从Python的RANDOM_STORY_URL提取
+ printf(" Headers:\n");
+ printf(" deviceId: %s\n", device_id);
+ printf(" deviceToken: %s\n", device_token);
+ printf(" Accept: text/event-stream\n");
+ printf(" Cache-Control: no-cache\n");
+ printf(" Content-Type: application/json\n");
+ printf(" Body: %s (length: %d)\n", json_body, json_len);
+
+
+ /* 发送 POST 请求 */
+ HTTPC_RESULT res = HttpClientPostRequest(&client, LN_STORY_RANDOM_URL, &clientData);
+ if (res != HTTP_SUCCESS) {
+ if (res == HTTP_EAGAIN) {
+ /* 驱动状态机直到成功或失败 */
+ while (1) {
+ HTTPC_RESULT rrp = HttpClientRecvResponse(&client, &clientData);
+ if (rrp == HTTP_SUCCESS) { break; }
+ if (rrp == HTTP_EAGAIN) { continue; }
+ printf("story random post failed %d\n", rrp);
+ HttpClientUnprepare(&clientData);
+ HttpClientClse(&client);
+ return ERRCODE_FAIL;
+ }
+ } else {
+ printf("story random: send POST request failed (code: %d)\n", res);
+ HttpClientUnprepare(&clientData);
+ HttpClientClse(&client);
+ return ERRCODE_FAIL;
+ }
+ }
+
+ /* 检查 HTTP 响应码 */
+ int http_code = HttpClientGetResponseCode(&client);
+ if (http_code != 200) {
+ printf("story random: invalid HTTP response code (%d)\n", http_code);
+ // 新增:打印响应体内容
+ if (clientData.responseBuf && clientData.responseBufLen > 0) {
+ char *resp = (char *)malloc(clientData.responseBufLen + 1);
+ if (resp) {
+ memcpy(resp, clientData.responseBuf, clientData.responseBufLen);
+ resp[clientData.responseBufLen] = '\0';
+ printf("story random: server response: %s\n", resp);
+ free(resp);
+ }
+ }
+ HttpClientUnprepare(&clientData);
+ HttpClientClse(&client);
+ return ERRCODE_FAIL;
+ }
+
+ /* 循环接收 SSE 分块数据(带累积处理)*/
+ int loop_guard = 0;
+ char sse_acc[4096] = {0}; // SSE 数据累积缓冲区
+ int sse_acc_len = 0;
+ const int MAX_LOOP = 2000; // 约 40 秒超时(20ms * 2000)
+ while (loop_guard++ < MAX_LOOP) {
+ HTTPC_RESULT recv_res = HttpClientRecvResponse(&client, &clientData);
+ if (recv_res == HTTP_SUCCESS || recv_res == HTTP_EAGAIN) {
+ if (clientData.responseBuf && clientData.responseBufLen > 0) {
+ // 累积并分发 SSE 数据
+ ln_sse_accumulate_and_dispatch(LN_HTTP_RECV_STORY_RANDOM,
+ clientData.responseBuf,
+ clientData.responseBufLen,
+ sse_acc, &sse_acc_len, sizeof(sse_acc));
+ HttpClientReset(&clientData); // 重置缓冲区继续接收
+ } else {
+ LOS_Msleep(20); // 无数据时短暂休眠
+ }
+ continue;
+ } else {
+ printf("story random: SSE receive ended (code: %d)\n", recv_res);
+ break;
+ }
+ }
+
+ /* 释放资源 */
+ HttpClientUnprepare(&clientData);
+ HttpClientClse(&client);
+ return ERRCODE_SUCC;
+}
+
+/* 故事-获取退出哄睡询问(JSON)*/
+static uint32_t ln_story_exit_inquiry_http(const char *device_id,
+ const char *device_token)
+{
+ /* CAT1 保活 */
+ cat1_api_add_cat1_vote(); cat1_api_wakeup_cat1(1); cat1_api_keep_wakeup(1); cat1_api_disable_cat1_cmd(0);
+
+ HttpClient client = (HttpClient){0}; HttpClientData clientData = (HttpClientData){0};
+ client.isHttp = false; client.remotePort = 443;
+
+ /* 普通JSON头 */
+ char header_buf[512];
+ int hdr = snprintf(header_buf, sizeof(header_buf),
+ "deviceId: %s\r\ndeviceToken: %s\r\nContent-Type: application/json\r\n",
+ device_id, device_token);
+ printf("ln_story_finish_http header_buf: %s\n", header_buf);
+ if (hdr <= 0 || hdr >= (int)sizeof(header_buf)) return ERRCODE_FAIL;
+ HttpClientSetCustomHeader(&client, header_buf);
+
+ HTTPC_RESULT prep = ln_http_prepare_auto(&clientData, 2048, 8 * 1024);
+ if (prep != HTTP_SUCCESS) return ERRCODE_FAIL;
+
+ clientData.postBuf = (char *)"{}";
+ clientData.postBufLen = 2;
+ clientData.postContentType = (char *)"application/json";
+
+ HTTPC_RESULT res = HttpClientPostRequest(&client, LN_STORY_EXIT_INQUIRY_URL, &clientData);
+ if (res != HTTP_SUCCESS) { printf("story exit inquiry post failed %d\n", res); goto end; }
+ if (HttpClientGetResponseCode(&client) != 200) { printf("story exit inquiry HTTP %d\n", HttpClientGetResponseCode(&client)); goto end; }
+
+ if (clientData.responseBuf && clientData.responseBufLen > 0)
+ {
+ // 解析响应JSON,提取audioUrl等字段
+ char *json_text = (char *)malloc(clientData.responseBufLen + 1);
+ if (json_text)
+ {
+ memcpy(json_text, clientData.responseBuf, clientData.responseBufLen);
+ json_text[clientData.responseBufLen] = '\0';
+ cJSON *root = cJSON_Parse(json_text);
+ if (root)
+ {
+ cJSON *errorCode = cJSON_GetObjectItem(root, "errorCode");
+ if (errorCode && !cJSON_IsNull(errorCode))
+ {
+ // 处理认证失败等错误
+ printf("[EXIT_INQUIRY] Error: %s\n", cJSON_Print(errorCode));
+ }
+ else
+ {
+ cJSON *data = cJSON_GetObjectItem(root, "data");
+ if (data && cJSON_IsObject(data))
+ {
+ cJSON *audioUrl = cJSON_GetObjectItem(data, "audioUrl");
+ if (audioUrl && cJSON_IsString(audioUrl))
+ {
+ printf("[EXIT_INQUIRY] Play audio: %s\n", audioUrl->valuestring);
+ printf("[EXIT_INQUIRY] 触发音频播放\n");
+ // 触发音频播放(调用播放接口)
+ // ...
+ }
+ }
+ }
+ cJSON_Delete(root);
+ }
+ free(json_text);
+ }
+ do_ln_http_server_recv_data(LN_HTTP_RECV_STORY_EXIT,
+ clientData.responseBuf,
+ (uint32_t)clientData.responseBufLen);
+ }
+
+end:
+ HttpClientUnprepare(&clientData); HttpClientClse(&client); return ERRCODE_SUCC;
+}
+
+/* 故事-确认结束哄睡模式(JSON)*/
+static uint32_t ln_story_finish_http(const char *device_id,
+ const char *device_token)
+{
+ /* CAT1 保活 */
+ cat1_api_add_cat1_vote(); cat1_api_wakeup_cat1(1); cat1_api_keep_wakeup(1); cat1_api_disable_cat1_cmd(0);
+
+ HttpClient client = (HttpClient){0}; HttpClientData clientData = (HttpClientData){0};
+ client.isHttp = false; client.remotePort = 443;
+
+ char header_buf[512]; int hdr = snprintf(header_buf, sizeof(header_buf),
+ "deviceId: %s\r\ndeviceToken: %s\r\nContent-Type: application/json\r\n",
+ device_id, device_token);
+ if (hdr <= 0 || hdr >= (int)sizeof(header_buf)) return ERRCODE_FAIL;
+ HttpClientSetCustomHeader(&client, header_buf);
+
+ HTTPC_RESULT prep = ln_http_prepare_auto(&clientData, 2048, 8 * 1024);
+ if (prep != HTTP_SUCCESS) return ERRCODE_FAIL;
+
+ clientData.postBuf = (char *)"{}"; clientData.postBufLen = 2; clientData.postContentType = (char *)"application/json";
+
+ HTTPC_RESULT res = HttpClientPostRequest(&client, LN_STORY_FINISH_URL, &clientData);
+ if (res != HTTP_SUCCESS) { printf("story finish post failed %d\n", res); goto end; }
+ if (HttpClientGetResponseCode(&client) != 200)
+ {
+ printf("story finish HTTP %d\n", HttpClientGetResponseCode(&client));
+ // 解析非200响应中的错误信息
+ if (clientData.responseBuf && clientData.responseBufLen > 0)
+ {
+ char *json_text = (char *)malloc(clientData.responseBufLen + 1);
+ if (json_text)
+ {
+ memcpy(json_text, clientData.responseBuf, clientData.responseBufLen);
+ json_text[clientData.responseBufLen] = '\0';
+ cJSON *root = cJSON_Parse(json_text);
+ if (root)
+ {
+ cJSON *errorCode = cJSON_GetObjectItem(root, "errorCode");
+ if (errorCode && cJSON_IsString(errorCode))
+ {
+ printf("[STORY_FINISH] Error: %s\n", errorCode->valuestring);
+ }
+ cJSON_Delete(root);
+ }
+ free(json_text);
+ }
+ }
+ goto end;
+ }
+
+ if (clientData.responseBuf && clientData.responseBufLen > 0) {
+ do_ln_http_server_recv_data(LN_HTTP_RECV_STORY_FINISH,
+ clientData.responseBuf,
+ (uint32_t)clientData.responseBufLen);
+ }
+
+end:
+ HttpClientUnprepare(&clientData); HttpClientClse(&client); return ERRCODE_SUCC;
+}
+
+/* ============================ 故事相关接口 End ============================ */
+
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)) {
+ 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)) {
+ 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)
+ {
+ 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)
+ {
+ ln_story_finish_http(uapi_ln_get_device_id(), uapi_ln_get_device_token());
+ }
if (mail.data != NULL)
{
printf("free(mail.data)\n");
{
continue;
}
- if (mail.cmd == LN_HTTP_SERVICE_CMD_SSE_RECV)
+ if (mail.cmd == LN_HTTP_SERVICE_CMD_SSE_RECV
+ || mail.cmd == LN_HTTP_RECV_STORY_CHOOSE
+ || mail.cmd == LN_HTTP_RECV_STORY_RANDOM
+ || mail.cmd == LN_HTTP_RECV_STORY_EXIT
+ || mail.cmd == LN_HTTP_RECV_STORY_FINISH)
{
if (mail.data && mail.len)
{
- /* 直接打印分片数据(可能包含多行 data:)*/
- printf("SSE raw len=%u\n", mail.len);
+ /* 分类打印,便于区分不同来源 */
+ const char *tag = (mail.cmd == LN_HTTP_SERVICE_CMD_SSE_RECV) ? "SPEECH_CHAT" :
+ (mail.cmd == LN_HTTP_RECV_STORY_CHOOSE) ? "STORY_CHOOSE" :
+ (mail.cmd == LN_HTTP_RECV_STORY_RANDOM) ? "STORY_RANDOM" :
+ (mail.cmd == LN_HTTP_RECV_STORY_EXIT) ? "STORY_EXIT" :
+ (mail.cmd == LN_HTTP_RECV_STORY_FINISH) ? "STORY_FINISH" : "UNKNOWN";
+ printf("[%s] SSE raw len=%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("SSE raw data=%s\n", buf);
+ printf("[%s] SSE raw data=%s\n", tag, buf);
free(buf);
}
}