From: cheng Date: Wed, 17 Sep 2025 05:56:39 +0000 (+0800) Subject: 雷鸟:添加获取是否绑定接口 X-Git-Tag: leiniao_debug_1.0.0_20250922_020716~71^2~1 X-Git-Url: http://git.snicker.com.cn/css/static/gitweb.css?a=commitdiff_plain;h=f05419b6deeb8728c3ad66b7fbf240ee59378b01;p=mirrors%2FFD230.git 雷鸟:添加获取是否绑定接口 --- diff --git a/code/sdk/zhihui/leiniao/audio_stream/audio_stream_player.cpp b/code/sdk/zhihui/leiniao/audio_stream/audio_stream_player.cpp index 690e0c36b..5b6b6a95e 100644 --- a/code/sdk/zhihui/leiniao/audio_stream/audio_stream_player.cpp +++ b/code/sdk/zhihui/leiniao/audio_stream/audio_stream_player.cpp @@ -677,6 +677,25 @@ uint32_t ln_audio_player_init(void) return ERRCODE_SUCC; } +uint32_t ln_audio_player_pause(void) +{ + if (g_ln_audio_player == nullptr) { + return ERRCODE_SUCC; + } + (void)AudioStreamPlayerPause(g_ln_audio_player); + AudioStreamPlayerFlush(g_ln_audio_player); + return ERRCODE_SUCC; +} + +uint32_t ln_audio_player_resume(void) +{ + if (g_ln_audio_player == nullptr) { + return ERRCODE_SUCC; + } + (void)AudioStreamPlayerResume(g_ln_audio_player); + return ERRCODE_SUCC; +} + int32_t ln_audio_player_write(const uint8_t* data, uint32_t size) { if (g_ln_audio_player == nullptr) { diff --git a/code/sdk/zhihui/leiniao/audio_stream/audio_stream_player.h b/code/sdk/zhihui/leiniao/audio_stream/audio_stream_player.h index aa84d5208..2da912191 100644 --- a/code/sdk/zhihui/leiniao/audio_stream/audio_stream_player.h +++ b/code/sdk/zhihui/leiniao/audio_stream/audio_stream_player.h @@ -150,6 +150,8 @@ int32_t AudioStreamPlayerDestroy(AudioStreamPlayerHandle handle); uint32_t ln_audio_player_init(void); int32_t ln_audio_player_write(const uint8_t* data, uint32_t size); int32_t ln_audio_player_get_stats(AudioStreamStats* stats); +uint32_t ln_audio_player_pause(void); +uint32_t ln_audio_player_resume(void); #ifdef __cplusplus } diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c index 53aa2c4a9..a69ff8386 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c @@ -40,6 +40,9 @@ char g_ln_last_package_url[512] = {0}; // 最近一次查询到的 OTA 包 URL char g_ln_last_target_version[64] = {0}; // 最近一次查询到的 OTA 包目标版本 char g_ln_last_package_md5[65] = {0}; // 最近一次查询到的 OTA 包 MD5 int g_ln_last_package_size = 0; // 最近一次查询到的 OTA 包大小(字节) +static int g_ln_audio_download_cancel = 0; /* 0=正常, 1=取消 */ +int g_ln_is_device_bound = -1; /* 设备绑定状态 */ +char g_ln_device_user_id[64] = {0}; // 设备绑定用户ID /* 获取设备id: 设备唯一标识 */ char *uapi_ln_get_device_id(void) @@ -133,6 +136,32 @@ const char *uapi_ln_get_story_choose_audio_path(void) { return "/user/leiniao/story_choose_audio.mp3"; } + +void uapi_ln_audio_download_is_cancel(int status) +{ + g_ln_audio_download_cancel = status; + if(g_ln_audio_download_cancel) + { + ln_audio_player_pause(); + } + else + { + ln_audio_player_resume(); + } +} + +/* 获取是否绑定用户 */ +uint32_t uapi_ln_is_device_bound(void) +{ + return g_ln_is_device_bound; +} + +/* 获取设备绑定用户ID */ +const char* uapi_ln_get_user_id(void) +{ + return g_ln_device_user_id; +} + /* 自适应申请HttpClient缓冲(保证header>=2048),失败则逐步扩容重试 */ HTTPC_RESULT ln_http_prepare_auto(HttpClientData *clientData, int header_size, int resp_size) { @@ -583,9 +612,13 @@ static uint32_t ln_download_mp3_file_advanced(const char *audio_url, const char return ERRCODE_FAIL; } - // 接收响应数据 + // 接收响应数据(支持取消) do { + if (g_ln_audio_download_cancel) { + printf("[SSE] download canceled by user\n"); + break; + } HTTPC_RESULT recv_res = HttpClientRecvResponse(&client, &client_data); if (recv_res == HTTP_SUCCESS || recv_res == HTTP_EAGAIN) { @@ -848,6 +881,11 @@ uint32_t ln_parse_file_and_process_data(const char *file_path, int interface_typ while (fgets(line, sizeof(line), fp)) { + if (g_ln_audio_download_cancel) { + printf("[SSE] download canceled by user\n"); + break; + } + line_count++; // 去除行尾的换行符 @@ -965,8 +1003,19 @@ static void ln_http_server_send_task(void const *arg) } 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()); + LnDeviceBindStatus st = LN_DEVICE_BIND_STATUS_ERROR; + (void)uapi_ln_device_get_user_id(&st, g_ln_device_user_id, sizeof(g_ln_device_user_id)); + /* 将内部状态映射为上层更直观的 1/0/ERRCODE_FAIL */ + if (st == LN_DEVICE_BIND_STATUS_BOUND) { + g_ln_is_device_bound = 1; + } else if (st == LN_DEVICE_BIND_STATUS_UNBOUND) { + g_ln_is_device_bound = 0; + } else { + g_ln_is_device_bound = ERRCODE_FAIL; + g_ln_device_user_id[0] = '\0'; + } + printf("LN_HTTP_SERVICE_CMD_GET_USER_ID:获取设备绑定用户ID: %s\n", uapi_ln_get_user_id()); + printf("LN_HTTP_SERVICE_CMD_GET_USER_ID:获取设备绑定用户ID状态: %d\n", uapi_ln_is_device_bound()); } else if (mail.cmd == LN_HTTP_SERVICE_CMD_OTA_GET_TASK) { @@ -1028,30 +1077,32 @@ static void ln_http_server_send_task(void const *arg) 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 + // #ifdef BOARD_N9 + // if (ln_story_player_simple_pause()) + // { + // printf("Playback paused successfully\n"); + // } + // else + // { + // printf("Failed to pause playback\n"); + // } + // #endif + uapi_ln_audio_download_is_cancel(1); } 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 + // #ifdef BOARD_N9 + // if (ln_story_player_simple_resume()) + // { + // printf("Playback resumed successfully\n"); + // } + // else + // { + // printf("Failed to resume playback\n"); + // } + // #endif + uapi_ln_audio_download_is_cancel(0); } if (mail.data != NULL) { diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h index 6c2dfe054..965f7b857 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.h @@ -124,6 +124,15 @@ typedef struct { char md5[65]; /* MD5(来自任务),仅状态为COMPLETED时有效 */ } OtaDownloadMsg; +/* 设备绑定状态 */ +typedef enum +{ + LN_DEVICE_BIND_STATUS_UNBOUND = 0, /* 未绑定,data 为 null */ + LN_DEVICE_BIND_STATUS_BOUND = 1, /* 已绑定,返回有效用户ID */ + LN_DEVICE_BIND_STATUS_AUTH_FAILURE = 2, /* 认证失败(Token 无效或过期)*/ + LN_DEVICE_BIND_STATUS_ERROR = 3 /* 其他错误(网络/解析等)*/ +} LnDeviceBindStatus; + /* 初始化 LN HTTP 服务 */ errcode_t uapi_ln_http_server_init(void); /* 通用发送接口:向 LN HTTP 发送队列投递消息 */ @@ -151,6 +160,12 @@ const char *uapi_ln_ota_get_saved_path(void); const char *uapi_ln_get_speechchat_audio_path(void); /* 获取选择故事录音音频路径 */ const char *uapi_ln_get_story_choose_audio_path(void); +/* 音频下载/播放控制 */ +void uapi_ln_audio_download_is_cancel(int status); +/* 获取是否绑定用户 */ +uint32_t uapi_ln_is_device_bound(void); +/* 获取设备绑定用户ID */ +const char* uapi_ln_get_user_id(void); /* ============================== 共享全局状态(跨文件) ============================== */ extern char *g_device_token; @@ -172,6 +187,7 @@ uint32_t ln_token_load_json(char **token_out, uint64_t *expire_timestamp_out); uint32_t ln_token_is_expired(int *expired_out); /* 主动刷新设备Token(调用HTTP接口),并落盘保存 */ uint32_t uapi_ln_refresh_device_token(void); +uint32_t uapi_ln_device_get_user_id(LnDeviceBindStatus *out_status, char *out_user_id, uint32_t out_user_id_len); /* ============================== 各接口函数声明 ============================== */ uint32_t ln_get_device_token_http(const char *device_id, diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api_device_info.c b/code/sdk/zhihui/leiniao/imsl_ln/ln_api_device_info.c index 4d8e23322..fdbe99d5c 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api_device_info.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api_device_info.c @@ -1,5 +1,7 @@ #include "ln_api.h" #include +#include +#include // 获取设备角色信息 uint32_t ln_device_get_character_http(const char *device_id, @@ -140,3 +142,118 @@ end: HttpClientClse(&client); return ERRCODE_SUCC; } + +/* + * 简单实用的同步接口:获取设备绑定用户ID + * - LN_DEVICE_BIND_STATUS_BOUND: 已绑定,out_user_id 返回用户ID + * - LN_DEVICE_BIND_STATUS_UNBOUND: 未绑定 + * - LN_DEVICE_BIND_STATUS_AUTH_FAILURE: 认证失败 + * - LN_DEVICE_BIND_STATUS_ERROR: 其他错误 + */ +uint32_t uapi_ln_device_get_user_id(LnDeviceBindStatus *out_status, char *out_user_id, uint32_t out_user_id_len) +{ + if (out_status == NULL || out_user_id == NULL || out_user_id_len == 0) + { + return ERRCODE_FAIL; + } + *out_status = LN_DEVICE_BIND_STATUS_ERROR; + out_user_id[0] = '\0'; + + const char *device_id = uapi_ln_get_device_id(); + const char *token = uapi_ln_get_device_token(); + if (!device_id || !token) + { + *out_status = LN_DEVICE_BIND_STATUS_AUTH_FAILURE; + return ERRCODE_FAIL; + } + +/* 发起请求 */ +#ifdef SUPPORT_CAT1_SERVICE + cat1_api_add_cat1_vote(); + cat1_api_wakeup_cat1(1); + cat1_api_keep_wakeup(1); + cat1_api_disable_cat1_cmd(1); + LOS_Msleep(200); +#endif + + 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, 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, LN_CLIENT_PREPARE_SIZE); + if (prep != HTTP_SUCCESS) + { + return ERRCODE_FAIL; + } + + HTTPC_RESULT res = HttpClientGetRequest(&client, LN_DEVICE_GET_USER_ID_URL, &clientData); + if (res != HTTP_SUCCESS) + { + HttpClientUnprepare(&clientData); + HttpClientClse(&client); + return ERRCODE_FAIL; + } + + int code = HttpClientGetResponseCode(&client); + if (code == 200) + { + /* 成功响应:解析JSON,判断 data 是否为 null 或字符串 */ + if (clientData.responseBuf && clientData.responseBufLen > 0) + { + int real_len = clientData.responseContentLen > 0 ? clientData.responseContentLen : clientData.responseBufLen; + char *buf = (char *)malloc((size_t)real_len + 1); + if (buf) + { + memcpy(buf, clientData.responseBuf, (size_t)real_len); + buf[real_len] = '\0'; + cJSON *root = cJSON_Parse(buf); + if (root) + { + cJSON *data = cJSON_GetObjectItem(root, "data"); + if (data == NULL || cJSON_IsNull(data)) + { + *out_status = LN_DEVICE_BIND_STATUS_UNBOUND; + } + else if (cJSON_IsString(data) && data->valuestring && data->valuestring[0]) + { + *out_status = LN_DEVICE_BIND_STATUS_BOUND; + strncpy(out_user_id, data->valuestring, out_user_id_len - 1); + out_user_id[out_user_id_len - 1] = '\0'; + } + else + { + *out_status = LN_DEVICE_BIND_STATUS_ERROR; + } + cJSON_Delete(root); + } + free(buf); + } + } + } + else if (code == 401) + { + /* 认证失败 */ + *out_status = LN_DEVICE_BIND_STATUS_AUTH_FAILURE; + } + else + { + *out_status = LN_DEVICE_BIND_STATUS_ERROR; + } + + HttpClientUnprepare(&clientData); + HttpClientClse(&client); + return ERRCODE_SUCC; +} diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api_token.c b/code/sdk/zhihui/leiniao/imsl_ln/ln_api_token.c index 1ba108096..1c6fa8d23 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api_token.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api_token.c @@ -55,7 +55,7 @@ static void ln_mkdir_p(const char *path) WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_mkdir_p: path is NULL"); return; } - (void)mkdir(LN_TOKEN_DIR, 0755); + (void)mkdir(path, 0755); } /* 保存设备Token到本地 */ @@ -66,6 +66,7 @@ static uint32_t ln_token_save_json(const char *token, uint64_t expire_timestamp) WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_token_save_json: token is NULL"); return ERRCODE_FAIL; } + ln_mkdir_p(LN_DATA_PATH); ln_mkdir_p(LN_TOKEN_DIR); /* 生成create_time字符串 */ @@ -86,7 +87,7 @@ static uint32_t ln_token_save_json(const char *token, uint64_t expire_timestamp) if (text == NULL) return ERRCODE_FAIL; - FILE *fp = fopen(LN_TOKEN_FILE, "wb"); + FILE *fp = fopen(LN_TOKEN_FILE, "wb+"); if (!fp) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ln_token_save_json: fopen failed");