From bf8eeed634287ff9c1a686244e79b791af1406d9 Mon Sep 17 00:00:00 2001 From: "ethan.du" Date: Fri, 24 Apr 2020 17:30:48 +0800 Subject: [PATCH] bugfix ota download file imcomplete --- platform/os/freertos/HAL_OS_freertos.c | 4 ++ platform/os/linux/HAL_OS_linux.c | 3 ++ platform/os/nos/HAL_OS_nos.c | 4 ++ samples/ota/ota_sample.c | 19 +++++-- src/ota/include/ota_internal.h | 30 +---------- src/ota/src/ota_client.c | 71 +++++++++++++++----------- src/ota/src/ota_lib.c | 39 +++++++++++++- src/sdk-impl/uiot_export_ota.h | 62 +++++++++++++++++++--- src/sdk-impl/uiot_import.h | 7 +++ 9 files changed, 167 insertions(+), 72 deletions(-) diff --git a/platform/os/freertos/HAL_OS_freertos.c b/platform/os/freertos/HAL_OS_freertos.c index 38ae5b2..b7e5479 100644 --- a/platform/os/freertos/HAL_OS_freertos.c +++ b/platform/os/freertos/HAL_OS_freertos.c @@ -143,6 +143,10 @@ int HAL_FileWrite(void *dest, uint32_t offset, void *src, uint32_t size){ return 0; } +void HAL_FileClose(void *fp){ + ; +} + IoT_Error_t HAL_GetProductSN(_OU_ char productSN[IOT_PRODUCT_SN_LEN + 1]) { #ifdef DEBUG_DEV_INFO_USED int len = strlen(sg_product_sn); diff --git a/platform/os/linux/HAL_OS_linux.c b/platform/os/linux/HAL_OS_linux.c index ec49971..c399bde 100644 --- a/platform/os/linux/HAL_OS_linux.c +++ b/platform/os/linux/HAL_OS_linux.c @@ -152,6 +152,9 @@ int HAL_FileWrite(void *dest, uint32_t offset, void *src, uint32_t size){ return FAILURE_RET; } +void HAL_FileClose(void *fp){ + fclose((FILE *)fp); +} IoT_Error_t HAL_GetProductSN(_OU_ char productSN[IOT_PRODUCT_SN_LEN + 1]) { #ifdef DEBUG_DEV_INFO_USED diff --git a/platform/os/nos/HAL_OS_nos.c b/platform/os/nos/HAL_OS_nos.c index 2fa5627..f3532ac 100644 --- a/platform/os/nos/HAL_OS_nos.c +++ b/platform/os/nos/HAL_OS_nos.c @@ -104,6 +104,10 @@ int HAL_FileWrite(void *dest, uint32_t offset, void *src, uint32_t size){ return 0; } +void HAL_FileClose(void *fp){ + ; +} + IoT_Error_t HAL_GetProductSN(_OU_ char productSN[IOT_PRODUCT_SN_LEN + 1]) { #ifdef DEBUG_DEV_INFO_USED int len = strlen(sg_product_sn); diff --git a/samples/ota/ota_sample.c b/samples/ota/ota_sample.c index b239a14..b239a9b 100644 --- a/samples/ota/ota_sample.c +++ b/samples/ota/ota_sample.c @@ -89,6 +89,13 @@ static int _setup_connect_init_params(MQTTInitParams* initParams) return SUCCESS_RET; } +int IOT_OTA_FetchCallback_func(void *handle, IOT_OTA_UpstreamMsgType state) +{ + OTA_Struct_t * h_ota = (OTA_Struct_t *) handle; + printf("file:%s, state:%d\r\n",h_ota->download_file_name, state); + return SUCCESS_RET; +} + int main(int argc, char **argv) { int rc; @@ -107,7 +114,7 @@ int main(int argc, char **argv) return FAILURE_RET; } - void *h_ota = IOT_OTA_Init(UIOT_MY_PRODUCT_SN, UIOT_MY_DEVICE_SN, client); + void *h_ota = IOT_OTA_Init(UIOT_MY_PRODUCT_SN, UIOT_MY_DEVICE_SN, client, IOT_OTA_FetchCallback_func); if (NULL == h_ota) { IOT_MQTT_Destroy(&client); LOG_ERROR("init OTA failed"); @@ -124,8 +131,10 @@ int main(int argc, char **argv) LOG_ERROR("Request firmware failed"); return FAILURE_RET; } - - IOT_MQTT_Yield(client, 5000); - - return 0; + + while(1) + { + IOT_MQTT_Yield(client, 5000); + } } + diff --git a/src/ota/include/ota_internal.h b/src/ota/include/ota_internal.h index b045552..72827f2 100644 --- a/src/ota/include/ota_internal.h +++ b/src/ota/include/ota_internal.h @@ -24,34 +24,6 @@ extern "C" { #include "uiot_export_ota.h" -typedef enum { - - OTA_REPORT_UNDEFINED_ERROR = -6, - OTA_REPORT_FIRMWARE_BURN_FAILED = -5, - OTA_REPORT_MD5_MISMATCH = -4, - OTA_REPORT_DOWNLOAD_TIMEOUT = -3, - OTA_REPORT_SIGNATURE_EXPIRED = -2, - OTA_REPORT_FIRMWARE_NOT_EXIST = -1, - OTA_REPORT_NONE = 0, - OTA_REPORT_DOWNLOADING = 1, - OTA_REPORT_BURNING = 2, - OTA_REPORT_SUCCESS = 3, - OTA_REQUEST_FIRMWARE = 4, - OTA_REPORT_VERSION = 5, - -} IOT_OTA_UpstreamMsgType; - -/* OTA状态 */ -typedef enum { - - OTA_STATE_UNINITED = 0, /* 未初始化 */ - OTA_STATE_INITED, /* 初始化完成 */ - OTA_STATE_FETCHING, /* 正在下载固件 */ - OTA_STATE_FETCHED, /* 固件下载完成 */ - OTA_STATE_DISCONNECTED /* 连接已经断开 */ - -} IOT_OTA_State; - // OTA Signal Channel typedef void (*OnOTAMessageCallback)(void *pContext, const char *msg, uint32_t msgLen); @@ -84,7 +56,7 @@ void ota_lib_md5_deinit(void *md5); int ota_lib_get_msg_type(char *json, char **type); -int ota_lib_get_params(char *json, char **url, char **version, char **md5, +int ota_lib_get_params(char *json, char **url, char **file_name, char **version, char **md5, uint32_t *fileSize); int ota_lib_gen_upstream_msg(char *buf, size_t bufLen, const char *version, int progress, diff --git a/src/ota/src/ota_client.c b/src/ota/src/ota_client.c index b1e5fd3..dbfca71 100644 --- a/src/ota/src/ota_client.c +++ b/src/ota/src/ota_client.c @@ -62,26 +62,6 @@ static void print_progress(uint32_t percent) HAL_Printf("Download: [%s] %d%%\r\n", progress_sign, percent); } -typedef struct { - uint32_t id; /* message id */ - IOT_OTA_State state; /* OTA state */ - uint32_t size_last_fetched; /* size of last downloaded */ - uint32_t size_fetched; /* size of already downloaded */ - uint32_t size_file; /* size of file */ - - char *url; /* point to URL */ - char *version; /* point to version */ - char *md5sum; /* MD5 string */ - - void *md5; /* MD5 handle */ - void *ch_signal; /* channel handle of signal exchanged with OTA server */ - void *ch_fetch; /* channel handle of download */ - - int err; /* last error code */ - - Timer report_timer; -} OTA_Struct_t; - static void _ota_callback(void *pContext, const char *msg, uint32_t msg_len) { char *msg_method = NULL; char *msg_str = NULL; @@ -115,7 +95,7 @@ static void _ota_callback(void *pContext, const char *msg, uint32_t msg_len) { goto do_exit; } - if (SUCCESS_RET != ota_lib_get_params(msg_str, &h_ota->url, &h_ota->version, + if (SUCCESS_RET != ota_lib_get_params(msg_str, &h_ota->url, &h_ota->download_file_name, &h_ota->version, &h_ota->md5sum, &h_ota->size_file)) { LOG_ERROR("Get firmware parameter failed"); goto do_exit; @@ -243,8 +223,7 @@ do_exit: return ret; } - -void *IOT_OTA_Init(const char *product_sn, const char *device_sn, void *ch_signal) +void *IOT_OTA_Init(const char *product_sn, const char *device_sn, void *ch_signal, IOT_OTA_FetchCallback fetch_callback_func) { POINTER_VALID_CHECK(product_sn, NULL); POINTER_VALID_CHECK(device_sn, NULL); @@ -265,6 +244,8 @@ void *IOT_OTA_Init(const char *product_sn, const char *device_sn, void *ch_signa goto do_exit; } + h_ota->fetch_callback_func = fetch_callback_func; + h_ota->md5 = ota_lib_md5_init(); if (NULL == h_ota->md5) { LOG_ERROR("initialize md5 failed"); @@ -303,7 +284,6 @@ int IOT_OTA_Destroy(void *handle) } osc_deinit(h_ota->ch_signal); - ofc_deinit(h_ota->ch_fetch); ota_lib_md5_deinit(h_ota->md5); if (NULL != h_ota->url) { @@ -318,10 +298,29 @@ int IOT_OTA_Destroy(void *handle) HAL_Free(h_ota->md5sum); } + if (NULL != h_ota->download_file_name) { + HAL_Free(h_ota->download_file_name); + } + HAL_Free(h_ota); return SUCCESS_RET; } +void IOT_OTA_Clear(void *handle) +{ + OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; + memset(h_ota->url, 0, strlen(h_ota->url)); + memset(h_ota->download_file_name, 0, strlen(h_ota->download_file_name)); + memset(h_ota->version, 0, strlen(h_ota->version)); + memset(h_ota->md5sum, 0, strlen(h_ota->md5sum)); + h_ota->state = OTA_STATE_UNINITED; + h_ota->size_last_fetched = 0; + h_ota->size_fetched = 0; + h_ota->size_file = 0; + ota_lib_md5_deinit(h_ota->md5); + h_ota->md5 = ota_lib_md5_init(); + return; +} int IOT_OTA_ReportVersion(void *handle, const char *version) { @@ -335,11 +334,16 @@ int IOT_OTA_RequestFirmware(void *handle, const char *version) } int IOT_OTA_ReportSuccess(void *handle, const char *version) -{ +{ + OTA_Struct_t *h_ota = (OTA_Struct_t *)handle; + + if(h_ota->fetch_callback_func != NULL) + { + h_ota->fetch_callback_func(handle, OTA_REPORT_SUCCESS); + } return send_upstream_msg_with_version(handle, version, OTA_REPORT_SUCCESS); } - int IOT_OTA_ReportFail(void *handle, IOT_OTA_ReportErrCode err_code) { POINTER_VALID_CHECK(handle, ERR_OTA_INVALID_PARAM); @@ -374,6 +378,9 @@ int IOT_OTA_ReportFail(void *handle, IOT_OTA_ReportErrCode err_code) goto do_exit; } + if(h_ota->fetch_callback_func != NULL) + h_ota->fetch_callback_func(handle, (IOT_OTA_UpstreamMsgType)err_code); + do_exit: if (NULL != msg_upstream) { HAL_Free(msg_upstream); @@ -597,9 +604,9 @@ int IOT_OTA_fw_download(void *handle) IOT_OTA_Ioctl(h_ota, OTA_IOCTL_FILE_SIZE, &file_size, 4); - if (NULL == (fp = HAL_FileOpen("ota.bin"))) { - LOG_ERROR("open file failed"); - goto __exit; + if (NULL == (fp = HAL_FileOpen(h_ota->download_file_name))) { + LOG_ERROR("open file failed"); + return ERR_OTA_INVALID_PARAM; } buffer_read = (char *)HAL_Malloc(HTTP_OTA_BUFF_LEN); @@ -651,8 +658,10 @@ int IOT_OTA_fw_download(void *handle) __exit: if (buffer_read != NULL) - HAL_Free(buffer_read); - + HAL_Free(buffer_read); + IOT_OTA_Clear(h_ota); + HAL_FileClose(fp); + return ret; } diff --git a/src/ota/src/ota_lib.c b/src/ota/src/ota_lib.c index 45c1095..92709da 100644 --- a/src/ota/src/ota_lib.c +++ b/src/ota/src/ota_lib.c @@ -64,8 +64,36 @@ int ota_lib_get_msg_type(char *json, char **type) { FUNC_EXIT_RC(SUCCESS_RET); } +static int _utils_parse_name(const char *url, char *name) { + char *host_ptr = (char *) strstr(url, "://"); + uint32_t name_len = 0; + char *path_ptr; + char *name_ptr; -int ota_lib_get_params(char *json, char **url, char **version, char **md5, + if (host_ptr == NULL) { + return -1; /* URL is invalid */ + } + host_ptr += 3; + + path_ptr = strchr(host_ptr, '/'); + if (NULL == path_ptr) { + return -2; + } + + name_ptr = strchr(path_ptr, '?'); + if (NULL == name_ptr) { + return -2; + } + + name_len = name_ptr - path_ptr; + + memcpy(name, path_ptr + 1, name_len - 1); + name[name_len] = '\0'; + + return SUCCESS_RET; +} + +int ota_lib_get_params(char *json, char **url, char **file_name, char **version, char **md5, uint32_t *fileSize) { FUNC_ENTRY; @@ -73,6 +101,7 @@ int ota_lib_get_params(char *json, char **url, char **version, char **md5, char *version_str; char *url_str; char *md5_str; + char *name_str; /* get version */ if (NULL == (version_str = LITE_json_value_of(VERSION_FIELD, json))) { @@ -94,6 +123,14 @@ int ota_lib_get_params(char *json, char **url, char **version, char **md5, } *url = url_str; + if(NULL == (name_str = HAL_Malloc(strlen(url_str)))) + { + LOG_ERROR("malloc url_str failed"); + FUNC_EXIT_RC(ERR_OTA_GENERAL_FAILURE); + } + _utils_parse_name(url_str, name_str); + *file_name = name_str; + /* get md5 */ if (NULL == (md5_str = LITE_json_value_of(MD5_FIELD, json))) { LOG_ERROR("get value of md5 failed"); diff --git a/src/sdk-impl/uiot_export_ota.h b/src/sdk-impl/uiot_export_ota.h index 5455825..5901f93 100644 --- a/src/sdk-impl/uiot_export_ota.h +++ b/src/sdk-impl/uiot_export_ota.h @@ -50,18 +50,70 @@ typedef enum { } IOT_OTA_ReportErrCode; +typedef enum { + + OTA_REPORT_UNDEFINED_ERROR = -6, + OTA_REPORT_FIRMWARE_BURN_FAILED = -5, + OTA_REPORT_MD5_MISMATCH = -4, + OTA_REPORT_DOWNLOAD_TIMEOUT = -3, + OTA_REPORT_SIGNATURE_EXPIRED = -2, + OTA_REPORT_FIRMWARE_NOT_EXIST = -1, + OTA_REPORT_NONE = 0, + OTA_REPORT_DOWNLOADING = 1, + OTA_REPORT_BURNING = 2, + OTA_REPORT_SUCCESS = 3, + OTA_REQUEST_FIRMWARE = 4, + OTA_REPORT_VERSION = 5, + +} IOT_OTA_UpstreamMsgType; + +typedef int (*IOT_OTA_FetchCallback)(void *handle, IOT_OTA_UpstreamMsgType state); + +/* OTA状态 */ +typedef enum { + + OTA_STATE_UNINITED = 0, /* 未初始化 */ + OTA_STATE_INITED, /* 初始化完成 */ + OTA_STATE_FETCHING, /* 正在下载固件 */ + OTA_STATE_FETCHED, /* 固件下载完成 */ + OTA_STATE_DISCONNECTED /* 连接已经断开 */ + +} IOT_OTA_State; + +typedef struct { + uint32_t id; /* message id */ + IOT_OTA_State state; /* OTA state */ + uint32_t size_last_fetched; /* size of last downloaded */ + uint32_t size_fetched; /* size of already downloaded */ + uint32_t size_file; /* size of file */ + + char *url; /* point to URL */ + char *download_file_name; /* download file name */ + char *version; /* point to version */ + char *md5sum; /* MD5 string */ + + void *md5; /* MD5 handle */ + void *ch_signal; /* channel handle of signal exchanged with OTA server */ + void *ch_fetch; /* channel handle of download */ + + int err; /* last error code */ + + Timer report_timer; + IOT_OTA_FetchCallback fetch_callback_func; +} OTA_Struct_t; /** * @brief 初始化OTA模块和返回句柄 * MQTT客户端必须在调用此接口之前进行初始化 * - * @param product_sn: 指定产品序列号 - * @param device_sn: 指定设备序列号 - * @param ch_signal: 指定的信号通道. + * @param product_sn: 指定产品序列号 + * @param device_sn: 指定设备序列号 + * @param ch_signal: 指定的信号通道. + * @param fetch_callback_func: ota下载完成后的回调函数指针. * * @retval : 成功则返回句柄,失败返回NULL */ -void *IOT_OTA_Init(const char *product_sn, const char *device_sn, void *ch_signal); +void *IOT_OTA_Init(const char *product_sn, const char *device_sn, void *ch_signal, IOT_OTA_FetchCallback fetch_callback_func); /** @@ -101,7 +153,6 @@ int IOT_OTA_ReportVersion(void *handle, const char *version); */ int IOT_OTA_ReportProgress(void *handle, int progress, IOT_OTA_ProgressState state); - /** * @brief 向OTA服务器上报升级成功 * @@ -113,7 +164,6 @@ int IOT_OTA_ReportProgress(void *handle, int progress, IOT_OTA_ProgressState sta */ int IOT_OTA_ReportSuccess(void *handle, const char *version); - /** * @brief 向OTA服务器上报失败信息 * diff --git a/src/sdk-impl/uiot_import.h b/src/sdk-impl/uiot_import.h index 0dc4897..37cb773 100644 --- a/src/sdk-impl/uiot_import.h +++ b/src/sdk-impl/uiot_import.h @@ -143,6 +143,13 @@ void *HAL_FileOpen(char *file_path); */ int HAL_FileWrite(void *dest, uint32_t offset, void *src, uint32_t size); +/** + * @brief 关闭要写的文件. + * + * @param fp 文件指针. + */ +void HAL_FileClose(void *fp); + /** * @brief 获取产品序列号。从设备持久化存储(例如FLASH)中读取产品序列号。 *