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)
{
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 ---------------------------------- */
{(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)
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;
}
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获取 ============================== */
#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]随机串 */
}
}
-/* 通用:设置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,
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);
}
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:
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);
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:
/* ============================ 故事相关接口 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 ============================ */
{
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\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");
|| 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)
{
(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);