From 1e0ccc089f8b036da994ec813ec99d76bcd7d6bd Mon Sep 17 00:00:00 2001 From: luozheng <1732036298@qq.com> Date: Wed, 3 Sep 2025 16:24:52 +0800 Subject: [PATCH] =?utf8?q?=E9=9B=B7=E9=B8=9F=E6=B7=BB=E5=8A=A0"=E8=AE=BE?= =?utf8?q?=E5=A4=87=E4=BF=A1=E6=81=AF=E6=8E=A5=E5=8F=A3"at=E6=B5=8B?= =?utf8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../zhihui/leiniao/imsl_ln/leiniao_api_at.c | 32 +++ code/sdk/zhihui/leiniao/imsl_ln/ln_api.c | 191 +++++++++++++++--- code/sdk/zhihui/leiniao/imsl_ln/ln_api.h | 9 +- 3 files changed, 206 insertions(+), 26 deletions(-) diff --git a/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c b/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c index 09bfcec9e..f46655b04 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c @@ -516,6 +516,17 @@ static uint32_t ln_get_device_token_at(uint8_t *para, uint32_t paraLen, char *st return ERRCODE_SUCC; } +/* AT^LN_CLEAR_TOKEN */ +//清除设备Token +static uint32_t ln_clear_device_token_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd) +{ + VAD_UNUSED(para); + VAD_UNUSED(paraLen); + VAD_UNUSED(strCommonCmd); + uapi_ln_clear_device_token(); + return ERRCODE_SUCC; +} + // AT^LN_SPEECH_CHAT=deviceId,deviceToken[,audioPath] static uint32_t ln_speech_chat_stream_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd) { @@ -586,6 +597,24 @@ static uint32_t ln_story_finish_at(uint8_t *para, uint32_t paraLen, char *strCom return ERRCODE_SUCC; } +/* 设备-获取角色信息:AT^LN_DEV_CHARACTER */ +static uint32_t ln_device_get_character_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd) +{ + VAD_UNUSED(para); VAD_UNUSED(paraLen); VAD_UNUSED(strCommonCmd); + printf("[LN][DEVICE_GET_CHARACTER]\n"); + do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_GET_CHARACTER, NULL, 0); + return ERRCODE_SUCC; +} + +/* 设备-获取绑定用户ID:AT^LN_DEV_USERID */ +static uint32_t ln_device_get_userid_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd) +{ + VAD_UNUSED(para); VAD_UNUSED(paraLen); VAD_UNUSED(strCommonCmd); + printf("[LN][DEVICE_GET_USER_ID]\n"); + do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_GET_USER_ID, NULL, 0); + return ERRCODE_SUCC; +} + static const at_cmd_table_t g_ln_api_cmd[] = { /* ----------------------------------- VAD ---------------------------------- */ @@ -599,12 +628,15 @@ static const at_cmd_table_t g_ln_api_cmd[] = { {(char *)"AT^VAD_HELP", vad_help, (char *)"显示帮助信息"}, /* ---------------------------------- 雷鸟API --------------------------------- */ {(char *)"AT^LN_GET_TOKEN", ln_get_device_token_at, (char *)"获取雷鸟设备Token: AT^LN_GET_TOKEN[=deviceId,deviceIccid,deviceModel,deviceVersion]"}, + {(char *)"AT^LN_CLEAR_TOKEN", ln_clear_device_token_at, (char *)"清除雷鸟设备Token: AT^LN_CLEAR_TOKEN"}, {(char *)"AT^LN_SPEECH_CHAT", ln_speech_chat_stream_at, (char *)"语音对话流: AT^LN_SPEECH_CHAT"}, /* 故事相关 AT 指令 */ {(char *)"AT^LN_STORY_CHOOSE", ln_story_choose_at, (char *)"选择故事(SSE): AT^LN_STORY_CHOOSE=user/story_request.mp3"}, {(char *)"AT^LN_STORY_RANDOM", ln_story_random_at, (char *)"随机故事(SSE): AT^LN_STORY_RANDOM=童话故事"}, {(char *)"AT^LN_STORY_EXIT", ln_story_exit_inquiry_at, (char *)"获取退出哄睡询问(JSON): AT^LN_STORY_EXIT"}, {(char *)"AT^LN_STORY_FINISH", ln_story_finish_at, (char *)"确认结束哄睡(JSON): AT^LN_STORY_FINISH"}, + {(char *)"AT^LN_DEV_CHARACTER", ln_device_get_character_at, (char *)"获取设备角色信息(JSON,GET): AT^LN_DEV_CHARACTER"}, + {(char *)"AT^LN_DEV_USERID", ln_device_get_userid_at, (char *)"获取设备绑定用户ID(JSON,GET): AT^LN_DEV_USERID"}, }; at_cmd_table_t *get_leiniao_api_cmd_table(uint32_t *cmd_count) diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c index 48e1d7ad9..0f7f76347 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c @@ -18,7 +18,7 @@ static unsigned long g_ln_send_queue = 0xFFFFFFFF; static unsigned long g_ln_recv_queue = 0xFFFFFFFF; static char *g_device_id = NULL; -static char *g_device_token = NULL; +static char *g_device_token = NULL;//设备token,服务器获取 static char *g_device_iccid = NULL; static char *g_device_model = NULL; static char *g_device_version = NULL; @@ -57,6 +57,16 @@ char *uapi_ln_get_device_token(void) } return g_device_token; } +/* 清除设备token */ +void uapi_ln_clear_device_token(void) +{ + if(g_device_token != NULL) + { + printf("clear device token\n"); + free(g_device_token); + g_device_token = NULL; + } +} /* ============================== 雷鸟设备Token获取 ============================== */ @@ -71,10 +81,14 @@ char *uapi_ln_get_device_token(void) #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_DEVICE_GET_CHARACTER_PATH "/v1/device/getCharacter" +#define LN_DEVICE_GET_USER_ID_PATH "/v1/device/getUserId" #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_DEVICE_GET_CHARACTER_URL LN_BASE_URL LN_DEVICE_GET_CHARACTER_PATH +#define LN_DEVICE_GET_USER_ID_URL LN_BASE_URL LN_DEVICE_GET_USER_ID_PATH #define LN_SIGN_SECRET "vDdXVXgPUEUM6_piUjz5AEhMvYTSFzQdPaN-ogKnSus=" /* 生成[a-zA-Z0-9]随机串 */ @@ -525,21 +539,6 @@ static void ln_sse_accumulate_and_dispatch(int cmd, const char *data, int data_l } } -/* 通用:设置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, @@ -864,6 +863,7 @@ static uint32_t ln_story_random_http(const char *device_id, static uint32_t ln_story_exit_inquiry_http(const char *device_id, const char *device_token) { + if (!device_id || !device_token) 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); @@ -926,9 +926,12 @@ static uint32_t ln_story_exit_inquiry_http(const char *device_id, } free(json_text); } - do_ln_http_server_recv_data(LN_HTTP_RECV_STORY_EXIT, - clientData.responseBuf, - (uint32_t)clientData.responseBufLen); + // clientData.responseBufLen 表示的是缓冲区的总大小(提前分配的内存大小),而非实际有效的响应数据长度。 + // 实际有效的响应数据长度应使用 clientData.responseContentLen(HTTP 响应体的真实长度)。 + // 当 responseBufLen 大于 responseContentLen 时,responseBuf 中从 responseContentLen 到 responseBufLen 的部分是未使用的内存(可能残留之前的垃圾数据), + // 这些数据被当作有效内容传递并打印,导致乱码。 + int real_len = clientData.responseContentLen > 0 ? clientData.responseContentLen : clientData.responseBufLen; + do_ln_http_server_recv_data(LN_HTTP_RECV_STORY_EXIT,clientData.responseBuf,(uint32_t)real_len); } end: @@ -939,6 +942,7 @@ end: static uint32_t ln_story_finish_http(const char *device_id, const char *device_token) { + if (!device_id || !device_token) 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); @@ -985,10 +989,10 @@ static uint32_t ln_story_finish_http(const char *device_id, 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); + if (clientData.responseBuf && clientData.responseBufLen > 0) + { + int real_len = clientData.responseContentLen > 0 ? clientData.responseContentLen : clientData.responseBufLen; + do_ln_http_server_recv_data(LN_HTTP_RECV_STORY_FINISH,clientData.responseBuf,(uint32_t)real_len); } end: @@ -998,6 +1002,124 @@ end: /* ============================ 故事相关接口 End ============================ */ +/* ============================ 设备信息接口 start ============================ */ +/* 设备-获取角色信息(GET, JSON)*/ +static uint32_t ln_device_get_character_http(const char *device_id, + const char *device_token) +{ + if (!device_id || !device_token) 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); + + 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\n""deviceToken: %s\r\n""Content-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; + + HTTPC_RESULT res = HttpClientGetRequest(&client, LN_DEVICE_GET_CHARACTER_URL, &clientData); + if (res != HTTP_SUCCESS) { printf("device getCharacter get failed %d\n", res); goto end; } + if (HttpClientGetResponseCode(&client) != 200) + { + printf("device getCharacter 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) { + int real_len = clientData.responseContentLen > 0 ? clientData.responseContentLen : clientData.responseBufLen; + do_ln_http_server_recv_data(LN_HTTP_RECV_DEVICE_CHARACTER, clientData.responseBuf, (uint32_t)real_len); + } + +end: + HttpClientUnprepare(&clientData); HttpClientClse(&client); return ERRCODE_SUCC; +} + +/* 设备-获取绑定用户ID(GET, JSON)*/ +static uint32_t ln_device_get_user_id_http(const char *device_id, + const char *device_token) +{ + if (!device_id || !device_token) 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); + + 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\n""deviceToken: %s\r\n""Content-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; + + HTTPC_RESULT res = HttpClientGetRequest(&client, LN_DEVICE_GET_USER_ID_URL, &clientData); + if (res != HTTP_SUCCESS) { printf("device getUserId get failed %d\n", res); goto end; } + if (HttpClientGetResponseCode(&client) != 200) { + printf("device getUserId 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) { + int real_len = clientData.responseContentLen > 0 ? clientData.responseContentLen : clientData.responseBufLen; + do_ln_http_server_recv_data(LN_HTTP_RECV_DEVICE_USER_ID, clientData.responseBuf, (uint32_t)real_len); + } + +end: + HttpClientUnprepare(&clientData); HttpClientClse(&client); return ERRCODE_SUCC; +} +/* ============================ 设备信息接口 End ============================ */ @@ -1031,6 +1153,7 @@ static void ln_http_server_send_task(void const *arg) { 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); @@ -1039,6 +1162,7 @@ static void ln_http_server_send_task(void const *arg) 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); } @@ -1046,18 +1170,31 @@ static void ln_http_server_send_task(void const *arg) 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\n"); + ln_device_get_user_id_http(uapi_ln_get_device_id(), uapi_ln_get_device_token()); + } if (mail.data != NULL) { printf("free(mail.data)\n"); @@ -1086,7 +1223,9 @@ static void ln_http_server_recv_task(void const *arg) || 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) + || mail.cmd == LN_HTTP_RECV_STORY_FINISH + || mail.cmd == LN_HTTP_RECV_DEVICE_CHARACTER + || mail.cmd == LN_HTTP_RECV_DEVICE_USER_ID) { if (mail.data && mail.len) { @@ -1095,7 +1234,9 @@ static void ln_http_server_recv_task(void const *arg) (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"; + (mail.cmd == LN_HTTP_RECV_STORY_FINISH) ? "STORY_FINISH" : + (mail.cmd == LN_HTTP_RECV_DEVICE_CHARACTER) ? "DEVICE_CHARACTER" : + (mail.cmd == LN_HTTP_RECV_DEVICE_USER_ID) ? "DEVICE_USER_ID" : "UNKNOWN"; printf("[%s] SSE raw len=%u\n", tag, mail.len); /* 确保可打印:追加\0 */ char *buf = (char *)malloc(mail.len + 1); diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h index 53b7c5c68..9cd6a8da2 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h @@ -29,6 +29,12 @@ typedef struct #define LN_HTTP_RECV_STORY_RANDOM 0x21 /* 故事-随机故事 接收 */ #define LN_HTTP_RECV_STORY_EXIT 0x22 /* 故事-退出哄睡询问 接收 */ #define LN_HTTP_RECV_STORY_FINISH 0x23 /* 故事-确认结束哄睡模式 接收 */ +/* 设备信息相关命令 */ +#define LN_HTTP_SERVICE_CMD_GET_CHARACTER 0x30 /* 获取设备角色信息(JSON, GET)*/ +#define LN_HTTP_SERVICE_CMD_GET_USER_ID 0x31 /* 获取设备绑定用户ID(JSON, GET)*/ +/* 设备信息相关接收命令 */ +#define LN_HTTP_RECV_DEVICE_CHARACTER 0x40 /* 设备角色信息 接收 */ +#define LN_HTTP_RECV_DEVICE_USER_ID 0x41 /* 设备绑定用户ID 接收 */ typedef struct { @@ -74,7 +80,8 @@ char *uapi_ln_get_device_model(void); char *uapi_ln_get_device_version(void); /* 获取设备token */ char *uapi_ln_get_device_token(void); - +/* 清除设备token */ +void uapi_ln_clear_device_token(void); #ifdef __cplusplus } #endif -- 2.17.1