添加屏保切换at指令待ui验证 2436/1
authorluozheng <1732036298@qq.com>
Mon, 29 Sep 2025 03:16:41 +0000 (11:16 +0800)
committerluozheng <1732036298@qq.com>
Mon, 29 Sep 2025 03:16:41 +0000 (11:16 +0800)
code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c
code/sdk/zhihui/leiniao/imsl_ln/ln_api.h
code/sdk/zhihui/leiniao/imsl_ln/ln_api_device_info.c

index dfa8798..3cbb8da 100644 (file)
@@ -1770,6 +1770,17 @@ static uint32_t ln_api_error_at(uint8_t *para, uint32_t paraLen, char *strCommon
     return ERRCODE_SUCC;
 }
 
+static uint32_t ln_notify_screen_image_at(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    VAD_UNUSED(para);
+    VAD_UNUSED(paraLen);
+    VAD_UNUSED(strCommonCmd);
+    push_screen_image_download_success_notification();
+    printf("+LN_NOTIFY_SCREEN_IMAGE: OK\n");
+    printf("[LN][NOTIFY_SCREEN_IMAGE] ok\n");
+    return ERRCODE_SUCC;
+}
+
 static const at_cmd_table_t g_ln_api_cmd[] = {
     /* ----------------------------------- VAD ---------------------------------- */
     {(char *)"AT^VAD_INIT", vad_init, (char *)"初始化 VAD"},
@@ -1833,6 +1844,8 @@ static const at_cmd_table_t g_ln_api_cmd[] = {
     {(char *)"AT^LN_SWITCH_EXPRESSION", ln_switch_expression_at, (char *)"切换表情视频: AT^LN_SWITCH_EXPRESSION=<video_path>"},
     {(char *)"AT^LN_API_ERROR", ln_api_error_at, (char *)"推送协议错误: AT^LN_API_ERROR[=message]"},
     {(char *)"AT^LN_NOTIFY_BIND_AND_UNBIND", ln_notify_bind_and_unbind_at, (char *)"通知用户绑定或解绑: AT^LN_NOTIFY_BIND_AND_UNBIND=1/0"},
+    {(char *)"AT^LN_NOTIFY_SCREEN_IMAGE", ln_notify_screen_image_at, (char *)"通知切换屏保: AT^LN_NOTIFY_SCREEN_IMAGE"},
+    
     
     /* 内存查看相关AT命令 */
     {(char *)"AT^LN_MEMORY_INFO", ln_memory_info_at, (char *)"查看系统内存信息: AT^LN_MEMORY_INFO"},
index d3756df..d229e28 100644 (file)
@@ -230,6 +230,7 @@ void ln_read_character_config(void);
 
 // 解析设备角色配置
 void ln_parse_character_config(const char *json_buf, int json_len);
+void ln_parse_character_config_local(const char *json_buf, int json_len);
 /* 解析哄睡模式开始 */
 void ln_parse_sleep_mode_start(const char *json_str, int json_len);
 /* 解析哄睡模式结束 */
index fd05897..38e1360 100644 (file)
@@ -145,8 +145,8 @@ void ln_parse_character_config(const char *json_buf, int json_len)
     cJSON *message = cJSON_GetObjectItem(root, "message");
     if (errorCode && !cJSON_IsNull(errorCode))
     {
-        printf("[DEVICE_CHARACTER] server error: %s\n",cJSON_IsString(errorCode) ? errorCode->valuestring : "unknown");
-        printf("[DEVICE_CHARACTER] server message: %s\n",cJSON_IsString(message) ? message->valuestring : "unknown");
+        printf("[DEVICE_CHARACTER] server error: %s\n", cJSON_IsString(errorCode) ? errorCode->valuestring : "unknown");
+        printf("[DEVICE_CHARACTER] server message: %s\n", cJSON_IsString(message) ? message->valuestring : "unknown");
         // 推送协议错误通知到UI
         push_api_error_notification(cJSON_IsString(message) ? message->valuestring : "unknown");
         cJSON_Delete(root);
@@ -172,7 +172,6 @@ void ln_parse_character_config(const char *json_buf, int json_len)
     ln_assign_dup(&g_ln_character_config.character_name,
                   (cname && cJSON_IsString(cname)) ? cname->valuestring : "");
 
-
     // "data": {
     // "characterId": "char_001",
     // "characterName": "小艾",
@@ -242,18 +241,19 @@ void ln_parse_character_config(const char *json_buf, int json_len)
     printf("  avatar_screen_image_as_emoji: %d\n", g_ln_character_config.avatar_screen_image_as_emoji);
 
     // 如果屏保图片不为空,则保存到本地
-    if (g_ln_character_config.avatar_screen_image && strlen(g_ln_character_config.avatar_screen_image) > 0 
-        && g_ln_character_config.avatar_screen_image_as_emoji == 1)
+    if (g_ln_character_config.avatar_screen_image && strlen(g_ln_character_config.avatar_screen_image) > 0 && g_ln_character_config.avatar_screen_image_as_emoji == 1)
     {
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DEVICE_CHARACTER] 屏保图片不为空,下载屏保图片");
         // 下载屏保图片,eg:"https://example.com/new_avatar.bin"
         ln_download_file_req_t req;
         memset(&req, 0, sizeof(req));
         /* 分配与拷贝,发送方分配,接收方负责释放 */
-        if (g_ln_character_config.avatar_screen_image) {
+        if (g_ln_character_config.avatar_screen_image)
+        {
             size_t ulen = strlen(g_ln_character_config.avatar_screen_image);
             req.url = (char *)malloc(ulen + 1);
-            if (req.url) {
+            if (req.url)
+            {
                 memcpy(req.url, g_ln_character_config.avatar_screen_image, ulen + 1);
             }
         }
@@ -261,12 +261,12 @@ void ln_parse_character_config(const char *json_buf, int json_len)
             const char *save = LN_DEVICE_SCREEN_IMAGE_FILE;
             size_t slen = strlen(save);
             req.save_path = (char *)malloc(slen + 1);
-            if (req.save_path) {
+            if (req.save_path)
+            {
                 memcpy(req.save_path, save, slen + 1);
             }
         }
         do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_DOWNLOAD_SCREEN_IMAGE, (char *)&req, sizeof(req));
-
     }
 
     /* 推送角色配置更改通知 */
@@ -283,6 +283,180 @@ void ln_parse_character_config(const char *json_buf, int json_len)
     ln_clear_character_config();
 }
 
+// 本地解析
+void ln_parse_character_config_local(const char *json_buf, int json_len)
+{
+    if (!json_buf || json_len <= 0)
+    {
+        printf("[DEVICE_CHARACTER] invalid json input\n");
+        return;
+    }
+
+    char *text = (char *)malloc((size_t)json_len + 1);
+    if (!text)
+        return;
+    memcpy(text, json_buf, (size_t)json_len);
+    text[json_len] = '\0';
+
+    cJSON *root = cJSON_Parse(text);
+    if (!root)
+    {
+        printf("[DEVICE_CHARACTER] json parse failed\n");
+        free(text);
+        return;
+    }
+
+    cJSON *errorCode = cJSON_GetObjectItem(root, "errorCode");
+    cJSON *message = cJSON_GetObjectItem(root, "message");
+    if (errorCode && !cJSON_IsNull(errorCode))
+    {
+        printf("[DEVICE_CHARACTER] server error: %s\n", cJSON_IsString(errorCode) ? errorCode->valuestring : "unknown");
+        printf("[DEVICE_CHARACTER] server message: %s\n", cJSON_IsString(message) ? message->valuestring : "unknown");
+        // 推送协议错误通知到UI
+        push_api_error_notification(cJSON_IsString(message) ? message->valuestring : "unknown");
+        cJSON_Delete(root);
+        free(text);
+        return;
+    }
+
+    cJSON *data = cJSON_GetObjectItem(root, "data");
+    if (!data || !cJSON_IsObject(data))
+    {
+        printf("[DEVICE_CHARACTER] no data object\n");
+        cJSON_Delete(root);
+        free(text);
+        return;
+    }
+
+    /* 基础字段 */
+    cJSON *cid = cJSON_GetObjectItem(data, "characterId");
+    cJSON *cname = cJSON_GetObjectItem(data, "characterName");
+    ln_assign_dup(&g_ln_character_config.character_id,
+                  (cid && cJSON_IsString(cid)) ? cid->valuestring : "");
+
+    ln_assign_dup(&g_ln_character_config.character_name,
+                  (cname && cJSON_IsString(cname)) ? cname->valuestring : "");
+
+    // "data": {
+    // "characterId": "char_001",
+    // "characterName": "小艾",
+    // "characterAvatar": {
+    //   "eyesShape": "upturned-eyes",
+    //   "hairColor": "blue",
+    //   "eyesColor": "green",
+    //   "hairStyle": "side-parted-comma",
+    //   "deviceScreen": "https://example.com/new_avatar.bin",
+    //   "screenImageAsEmoji": true
+    // }
+
+    /* 头像配置 */
+    cJSON *avatar = cJSON_GetObjectItem(data, "characterAvatar");
+    if (avatar && cJSON_IsObject(avatar))
+    {
+        cJSON *hairColor = cJSON_GetObjectItem(avatar, "hairColor");
+        cJSON *eyesColor = cJSON_GetObjectItem(avatar, "eyesColor");
+        cJSON *hairStyle = cJSON_GetObjectItem(avatar, "hairStyle");
+        cJSON *eyesShape = cJSON_GetObjectItem(avatar, "eyesShape");
+        cJSON *deviceScreen = cJSON_GetObjectItem(avatar, "deviceScreen");
+        cJSON *deviceScreenAsEmoji = cJSON_GetObjectItem(avatar, "screenImageAsEmoji");
+
+        ln_assign_dup(&g_ln_character_config.avatar_hair_color,
+                      (hairColor && cJSON_IsString(hairColor)) ? hairColor->valuestring : "");
+
+        ln_assign_dup(&g_ln_character_config.avatar_eyes_color,
+                      (eyesColor && cJSON_IsString(eyesColor)) ? eyesColor->valuestring : "");
+
+        ln_assign_dup(&g_ln_character_config.avatar_hair_style,
+                      (hairStyle && cJSON_IsString(hairStyle)) ? hairStyle->valuestring : "");
+
+        ln_assign_dup(&g_ln_character_config.avatar_eyes_shape,
+                      (eyesShape && cJSON_IsString(eyesShape)) ? eyesShape->valuestring : "");
+
+        ln_assign_dup(&g_ln_character_config.avatar_screen_image,
+                      (deviceScreen && cJSON_IsString(deviceScreen)) ? deviceScreen->valuestring : "");
+
+        g_ln_character_config.avatar_screen_image_as_emoji =
+            (deviceScreenAsEmoji && cJSON_IsBool(deviceScreenAsEmoji)) ? (cJSON_IsTrue(deviceScreenAsEmoji) ? 1 : 0) : 0;
+    }
+    else
+    {
+        /* 缺省时清空结构体字段 */
+        ln_assign_dup(&g_ln_character_config.avatar_hair_color, "");
+        ln_assign_dup(&g_ln_character_config.avatar_eyes_color, "");
+        ln_assign_dup(&g_ln_character_config.avatar_hair_style, "");
+        ln_assign_dup(&g_ln_character_config.avatar_eyes_shape, "");
+        ln_assign_dup(&g_ln_character_config.avatar_screen_image, "");
+        g_ln_character_config.avatar_screen_image_as_emoji = 0;
+    }
+
+    // 将json体落库
+    ln_save_character_config(text);
+
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DEVICE_CHARACTER] push character config change notification");
+
+    /* 打印解析结果 */
+    printf("[DEVICE_CHARACTER] parsed:\n");
+    printf("  character_id: %s\n", g_ln_character_config.character_id ? g_ln_character_config.character_id : "");
+    printf("  character_name: %s\n", g_ln_character_config.character_name ? g_ln_character_config.character_name : "");
+    printf("  avatar_hair_color: %s\n", g_ln_character_config.avatar_hair_color ? g_ln_character_config.avatar_hair_color : "");
+    printf("  avatar_eyes_color: %s\n", g_ln_character_config.avatar_eyes_color ? g_ln_character_config.avatar_eyes_color : "");
+    printf("  avatar_hair_style: %s\n", g_ln_character_config.avatar_hair_style ? g_ln_character_config.avatar_hair_style : "");
+    printf("  avatar_eyes_shape: %s\n", g_ln_character_config.avatar_eyes_shape ? g_ln_character_config.avatar_eyes_shape : "");
+    printf("  avatar_screen_image: %s\n", g_ln_character_config.avatar_screen_image ? g_ln_character_config.avatar_screen_image : "");
+    printf("  avatar_screen_image_as_emoji: %d\n", g_ln_character_config.avatar_screen_image_as_emoji);
+
+    // 如果LN_DEVICE_SCREEN_IMAGE_FILE存在直接发送切换屏保通知
+    if (access(LN_DEVICE_SCREEN_IMAGE_FILE, F_OK) != -1)
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DEVICE_CHARACTER] 屏保图片存在,直接发送切换屏保通知");
+        push_screen_image_download_success_notification();
+    }
+    else
+    {
+        // 如果屏保图片不为空,则保存到本地
+        if (g_ln_character_config.avatar_screen_image && strlen(g_ln_character_config.avatar_screen_image) > 0 && g_ln_character_config.avatar_screen_image_as_emoji == 1)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DEVICE_CHARACTER] 屏保图片不为空,下载屏保图片");
+            // 下载屏保图片,eg:"https://example.com/new_avatar.bin"
+            ln_download_file_req_t req;
+            memset(&req, 0, sizeof(req));
+            /* 分配与拷贝,发送方分配,接收方负责释放 */
+            if (g_ln_character_config.avatar_screen_image)
+            {
+                size_t ulen = strlen(g_ln_character_config.avatar_screen_image);
+                req.url = (char *)malloc(ulen + 1);
+                if (req.url)
+                {
+                    memcpy(req.url, g_ln_character_config.avatar_screen_image, ulen + 1);
+                }
+            }
+            {
+                const char *save = LN_DEVICE_SCREEN_IMAGE_FILE;
+                size_t slen = strlen(save);
+                req.save_path = (char *)malloc(slen + 1);
+                if (req.save_path)
+                {
+                    memcpy(req.save_path, save, slen + 1);
+                }
+            }
+            do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_DOWNLOAD_SCREEN_IMAGE, (char *)&req, sizeof(req));
+        }
+
+        /* 推送角色配置更改通知 */
+        push_character_config_change_notification(g_ln_character_config.character_id,
+                                                  g_ln_character_config.character_name,
+                                                  g_ln_character_config.avatar_eyes_shape,
+                                                  g_ln_character_config.avatar_hair_color,
+                                                  g_ln_character_config.avatar_eyes_color,
+                                                  g_ln_character_config.avatar_hair_style,
+                                                  g_ln_character_config.avatar_screen_image_as_emoji);
+
+        cJSON_Delete(root);
+        free(text);
+        ln_clear_character_config();
+    }
+}
+
 // 获取设备角色信息
 uint32_t ln_device_get_character_http(const char *device_id,
                                       const char *device_token)