fota_ftp_demo.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. /*================================================================
  2. Copyright (c) 2021, Quectel Wireless Solutions Co., Ltd. All rights reserved.
  3. Quectel Wireless Solutions Proprietary and Confidential.
  4. =================================================================*/
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include "ql_type.h"
  9. #include "ql_api_osi.h"
  10. #include "ql_log.h"
  11. #include "ql_api_datacall.h"
  12. #include "ql_fs.h"
  13. #include "ql_power.h"
  14. #include "ql_api_dev.h"
  15. #include "ql_api_fota.h"
  16. #include "ql_ftp_client.h"
  17. #include "ql_app_feature_config.h"
  18. #define QL_FOTA_FTP_LOG_LEVEL QL_LOG_LEVEL_INFO
  19. #define QL_FOTA_FTP_LOG(msg, ...) QL_LOG(QL_FOTA_FTP_LOG_LEVEL, "ql_FOTA_ftp", msg, ##__VA_ARGS__)
  20. #define QL_FOTA_FTP_LOG_PUSH(msg, ...) QL_LOG_PUSH("ql_FOTA_ftp", msg, ##__VA_ARGS__)
  21. #define QL_APP_FEATURE_FTP_FOTA
  22. #ifdef QL_APP_FEATURE_FTP_FOTA
  23. #define QL_VERSION_MAX 256
  24. float approximate_zero = 1e-6; //近似0值,用于两个浮点型变量判相等
  25. /* 默认配置,用户可自行修改 */
  26. bool file_progress_show = true; //默认显示下载进度
  27. char local_filename[] = "UFS:fota.pac"; //本地默认升级包地址
  28. int profile_idx = 1; //cid
  29. uint8_t nSim = 0; //sid
  30. //FTP服务器相关信息
  31. char hostname[] = "120.27.243.131"; //FTP服务器 IP:端口号
  32. char username[] = "qx"; //FTP服务器用户名
  33. char password[] = "qx900"; //FTP服务器用户密码
  34. char file_full_path[] = "4G04/EC600G/output.pack"; //FTP服务器文件路径
  35. ql_task_t fota_ftp_task = NULL;
  36. typedef enum{
  37. QL_FTP_FOTA_SUCCESS = 0,
  38. QL_ERROR_INVALID_PARAM = -1,
  39. }ql_fota_ftp_error_code_e;
  40. typedef enum{
  41. DOWN_INIT, //初始阶段
  42. DOWN_DOWNING, //下载中
  43. DOWN_INTR, //下载被中断
  44. DOWN_DOWNED, //下载完成
  45. DOWN_NOSPACE, //没有空间
  46. DOWN_OTHER_ERROR, //执行下载时其他错误
  47. }fota_down_state;
  48. typedef struct{
  49. bool show; //是否显示文件下载进度
  50. unsigned long total_size; //从FTP服务器所要下载的文件总大小
  51. unsigned long downloaded_size; //已下载到本地的FOTA文件大小
  52. unsigned long last_downloaded_size; //上次下载完成后文件的大小
  53. }fota_file_progress;
  54. typedef struct{
  55. void *ftp_handle; //用于与FTP服务器进行文件交互的句柄
  56. bool poweroutage_resume; //0-不支持断点续传,1-支持断点续传
  57. int profile_idx; //cid
  58. uint8_t nSim; //sid
  59. fota_down_state down_state; //当前从FTP服务器下载文件的下载状态
  60. fota_file_progress file_progress; //当前从FTP服务器文件信息和已下载文件的具体进度信息
  61. char local_filename[QL_FOTA_PACK_NAME_MAX_LEN]; //下载到本地的升级文件的位置
  62. //FTP服务器相关
  63. char hostname[256]; //FTP服务器: IP地址+端口号 (IP地址:端口号)
  64. char username[256]; //FTP服务器用户名
  65. char password[256]; //FTP服务器用户密码
  66. char file_full_path[256]; //所要从FTP服务器上获取的文件的具体路径信息,包括文件名. (文件路径/文件名)
  67. }fota_ftp_client_t;
  68. fota_ftp_client_t fota_ftp_cli = {.down_state = DOWN_INIT};
  69. int fota_ftp_client_init(fota_ftp_client_t *fota_ftp_cli_p)
  70. {
  71. int ret = QL_FTP_FOTA_SUCCESS;
  72. QFILE local_file_fd = -1; //用来保存本地FTP FOTA文件的文件描述符
  73. fota_ftp_cli_p->poweroutage_resume = true;
  74. fota_ftp_cli_p->profile_idx = profile_idx;
  75. fota_ftp_cli_p->nSim = nSim;
  76. fota_ftp_cli_p->down_state = DOWN_INIT;
  77. fota_ftp_cli_p->file_progress.show = file_progress_show;
  78. fota_ftp_cli_p->file_progress.total_size = 0; //等连接到FTP服务器,获得服务器文件大小后才赋值
  79. fota_ftp_cli_p->file_progress.downloaded_size = 0;
  80. fota_ftp_cli_p->file_progress.last_downloaded_size = 0;
  81. memcpy(fota_ftp_cli_p->local_filename, local_filename, strlen(local_filename) ); //默认升级包地址
  82. //FTP服务器相关信息
  83. memcpy(fota_ftp_cli_p->hostname, hostname, strlen(hostname) );
  84. memcpy(fota_ftp_cli_p->username, username, strlen(username) );
  85. memcpy(fota_ftp_cli_p->password, password, strlen(password) );
  86. memcpy(fota_ftp_cli_p->file_full_path, file_full_path, strlen(file_full_path) );
  87. //本次对FTP服务器的文件进行操作时,文件句柄都需要重新创建
  88. fota_ftp_cli_p->ftp_handle = ql_ftp_client_new();
  89. if (NULL == fota_ftp_cli_p->ftp_handle)
  90. {
  91. //未成功创建句柄时,返回错误,并且退出线程
  92. ret = QL_ERROR_INVALID_PARAM;
  93. }
  94. local_file_fd = ql_fopen(fota_ftp_cli_p->local_filename,"wb+");
  95. if(local_file_fd <= 0)
  96. {
  97. QL_FOTA_FTP_LOG("ftp fota loc file open failed ret : %d!",local_file_fd);
  98. ret = QL_ERROR_INVALID_PARAM;
  99. }
  100. ql_fclose(local_file_fd);
  101. return ret;
  102. }
  103. int fota_ftp_net_register(uint8_t nSim,int profile_idx)
  104. {
  105. int ret = QL_FTP_FOTA_SUCCESS;
  106. ql_data_call_info_s info;
  107. memset(&info, 0x00, sizeof(ql_data_call_info_s));
  108. for (int i = 0; i < 10; i++)
  109. {
  110. ret = ql_network_register_wait(nSim, 120);
  111. if (QL_FTP_FOTA_SUCCESS == ret)
  112. {
  113. break;
  114. }
  115. ql_rtos_task_sleep_s(1);
  116. }
  117. if (QL_FTP_FOTA_SUCCESS != ret)
  118. {
  119. QL_FOTA_FTP_LOG("network register failure!");
  120. return QL_ERROR_INVALID_PARAM;
  121. }
  122. ret = ql_set_data_call_asyn_mode(nSim, profile_idx, 0);
  123. QL_FOTA_FTP_LOG("network datacall asyn mode ret = %d",ret);
  124. ql_start_data_call(nSim, profile_idx, QL_PDP_TYPE_IP, "uninet", NULL, NULL, 0);
  125. QL_FOTA_FTP_LOG("network datacall result ret = %d",ret);
  126. if (0 != ret)
  127. {
  128. QL_FOTA_FTP_LOG("data call failure!");
  129. }
  130. ret = ql_get_data_call_info(nSim, profile_idx, &info);
  131. if (0 != ret)
  132. {
  133. ql_stop_data_call(nSim, profile_idx);
  134. return QL_ERROR_INVALID_PARAM;
  135. }
  136. return ret;
  137. }
  138. int fota_ftp_server_connect(fota_ftp_client_t *fota_ftp_cli_p)
  139. {
  140. int ret = QL_FTP_FOTA_SUCCESS;
  141. uint16_t sim_cid;
  142. ret = ql_bind_sim_and_profile(fota_ftp_cli_p->nSim, fota_ftp_cli_p->profile_idx, &sim_cid);
  143. if (ret != QL_DATACALL_SUCCESS)
  144. {
  145. return QL_ERROR_INVALID_PARAM;
  146. }
  147. ql_ftp_client_setopt(fota_ftp_cli_p->ftp_handle, QL_FTP_CLIENT_SIM_CID, sim_cid);
  148. ql_ftp_client_setopt(fota_ftp_cli_p->ftp_handle, QL_FTP_CLIENT_OPT_PDP_CID, fota_ftp_cli_p->profile_idx);
  149. ret = ql_ftp_client_open(fota_ftp_cli_p->ftp_handle, fota_ftp_cli_p->hostname, fota_ftp_cli_p->username, fota_ftp_cli_p->password);
  150. QL_FOTA_FTP_LOG("********** ql_ftp_client_open ret:%d **********",ret);
  151. return ret;
  152. }
  153. int fota_ftp_get_server_file_size(fota_ftp_client_t *fota_ftp_cli_p)
  154. {
  155. QL_FOTA_FTP_LOG("********** fota_ftp_get_server_file_size ***********");
  156. int ret = QL_FTP_FOTA_SUCCESS;
  157. double file_size = 0;
  158. ret = ql_ftp_client_size(fota_ftp_cli_p->ftp_handle, fota_ftp_cli_p->file_full_path, &file_size);
  159. fota_ftp_cli_p->file_progress.total_size = file_size;
  160. QL_FOTA_FTP_LOG("********** fota_ftp_cli_p->file_progress.total_size : %d **********", fota_ftp_cli_p->file_progress.total_size);
  161. return ret;
  162. }
  163. int fota_ftp_net_connect_ready(fota_ftp_client_t *fota_ftp_cli_p)
  164. {
  165. int ret = QL_FTP_FOTA_SUCCESS;
  166. int residual_space_size = 0;
  167. //网络注册,连接
  168. ret = fota_ftp_net_register(fota_ftp_cli_p->nSim, fota_ftp_cli_p->profile_idx);
  169. if (QL_FTP_FOTA_SUCCESS != ret)
  170. {
  171. QL_FOTA_FTP_LOG("********** Network registration failed **********");
  172. ret = QL_ERROR_INVALID_PARAM;
  173. goto exit;
  174. }
  175. //向FTP服务器发起连接请求
  176. ret = fota_ftp_server_connect(fota_ftp_cli_p);
  177. if (QL_FTP_FOTA_SUCCESS != ret)
  178. {
  179. //未成功与FTP服务器建立连接
  180. QL_FOTA_FTP_LOG("********** The connection to the FTP server was unsuccessful **********");
  181. ret = QL_ERROR_INVALID_PARAM;
  182. goto exit;
  183. }
  184. //获取FTP服务器所要下载的文件大小
  185. if (0 != fota_ftp_get_server_file_size(fota_ftp_cli_p))
  186. {
  187. //文件不存在于FTP服务器上
  188. QL_FOTA_FTP_LOG("********** The file to be downloaded does not exist or failed on the FTP server **********");
  189. //断开与FTP服务器的连接
  190. ql_ftp_client_close(fota_ftp_cli_p->ftp_handle);
  191. ret = QL_ERROR_INVALID_PARAM;
  192. goto exit;
  193. }
  194. //获取模块剩余空间大小
  195. residual_space_size = ql_fs_free_size(fota_ftp_cli_p->local_filename);
  196. QL_FOTA_FTP_LOG("********** residual_space_size:%d ftp file total_size:%d**********", residual_space_size,fota_ftp_cli_p->file_progress.total_size);
  197. //判断文件空间是否足够
  198. //当 total_size - downloaded_size > residual_space_size 时 空间不足
  199. if (fota_ftp_cli_p->file_progress.total_size > residual_space_size)
  200. {
  201. //剩余空间不足,无法下载FOTA文件
  202. QL_FOTA_FTP_LOG("********** There is not enough free space to download FOTA files **********");
  203. fota_ftp_cli_p->down_state = DOWN_NOSPACE;
  204. ql_remove(fota_ftp_cli_p->local_filename);
  205. //断开与FTP服务器的连接
  206. ql_ftp_client_close(fota_ftp_cli_p->ftp_handle);
  207. ret = QL_ERROR_INVALID_PARAM;
  208. goto exit;
  209. }
  210. exit:
  211. return ret;
  212. }
  213. void fota_ftp_show_file_progress(fota_ftp_client_t *fota_ftp_cli_p)
  214. {
  215. float last_download_progress = 0; //上次下载完成后的进度信息
  216. float download_progress = 0; //本次下载完成后的进度信息
  217. //避免除0中断
  218. if (0 == fota_ftp_cli_p->file_progress.total_size)
  219. {
  220. return;
  221. }
  222. last_download_progress = (float)(fota_ftp_cli_p->file_progress.last_downloaded_size)/(fota_ftp_cli_p->file_progress.total_size);
  223. download_progress = (float)(fota_ftp_cli_p->file_progress.downloaded_size)/(fota_ftp_cli_p->file_progress.total_size);
  224. //相同的进度不予显示
  225. if ( (download_progress - last_download_progress) < approximate_zero )
  226. {
  227. return;
  228. }
  229. download_progress = download_progress * 100;
  230. QL_FOTA_FTP_LOG("*************************************************************");
  231. QL_FOTA_FTP_LOG("********** Current file download progress : %.1f%% **********", download_progress);
  232. QL_FOTA_FTP_LOG("*************************************************************");
  233. }
  234. size_t fota_ftp_write_cb(void *ptr, size_t size, size_t nmemb, void *stream)
  235. {
  236. QL_FOTA_FTP_LOG("********** fota_ftp_write_cb **********");
  237. int ret = 0;
  238. QFILE fd = -1;
  239. fota_ftp_client_t *user_data;
  240. user_data = (fota_ftp_client_t *)stream;
  241. //"ab" 打开或新建一个二进制文件,只允许在文件末尾追写
  242. fd = ql_fopen(user_data->local_filename, "ab");
  243. //回写数据前将状态置为中断,ql_fwrite出现异常无法继续执行下去时,将会一直保持此状态,再次调用FTP FOTA线程时,将使用本次的断点信息继续下载
  244. user_data->down_state = DOWN_INTR;
  245. ret = ql_fwrite(ptr, size, nmemb, fd);
  246. QL_FOTA_FTP_LOG("ql_fwrite ret = %d",ret);
  247. ql_fclose(fd);
  248. if (size*nmemb == ret)
  249. {
  250. user_data->file_progress.downloaded_size += size*nmemb;
  251. if (true == user_data->file_progress.show)
  252. {
  253. //显示本次调用回调fota_ftp_write_cb,回写文件当前下载进度
  254. fota_ftp_show_file_progress(user_data);
  255. }
  256. user_data->file_progress.last_downloaded_size = user_data->file_progress.downloaded_size;
  257. //当前状态还视为下载中,是否下载完成在 fota_ftp_get_file 通过本地文件与服务器文件大小进行判断
  258. user_data->down_state = DOWN_DOWNING;
  259. }
  260. else
  261. {
  262. if (QL_FILE_NO_SPACE == ret)
  263. {
  264. //空间不足,无法写入数据
  265. user_data->down_state = DOWN_NOSPACE;
  266. }
  267. else
  268. {
  269. user_data->down_state = DOWN_OTHER_ERROR;
  270. }
  271. return 0;
  272. }
  273. //ret的其余错误码均视为回写过程中的异常中断
  274. QL_FOTA_FTP_LOG();
  275. return size*nmemb;
  276. }
  277. void fota_ftp_get_file(fota_ftp_client_t *fota_ftp_cli_p)
  278. {
  279. QL_FOTA_FTP_LOG("********** fota_ftp_get_file **********");
  280. int ret;
  281. //设置文件下载起始偏移为上次文件下载之后的位置,初始偏移量为0
  282. QL_FOTA_FTP_LOG("********** downloaded_size : %ld**********", fota_ftp_cli_p->file_progress.downloaded_size);
  283. ql_ftp_client_setopt(fota_ftp_cli_p->ftp_handle, QL_FTP_CLIENT_OPT_START_POS, fota_ftp_cli_p->file_progress.downloaded_size);
  284. ret = ql_ftp_client_get_ex(fota_ftp_cli_p->ftp_handle, fota_ftp_cli_p->file_full_path, NULL, fota_ftp_write_cb, (void *)fota_ftp_cli_p);
  285. QL_FOTA_FTP_LOG("********** ql_ftp_client_get_ex : %d **********", ret);
  286. if ( (QL_FTP_FOTA_SUCCESS != ret) && (DOWN_DOWNING == fota_ftp_cli_p->down_state) )
  287. {
  288. //fota_ftp_cli_p->down_state 被置为 DOWN_DOWNING,说明已经执行了回调函数fota_ftp_write_cb,且最后一次执行回调时还在下载中
  289. //由于网络异常,导致回写无法继续进行,ql_ftp_client_get_ex返回错误,fota_ftp_cli_p->down_state为上次正常执行时的状态
  290. //下载状态设置为阻塞状态,并尝试下一次FTP文件获取请求
  291. //下载过程中网络异常
  292. fota_ftp_cli_p->down_state = DOWN_INTR;
  293. return;
  294. }
  295. if (DOWN_INTR == fota_ftp_cli_p->down_state)
  296. {
  297. //下载中断的状态,还未正确执行fota_ftp_write_cb而修改
  298. return;
  299. }
  300. if (DOWN_NOSPACE == fota_ftp_cli_p->down_state)
  301. {
  302. //由于空间不足导致ql_ftp_client_get_ex返回值异常,直接退出
  303. return;
  304. }
  305. if (QL_FTP_FOTA_SUCCESS != ret)
  306. {
  307. //ql_ftp_client_get_ex 配置参数错误,导致无法正确调用写回调函数
  308. fota_ftp_cli_p->down_state = DOWN_OTHER_ERROR;
  309. return;
  310. }
  311. if (fota_ftp_cli_p->file_progress.downloaded_size >= fota_ftp_cli_p->file_progress.total_size)
  312. {
  313. //文件已下载大小和FTP 服务器文件大小一致,完成文件下载
  314. fota_ftp_cli_p->down_state = DOWN_DOWNED;
  315. }
  316. }
  317. void fota_ftp_file_download(fota_ftp_client_t *fota_ftp_cli_p)
  318. {
  319. //向FTP服务器请求最多10次FTP FOTA文件下载
  320. for (int i = 0; i < 10; i++)
  321. {
  322. QL_FOTA_FTP_LOG("*************** down_state : %d ******************", fota_ftp_cli_p->down_state);
  323. if (DOWN_DOWNED == fota_ftp_cli_p->down_state)
  324. {
  325. //下载完成
  326. QL_FOTA_FTP_LOG("FTP FOTA file download complete");
  327. break;
  328. }
  329. else if (DOWN_NOSPACE == fota_ftp_cli_p->down_state)
  330. {
  331. //在当前file_download阶段发生了空间不足的情况,表明net_connect_ready阶段时候获取的目标文件大小 和 当前file_download阶段下载的文件不是同一内容的文件,仅仅同名
  332. //在net_connect_ready阶段获取了文件大小后 到 file_download阶段 开始真正文件下载前,这一时间间隔当中服务器的文件可能被同名替换,或者在下载文件过程中,文件被同名替换
  333. //这样的文件和初始目标文件不同,应该被删除
  334. //目标文件被替换,导致下载FOTA包的空间不足
  335. QL_FOTA_FTP_LOG("********** The object file on the server has been replaced and there is not enough space left in the FOTA package after downloading the replacement **********");
  336. //删除文件
  337. ql_remove(fota_ftp_cli_p->local_filename);
  338. //下载状态置为初始状态,等待下一次的FTP FOTA下载
  339. fota_ftp_cli_p->down_state = DOWN_INIT;
  340. break;
  341. }
  342. else if (DOWN_OTHER_ERROR == fota_ftp_cli_p->down_state)
  343. {
  344. //ql_ftp_client_get_ex 函数参数配置错误,导致下载FTP文件时发生错误
  345. QL_FOTA_FTP_LOG("********** The ql_ftp_client_get_ex function parameter configuration error, resulting in an error when downloading FTP files **********");
  346. break;
  347. }
  348. //FTP FOTA文件下载
  349. fota_ftp_get_file(fota_ftp_cli_p);
  350. //等待10s继续下载
  351. ql_rtos_task_sleep_s(10);
  352. }
  353. //断开与FTP服务器的连接
  354. ql_ftp_client_close(fota_ftp_cli_p->ftp_handle);
  355. }
  356. void fota_ftp_file_check(fota_ftp_client_t *fota_ftp_cli_p)
  357. {
  358. int ret = QL_FTP_FOTA_SUCCESS;
  359. //文件下载完成,FOTA文件本地校验
  360. if (DOWN_DOWNED == fota_ftp_cli_p->down_state)
  361. {
  362. ret = ql_fota_image_verify(fota_ftp_cli_p->local_filename);
  363. if (QL_FTP_FOTA_SUCCESS != ret)
  364. {
  365. QL_FOTA_FTP_LOG("ret=%d ********** [%s]package is invalid FOTA **********",ret, fota_ftp_cli_p->local_filename);
  366. //删除无效的FOTA文件
  367. ret = ql_remove(fota_ftp_cli_p->local_filename);
  368. fota_ftp_cli_p->down_state = DOWN_INIT;
  369. if (QL_FTP_FOTA_SUCCESS == ret)
  370. {
  371. QL_FOTA_FTP_LOG("********** delete file success **********");
  372. }
  373. }
  374. else
  375. {
  376. //校验成功
  377. QL_FOTA_FTP_LOG("********** download is sucess ,system will reset power! **********");
  378. //设置升级
  379. ql_rtos_task_sleep_s(5);
  380. ql_power_reset(RESET_NORMAL);
  381. }
  382. }
  383. else
  384. {
  385. QL_FOTA_FTP_LOG("********** download is failed ,remove file! **********");
  386. ret = ql_remove(fota_ftp_cli_p->local_filename);
  387. fota_ftp_cli_p->down_state = DOWN_INIT;
  388. if (QL_FTP_FOTA_SUCCESS == ret)
  389. {
  390. QL_FOTA_FTP_LOG("********** delete file success **********");
  391. }
  392. }
  393. return;
  394. }
  395. ql_fota_result_e fota_ftp_result_process(void)
  396. {
  397. ql_fota_result_e p_fota_result = 0;
  398. //获取升级结果
  399. if ( ql_fota_get_result(&p_fota_result) != QL_FOTA_SUCCESS )
  400. {
  401. QL_FOTA_FTP_LOG("ql_fota_get_result failed ");
  402. return QL_FOTA_STATUS_INVALID;
  403. }
  404. if ( p_fota_result == QL_FOTA_FINISHED )
  405. {
  406. QL_FOTA_FTP_LOG("update finished");
  407. ql_fota_file_reset(TRUE);
  408. return QL_FOTA_FINISHED;
  409. }
  410. else if(p_fota_result == QL_FOTA_READY)
  411. {
  412. QL_FOTA_FTP_LOG("fota ready bigen power reset ");
  413. ql_rtos_task_sleep_s(5);
  414. ql_power_reset(RESET_NORMAL);
  415. }
  416. else if(p_fota_result == QL_FOTA_NOT_EXIST)
  417. {
  418. QL_FOTA_FTP_LOG("fota file not exist");
  419. ql_fota_file_reset(TRUE);
  420. return QL_FOTA_NOT_EXIST;
  421. }
  422. QL_FOTA_FTP_LOG("fota result status invalid");
  423. return QL_FOTA_STATUS_INVALID;
  424. }
  425. void fota_ftp_app_thread()
  426. {
  427. //延迟启动30S
  428. ql_rtos_task_sleep_s(30);
  429. int ret = QL_FTP_FOTA_SUCCESS;
  430. char version_buf[QL_VERSION_MAX] = {0};
  431. ql_dev_get_firmware_version(version_buf, sizeof(version_buf));
  432. QL_FOTA_FTP_LOG("current version: %s", version_buf);
  433. fota_ftp_client_t *fota_ftp_cli_p = &fota_ftp_cli;
  434. if(fota_ftp_result_process() == QL_FOTA_FINISHED)
  435. {
  436. goto init_error_exit;
  437. }
  438. ret = fota_ftp_client_init(fota_ftp_cli_p);
  439. if (QL_FTP_FOTA_SUCCESS != ret)
  440. {
  441. goto init_error_exit;
  442. }
  443. ret = fota_ftp_net_connect_ready(fota_ftp_cli_p);
  444. if (QL_FTP_FOTA_SUCCESS != ret)
  445. {
  446. goto exit;
  447. }
  448. //向FTP服务器进行FTP FOTA文件下载请求
  449. fota_ftp_file_download(fota_ftp_cli_p);
  450. //文件下载完成,FOTA文件本地校验
  451. fota_ftp_file_check(fota_ftp_cli_p);
  452. exit:
  453. ql_ftp_client_release(fota_ftp_cli_p->ftp_handle);
  454. init_error_exit:
  455. QL_FOTA_FTP_LOG("********** exit ql_ftp_fota_demo **********");
  456. ql_rtos_task_delete(fota_ftp_task);
  457. }
  458. #endif
  459. void ql_fota_ftp_app_init()
  460. {
  461. #ifdef QL_APP_FEATURE_FTP_FOTA
  462. QL_FOTA_FTP_LOG("ftp fota demo support!");
  463. QlOSStatus err = QL_OSI_SUCCESS;
  464. err = ql_rtos_task_create(&fota_ftp_task, 1024*16, APP_PRIORITY_HIGH, "QfotaFtp", fota_ftp_app_thread, NULL, 5);
  465. if (err != QL_OSI_SUCCESS)
  466. {
  467. QL_FOTA_FTP_LOG("created task failed");
  468. }
  469. #endif
  470. }