OTAUpdater.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #include "OTAUpdater.h"
  2. // 使用 extern 声明全局变量
  3. extern String serverAddress;
  4. extern String deviceID;
  5. OTAUpdater::OTAUpdater(uint16_t port, const String& currentVersion)
  6. : _port(port), _currentVersion(currentVersion) {} // 移除 _serverUrl 初始化
  7. void OTAUpdater::checkForUpdates() {
  8. // 添加调试信息,打印设备ID
  9. Serial.println("设备ID: " + deviceID); // 确保设备ID被正确传递
  10. // 检查 WiFi 连接状态
  11. while (true) {
  12. // 尝试连接 WiFi,超时时间为 30 秒
  13. if (connectWiFiWithTimeout(30000)) {
  14. Serial.println("[信息] Wi-Fi 连接成功。");
  15. break; // 连接成功,退出循环
  16. } else {
  17. Serial.println("[信息] Wi-Fi 连接失败,进入配置模式...");
  18. setupWiFiConfig(); // 进入配置模式,超时时间为 60 秒
  19. }
  20. }
  21. Serial.println("正在检查更新...");
  22. // 构建完整的 OTA 服务器 URL,使用全局变量 serverAddress 和 _port
  23. String fullServerUrl = "http://" + serverAddress + ":" + otaPort;
  24. Serial.println("OTA 服务器地址: " + fullServerUrl);
  25. // 向服务器发送设备ID和当前固件版本,检查是否有更新
  26. HTTPClient http;
  27. String checkUpdateUrl = fullServerUrl + "/check-update";
  28. http.begin(checkUpdateUrl);
  29. http.addHeader("Content-Type", "application/json");
  30. // 构建JSON请求体
  31. String json = "{\"device_id\":\"" + deviceID + "\",\"version\":\"" + _currentVersion + "\"}";
  32. http.addHeader("Content-Type", "application/json");
  33. int httpCode = http.POST(json);
  34. // 处理响应
  35. if (httpCode == HTTP_CODE_OK) {
  36. String response = http.getString();
  37. if (response == "update") {
  38. Serial.println("发现新固件,开始下载...");
  39. if (downloadAndUpdateFirmware()) {
  40. Serial.println("固件更新成功,即将重启...");
  41. delay(1000);
  42. Serial.println("1秒后重启...");
  43. delay(1000);
  44. ESP.restart();
  45. }
  46. } else {
  47. Serial.println("无可用更新");
  48. }
  49. } else {
  50. Serial.println("检查更新失败,HTTP错误代码: " + String(httpCode));
  51. }
  52. http.end();
  53. }
  54. bool OTAUpdater::downloadAndUpdateFirmware() {
  55. // 构建完整的 OTA 服务器 URL,使用全局变量 serverAddress 和 _port
  56. String fullServerUrl = "http://" + serverAddress + ":" + otaPort;
  57. String firmwareUrl = fullServerUrl + "/firmware";
  58. HTTPClient http;
  59. http.begin(firmwareUrl);
  60. // 设置 HTTP 超时时间(单位:毫秒)
  61. http.setTimeout(20000); // 20秒超时
  62. int httpCode = http.GET();
  63. if (httpCode == HTTP_CODE_OK) {
  64. // 获取固件文件大小
  65. int contentLength = http.getSize();
  66. if (contentLength <= 0) {
  67. Serial.println("无效的固件文件大小。");
  68. http.end();
  69. return false;
  70. }
  71. // 开始更新
  72. if (Update.begin(contentLength)) {
  73. // 获取数据流
  74. WiFiClient* stream = http.getStreamPtr();
  75. // 设置数据流超时时间(单位:毫秒)
  76. stream->setTimeout(20000); // 20秒超时
  77. // 记录下载开始时间
  78. unsigned long startTime = millis();
  79. size_t written = 0;
  80. // 分块下载固件数据
  81. while (written < contentLength) {
  82. // 检查是否超时
  83. if (millis() - startTime > 20000) { // 20秒超时
  84. Serial.println("下载超时,中断更新。");
  85. http.end();
  86. Update.end(false); // 结束更新并标记为失败
  87. return false;
  88. }
  89. // 读取数据块
  90. size_t available = stream->available();
  91. if (available > 0) {
  92. uint8_t buffer[128]; // 缓冲区大小
  93. size_t read = stream->readBytes(buffer, min(sizeof(buffer), available));
  94. written += Update.write(buffer, read);
  95. } else {
  96. // 如果没有数据,等待一段时间
  97. delay(100);
  98. }
  99. }
  100. // 检查是否下载完成
  101. if (written == contentLength) {
  102. Serial.println("固件写入成功。");
  103. } else {
  104. Serial.println("固件写入失败。");
  105. http.end();
  106. Update.end(false); // 结束更新并标记为失败
  107. return false;
  108. }
  109. // 结束更新
  110. if (Update.end()) {
  111. Serial.println("固件更新完成。");
  112. http.end();
  113. return true;
  114. } else {
  115. Serial.println("固件更新结束失败。");
  116. http.end();
  117. return false;
  118. }
  119. } else {
  120. Serial.println("空间不足,无法开始OTA更新。");
  121. http.end();
  122. return false;
  123. }
  124. } else {
  125. Serial.println("下载固件失败,HTTP错误代码: " + String(httpCode));
  126. http.end();
  127. return false;
  128. }
  129. http.end();
  130. return false;
  131. }