当前位置:   article > 正文

ESP8266/ESP32 SDK3 OTA升级

ESP8266/ESP32 SDK3 OTA升级

1、本示例适合于ESP8266和ESP32的OTA升级,使用官方的RTOS SDK3的框架编程,用户只要给出URL,代码自动解析出域名、IP、端口、文件路径等信息,然后通过HTTP请求下载固件。

2、本人测试固件放到阿里云对象存储OSS中,可以参考以下链接说明。或者自己搭建局域网服务器。

阿里云对象存储上传文件_dear_Wally的博客-CSDN博客

3、user_fota.c

  1. #include "user_fota.h"
  2. //===================================================================
  3. // 变量定义
  4. //===================================================================
  5. static const char *TAG = "user_fota";
  6. static bool ota_fail_flag;
  7. static bool ota_runing_flag = false;
  8. /********************************************************************
  9. *@brief 复制src到新内存
  10. *@param[in] src
  11. *@return 返回字符串指针,指针不为NULL时,用完之后需要释放内存
  12. *******************************************************************/
  13. char *user_copy_new_memory(const char *src)
  14. {
  15. char *dec = NULL;
  16. int len = strlen(src);
  17. dec = (char *)malloc(len+1);
  18. if(dec == NULL)
  19. {
  20. ESP_LOGE(TAG, "user_copy_new_memory malloc fail");
  21. return NULL;
  22. }
  23. int i;
  24. for(i=0;i<len;i++)
  25. {
  26. dec[i] = src[i];
  27. }
  28. dec[i] = '\0';
  29. return dec;
  30. }
  31. /********************************************************************
  32. *@brief 获取url的字符串
  33. *@param[in] url 完整的url
  34. *@param[in] puri 调用http_parser_parse_url解析之后的值
  35. *@param[in] uf 需要获取url字符串的类型
  36. *@return 返回字符串指针,指针不为NULL时,用完之后需要释放内存
  37. *******************************************************************/
  38. char *user_url_parser_get_str(const char *url,const struct http_parser_url *puri,uint8_t uf)
  39. {
  40. char *data = NULL;
  41. int len = puri->field_data[uf].len; //获取字符长度
  42. int off = puri->field_data[uf].off; //获取字符偏移
  43. if(len && (puri->field_set&(0x01<<uf))) //字符有效并且长度不为0
  44. {
  45. data = (char *)malloc(len+1); //申请内存,最后一个字节需要填入'\0',所有加1
  46. if(data != NULL)
  47. {
  48. int i;
  49. for(i=0;i<len;i++)
  50. {
  51. data[i] = url[off+i]; //复制字符串到返回内存空间
  52. }
  53. data[i] = '\0'; //最后一个字节需要填入'\0'
  54. }
  55. }
  56. return data;
  57. }
  58. /********************************************************************
  59. *@brief 获取OTA是否正在运行
  60. *@param[in]
  61. *@return true:正在OTA
  62. *******************************************************************/
  63. bool fota_is_runing()
  64. {
  65. return ota_runing_flag;
  66. }
  67. /*read buffer by byte still delim ,return read bytes counts*/
  68. static int read_until(const char *buffer, char delim, int len)
  69. {
  70. int i = 0;
  71. while (buffer[i] != delim && i < len) {
  72. ++i;
  73. }
  74. return i + 1;
  75. }
  76. bool _esp_ota_firm_parse_http(esp_ota_firm_t *ota_firm, const char *text, size_t total_len, size_t *parse_len)
  77. {
  78. /* i means current position */
  79. int i = 0, i_read_len = 0;
  80. char *ptr = NULL, *ptr2 = NULL;
  81. char length_str[32];
  82. while (text[i] != 0 && i < total_len) {
  83. if (ota_firm->content_len == 0 && (ptr = (char *)strstr(text, "Content-Length")) != NULL) {
  84. ptr += 16;
  85. ptr2 = (char *)strstr(ptr, "\r\n");
  86. memset(length_str, 0, sizeof(length_str));
  87. memcpy(length_str, ptr, ptr2 - ptr);
  88. ota_firm->content_len = atoi(length_str);
  89. ota_firm->ota_size = ota_firm->content_len;
  90. ota_firm->ota_offset = 0;
  91. ESP_LOGI(TAG, "parse Content-Length:%d, ota_size %d", ota_firm->content_len, ota_firm->ota_size);
  92. }
  93. i_read_len = read_until(&text[i], '\n', total_len - i);
  94. if (i_read_len > total_len - i) {
  95. ESP_LOGE(TAG, "recv malformed http header");
  96. ota_fail_flag = true;
  97. return false;
  98. }
  99. // if resolve \r\n line, http header is finished
  100. if (i_read_len == 2) {
  101. if (ota_firm->content_len == 0) {
  102. ESP_LOGE(TAG, "did not parse Content-Length item");
  103. ota_fail_flag = true;
  104. return false;
  105. }
  106. *parse_len = i + 2;
  107. return true;
  108. }
  109. i += i_read_len;
  110. }
  111. return false;
  112. }
  113. static size_t esp_ota_firm_do_parse_msg(esp_ota_firm_t *ota_firm, const char *in_buf, size_t in_len)
  114. {
  115. size_t tmp;
  116. size_t parsed_bytes = in_len;
  117. switch (ota_firm->state) {
  118. case ESP_OTA_INIT:
  119. if (_esp_ota_firm_parse_http(ota_firm, in_buf, in_len, &tmp)) {
  120. ota_firm->state = ESP_OTA_PREPARE;
  121. ESP_LOGD(TAG, "Http parse %d bytes", tmp);
  122. parsed_bytes = tmp;
  123. }
  124. break;
  125. case ESP_OTA_PREPARE:
  126. ota_firm->read_bytes += in_len;
  127. if (ota_firm->read_bytes >= ota_firm->ota_offset) {
  128. ota_firm->buf = &in_buf[in_len - (ota_firm->read_bytes - ota_firm->ota_offset)];
  129. ota_firm->bytes = ota_firm->read_bytes - ota_firm->ota_offset;
  130. ota_firm->write_bytes += ota_firm->read_bytes - ota_firm->ota_offset;
  131. ota_firm->state = ESP_OTA_START;
  132. ESP_LOGD(TAG, "Receive %d bytes and start to update", ota_firm->read_bytes);
  133. ESP_LOGD(TAG, "Write %d total %d", ota_firm->bytes, ota_firm->write_bytes);
  134. }
  135. break;
  136. case ESP_OTA_START:
  137. if (ota_firm->write_bytes + in_len > ota_firm->ota_size) {
  138. ota_firm->bytes = ota_firm->ota_size - ota_firm->write_bytes;
  139. ota_firm->state = ESP_OTA_RECVED;
  140. } else
  141. ota_firm->bytes = in_len;
  142. ota_firm->buf = in_buf;
  143. ota_firm->write_bytes += ota_firm->bytes;
  144. ESP_LOGD(TAG, "Write %d total %d", ota_firm->bytes, ota_firm->write_bytes);
  145. break;
  146. case ESP_OTA_RECVED:
  147. parsed_bytes = 0;
  148. ota_firm->state = ESP_OTA_FINISH;
  149. break;
  150. default:
  151. parsed_bytes = 0;
  152. ESP_LOGD(TAG, "State is %d", ota_firm->state);
  153. break;
  154. }
  155. return parsed_bytes;
  156. }
  157. static void esp_ota_firm_parse_msg(esp_ota_firm_t *ota_firm, const char *in_buf, size_t in_len)
  158. {
  159. size_t parse_bytes = 0;
  160. ESP_LOGD(TAG, "Input %d bytes", in_len);
  161. do {
  162. size_t bytes = esp_ota_firm_do_parse_msg(ota_firm, in_buf + parse_bytes, in_len - parse_bytes);
  163. ESP_LOGD(TAG, "Parse %d bytes", bytes);
  164. if(ota_fail_flag)
  165. {
  166. return;
  167. }
  168. if (bytes)
  169. parse_bytes += bytes;
  170. } while (parse_bytes != in_len);
  171. }
  172. static inline int esp_ota_firm_is_finished(esp_ota_firm_t *ota_firm)
  173. {
  174. return (ota_firm->state == ESP_OTA_FINISH || ota_firm->state == ESP_OTA_RECVED);
  175. }
  176. static inline int esp_ota_firm_can_write(esp_ota_firm_t *ota_firm)
  177. {
  178. return (ota_firm->state == ESP_OTA_START || ota_firm->state == ESP_OTA_RECVED);
  179. }
  180. static inline const char* esp_ota_firm_get_write_buf(esp_ota_firm_t *ota_firm)
  181. {
  182. return ota_firm->buf;
  183. }
  184. static inline size_t esp_ota_firm_get_write_bytes(esp_ota_firm_t *ota_firm)
  185. {
  186. return ota_firm->bytes;
  187. }
  188. static void esp_ota_firm_init(esp_ota_firm_t *ota_firm, const esp_partition_t *update_partition)
  189. {
  190. memset(ota_firm, 0, sizeof(esp_ota_firm_t));
  191. ota_firm->state = ESP_OTA_INIT;
  192. ota_firm->ota_num = get_ota_partition_count();
  193. ota_firm->update_ota_num = update_partition->subtype - ESP_PARTITION_SUBTYPE_APP_OTA_0;
  194. ESP_LOGI(TAG, "Totoal OTA number %d update to %d part", ota_firm->ota_num, ota_firm->update_ota_num);
  195. }
  196. /********************************************************************
  197. *@brief 释放HTTP信息内存
  198. *@param[in]
  199. *@return <0失败
  200. *******************************************************************/
  201. void user_free_http_info(user_http_info_t *user_http_info)
  202. {
  203. if(user_http_info->url_buff != NULL)
  204. {
  205. free(user_http_info->url_buff);
  206. user_http_info->url_buff = NULL;
  207. }
  208. if(user_http_info->url_type_buff != NULL)
  209. {
  210. free(user_http_info->url_type_buff);
  211. user_http_info->url_type_buff = NULL;
  212. }
  213. if(user_http_info->url_host_buff != NULL)
  214. {
  215. free(user_http_info->url_host_buff);
  216. user_http_info->url_host_buff = NULL;
  217. }
  218. if(user_http_info->url_port_buff != NULL)
  219. {
  220. free(user_http_info->url_port_buff);
  221. user_http_info->url_port_buff = NULL;
  222. }
  223. if(user_http_info->url_path_buff != NULL)
  224. {
  225. free(user_http_info->url_path_buff);
  226. user_http_info->url_path_buff = NULL;
  227. }
  228. }
  229. /********************************************************************
  230. *@brief 连接到HTTP服务器
  231. *@param[in]
  232. *@return <0失败
  233. *******************************************************************/
  234. int user_connect_http_server(const char *url,user_http_info_t *user_http_info)
  235. {
  236. user_http_info->url_buff = NULL;
  237. user_http_info->url_type_buff = NULL;
  238. user_http_info->url_host_buff = NULL;
  239. user_http_info->url_port_buff = NULL;
  240. user_http_info->url_path_buff = NULL;
  241. user_http_info->http_socket = -1;
  242. //复制URL到新内存空间
  243. user_http_info->url_buff = user_copy_new_memory(url);
  244. if(user_http_info->url_buff == NULL)
  245. {
  246. ESP_LOGE(TAG, "http url malloc fail");
  247. return -1;
  248. }
  249. ESP_LOGD(TAG, "http url parser = %s", user_http_info->url_buff);
  250. struct http_parser_url puri;
  251. http_parser_url_init(&puri);
  252. int ret = http_parser_parse_url(user_http_info->url_buff, strlen(user_http_info->url_buff), 0, &puri);
  253. if (ret != 0) {
  254. ESP_LOGE(TAG, "http url parser fail: %d",ret);
  255. return -1;
  256. }
  257. //获取协议类型
  258. user_http_info->url_type_buff = user_url_parser_get_str(user_http_info->url_buff,&puri,UF_SCHEMA);
  259. //获取主机域名
  260. user_http_info->url_host_buff = user_url_parser_get_str(user_http_info->url_buff,&puri,UF_HOST);
  261. if(user_http_info->url_host_buff == NULL)
  262. {
  263. ESP_LOGE(TAG, "http url host parser fail");
  264. return -1;
  265. }
  266. //获取主机端口
  267. user_http_info->url_port_buff = user_url_parser_get_str(user_http_info->url_buff,&puri,UF_PORT);
  268. if(user_http_info->url_port_buff == NULL)
  269. {
  270. //端口没有给出时默认为80
  271. user_http_info->url_port_buff = user_copy_new_memory("80");
  272. if(user_http_info->url_port_buff == NULL)
  273. {
  274. ESP_LOGE(TAG, "http port_buff user_copy_new_memory fail");
  275. return -1;
  276. }
  277. }
  278. //获取文件路径
  279. user_http_info->url_path_buff = user_url_parser_get_str(user_http_info->url_buff,&puri,UF_PATH);
  280. if(user_http_info->url_path_buff == NULL)
  281. {
  282. ESP_LOGE(TAG, "http url path parser fail");
  283. return -1;
  284. }
  285. const struct addrinfo hints = {
  286. .ai_family = AF_INET,
  287. .ai_socktype = SOCK_STREAM,
  288. };
  289. struct addrinfo *http_addrinfo = NULL;
  290. struct in_addr *ip_addr;
  291. //域名转换为IP
  292. ret = getaddrinfo(user_http_info->url_host_buff, user_http_info->url_port_buff, &hints, &http_addrinfo);
  293. if(ret != 0 || http_addrinfo == NULL) {
  294. ESP_LOGE(TAG, "http DNS failed ret=%d http_addrinfo=%p", ret, http_addrinfo);
  295. return -1;
  296. }
  297. //获取IP地址
  298. ip_addr = &((struct sockaddr_in *)http_addrinfo->ai_addr)->sin_addr;
  299. ESP_LOGI(TAG, "http DNS succeeded. IP=%s", inet_ntoa(*ip_addr));
  300. //创建TCP socket
  301. user_http_info->http_socket = socket(http_addrinfo->ai_family, http_addrinfo->ai_socktype, 0);
  302. if(user_http_info->http_socket < 0) {
  303. ESP_LOGE(TAG, "http allocate socket failed.");
  304. return -1;
  305. }
  306. ESP_LOGI(TAG, "http socket success");
  307. //通过TCP连接到服务器
  308. ret = connect(user_http_info->http_socket, http_addrinfo->ai_addr, http_addrinfo->ai_addrlen);
  309. freeaddrinfo(http_addrinfo);
  310. if(ret != 0)
  311. {
  312. close(user_http_info->http_socket);
  313. return -1;
  314. }
  315. ESP_LOGI(TAG, "http connect success");
  316. return 0;
  317. }
  318. /********************************************************************
  319. *@brief FOTA任务函数
  320. *@param[in]
  321. *@return
  322. *******************************************************************/
  323. static void user_fota_task(void *pvParameters)
  324. {
  325. ESP_LOGD(TAG, "starting fota. flash: %s", CONFIG_ESPTOOLPY_FLASHSIZE);
  326. ota_runing_flag = true;
  327. ota_fail_flag = false;
  328. esp_err_t err;
  329. esp_ota_handle_t update_handle = 0;
  330. const esp_partition_t *update_partition = NULL;
  331. const esp_partition_t *configured = esp_ota_get_boot_partition();
  332. const esp_partition_t *running = esp_ota_get_running_partition();
  333. if (configured != running) {
  334. ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x",
  335. configured->address, running->address);
  336. ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)");
  337. }
  338. ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)",
  339. running->type, running->subtype, running->address);
  340. user_http_info_t user_http_info;
  341. int ret;
  342. //OTA0固件地址为0x10000,OTA1固件地址为0x110000
  343. if(running->address == 0x10000)
  344. {
  345. //升级版本为1.0.1的固件
  346. ret = user_connect_http_server(USER_FOTA_URL1,&user_http_info);
  347. }
  348. else
  349. {
  350. //升级版本为1.0.0的固件
  351. ret = user_connect_http_server(USER_FOTA_URL0,&user_http_info);
  352. }
  353. if(ret < 0)
  354. {
  355. goto fail1;
  356. }
  357. //GET请求
  358. const char *GET_FORMAT =
  359. "GET %s HTTP/1.0\r\n"
  360. "Host: %s:%s\r\n"
  361. "Accept: application/octet-stream\r\n"
  362. "Accept-Encoding: identity\r\n"
  363. "User-Agent: esp8266\r\n\r\n";
  364. char *http_request = NULL;
  365. int request_len = asprintf(&http_request, GET_FORMAT, user_http_info.url_path_buff, user_http_info.url_host_buff , user_http_info.url_port_buff);
  366. //是否分配内存失败
  367. if (request_len < 0)
  368. {
  369. ESP_LOGE(TAG, "http request asprintf failed");
  370. goto fail2;
  371. }
  372. //打印请求内容
  373. printf("http_request:\r\n%s",http_request);
  374. char *http_recv_buff = NULL;
  375. char *http_text_buff = NULL;
  376. if((http_recv_buff = (char *)malloc(USER_FOTA_RECV_BUFFSIZE+1)) == NULL)
  377. {
  378. ESP_LOGE(TAG, "http http_recv_buff malloc fail");
  379. goto fail3;
  380. }
  381. if((http_text_buff = (char *)malloc(USER_FOTA_TEXT_BUFFSIZE+1)) == NULL)
  382. {
  383. ESP_LOGE(TAG, "http http_text_buff malloc fail");
  384. goto fail3;
  385. }
  386. //发送请求
  387. if(send(user_http_info.http_socket, http_request, request_len, 0) < 0)
  388. {
  389. ESP_LOGE(TAG, "http send failed");
  390. goto fail3;
  391. }
  392. ESP_LOGI(TAG, "http send success");
  393. //可以释放内存,后面没有使用该变量
  394. free(http_request);
  395. http_request = NULL;
  396. user_free_http_info(&user_http_info);
  397. //获取下一个更新分区
  398. update_partition = esp_ota_get_next_update_partition(NULL);
  399. ESP_LOGD(TAG, "writing to partition subtype %d at offset 0x%x",
  400. update_partition->subtype, update_partition->address);
  401. assert(update_partition != NULL);
  402. ESP_LOGD(TAG, "esp_ota_begin ........");
  403. //擦除OTA区域FLASH,这里等待时间较长
  404. err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
  405. if (err != ESP_OK) {
  406. ESP_LOGE(TAG, "esp_ota_begin failed, error=%d", err);
  407. goto fail3;
  408. }
  409. ESP_LOGD(TAG, "esp_ota_begin succeeded");
  410. int binary_file_length = 0;
  411. bool flag = true;
  412. esp_ota_firm_t ota_firm;
  413. esp_ota_firm_init(&ota_firm, update_partition);
  414. while (flag) {
  415. memset(http_recv_buff, 0, USER_FOTA_RECV_BUFFSIZE);
  416. memset(http_text_buff, 0, USER_FOTA_TEXT_BUFFSIZE);
  417. int buff_len = recv(user_http_info.http_socket, http_recv_buff, USER_FOTA_RECV_BUFFSIZE, 0);
  418. //接收错误
  419. if (buff_len < 0)
  420. {
  421. ESP_LOGE(TAG, "Error: receive data error! errno=%d", errno);
  422. goto fail3;
  423. }
  424. //接收数据
  425. else if (buff_len > 0)
  426. {
  427. esp_ota_firm_parse_msg(&ota_firm, http_recv_buff, buff_len);
  428. if(ota_fail_flag)
  429. {
  430. goto fail3;
  431. }
  432. if (!esp_ota_firm_can_write(&ota_firm))
  433. continue;
  434. memcpy(http_text_buff, esp_ota_firm_get_write_buf(&ota_firm), esp_ota_firm_get_write_bytes(&ota_firm));
  435. buff_len = esp_ota_firm_get_write_bytes(&ota_firm);
  436. err = esp_ota_write( update_handle, (const void *)http_text_buff, buff_len);
  437. if (err != ESP_OK) {
  438. ESP_LOGE(TAG, "Error: esp_ota_write failed! err=0x%x", err);
  439. goto fail3;
  440. }
  441. binary_file_length += buff_len;
  442. ESP_LOGI(TAG, "Have written image length %d", binary_file_length);
  443. }
  444. //接收完成
  445. else if (buff_len == 0)
  446. {
  447. flag = false;
  448. ESP_LOGI(TAG, "ota all packets received");
  449. } else {
  450. ESP_LOGE(TAG, "Unexpected recv result");
  451. }
  452. if (esp_ota_firm_is_finished(&ota_firm))
  453. break;
  454. }
  455. ESP_LOGI(TAG, "Total Write binary data length : %d", binary_file_length);
  456. //校验固件
  457. if (esp_ota_end(update_handle) != ESP_OK) {
  458. ESP_LOGE(TAG, "esp_ota_end failed!");
  459. goto fail3;
  460. }
  461. //设在启动分区
  462. err = esp_ota_set_boot_partition(update_partition);
  463. if (err != ESP_OK) {
  464. ESP_LOGE(TAG, "esp_ota_set_boot_partition failed! err=0x%x", err);
  465. goto fail3;
  466. }
  467. ESP_LOGI(TAG, "ota success restart system!");
  468. //关闭TCP连接
  469. close(user_http_info.http_socket);
  470. vTaskDelay(100/portTICK_RATE_MS);
  471. //重启设备
  472. esp_restart();
  473. fail3:
  474. if(http_recv_buff != NULL)
  475. {
  476. free(http_recv_buff);
  477. }
  478. if(http_text_buff != NULL)
  479. {
  480. free(http_text_buff);
  481. }
  482. fail2:
  483. if(http_request != NULL)
  484. {
  485. free(http_request);
  486. }
  487. close(user_http_info.http_socket);
  488. fail1:
  489. user_free_http_info(&user_http_info);
  490. ESP_LOGE(TAG, "ota failed!");
  491. ota_runing_flag = false;
  492. vTaskDelete(NULL);
  493. }
  494. /********************************************************************
  495. *@brief FOTA初始化函数
  496. *@param[in]
  497. *@return
  498. *******************************************************************/
  499. void user_fota_init()
  500. {
  501. xTaskCreate(user_fota_task, "user_fota_task", 8192, NULL, 5, NULL);
  502. }

4、user_fota.h

  1. #ifndef _USER_FOTA_H_
  2. #define _USER_FOTA_H_
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include "sdkconfig.h"
  6. #include "freertos/FreeRTOS.h"
  7. #include "freertos/task.h"
  8. #include "freertos/event_groups.h"
  9. #include "esp_system.h"
  10. #include "esp_spi_flash.h"
  11. #include "nvs_flash.h"
  12. #include "esp_log.h"
  13. #include "esp_netif.h"
  14. #include "esp_event.h"
  15. #include "esp_wifi.h"
  16. #include "lwip/sockets.h"
  17. #include "lwip/dns.h"
  18. #include "lwip/netdb.h"
  19. #include "esp_log.h"
  20. #include "nvs.h"
  21. #include "nvs_flash.h"
  22. #include "esp_ota_ops.h"
  23. #include "esp_http_client.h"
  24. #include "esp_https_ota.h"
  25. #include "esp_ota_ops.h"
  26. #include "esp_netif.h"
  27. //===================================================================
  28. // 常量定义
  29. //===================================================================
  30. //固件版本为1.0.0的URL
  31. #define USER_FOTA_URL0 "http://xxxx.oss-cn-shenzhen.aliyuncs.com/esp8266/fota_v1.0.0.bin"
  32. //固件版本为1.0.1的URL
  33. #define USER_FOTA_URL1 "http://xxxx.oss-cn-shenzhen.aliyuncs.com/esp8266/fota_v1.0.1.bin"
  34. #define USER_FOTA_RECV_BUFFSIZE 1024
  35. #define USER_FOTA_TEXT_BUFFSIZE 1500
  36. //===================================================================
  37. // 定义结构体
  38. //===================================================================
  39. typedef enum esp_ota_firm_state {
  40. ESP_OTA_INIT = 0,
  41. ESP_OTA_PREPARE,
  42. ESP_OTA_START,
  43. ESP_OTA_RECVED,
  44. ESP_OTA_FINISH,
  45. } esp_ota_firm_state_t;
  46. typedef struct esp_ota_firm {
  47. uint8_t ota_num;
  48. uint8_t update_ota_num;
  49. esp_ota_firm_state_t state;
  50. size_t content_len;
  51. size_t read_bytes;
  52. size_t write_bytes;
  53. size_t ota_size;
  54. size_t ota_offset;
  55. const char *buf;
  56. size_t bytes;
  57. } esp_ota_firm_t;
  58. typedef struct {
  59. char *url_buff;
  60. char *url_type_buff; //解析后的url协议类型字符串缓存
  61. char *url_host_buff; //解析后的url主机域名字符串缓存
  62. char *url_port_buff; //解析后的url主机端口字符串缓存
  63. char *url_path_buff; //解析后的url文件路径字符串缓存
  64. int http_socket; //当前连接http的套接字
  65. }user_http_info_t;
  66. //===================================================================
  67. // 函数声明
  68. //===================================================================
  69. void user_fota_init();
  70. bool fota_is_runing();
  71. #endif

5、使用说明

  更改头文件的URL为你服务器固件的URL,这里我们放两个固件fota_v1.0.0.bin和fota_v1.0.1.bin,执行OTA时会循环升级这两个固件

  1. //固件版本为1.0.0的URL
  2. #define USER_FOTA_URL0 "http://xxxx.oss-cn-shenzhen.aliyuncs.com/esp8266/fota_v1.0.0.bin"
  3. //固件版本为1.0.1的URL
  4. #define USER_FOTA_URL1 "http://xxxx.oss-cn-shenzhen.aliyuncs.com/esp8266/fota_v1.0.1.bin"

WIFI连接成功之后,执行以下代码开始OTA

  1. //当前没有运行OTA,才能进行OTA
  2. if(!fota_is_runing())
  3. {
  4. user_fota_init();
  5. }

6、本人写了个自动OTA demo,每次上电连接WIFI之后进行OTA,目前升级1000+以上,未发现异常,中途未出现过失败、中断。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/600679
推荐阅读
相关标签
  

闽ICP备14008679号