From b53f1dccba5d3046701b0fdb118dfa6de16a8de2 Mon Sep 17 00:00:00 2001 From: hcj <1224667075@qq.com> Date: Mon, 15 Dec 2025 14:54:20 +0800 Subject: [PATCH] =?utf8?q?=E5=A2=9E=E5=8A=A0spi=E4=B8=8B=E8=BD=BD=E6=94=AF?= =?utf8?q?=E6=8C=81=E5=BB=B6=E6=97=B6=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- cat1modem/src/LeiNiao/cat1Service.py | 42 +++++++++------- cat1modem/src/LeiNiao/httpfiledownload.py | 10 ++-- .../Service/http_file_download_client.c | 50 +++++++++---------- .../include/http_file_download_client.h | 9 ++-- code/sdk/zhihui/4gTest/cat1_at_cmd.c | 4 +- .../zhihui/leiniao/imsl_ln/leiniao_api_at.c | 14 +++--- code/sdk/zhihui/leiniao/imsl_ln/ln_api.c | 4 +- code/sdk/zhihui/leiniao/imsl_ln/ln_api_ota.c | 2 +- .../leiniao/imsl_ln/ln_websoket_api_ext.c | 8 ++- code/sdk/zhihui/utils/custom_spi.c | 2 +- 10 files changed, 80 insertions(+), 65 deletions(-) diff --git a/cat1modem/src/LeiNiao/cat1Service.py b/cat1modem/src/LeiNiao/cat1Service.py index 5f169bc70..f7fcd288e 100644 --- a/cat1modem/src/LeiNiao/cat1Service.py +++ b/cat1modem/src/LeiNiao/cat1Service.py @@ -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 diff --git a/cat1modem/src/LeiNiao/httpfiledownload.py b/cat1modem/src/LeiNiao/httpfiledownload.py index 957c9724b..331785811 100644 --- a/cat1modem/src/LeiNiao/httpfiledownload.py +++ b/cat1modem/src/LeiNiao/httpfiledownload.py @@ -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: diff --git a/code/sdk/zhihui/4g/cat1Service/Service/http_file_download_client.c b/code/sdk/zhihui/4g/cat1Service/Service/http_file_download_client.c index 9639b36a3..9859f2439 100644 --- a/code/sdk/zhihui/4g/cat1Service/Service/http_file_download_client.c +++ b/code/sdk/zhihui/4g/cat1Service/Service/http_file_download_client.c @@ -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) { diff --git a/code/sdk/zhihui/4g/cat1Service/include/http_file_download_client.h b/code/sdk/zhihui/4g/cat1Service/include/http_file_download_client.h index b1aa71311..4f7b8e2a3 100644 --- a/code/sdk/zhihui/4g/cat1Service/include/http_file_download_client.h +++ b/code/sdk/zhihui/4g/cat1Service/include/http_file_download_client.h @@ -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收到完成消息时) diff --git a/code/sdk/zhihui/4gTest/cat1_at_cmd.c b/code/sdk/zhihui/4gTest/cat1_at_cmd.c index 0ae2c2256..af26ad2d9 100644 --- a/code/sdk/zhihui/4gTest/cat1_at_cmd.c +++ b/code/sdk/zhihui/4gTest/cat1_at_cmd.c @@ -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; diff --git a/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c b/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c index 8584242fb..4958bfc7c 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/leiniao_api_at.c @@ -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); diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c index de67e5d20..f25c625cd 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api.c @@ -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); diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_api_ota.c b/code/sdk/zhihui/leiniao/imsl_ln/ln_api_ota.c index 2e08c8250..cc6a4e3b1 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_api_ota.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_api_ota.c @@ -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(); diff --git a/code/sdk/zhihui/leiniao/imsl_ln/ln_websoket_api_ext.c b/code/sdk/zhihui/leiniao/imsl_ln/ln_websoket_api_ext.c index 8b782dc44..f41f93e21 100644 --- a/code/sdk/zhihui/leiniao/imsl_ln/ln_websoket_api_ext.c +++ b/code/sdk/zhihui/leiniao/imsl_ln/ln_websoket_api_ext.c @@ -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) { // 获取下载统计信息 diff --git a/code/sdk/zhihui/utils/custom_spi.c b/code/sdk/zhihui/utils/custom_spi.c index 4e35dec87..71265c8f1 100644 --- a/code/sdk/zhihui/utils/custom_spi.c +++ b/code/sdk/zhihui/utils/custom_spi.c @@ -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++; -- 2.17.1