ota支持进度下载 2216/1 2216/head 2217/target/1
authorxue <2144439972@qq.com>
Wed, 10 Sep 2025 03:40:37 +0000 (11:40 +0800)
committerxue <2144439972@qq.com>
Wed, 10 Sep 2025 03:40:37 +0000 (11:40 +0800)
code/sdk/application/brandy/brandy_standard/thread_pri_init.c
code/sdk/zhihui/leiniao/imsl_ln/ln_api.h
code/sdk/zhihui/leiniao/imsl_ln/ln_api_ota.c

index c0f289e..826fe0a 100644 (file)
@@ -630,6 +630,9 @@ static void thread_main(const void *unused)
     startup_post_init();\r
 #endif\r
     set_startup_finish_flag();\r
+#ifdef SUPPORT_LEINIAO\r
+    uapi_ln_http_server_init();\r
+#endif\r
 }\r
 \r
 void thread_pri_init(void)\r
index 4394554..28ae901 100644 (file)
@@ -11,6 +11,8 @@ extern "C"
 /* HTTP types for helper function prototypes */
 #include "netstack/http/include/httpclient.h"
 
+#include "wearable_log.h"
+
 typedef struct
 {
     int cmd;
@@ -44,6 +46,8 @@ typedef struct
 /* OTA 包保存目录(最终文件仍将放在 /user/ 下)*/
 #define LN_OTA_SAVE_DIR "/user"
 
+#define LN_CLIENT_PREPARE_SIZE 2*1024
+
 #define LN_HTTP_SERVICE_CMD_GET_DEVICE_TOKEN 0x1 /* 获取设备 token */
 #define LN_HTTP_SERVICE_CMD_SPEECH_CHAT_STREAM 0x2 /* 语音对话流 */
 #define LN_HTTP_SERVICE_CMD_SSE_RECV 0x3 /* 语音对话流分片接收 */
index 9dec066..b422633 100644 (file)
@@ -206,6 +206,158 @@ static int ln_download_file_to_path_range(const char *full_url, const char *save
     return 0;
 }
 
+/* 采用http_download风格实现的文件下载函数
+ * 功能:从指定URL下载文件到指定路径(已知总大小)
+ * 参数:full_url - 完整下载URL
+ *       save_path - 保存路径
+ *       total_size - 已知的文件总大小(字节)
+ * 返回:0 - 成功,非0 - 失败
+ */
+static int ln_download_file_to_path(const char *full_url, const char *save_path, int total_size)
+{
+    // 参数校验(包含total_size的检查)
+    if (!full_url || !save_path || total_size <= 0)
+    {
+        printf("[OTA] invalid parameters: url=%p, path=%p, total_size=%d\n",
+               full_url, save_path, total_size);
+        return -1;
+    }
+    printf("[OTA] starting download: %s -> %s, total_size=%d bytes\n",
+           full_url, save_path, total_size);
+
+    /* CAT1 网络保活处理 */
+    cat1_api_add_cat1_vote();
+    cat1_api_wakeup_cat1(1);
+    cat1_api_keep_wakeup(1);
+    cat1_api_disable_cat1_cmd(0);
+    LOS_Msleep(300); // 等待模块就绪
+
+    /* 初始化HTTP客户端(与http_download风格一致) */
+    HttpClient client = {0};
+    HttpClientData client_data = {0};
+    int ret = -1;
+    size_t total_written = 0; // 已写入文件的总字节数
+
+    // 打开文件准备写入
+    FILE *fd = fopen(save_path, "wb");
+    if (!fd)
+    {
+        printf("[OTA] fopen failed for %s:\n", save_path);
+        return -1;
+    }
+
+    HTTPC_RESULT prep = ln_http_prepare_auto(&client_data, 2048, LN_CLIENT_PREPARE_SIZE);
+    if (prep != HTTP_SUCCESS)
+    {
+        printf("[OTA] range prepare failed: %d\n", prep);
+        fclose(fd);
+        return -1;
+    }
+
+    // 建立连接(与http_download流程一致)
+    ret = HttpClientConn(&client, full_url);
+    if (ret != 0)
+    {
+        printf("[OTA] connection failed, ret=0x%x\n", ret);
+        fclose(fd);
+        HttpClientUnprepare(&client_data);
+        return ret;
+    }
+
+    // 发送GET请求
+    ret = HttpClientSend(&client, full_url, HTTP_GET, &client_data);
+    if (ret != 0)
+    {
+        printf("[OTA] send request failed, ret=0x%x\n", ret);
+        HttpClientClse(&client);
+        fclose(fd);
+        HttpClientUnprepare(&client_data);
+        return ret;
+    }
+
+    // 循环接收响应数据(参考http_download的do-while循环)
+    printf("[OTA] starting to receive data...\n");
+    do
+    {
+        ret = HttpClientRecvResponse(&client, &client_data);
+        printf("[OTA] receive response: %d\n", ret);
+        if (ret == HTTP_SUCCESS || ret == HTTP_EAGAIN)
+        {
+            // 处理接收到的数据块
+            if (client_data.contentBlockLen > 0)
+            {
+                printf("[OTA] received block: %d bytes\n", client_data.contentBlockLen);
+                // 写入文件(与http_download的写入逻辑一致)
+                size_t written = fwrite(client_data.responseBuf, 1,
+                                        client_data.contentBlockLen, fd);
+                if (written != client_data.contentBlockLen)
+                {
+                    printf("[OTA] write file failed, written=%zu, expected=%d\n",
+                           written, client_data.contentBlockLen);
+                    ret = -1;
+                    break;
+                }
+                total_written += written;
+                // 进度上报(使用已知的total_size计算)
+                int percent = (int)((total_written * 100) / total_size);
+                if (percent > 100)
+                    percent = 100; // 防止超过100%
+                char prog[128];
+                snprintf(prog, sizeof(prog),
+                         "{\"status\":%d,\"progress\":%d}",
+                         OTA_DOWNLOAD_STATUS_PROGRESS, percent);
+                do_ln_http_server_recv_data(LN_HTTP_RECV_OTA_DOWNLOAD_MSG,
+                                            prog, strlen(prog));
+                printf("[OTA] progress: %d%% (%zu/%d)\n",
+                       percent, total_written, total_size);
+
+                // 检查是否超过预期总大小
+                if (total_written > (size_t)total_size)
+                {
+                    printf("[OTA] received more than expected! total_written=%zu > total_size=%d\n",
+                           total_written, total_size);
+                    ret = -1;
+                    break;
+                }
+            }
+        }
+        else
+        {
+            printf("[OTA] receive failed, ret=0x%x\n", ret);
+            break;
+        }
+    } while (client_data.isMore && total_written < (size_t)total_size); // 双重条件判断
+    // 检查下载结果(参考http_download的结果校验)
+    if (ret == 0 && client.responseCode == 200)
+    {
+        // 验证是否下载完整(使用已知的total_size)
+        if (total_written == (size_t)total_size)
+        {
+            printf("[OTA] download complete! total size: %d bytes\n", total_size);
+            ret = 0;
+        }
+        else
+        {
+            printf("[OTA] download incomplete! received=%zu, expected=%d\n",
+                   total_written, total_size);
+            ret = -1;
+        }
+    }
+    else
+    {
+        printf("[OTA] download failed! response code: %d, ret=0x%x\n",
+               client.responseCode, ret);
+    }
+
+    // 资源清理(与http_download保持一致)
+    fclose(fd);
+    HttpClientClse(&client);
+    HttpClientUnprepare(&client_data);
+    printf("[OTA] download process finished\n");
+
+    return ret;
+}
+
 uint32_t ln_ota_download_flow_http(const char *device_id,
                                    const char *device_token,
                                    const char *source_version)
@@ -227,7 +379,7 @@ uint32_t ln_ota_download_flow_http(const char *device_id,
     int dres;
     if (g_ln_last_package_size > 0)
     {
-        dres = ln_download_file_to_path_range(g_ln_last_package_url, save_path, g_ln_last_package_size);
+        dres = ln_download_file_to_path(g_ln_last_package_url, save_path, g_ln_last_package_size);
     }
     if (dres != 0)
     {