将大字符串字段的结构体改成“按需分配”的指针成员
authorluozheng <1732036298@qq.com>
Mon, 22 Sep 2025 11:28:46 +0000 (19:28 +0800)
committerluozheng <1732036298@qq.com>
Mon, 22 Sep 2025 11:28:46 +0000 (19:28 +0800)
code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c
code/sdk/zhihui/leiniao/imsl_ln/ln_api.c
code/sdk/zhihui/leiniao/imsl_ln/ln_api.h
code/sdk/zhihui/leiniao/imsl_ln/ln_api_device_info.c
code/sdk/zhihui/leiniao/imsl_ln/ln_api_schedule.c
code/sdk/zhihui/leiniao/ln_api_cpp/ln_api_interface.h

index 22e5cd5..d0ce9f2 100644 (file)
@@ -31,7 +31,7 @@ static struct VadConfig g_vad_config = {0};
 
 // 音频缓冲区(用于真实语音测试)
 #define VAD_AUDIO_BUFFER_SIZE 3200 // 200ms @ 16kHz
-static int16_t g_audio_buffer[VAD_AUDIO_BUFFER_SIZE];
+static int16_t *g_audio_buffer = NULL; /* heap allocated */
 static int g_audio_buffer_pos = 0;
 
 /* 录音封装(由 C++ 提供,C 接口声明) */
@@ -93,9 +93,24 @@ static int AnalyzePcmFileWithVad(const char *pcm_path)
 /* ---------------- 实时录音并同步喂给 VAD(基于文件尾随) ---------------- */
 static volatile bool g_vad_live_running = false;
 static MediaThreadIdHandle g_vad_tail_thread = NULL;
-static char g_vad_live_path[256] = "/user/vad_live.pcm";
+#define LN_VAD_PATH_CAP 256
+static char *g_vad_live_path = NULL; /* heap allocated, cap LN_VAD_PATH_CAP */
 static int g_vad_prev_status = -1;
 
+static void EnsureVadLivePathInitialized(void)
+{
+    if (g_vad_live_path == NULL)
+    {
+        g_vad_live_path = (char *)malloc(LN_VAD_PATH_CAP);
+        if (g_vad_live_path)
+        {
+            g_vad_live_path[0] = '\0';
+            strncpy(g_vad_live_path, "/user/vad_live.pcm", LN_VAD_PATH_CAP - 1);
+            g_vad_live_path[LN_VAD_PATH_CAP - 1] = '\0';
+        }
+    }
+}
+
 // 尾随线程,持续从文件中读取数据并喂给 VAD
 static void *VadTailThread(void *arg)
 {
@@ -108,7 +123,8 @@ static void *VadTailThread(void *arg)
     /* 等待文件可读 */
     while (g_vad_live_running && fp == NULL)
     {
-        fp = fopen(g_vad_live_path, "rb");
+        EnsureVadLivePathInitialized();
+        fp = fopen(g_vad_live_path ? g_vad_live_path : "/user/vad_live.pcm", "rb");
         if (fp == NULL)
         {
             usleep(50 * 1000);
@@ -162,7 +178,8 @@ static void *StartRecordThread(void *arg)
 {
     printf("VAD StartRecordThread\n");
     (void)arg;
-    const char *startArgs[6] = {"01", "pcm", "16000", "1", "16", g_vad_live_path};
+    EnsureVadLivePathInitialized();
+    const char *startArgs[6] = {"01", "pcm", "16000", "1", "16", g_vad_live_path ? g_vad_live_path : "/user/vad_live.pcm"};
     (void)AudioCaptureSample(6, startArgs);
     return NULL;
 }
@@ -391,14 +408,18 @@ static uint32_t vad_record_start(uint8_t *para, uint32_t paraLen, char *strCommo
     }
 
     /* 可选自定义输出路径 */
-    const char *out_path = (const char *)g_vad_live_path;
+    EnsureVadLivePathInitialized();
+    const char *out_path = (const char *)(g_vad_live_path ? g_vad_live_path : "/user/vad_live.pcm");
     uint8_t argvbuf[VAD_MAX_ARGC][VAD_MAX_ARGV_LEN] = {0};
     uint32_t argc = 0;
     if (para != NULL && paraLen > 0 && ConvertCmdToParam(para, paraLen, argvbuf, &argc) == VAD_SUCCESS && argc >= 1)
     {
-        strncpy(g_vad_live_path, (const char *)argvbuf[0], sizeof(g_vad_live_path) - 1);
-        g_vad_live_path[sizeof(g_vad_live_path) - 1] = '\0';
-        out_path = g_vad_live_path;
+        if (g_vad_live_path)
+        {
+            strncpy(g_vad_live_path, (const char *)argvbuf[0], LN_VAD_PATH_CAP - 1);
+            g_vad_live_path[LN_VAD_PATH_CAP - 1] = '\0';
+            out_path = g_vad_live_path;
+        }
     }
 
     printf("=== VAD 实时录音开始 ===\n");
@@ -406,8 +427,11 @@ static uint32_t vad_record_start(uint8_t *para, uint32_t paraLen, char *strCommo
 
     /* 1) 确保目录存在并异步启动系统录音保存为 PCM(避免在 AT 线程上堆栈溢出) */
     EnsureParentDir(out_path);
-    strncpy(g_vad_live_path, out_path, sizeof(g_vad_live_path) - 1);
-    g_vad_live_path[sizeof(g_vad_live_path) - 1] = '\0';
+    if (g_vad_live_path)
+    {
+        strncpy(g_vad_live_path, out_path, LN_VAD_PATH_CAP - 1);
+        g_vad_live_path[LN_VAD_PATH_CAP - 1] = '\0';
+    }
     StartRecordThread(NULL);
 
     /* 2) 启动尾随线程实时喂给 VAD */
index 7418d58..986f4f0 100644 (file)
@@ -398,14 +398,12 @@ static void ln_handle_ota_task_response(const char *json_buf, int json_len)
     {
         /* 强制升级:直接触发下载 */
         printf("[OTA] force upgrade: trigger download(强制升级:直接触发下载)\n");
-        push_ota_status(OTA_UI_STATUS_START);
-        do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_OTA_DOWNLOAD, NULL, 0);
+        push_ota_status(OTA_UI_STATUS_FORCE_START);
     }
     else if (ut == 0)
     {
         printf("[OTA] optional upgrade: waiting for user confirmation(可选升级:等待用户确认)\n");
-        do_ln_http_server_send_data(LN_HTTP_SERVICE_CMD_OTA_DOWNLOAD, NULL, 0);
-        push_ota_status(OTA_UI_STATUS_START);
+        push_ota_status(OTA_UI_STATUS_OPTIONAL_START);
     }
     else
     {
@@ -1025,7 +1023,12 @@ uint32_t ln_parse_file_and_process_data(const char *file_path, int interface_typ
         return ERRCODE_FAIL;
     }
 
-    char line[2048];
+    char *line = (char *)malloc(2048);
+    if (!line)
+    {
+        fclose(fp);
+        return ERRCODE_FAIL;
+    }
     int line_count = 0;
     int success_count = 0;
     int error_count = 0;
@@ -1045,7 +1048,7 @@ uint32_t ln_parse_file_and_process_data(const char *file_path, int interface_typ
         uapi_ln_audio_download_is_cancel(0);
     }
 
-    while (fgets(line, sizeof(line), fp))
+    while (fgets(line, 2048, fp))
     {
         if (g_ln_audio_download_cancel) {
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[SSE] download canceled by user\n");
@@ -1101,6 +1104,7 @@ uint32_t ln_parse_file_and_process_data(const char *file_path, int interface_typ
     }
 
     fclose(fp);
+    free(line);
 
     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[FILE_PARSE] processing completed: total lines=%d, success=%d, errors=%d\n", 
            line_count, success_count, error_count);
@@ -1429,32 +1433,6 @@ void do_ln_http_server_recv_data(int cmd, char *data, uint32_t len)
         if (recv_data.data) free(recv_data.data);
     }
 }
-/* WebSocket自动启动任务(网络就绪后启动WebSocket)*/
-static app_task_definition_t ln_ws_autostart_taskcfg = {0};
-static void ln_ws_autostart_task(void const *arg)
-{
-    printf("[LN][WS] autostart task running\n");
-    while (1)
-    {
-        /* 每3秒检查一次网络 */
-        if (uapi_dev_runtime_get_cat1_networkstat())
-        {
-            printf("[LN][WS] network online, try start websocket\n");
-            int ret = ln_ws_start(ln_ws_process_message);
-            if (ret == 0)
-            {
-                printf("[LN][WS] websocket started\n");
-                break; /* 启动成功后退出任务 */
-            }
-            else
-            {
-                printf("[LN][WS] start websocket failed: %d, retry later\n", ret);
-            }
-        }
-        usleep(3000 * 1000); // 休眠3秒
-    }
-    printf("[LN][WS] autostart task exit\n");
-}
 // 雷鸟http服务初始化
 errcode_t uapi_ln_http_server_init(void)
 {
@@ -1495,14 +1473,6 @@ errcode_t uapi_ln_http_server_init(void)
         /* 不中断HTTP服务,按需可返回失败 */
     }
 
-    // /* 创建WebSocket自动启动任务:每3秒检测一次网络并启动WS */
-    // ln_ws_autostart_taskcfg.create_queue_handle = NULL;
-    // ln_ws_autostart_taskcfg.attr.name = "ln_ws_autostart_task";
-    // ln_ws_autostart_taskcfg.attr.priority = osPriorityNormal;
-    // ln_ws_autostart_taskcfg.attr.stack_size = 0x1000;
-    // ln_ws_autostart_taskcfg.func = ln_ws_autostart_task;
-    // ln_ws_autostart_taskcfg.use_mem = USE_EXTEND_MEM;
-    // (void)uapi_create_osThread_custom(&ln_ws_autostart_taskcfg);
 
     return ERRCODE_SUCC;
 }
index b70c22f..ade4727 100644 (file)
@@ -145,13 +145,13 @@ typedef enum
 /* =================== 设备角色信息结构体定义 =================== */
 typedef struct
 {
-    char character_id[64];            // 角色ID
-    char character_name[64];          // 角色名称
-    char avatar_hair_color[64];       // 发色
-    char avatar_eyes_color[64];       // 瞳色
-    char avatar_hair_style[64];       // 发型
-    char avatar_eyes_shape[64];       // 眼型
-    char avatar_screen_image[256];    // 屏保图片
+    char *character_id;            // 角色ID
+    char *character_name;          // 角色名称
+    char *avatar_hair_color;       // 发色
+    char *avatar_eyes_color;       // 瞳色
+    char *avatar_hair_style;       // 发型
+    char *avatar_eyes_shape;       // 眼型
+    char *avatar_screen_image;     // 屏保图片
     int avatar_screen_image_as_emoji; // 屏保图片是否作为对话表情
 } LnCharacterConfig;
 
@@ -159,10 +159,10 @@ typedef struct
 typedef struct
 {
     int scheduleId;
-    char deviceId[64];
-    char scheduleName[128];
-    char reminderContent[512];
-    char reminderAudioUrl[512];
+    char *deviceId;
+    char *scheduleName;
+    char *reminderContent;
+    char *reminderAudioUrl;
     int enableVoice;
     int enableVibration;
 } ScheduleReminder;
@@ -170,7 +170,7 @@ typedef struct
 /* 日程 日程提醒醒配置配置信息结构体 */
 typedef struct
 {
-    char scheduleName[128]; // 日程名称
+    char *scheduleName; // 日程名称
 } ScheduleReminderConfig;
 
 /* 初始化 LN HTTP 服务 */
index f12026c..c48cd0d 100644 (file)
@@ -3,19 +3,25 @@
 #include <string.h>
 #include <cJSON.h>
 
-ScheduleReminder g_schedule_reminder = {0};
-/* å®\89å\85¨å\86\99å\85¥å¸®å\8a©å\87½æ\95° */
-static inline void ln_safe_strcpy(char *dst, size_t dst_size, const char *src)
+LnCharacterConfig g_ln_character_config = {0};
+/* å\8a¨æ\80\81å­\97符串工å\85· */
+static inline char *ln_strdup_s(const char *src)
 {
-    if (!dst || dst_size == 0)
-        return;
-    if (src == NULL)
-    {
-        dst[0] = '\0';
-        return;
-    }
-    strncpy(dst, src, dst_size - 1);
-    dst[dst_size - 1] = '\0';
+    if (src == NULL) src = "";
+    size_t len = strlen(src);
+    char *p = (char *)malloc(len + 1);
+    if (!p) return NULL;
+    memcpy(p, src, len + 1);
+    return p;
+}
+
+static inline void ln_assign_dup(char **dst, const char *src)
+{
+    if (!dst) return;
+    char *newp = ln_strdup_s(src);
+    if (!newp) return;
+    if (*dst) free(*dst);
+    *dst = newp;
 }
 
 /* 解析设备角色配置 JSON 并保存到全局结构体 */
@@ -63,13 +69,11 @@ void ln_parse_character_config(const char *json_buf, int json_len)
     /* 基础字段 */
     cJSON *cid = cJSON_GetObjectItem(data, "characterId");
     cJSON *cname = cJSON_GetObjectItem(data, "characterName");
-    ln_safe_strcpy(g_ln_character_config.character_id,
-                   sizeof(g_ln_character_config.character_id),
-                   (cid && cJSON_IsString(cid)) ? cid->valuestring : "");
+    ln_assign_dup(&g_ln_character_config.character_id,
+                  (cid && cJSON_IsString(cid)) ? cid->valuestring : "");
 
-    ln_safe_strcpy(g_ln_character_config.character_name,
-                   sizeof(g_ln_character_config.character_name),
-                   (cname && cJSON_IsString(cname)) ? cname->valuestring : "");
+    ln_assign_dup(&g_ln_character_config.character_name,
+                  (cname && cJSON_IsString(cname)) ? cname->valuestring : "");
 
     /* 头像配置 */
     cJSON *avatar = cJSON_GetObjectItem(data, "characterAvatar");
@@ -82,25 +86,20 @@ void ln_parse_character_config(const char *json_buf, int json_len)
         cJSON *screenImage = cJSON_GetObjectItem(avatar, "screenImage");
         cJSON *screenImageAsEmoji = cJSON_GetObjectItem(avatar, "screenImageAsEmoji");
 
-        ln_safe_strcpy(g_ln_character_config.avatar_hair_color,
-                       sizeof(g_ln_character_config.avatar_hair_color),
-                       (hairColor && cJSON_IsString(hairColor)) ? hairColor->valuestring : "");
+        ln_assign_dup(&g_ln_character_config.avatar_hair_color,
+                      (hairColor && cJSON_IsString(hairColor)) ? hairColor->valuestring : "");
 
-        ln_safe_strcpy(g_ln_character_config.avatar_eyes_color,
-                       sizeof(g_ln_character_config.avatar_eyes_color),
-                       (eyesColor && cJSON_IsString(eyesColor)) ? eyesColor->valuestring : "");
+        ln_assign_dup(&g_ln_character_config.avatar_eyes_color,
+                      (eyesColor && cJSON_IsString(eyesColor)) ? eyesColor->valuestring : "");
 
-        ln_safe_strcpy(g_ln_character_config.avatar_hair_style,
-                       sizeof(g_ln_character_config.avatar_hair_style),
-                       (hairStyle && cJSON_IsString(hairStyle)) ? hairStyle->valuestring : "");
+        ln_assign_dup(&g_ln_character_config.avatar_hair_style,
+                      (hairStyle && cJSON_IsString(hairStyle)) ? hairStyle->valuestring : "");
 
-        ln_safe_strcpy(g_ln_character_config.avatar_eyes_shape,
-                       sizeof(g_ln_character_config.avatar_eyes_shape),
-                       (eyesShape && cJSON_IsString(eyesShape)) ? eyesShape->valuestring : "");
+        ln_assign_dup(&g_ln_character_config.avatar_eyes_shape,
+                      (eyesShape && cJSON_IsString(eyesShape)) ? eyesShape->valuestring : "");
 
-        ln_safe_strcpy(g_ln_character_config.avatar_screen_image,
-                       sizeof(g_ln_character_config.avatar_screen_image),
-                       (screenImage && cJSON_IsString(screenImage)) ? screenImage->valuestring : "");
+        ln_assign_dup(&g_ln_character_config.avatar_screen_image,
+                      (screenImage && cJSON_IsString(screenImage)) ? screenImage->valuestring : "");
 
         g_ln_character_config.avatar_screen_image_as_emoji =
             (screenImageAsEmoji && cJSON_IsBool(screenImageAsEmoji)) ? (cJSON_IsTrue(screenImageAsEmoji) ? 1 : 0) : 0;
@@ -108,23 +107,23 @@ void ln_parse_character_config(const char *json_buf, int json_len)
     else
     {
         /* 缺省时清空结构体字段 */
-        g_ln_character_config.avatar_hair_color[0] = '\0';
-        g_ln_character_config.avatar_eyes_color[0] = '\0';
-        g_ln_character_config.avatar_hair_style[0] = '\0';
-        g_ln_character_config.avatar_eyes_shape[0] = '\0';
-        g_ln_character_config.avatar_screen_image[0] = '\0';
+        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;
     }
 
     /* 打印解析结果 */
     printf("[DEVICE_CHARACTER] parsed:\n");
-    printf("  character_id: %s\n", g_ln_character_config.character_id);
-    printf("  character_name: %s\n", g_ln_character_config.character_name);
-    printf("  avatar_hair_color: %s\n", g_ln_character_config.avatar_hair_color);
-    printf("  avatar_eyes_color: %s\n", g_ln_character_config.avatar_eyes_color);
-    printf("  avatar_hair_style: %s\n", g_ln_character_config.avatar_hair_style);
-    printf("  avatar_eyes_shape: %s\n", g_ln_character_config.avatar_eyes_shape);
-    printf("  avatar_screen_image: %s\n", g_ln_character_config.avatar_screen_image);
+    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);
 
     cJSON_Delete(root);
index e2f0463..343da38 100644 (file)
@@ -4,16 +4,27 @@
 #include "cJSON.h"
 #include "ln_api.h"
 
-LnCharacterConfig g_ln_character_config = {0};
+ScheduleReminder g_schedule_reminder = {0};
 ScheduleReminderConfig g_schedule_reminder_config = {0};
 
-// å®\89å\85¨å­\97符串å¤\8då\88¶å\87½æ\95°
-static void ln_safe_strcpy(char *dest, size_t dest_size, const char *src)
+// å\8a¨æ\80\81å­\97符串工å\85·
+static char *ln_strdup_s(const char *src)
 {
-    if (!dest || dest_size == 0 || !src)
-        return;
-    strncpy(dest, src, dest_size - 1);
-    dest[dest_size - 1] = '\0';
+    if (src == NULL) src = "";
+    size_t len = strlen(src);
+    char *p = (char *)malloc(len + 1);
+    if (!p) return NULL;
+    memcpy(p, src, len + 1);
+    return p;
+}
+
+static void ln_assign_dup(char **dst, const char *src)
+{
+    if (!dst) return;
+    char *newp = ln_strdup_s(src);
+    if (!newp) return;
+    if (*dst) free(*dst);
+    *dst = newp;
 }
 
 /* 解析日程提醒信息 */
@@ -74,21 +85,17 @@ void ln_parse_schedule_reminder(const char *json_buf, int json_len)
     // 填充全局结构体
     g_schedule_reminder.scheduleId = (scheduleId && cJSON_IsNumber(scheduleId)) ? scheduleId->valueint : 0;
 
-    ln_safe_strcpy(g_schedule_reminder.deviceId,
-                   sizeof(g_schedule_reminder.deviceId),
-                   (deviceId && cJSON_IsString(deviceId)) ? deviceId->valuestring : "");
+    ln_assign_dup(&g_schedule_reminder.deviceId,
+                  (deviceId && cJSON_IsString(deviceId)) ? deviceId->valuestring : "");
 
-    ln_safe_strcpy(g_schedule_reminder.scheduleName,
-                   sizeof(g_schedule_reminder.scheduleName),
-                   (scheduleName && cJSON_IsString(scheduleName)) ? scheduleName->valuestring : "");
+    ln_assign_dup(&g_schedule_reminder.scheduleName,
+                  (scheduleName && cJSON_IsString(scheduleName)) ? scheduleName->valuestring : "");
 
-    ln_safe_strcpy(g_schedule_reminder.reminderContent,
-                   sizeof(g_schedule_reminder.reminderContent),
-                   (reminderContent && cJSON_IsString(reminderContent)) ? reminderContent->valuestring : "");
+    ln_assign_dup(&g_schedule_reminder.reminderContent,
+                  (reminderContent && cJSON_IsString(reminderContent)) ? reminderContent->valuestring : "");
 
-    ln_safe_strcpy(g_schedule_reminder.reminderAudioUrl,
-                   sizeof(g_schedule_reminder.reminderAudioUrl),
-                   (reminderAudioUrl && cJSON_IsString(reminderAudioUrl)) ? reminderAudioUrl->valuestring : "");
+    ln_assign_dup(&g_schedule_reminder.reminderAudioUrl,
+                  (reminderAudioUrl && cJSON_IsString(reminderAudioUrl)) ? reminderAudioUrl->valuestring : "");
 
     g_schedule_reminder.enableVoice = (enableVoice && cJSON_IsNumber(enableVoice)) ? enableVoice->valueint : 0;
     g_schedule_reminder.enableVibration = (enableVibration && cJSON_IsNumber(enableVibration)) ? enableVibration->valueint : 0;
@@ -96,10 +103,10 @@ void ln_parse_schedule_reminder(const char *json_buf, int json_len)
     // 打印解析结果
     printf("[SCHEDULE_REMINDER] parsed successfully:\n");
     printf("  scheduleId: %d\n", g_schedule_reminder.scheduleId);
-    printf("  deviceId: %s\n", g_schedule_reminder.deviceId);
-    printf("  scheduleName: %s\n", g_schedule_reminder.scheduleName);
-    printf("  reminderContent: %s\n", g_schedule_reminder.reminderContent);
-    printf("  reminderAudioUrl: %s\n", g_schedule_reminder.reminderAudioUrl);
+    printf("  deviceId: %s\n", g_schedule_reminder.deviceId ? g_schedule_reminder.deviceId : "");
+    printf("  scheduleName: %s\n", g_schedule_reminder.scheduleName ? g_schedule_reminder.scheduleName : "");
+    printf("  reminderContent: %s\n", g_schedule_reminder.reminderContent ? g_schedule_reminder.reminderContent : "");
+    printf("  reminderAudioUrl: %s\n", g_schedule_reminder.reminderAudioUrl ? g_schedule_reminder.reminderAudioUrl : "");
     printf("  enableVoice: %d\n", g_schedule_reminder.enableVoice);
     printf("  enableVibration: %d\n", g_schedule_reminder.enableVibration);
 
@@ -156,13 +163,12 @@ void ln_parse_schedule_reminder_config(const char *json_buf, int json_len)
 
     // 解析日程名称字段
     cJSON *scheduleName = cJSON_GetObjectItem(data, "scheduleName");
-    ln_safe_strcpy(g_schedule_reminder_config.scheduleName,
-                   sizeof(g_schedule_reminder_config.scheduleName),
-                   (scheduleName && cJSON_IsString(scheduleName)) ? scheduleName->valuestring : "");
+    ln_assign_dup(&g_schedule_reminder_config.scheduleName,
+                  (scheduleName && cJSON_IsString(scheduleName)) ? scheduleName->valuestring : "");
 
     // 打印解析结果
     printf("[SCHEDULE_REMINDER_CONFIG] parsed successfully:\n");
-    printf("  scheduleName: %s\n", g_schedule_reminder_config.scheduleName);
+    printf("  scheduleName: %s\n", g_schedule_reminder_config.scheduleName ? g_schedule_reminder_config.scheduleName : "");
 
     // 清理资源
     cJSON_Delete(root);
index e158f5d..f72ab62 100644 (file)
@@ -29,7 +29,8 @@ ota升级状态
 */
 typedef enum {
     OTA_UI_STATUS_NOT_START  = 0,   /* 未开始 */
-    OTA_UI_STATUS_START,            /* 开始 */
+    OTA_UI_STATUS_FORCE_START,      /* ota强制开始升级状态 */
+    OTA_UI_STATUS_OPTIONAL_START,   /* ota可选开始升级状态 */
     OTA_UI_STATUS_FAILED,           /* 失败 */
     OTA_UI_STATUS_SUCCESS,          /* 成功 */
 } ota_ui_status_t;