ota.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #include <sys/queue.h>
  2. #include <sys/cdefs.h>
  3. /**
  4. * @Author: 李建
  5. * @Date: 2025/3/26 14:21
  6. * Description: OTA功能实现
  7. * Copyright: Copyright (©) 2025 永续绿建. All rights reserved.
  8. */
  9. #include <esp_err.h>
  10. #include <esp_http_client.h>
  11. #include <esp_log.h>
  12. #include <esp_https_ota.h>
  13. #include <cJSON.h>
  14. #include "ota.h"
  15. #include "stdint.h"
  16. #include "sub_device/command.h"
  17. #include "system/miscellaneous_interface.h"
  18. #include "display/lv_display.h"
  19. #include "lvgl_port.h"
  20. #include "main.h"
  21. #include "xf_controller.h"
  22. #include "lcd_st7701.h"
  23. extern const uint8_t server_cert_pem_start[] asm("_binary_ssl_pem_start");
  24. extern const uint8_t server_cert_pem_end[] asm("_binary_ssl_pem_end");
  25. static const char *TAG = "ota";
  26. uint32_t downloaded_size = 0;
  27. static ota_info_t ota_info;
  28. uint32_t old_progress = 0;
  29. uint32_t progress = 0;
  30. static bool isUpdating = false;
  31. static esp_err_t http_event_handler(esp_http_client_event_t *evt) {
  32. switch (evt->event_id) {
  33. case HTTP_EVENT_ERROR:
  34. ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
  35. lvgl_port_lock(-1);
  36. lv_obj_remove_flag(guider_ui.OTAPage_btn_exit, LV_OBJ_FLAG_HIDDEN);
  37. lvgl_port_unlock();
  38. break;
  39. case HTTP_EVENT_ON_CONNECTED:
  40. ESP_LOGI(TAG, "HTTP_EVENT_ON_CONNECTED");
  41. break;
  42. case HTTP_EVENT_HEADER_SENT:
  43. ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
  44. break;
  45. case HTTP_EVENT_ON_HEADER:
  46. ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
  47. break;
  48. case HTTP_EVENT_ON_DATA:
  49. downloaded_size += evt->data_len;
  50. progress = (downloaded_size * 100) / ota_info.fileSize;
  51. if(progress != old_progress) {
  52. ESP_LOGI(TAG, "progress=%lu%%", progress);
  53. old_progress = progress;
  54. }
  55. break;
  56. case HTTP_EVENT_ON_FINISH:
  57. ESP_LOGI(TAG, "HTTP_EVENT_ON_FINISH");
  58. break;
  59. case HTTP_EVENT_DISCONNECTED:
  60. ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED");
  61. break;
  62. case HTTP_EVENT_REDIRECT:
  63. ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT");
  64. break;
  65. }
  66. return ESP_OK;
  67. }
  68. _Noreturn void ota_task(void *pv) {
  69. ESP_LOGI(TAG, "Starting OTA example task, %ld,%ld",esp_get_free_internal_heap_size(), esp_get_minimum_free_heap_size());
  70. esp_http_client_config_t config = {
  71. .url = ota_info.url,
  72. .cert_pem = (char *) server_cert_pem_start,
  73. .event_handler = http_event_handler,
  74. .keep_alive_enable = true,
  75. };
  76. #ifdef CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK
  77. config.skip_cert_common_name_check = true;
  78. #endif
  79. esp_https_ota_config_t ota_config = {
  80. .http_config = &config,
  81. };
  82. ESP_LOGI(TAG, "Attempting to download update from %s", config.url);
  83. esp_err_t ret = esp_https_ota(&ota_config);
  84. if (ret == ESP_OK) {
  85. ESP_LOGI(TAG, "OTA Succeed, Rebooting...");
  86. // vTaskDelay( pdTICKS_TO_MS(3000));
  87. esp_restart();
  88. } else {
  89. ESP_LOGE(TAG, "Firmware upgrade failed");
  90. lvgl_port_lock(-1);
  91. lv_obj_remove_flag(guider_ui.OTAPage_btn_exit, LV_OBJ_FLAG_HIDDEN);
  92. lvgl_port_unlock();
  93. }
  94. while (1) {
  95. vTaskDelay(1000 / portTICK_PERIOD_MS);
  96. }
  97. }
  98. _Noreturn static void progress_task(void * pv) {
  99. while (1) {
  100. lvgl_port_lock(-1);
  101. lv_bar_set_value(guider_ui.OTAPage_bar_ota_progress, (int32_t) progress, false);
  102. lvgl_port_unlock();
  103. vTaskDelay(100 / portTICK_PERIOD_MS);
  104. }
  105. }
  106. static void start_ota() {
  107. lcd_st7701_backlight_on();
  108. ui_load_scr_animation(&guider_ui, &guider_ui.OTAPage, guider_ui.OTAPage_del,
  109. &guider_ui.screen_main_del, setup_scr_OTAPage,
  110. LV_SCR_LOAD_ANIM_MOVE_LEFT, 200, 0, false, false);
  111. lv_label_set_text(guider_ui.OTAPage_lab_ota_remote_version, ota_info.version);
  112. esp_app_desc_t * desc = esp_app_get_description();
  113. lv_label_set_text(guider_ui.OTAPage_lab_ota_current_version, desc->version);
  114. if(xTaskCreate(&ota_task, "ota_task", 8192, NULL, 5, NULL)!=pdTRUE)
  115. {
  116. ESP_LOGE(TAG, "create ota_task failed");
  117. lvgl_port_lock(-1);
  118. lv_obj_remove_flag(guider_ui.OTAPage_btn_exit, LV_OBJ_FLAG_HIDDEN);
  119. lvgl_port_unlock();
  120. }
  121. xTaskCreate(&progress_task, "update_task", 1024 * 2, NULL, 5, NULL);
  122. }
  123. /**
  124. * 设备OTA升级
  125. * @param params
  126. */
  127. void on_dev_upgrade(char *params) {
  128. if(isUpdating)return;
  129. cJSON *root = cJSON_Parse(params);
  130. cJSON *file_size = cJSON_GetObjectItemCaseSensitive(root, "file_size");
  131. cJSON *url = cJSON_GetObjectItemCaseSensitive(root, "url");
  132. cJSON *version = cJSON_GetObjectItemCaseSensitive(root, "version");
  133. ota_info.fileSize = file_size->valueint;
  134. snprintf(ota_info.url, sizeof(ota_info.url), "%s", url->valuestring);
  135. snprintf(ota_info.version, sizeof(ota_info.version), "%s", version->valuestring);
  136. stop_xf_controller();
  137. start_ota();
  138. cJSON_Delete(root);
  139. ESP_LOGI(TAG, "OTA info: fileSize=%lu, url=%s, version=%s", ota_info.fileSize, ota_info.url, ota_info.version);
  140. isUpdating = true;
  141. }
  142. // 初始化平台OTA功能指令
  143. void ota_init() {
  144. sparrow_command ota_cmd = {
  145. .name = "devUpgrade",
  146. .unpack = &on_dev_upgrade,
  147. };
  148. register_sparrow_command(ota_cmd);
  149. }