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