ota.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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 "lcd_st7701.h"
  22. extern const uint8_t server_cert_pem_start[] asm("_binary_ssl_pem_start");
  23. extern const uint8_t server_cert_pem_end[] asm("_binary_ssl_pem_end");
  24. static const char *TAG = "ota";
  25. uint32_t downloaded_size = 0;
  26. static ota_info_t ota_info;
  27. uint32_t old_progress = 0;
  28. uint32_t progress = 0;
  29. static bool isUpdating = false;
  30. static esp_err_t http_event_handler(esp_http_client_event_t *evt) {
  31. switch (evt->event_id) {
  32. case HTTP_EVENT_ERROR:
  33. ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
  34. lvgl_port_lock(-1);
  35. lv_obj_remove_flag(guider_ui.OTAPage_btn_exit, LV_OBJ_FLAG_HIDDEN);
  36. lvgl_port_unlock();
  37. break;
  38. case HTTP_EVENT_ON_CONNECTED:
  39. ESP_LOGI(TAG, "HTTP_EVENT_ON_CONNECTED");
  40. break;
  41. case HTTP_EVENT_HEADER_SENT:
  42. ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
  43. break;
  44. case HTTP_EVENT_ON_HEADER:
  45. ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
  46. break;
  47. case HTTP_EVENT_ON_DATA:
  48. downloaded_size += evt->data_len;
  49. progress = (downloaded_size * 100) / ota_info.fileSize;
  50. if(progress != old_progress) {
  51. ESP_LOGI(TAG, "progress=%lu%%", progress);
  52. old_progress = progress;
  53. }
  54. break;
  55. case HTTP_EVENT_ON_FINISH:
  56. ESP_LOGI(TAG, "HTTP_EVENT_ON_FINISH");
  57. break;
  58. case HTTP_EVENT_DISCONNECTED:
  59. ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED");
  60. break;
  61. case HTTP_EVENT_REDIRECT:
  62. ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT");
  63. break;
  64. }
  65. return ESP_OK;
  66. }
  67. _Noreturn void ota_task(void *pv) {
  68. ESP_LOGI(TAG, "Starting OTA example task, %ld,%ld",esp_get_free_internal_heap_size(), esp_get_minimum_free_heap_size());
  69. esp_http_client_config_t config = {
  70. .url = ota_info.url,
  71. .cert_pem = (char *) server_cert_pem_start,
  72. .event_handler = http_event_handler,
  73. .keep_alive_enable = true,
  74. };
  75. #ifdef CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK
  76. config.skip_cert_common_name_check = true;
  77. #endif
  78. esp_https_ota_config_t ota_config = {
  79. .http_config = &config,
  80. };
  81. ESP_LOGI(TAG, "Attempting to download update from %s", config.url);
  82. esp_err_t ret = esp_https_ota(&ota_config);
  83. if (ret == ESP_OK) {
  84. ESP_LOGI(TAG, "OTA Succeed, Rebooting...");
  85. // vTaskDelay( pdTICKS_TO_MS(3000));
  86. esp_restart();
  87. } else {
  88. ESP_LOGE(TAG, "Firmware upgrade failed");
  89. lvgl_port_lock(-1);
  90. lv_obj_remove_flag(guider_ui.OTAPage_btn_exit, LV_OBJ_FLAG_HIDDEN);
  91. lvgl_port_unlock();
  92. }
  93. while (1) {
  94. vTaskDelay(1000 / portTICK_PERIOD_MS);
  95. }
  96. }
  97. _Noreturn static void progress_task(void * pv) {
  98. while (1) {
  99. lvgl_port_lock(-1);
  100. lv_bar_set_value(guider_ui.OTAPage_bar_ota_progress, (int32_t) progress, false);
  101. lvgl_port_unlock();
  102. vTaskDelay(100 / portTICK_PERIOD_MS);
  103. }
  104. }
  105. static void start_ota() {
  106. lcd_st7701_backlight_on();
  107. ui_load_scr_animation(&guider_ui, &guider_ui.OTAPage, guider_ui.OTAPage_del,
  108. &guider_ui.screen_del, setup_scr_OTAPage,
  109. LV_SCR_LOAD_ANIM_MOVE_LEFT, 200, 0, false, false);
  110. lv_label_set_text(guider_ui.OTAPage_lab_ota_remote_version, ota_info.version);
  111. esp_app_desc_t * desc = esp_app_get_description();
  112. lv_label_set_text(guider_ui.OTAPage_lab_ota_current_version, desc->version);
  113. if(xTaskCreate(&ota_task, "ota_task", 8192, NULL, 5, NULL)!=pdTRUE)
  114. {
  115. ESP_LOGE(TAG, "create ota_task failed");
  116. lvgl_port_lock(-1);
  117. lv_obj_remove_flag(guider_ui.OTAPage_btn_exit, LV_OBJ_FLAG_HIDDEN);
  118. lvgl_port_unlock();
  119. }
  120. xTaskCreate(&progress_task, "update_task", 1024 * 2, NULL, 5, NULL);
  121. }
  122. /**
  123. * 设备OTA升级
  124. * @param params
  125. */
  126. void on_dev_upgrade(char *params) {
  127. if(isUpdating)return;
  128. cJSON *root = cJSON_Parse(params);
  129. cJSON *file_size = cJSON_GetObjectItemCaseSensitive(root, "file_size");
  130. cJSON *url = cJSON_GetObjectItemCaseSensitive(root, "url");
  131. cJSON *version = cJSON_GetObjectItemCaseSensitive(root, "version");
  132. ota_info.fileSize = file_size->valueint;
  133. snprintf(ota_info.url, sizeof(ota_info.url), "%s", url->valuestring);
  134. snprintf(ota_info.version, sizeof(ota_info.version), "%s", version->valuestring);
  135. // TODO: 停止所有子设备
  136. // stop_ac_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. }
  150. /***
  151. {
  152. "action": "cloudSend",
  153. "data": {
  154. "cmd": "devUpgrade",
  155. "params": {
  156. "file_size": 3160256,
  157. "md5": "971d0f743a12fa58f72dd3a89ae431c7",
  158. "url": "https://app.yongxulvjian.com/s/yongxu/1pw4ums98q0datl54tofrqe1sjxooeof/wire-controller.bin",
  159. "version": "2025-06-23 V1.1.8"
  160. }
  161. },
  162. "deviceCode": "50787D135B48",
  163. "msgId": 0,
  164. "subDeviceId": "",
  165. "timestamp": 1751936310
  166. }
  167. */