增加spi下载支持延时参数 2925/1
authorhcj <1224667075@qq.com>
Mon, 15 Dec 2025 06:54:20 +0000 (14:54 +0800)
committerhcj <1224667075@qq.com>
Mon, 15 Dec 2025 06:54:20 +0000 (14:54 +0800)
cat1modem/src/LeiNiao/cat1Service.py
cat1modem/src/LeiNiao/httpfiledownload.py
code/sdk/zhihui/4g/cat1Service/Service/http_file_download_client.c
code/sdk/zhihui/4g/cat1Service/include/http_file_download_client.h
code/sdk/zhihui/4gTest/cat1_at_cmd.c
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_ota.c
code/sdk/zhihui/leiniao/imsl_ln/ln_websoket_api_ext.c
code/sdk/zhihui/utils/custom_spi.c

index 5f169bc..f7fcd28 100644 (file)
@@ -379,25 +379,31 @@ class Cat1Service:
             TcpService = TcpServiceInit()
             TcpService.start_socket_thread()
         elif cmd== "1E":
-            # 解析参数,支持断点重传模式(格式:URL|resume_from_byte)
+            # 解析参数,支持断点重传和写延时配置
+            # 格式:
+            #   URL
+            #   URL|resume_from_byte
+            #   URL|resume_from_byte|write_delay_ms
             parm_str = str(parm)
-            if '|' in parm_str:
-                # 断点重传模式:分离URL和重传位置
-                parts = parm_str.split('|', 1)  # 只分割第一个|符号
-                if len(parts) == 2:
-                    url = parts[0]
-                    try:
-                        resume_from_byte = int(parts[1])
-                        download_file_spi(url, resume_from_byte=resume_from_byte)
-                    except ValueError:
-                        # 如果重传位置不是有效数字,使用默认值0
-                        download_file_spi(parts[0], resume_from_byte=0)
-                else:
-                    # 格式错误,使用默认模式
-                    download_file_spi(parm_str)
-            else:
-                # 普通下载模式
-                download_file_spi(parm_str)
+            url = parm_str
+            resume_from_byte = 0
+            write_delay_ms = 10
+
+            parts = parm_str.split('|')
+            if len(parts) >= 1 and parts[0]:
+                url = parts[0]
+            if len(parts) >= 2:
+                try:
+                    resume_from_byte = int(parts[1])
+                except ValueError:
+                    resume_from_byte = 0
+            if len(parts) >= 3:
+                try:
+                    write_delay_ms = int(parts[2])
+                except ValueError:
+                    write_delay_ms = 10
+
+            download_file_spi(url, resume_from_byte=resume_from_byte, write_delay_ms=write_delay_ms)
         elif cmd == "AC":#
             if self.ack_sem==1:
                 self.ack_sem=0
index 957c972..3317858 100644 (file)
@@ -719,7 +719,7 @@ class HttpFileDownloadSpiTest:
     直接从固定URL下载文件并通过SPI发送,用于测试SPI传输速度
     """
     
-    def __init__(self, url=None, timeout=30, sizeof=255, spi_obj=None, resume_from_byte=0):
+    def __init__(self, url=None, timeout=30, sizeof=255, spi_obj=None, resume_from_byte=0, write_delay_ms=10):
         """
         初始化SPI传输测试
         
@@ -734,6 +734,7 @@ class HttpFileDownloadSpiTest:
         self.timeout = timeout
         self.sizeof = sizeof
         self.resume_from_byte = max(0, int(resume_from_byte))  # 确保非负整数
+        self.write_delay_ms = max(0, int(write_delay_ms))      # SPI写入后的延时,默认10ms
         self.downloader = HttpFileDownloader(timeout=timeout, sizeof=sizeof)
         
         # 初始化SPI对象
@@ -929,7 +930,8 @@ class HttpFileDownloadSpiTest:
                                 if hasattr(self.spi_obj, 'write'):
                                     try:
                                         self.spi_obj.write(tx_buffer, chunk_len)
-                                        utime.sleep_ms(10)
+                                        if self.write_delay_ms > 0:
+                                            utime.sleep_ms(self.write_delay_ms)
                                     except Exception as e:
                                         clog.error("SPI write error: {}".format(e))
                                         self.close()
@@ -1157,7 +1159,7 @@ def start_spi_speed_test():
 # ==================== 外部接口函数 ====================
 # 提供简单的函数接口,可以从外部传入URL进行下载和SPI传输
 
-def download_file_spi(url, timeout=30, sizeof=255, spi_obj=None, resume_from_byte=0):
+def download_file_spi(url, timeout=30, sizeof=255, spi_obj=None, resume_from_byte=0, write_delay_ms=10):
     """
     下载文件并通过SPI传输的简单接口函数
     
@@ -1195,7 +1197,7 @@ def download_file_spi(url, timeout=30, sizeof=255, spi_obj=None, resume_from_byt
         clog.error("download_file_spi: Invalid URL parameter")
         return False, 0.0, -1
     
-    test = HttpFileDownloadSpiTest(url=url, timeout=timeout, sizeof=sizeof, spi_obj=spi_obj, resume_from_byte=resume_from_byte)
+    test = HttpFileDownloadSpiTest(url=url, timeout=timeout, sizeof=sizeof, spi_obj=spi_obj, resume_from_byte=resume_from_byte, write_delay_ms=write_delay_ms)
     try:
         success, download_time, file_size = test.start_download_and_send()
         if success:
index 9639b36..9859f24 100644 (file)
@@ -213,7 +213,7 @@ static void http_download_spi_error_callback(const custom_spi_error_info_t *erro
                 const char *file_path = (strlen(g_download_file_path) > 0) ? g_download_file_path : NULL;
                 
                 // 调用断点重传函数
-                int resume_ret = http_file_download_resume(g_download_url, file_path, g_total_received_bytes, 0);
+                int resume_ret = http_file_download_resume(g_download_url, file_path, g_total_received_bytes, 0, 0);
                 
                 if (resume_ret != 0) {
                     cat1_print_err("HTTP download: Failed to resume download, error: %d\n", resume_ret);
@@ -410,7 +410,7 @@ void http_file_download_deinit(void)
  * 3. 使用信号量阻塞等待下载完成
  * 4. 下载完成后关闭文件并返回
  */
-int http_file_download_start(const char *url, const char *file_path, uint32_t timeout_ms)
+int http_file_download_start(const char *url, const char *file_path, uint32_t timeout_ms, uint32_t write_delay_ms)
 {
     if (url == NULL || strlen(url) == 0) {
         cat1_print_err("HTTP file download: Invalid URL\n");
@@ -492,8 +492,15 @@ int http_file_download_start(const char *url, const char *file_path, uint32_t ti
         cat1_print_info("HTTP file download: Timeout timer restarted (%u ms)\n", g_download_timeout_ms);
     }
     
-    // 通过UDP发送下载指令到CAT1(携带URL地址)
-    udp_send_msg_toCat1(UDP_CMD_HTTP_FILE_DOWNLOAD, (char *)url);
+    // 通过UDP发送下载指令到CAT1,附带写延时参数(格式:URL|resume_from_byte|write_delay_ms)
+    char udp_msg[1024] = {0};
+    int msg_len = snprintf(udp_msg, sizeof(udp_msg), "%s|%u|%u", url, 0u, write_delay_ms);
+    if (msg_len < 0 || msg_len >= (int)sizeof(udp_msg)) {
+        cat1_print_err("HTTP file download: Failed to format UDP message\n");
+        g_download_state = HTTP_DOWNLOAD_STATE_IDLE;
+        return -1;
+    }
+    udp_send_msg_toCat1(UDP_CMD_HTTP_FILE_DOWNLOAD, udp_msg);
     
     cat1_print_info("HTTP file download: Download command sent, waiting for completion...\n");
     
@@ -563,7 +570,7 @@ int http_file_download_start(const char *url, const char *file_path, uint32_t ti
  * 3. 使用信号量阻塞等待下载完成
  * 4. 下载完成后关闭文件并返回
  */
-int http_file_download_start_with_resume(const char *url, const char *file_path, uint32_t resume_from_byte, uint32_t timeout_ms)
+int http_file_download_start_with_resume(const char *url, const char *file_path, uint32_t resume_from_byte, uint32_t timeout_ms, uint32_t write_delay_ms)
 {
     if (url == NULL || strlen(url) == 0) {
         cat1_print_err("HTTP file download: Invalid URL\n");
@@ -665,26 +672,19 @@ int http_file_download_start_with_resume(const char *url, const char *file_path,
         cat1_print_info("HTTP file download: Timeout timer restarted (%u ms)\n", g_download_timeout_ms);
     }
     
-    // 通过UDP发送下载指令到CAT1
-    if (resume_from_byte > 0) {
-        // 断点重传:发送URL|resume_from_byte格式
-        char udp_msg[1024] = {0};
-        int msg_len = snprintf(udp_msg, sizeof(udp_msg), "%s|%u", url, resume_from_byte);
-        if (msg_len < 0 || msg_len >= (int)sizeof(udp_msg)) {
-            cat1_print_err("HTTP file download: Failed to format UDP message\n");
-            if (g_download_file_fd >= 0) {
-                close(g_download_file_fd);
-                g_download_file_fd = -1;
-            }
-            return -1;
+    // 通过UDP发送下载指令到CAT1,附带写延时参数
+    char udp_msg[1024] = {0};
+    int msg_len = snprintf(udp_msg, sizeof(udp_msg), "%s|%u|%u", url, resume_from_byte, write_delay_ms);
+    if (msg_len < 0 || msg_len >= (int)sizeof(udp_msg)) {
+        cat1_print_err("HTTP file download: Failed to format UDP message\n");
+        if (g_download_file_fd >= 0) {
+            close(g_download_file_fd);
+            g_download_file_fd = -1;
         }
-        udp_send_msg_toCat1(UDP_CMD_HTTP_FILE_DOWNLOAD, udp_msg);
-        cat1_print_info("HTTP file download: Resume command sent (URL: %s, resume from byte: %u)\n", url, resume_from_byte);
-    } else {
-        // 从头下载:只发送URL
-        udp_send_msg_toCat1(UDP_CMD_HTTP_FILE_DOWNLOAD, (char *)url);
-        cat1_print_info("HTTP file download: Download command sent\n");
+        return -1;
     }
+    udp_send_msg_toCat1(UDP_CMD_HTTP_FILE_DOWNLOAD, udp_msg);
+    cat1_print_info("HTTP file download: Download command sent (URL: %s, resume from byte: %u, write delay: %u ms)\n", url, resume_from_byte, write_delay_ms);
     
     cat1_print_info("HTTP file download: Waiting for completion...\n");
     
@@ -759,7 +759,7 @@ int http_file_download_start_with_resume(const char *url, const char *file_path,
  * - 文件会在下载完成或出错时由回调函数自动关闭
  * - 可以通过 http_file_download_get_state() 查询下载状态
  */
-int http_file_download_resume(const char *url, const char *file_path, uint32_t resume_from_byte, uint32_t timeout_ms)
+int http_file_download_resume(const char *url, const char *file_path, uint32_t resume_from_byte, uint32_t timeout_ms, uint32_t write_delay_ms)
 {
     if (url == NULL || strlen(url) == 0) {
         cat1_print_err("HTTP file download resume: Invalid URL\n");
@@ -838,7 +838,7 @@ int http_file_download_resume(const char *url, const char *file_path, uint32_t r
     
     // 格式化UDP消息:URL|resume_from_byte
     char udp_msg[1024] = {0};
-    int msg_len = snprintf(udp_msg, sizeof(udp_msg), "%s|%u", url, resume_from_byte);
+    int msg_len = snprintf(udp_msg, sizeof(udp_msg), "%s|%u|%u", url, resume_from_byte, write_delay_ms);
     if (msg_len < 0 || msg_len >= (int)sizeof(udp_msg)) {
         cat1_print_err("HTTP file download resume: Failed to format UDP message\n");
         if (g_download_file_fd >= 0) {
index b1aa713..4f7b8e2 100644 (file)
@@ -50,6 +50,7 @@ void http_file_download_deinit(void);
  * @param url 要下载的文件URL
  * @param file_path 保存文件的路径,NULL或空字符串表示不保存文件(仅接收数据)
  * @param timeout_ms 超时时间(毫秒),0表示使用默认值(300秒)
+ * @param write_delay_ms SPI写入后的延时(毫秒),0表示使用默认(10ms)
  * @return 0成功,-1失败
  * 
  * 此函数会:
@@ -58,7 +59,7 @@ void http_file_download_deinit(void);
  * 3. 使用信号量阻塞等待下载完成
  * 4. 下载完成后关闭文件并返回
  */
-int http_file_download_start(const char *url, const char *file_path, uint32_t timeout_ms);
+int http_file_download_start(const char *url, const char *file_path, uint32_t timeout_ms, uint32_t write_delay_ms);
 
 /**
  * @brief 开始HTTP文件下载(阻塞接口,支持断点重传)
@@ -66,6 +67,7 @@ int http_file_download_start(const char *url, const char *file_path, uint32_t ti
  * @param file_path 保存文件的路径,NULL或空字符串表示不保存文件(仅接收数据)
  * @param resume_from_byte 断点重传起始字节位置(0表示从头开始下载)
  * @param timeout_ms 超时时间(毫秒),0表示使用默认值(300秒)
+ * @param write_delay_ms SPI写入后的延时(毫秒),0表示使用默认(10ms)
  * @return 0成功,-1失败
  * 
  * 此函数会:
@@ -74,7 +76,7 @@ int http_file_download_start(const char *url, const char *file_path, uint32_t ti
  * 3. 使用信号量阻塞等待下载完成
  * 4. 下载完成后关闭文件并返回
  */
-int http_file_download_start_with_resume(const char *url, const char *file_path, uint32_t resume_from_byte, uint32_t timeout_ms);
+int http_file_download_start_with_resume(const char *url, const char *file_path, uint32_t resume_from_byte, uint32_t timeout_ms, uint32_t write_delay_ms);
 
 /**
  * @brief 开始HTTP文件断点重传(非阻塞接口)
@@ -82,6 +84,7 @@ int http_file_download_start_with_resume(const char *url, const char *file_path,
  * @param file_path 保存文件的路径,NULL或空字符串表示不保存文件(仅接收数据)
  * @param resume_from_byte 断点重传起始字节位置(从该位置继续下载)
  * @param timeout_ms 超时时间(毫秒),此参数已废弃,保留用于兼容性
+ * @param write_delay_ms SPI写入后的延时(毫秒),0表示使用默认(10ms)
  * @return 0成功,-1失败
  * 
  * 此函数会:
@@ -95,7 +98,7 @@ int http_file_download_start_with_resume(const char *url, const char *file_path,
  * - 文件会在下载完成或出错时由回调函数自动关闭
  * - 可以通过 http_file_download_get_state() 查询下载状态
  */
-int http_file_download_resume(const char *url, const char *file_path, uint32_t resume_from_byte, uint32_t timeout_ms);
+int http_file_download_resume(const char *url, const char *file_path, uint32_t resume_from_byte, uint32_t timeout_ms, uint32_t write_delay_ms);
 
 /**
  * @brief 通知下载完成(由外部调用,例如从CAT1收到完成消息时)
index 0ae2c22..af26ad2 100644 (file)
@@ -515,7 +515,7 @@ static uint32_t at_http_download_start(uint8_t *para, uint32_t paraLen, char *st
     cat1_print_info("Timeout: %u ms (%u seconds)\n", timeout_ms, timeout_ms / 1000);
     
     // 开始下载(阻塞接口)
-    int result = http_file_download_start("https://file-virtual-person-qcl.test.leiniao.com/ambybox/Emotions/StraightEyes/Amber/WorkAndStudy.mp4", actual_file_path, timeout_ms);
+    int result = http_file_download_start("https://file-virtual-person-qcl.test.leiniao.com/ambybox/Emotions/StraightEyes/Amber/WorkAndStudy.mp4", actual_file_path, timeout_ms, 10);
     
     if (result == 0) {
         // 获取统计信息
@@ -646,7 +646,7 @@ static uint32_t at_http_download_client_test(uint8_t *para, uint32_t paraLen, ch
     cat1_print_info("HTTPDLCLIENT: No file path provided, data will not be saved\n");
     
     // 使用新的SPI传输接口(不保存文件)
-    int result = http_file_download_start(url, NULL, 0);  // 使用默认超时时间,不保存文件
+    int result = http_file_download_start(url, NULL, 0, 10);  // 使用默认超时时间,不保存文件
     
     if (result == 0) {
         uint32_t total_bytes, total_packets;
index 8584242..4958bfc 100644 (file)
@@ -456,14 +456,14 @@ static uint32_t ln_ws_send_random_story_at(uint8_t *para, uint32_t paraLen, char
     const char *story_theme = "冒险"; // 默认主题
     
     // 解析参数
-    if (para != NULL && paraLen > 0) {
-        uint8_t argv[LN_MAX_ARGC][LN_MAX_ARGV_LEN] = {0};
-        uint32_t argc = 0;
+    // if (para != NULL && paraLen > 0) {
+    //     uint8_t argv[LN_MAX_ARGC][LN_MAX_ARGV_LEN] = {0};
+    //     uint32_t argc = 0;
         
-        if (ConvertCmdToParam(para, paraLen, argv, &argc) == LN_SUCCESS && argc >= 1) {
-            story_theme = (const char *)argv[0];
-        }
-    }
+    //     if (ConvertCmdToParam(para, paraLen, argv, &argc) == LN_SUCCESS && argc >= 1) {
+    //         story_theme = (const char *)argv[0];
+    //     }
+    // }
     
     printf("[LN][WS_SEND_RANDOM_STORY] Sending random story request with theme: %s\n", story_theme);
     
index de67e5d..f25c625 100644 (file)
@@ -695,14 +695,14 @@ int uapi_ln_download_file_resume_with_retry(const char *url, const char *save_pa
     uapi_ln_add_vote();
 
     // int ret = uapi_ln_download_file_resume(url, save_path);
-    int ret = http_file_download_start(url, save_path, 300*100);
+    int ret = http_file_download_start(url, save_path, 300*100, 10);
     if (ERRCODE_SUCC != ret)
     {
         for (int i = 1; i <= max_retries; i++)
         {
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD_RESUME_WITH_RETRY] 重试 %d/%d", i, max_retries);
             // ret = uapi_ln_download_file_resume(url, save_path);
-            ret = http_file_download_start(url, save_path, 300*100);
+            ret = http_file_download_start(url, save_path, 300*100, 10);
             if (ERRCODE_SUCC == ret)
             {
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "[DOWNLOAD_RESUME_WITH_RETRY] 重试成功 %d", i);
index 2e08c82..cc6a4e3 100644 (file)
@@ -703,7 +703,7 @@ static int ln_download_file_to_path(const char *full_url, const char *save_path,
     }
 
     // 开始下载,超时时间设置为300秒(300*1000毫秒)
-    int ret = http_file_download_start(full_url, save_path, 300*1000);
+    int ret = http_file_download_start(full_url, save_path, 300*1000, 10);
     
     // 反初始化HTTP文件下载服务
     http_file_download_deinit();
index 8b782dc..f41f93e 100644 (file)
@@ -88,6 +88,8 @@ int ln_http_download_init(void)
         WEARABLE_LOGW(WEARABLE_LOG_MODULE_APP, "[HTTP_DL] Download service already initialized");
         return 0;
     }
+    cat_sync_timer_control(0);
+
     
     int ret = http_file_download_init(ln_http_download_data_callback);
     if (ret == 0) {
@@ -115,6 +117,8 @@ void ln_http_download_deinit(void)
                      g_py_ver, LN_HTTP_DOWNLOAD_MIN_PY_VER);
         return;
     }
+    cat_sync_timer_control(1);
+
     
     if (!g_download_service_initialized) {
         WEARABLE_LOGW(WEARABLE_LOG_MODULE_APP, "[HTTP_DL] Download service not initialized");
@@ -175,7 +179,7 @@ int ln_http_download_file_do(const char *url, uint32_t timeout_ms)
                   url, timeout_ms);
     
     // file_path传入NULL,不写入文件,数据通过内部回调处理
-    int ret = http_file_download_start(url, NULL, timeout_ms);
+    int ret = http_file_download_start(url, NULL, timeout_ms, 10);
     
     if (ret == 0) {
         // 获取下载统计信息
@@ -282,7 +286,7 @@ int ln_http_download_file_with_resume(const char *url, uint32_t resume_from_byte
     }
     
     // file_path传入NULL,不写入文件,数据通过内部回调处理
-    int ret = http_file_download_start_with_resume(url, NULL, resume_from_byte, timeout_ms);
+    int ret = http_file_download_start_with_resume(url, NULL, resume_from_byte, timeout_ms, 10);
     
     if (ret == 0) {
         // 获取下载统计信息
index 4e35dec..71265c8 100644 (file)
@@ -206,7 +206,7 @@ static void custom_spi_read_normal(void)
         }
         
         // 验证数据长度合理性(应该在0到SPI_PACKET_DATA_SIZE之间)
-        if (data_len > SPI_PACKET_DATA_SIZE || data_len==0) {
+        if (data_len > SPI_PACKET_DATA_SIZE ) {
             printf("SPI packet error: invalid data length %u (max: %u)\n", 
                    data_len, SPI_PACKET_DATA_SIZE);
             total_byte_error_cnt++;