ElegantOTA.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #ifndef ElegantOTA_h
  2. #define ElegantOTA_h
  3. #include "Arduino.h"
  4. #include "stdlib_noniso.h"
  5. #include "elegantWebpage.h"
  6. #if defined(ESP8266)
  7. #define HARDWARE "ESP8266"
  8. #include "ESP8266WiFi.h"
  9. #include "WiFiClient.h"
  10. #include "ESP8266WebServer.h"
  11. #include "ESP8266HTTPUpdateServer.h"
  12. #elif defined(ESP32)
  13. #define HARDWARE "ESP32"
  14. #include "WiFi.h"
  15. #include "WiFiClient.h"
  16. #include "WebServer.h"
  17. #include "Update.h"
  18. #endif
  19. class ElegantOtaClass{
  20. public:
  21. void setID(const char* id){
  22. _id = id;
  23. }
  24. // ESP8266 Codebase
  25. #if defined(ESP8266)
  26. void begin(ESP8266WebServer *server, const char * username = "", const char * password = ""){
  27. _server = server;
  28. if(strlen(username) > 0){
  29. _username = username;
  30. _password = password;
  31. _server->on("/update", HTTP_GET, [&](){
  32. if (!_server->authenticate(_username.c_str(), _password.c_str())) {
  33. return _server->requestAuthentication();
  34. }
  35. _server->sendHeader("Content-Encoding", "gzip");
  36. _server->send_P(200, "text/html", (const char*)ELEGANT_HTML, ELEGANT_HTML_SIZE);
  37. });
  38. _server->on("/update/identity", HTTP_GET, [&](){
  39. if (!_server->authenticate(_username.c_str(), _password.c_str())) {
  40. return _server->requestAuthentication();
  41. }
  42. #if defined(ESP8266)
  43. _server->send(200, "application/json", "{\"id\": "+_id+", \"hardware\": \"ESP8266\"}");
  44. #elif defined(ESP32)
  45. _server->send(200, "application/json", "{\"id\": "+_id+", \"hardware\": \"ESP32\"}");
  46. #endif
  47. });
  48. _httpUpdater.setup(server, "/update", _username.c_str(), _password.c_str());
  49. } else {
  50. _server->on("/update", HTTP_GET, [&](){
  51. _server->sendHeader("Content-Encoding", "gzip");
  52. _server->send_P(200, "text/html", (const char*)ELEGANT_HTML, ELEGANT_HTML_SIZE);
  53. });
  54. _server->on("/update/identity", HTTP_GET, [&](){
  55. #if defined(ESP8266)
  56. _server->send(200, "application/json", "{\"id\": "+_id+", \"hardware\": \"ESP8266\"}");
  57. #elif defined(ESP32)
  58. _server->send(200, "application/json", "{\"id\": "+_id+", \"hardware\": \"ESP32\"}");
  59. #endif
  60. });
  61. //TODO: handle MD5 paramter
  62. _httpUpdater.setup(server, "/update");
  63. }
  64. }
  65. // ESP32 Codebase
  66. #elif defined(ESP32)
  67. void begin(WebServer *server, const char * username = "", const char * password = ""){
  68. _server = server;
  69. if(strlen(username) > 0){
  70. _username = username;
  71. _password = password;
  72. _server->on("/update", HTTP_GET, [&](){
  73. if (!_server->authenticate(_username.c_str(), _password.c_str())) {
  74. return _server->requestAuthentication();
  75. }
  76. _server->sendHeader("Content-Encoding", "gzip");
  77. _server->send_P(200, "text/html", (const char*)ELEGANT_HTML, ELEGANT_HTML_SIZE);
  78. });
  79. _server->on("/update/identity", HTTP_GET, [&](){
  80. if (!_server->authenticate(_username.c_str(), _password.c_str())) {
  81. return _server->requestAuthentication();
  82. }
  83. #if defined(ESP8266)
  84. _server->send(200, "application/json", "{\"id\": \""+_id+"\", \"hardware\": \"ESP8266\"}");
  85. #elif defined(ESP32)
  86. _server->send(200, "application/json", "{\"id\": \""+_id+"\", \"hardware\": \"ESP32\"}");
  87. #endif
  88. });
  89. _server->on("/update", HTTP_POST, [&](){
  90. // Check Authentication before processing request
  91. if (!_server->authenticate(_username.c_str(), _password.c_str())) {
  92. return;
  93. }
  94. _server->sendHeader("Connection", "close");
  95. _server->send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
  96. ESP.restart();
  97. }, [&](){
  98. // Check Authentication before processing request
  99. if (!_server->authenticate(_username.c_str(), _password.c_str())) {
  100. return;
  101. }
  102. //TODO: handle MD5 paramter
  103. // Perform upload
  104. HTTPUpload& upload = _server->upload();
  105. if (upload.status == UPLOAD_FILE_START) {
  106. Serial.setDebugOutput(true);
  107. Serial.printf("Update: %s\n", upload.filename.c_str());
  108. if (upload.name == "filesystem") {
  109. if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_SPIFFS)) { //start with max available size
  110. Update.printError(Serial);
  111. }
  112. } else {
  113. if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_FLASH)) { //start with max available size
  114. Update.printError(Serial);
  115. }
  116. }
  117. } else if (upload.status == UPLOAD_FILE_WRITE) {
  118. if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
  119. Update.printError(Serial);
  120. }
  121. } else if (upload.status == UPLOAD_FILE_END) {
  122. if (Update.end(true)) { //true to set the size to the current progress
  123. Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
  124. } else {
  125. Update.printError(Serial);
  126. }
  127. Serial.setDebugOutput(false);
  128. } else {
  129. Serial.printf("Update Failed Unexpectedly (likely broken connection): status=%d\n", upload.status);
  130. }
  131. });
  132. } else {
  133. _server->on("/update", HTTP_GET, [&](){
  134. _server->sendHeader("Content-Encoding", "gzip");
  135. _server->send_P(200, "text/html", (const char*)ELEGANT_HTML, ELEGANT_HTML_SIZE);
  136. });
  137. _server->on("/update/identity", HTTP_GET, [&](){
  138. #if defined(ESP8266)
  139. _server->send(200, "application/json", "{\"id\": \""+_id+"\", \"hardware\": \"ESP8266\"}");
  140. #elif defined(ESP32)
  141. _server->send(200, "application/json", "{\"id\": \""+_id+"\", \"hardware\": \"ESP32\"}");
  142. #endif
  143. });
  144. _server->on("/update", HTTP_POST, [&](){
  145. _server->sendHeader("Connection", "close");
  146. _server->send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
  147. ESP.restart();
  148. }, [&](){
  149. //TODO: handle MD5 paramter
  150. // Perform upload
  151. HTTPUpload& upload = _server->upload();
  152. if (upload.status == UPLOAD_FILE_START) {
  153. Serial.setDebugOutput(true);
  154. if (upload.name == "filesystem") {
  155. if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_SPIFFS)) { //start with max available size
  156. Update.printError(Serial);
  157. }
  158. } else {
  159. if (!Update.begin(UPDATE_SIZE_UNKNOWN, U_FLASH)) { //start with max available size
  160. Update.printError(Serial);
  161. }
  162. }
  163. } else if (upload.status == UPLOAD_FILE_WRITE) {
  164. if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
  165. Update.printError(Serial);
  166. }
  167. } else if (upload.status == UPLOAD_FILE_END) {
  168. if (Update.end(true)) { //true to set the size to the current progress
  169. Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
  170. } else {
  171. Update.printError(Serial);
  172. }
  173. Serial.setDebugOutput(false);
  174. } else {
  175. Serial.printf("Update Failed Unexpectedly (likely broken connection): status=%d\n", upload.status);
  176. }
  177. });
  178. }
  179. }
  180. #endif
  181. private:
  182. #if defined(ESP8266)
  183. ESP8266WebServer *_server;
  184. ESP8266HTTPUpdateServer _httpUpdater;
  185. #endif
  186. #if defined(ESP32)
  187. WebServer *_server;
  188. #endif
  189. String getID(){
  190. String id = "";
  191. #if defined(ESP8266)
  192. id = String(ESP.getChipId());
  193. #elif defined(ESP32)
  194. id = String((uint32_t)ESP.getEfuseMac(), HEX);
  195. #endif
  196. id.toUpperCase();
  197. return id;
  198. }
  199. String _username;
  200. String _password;
  201. String _id = getID();
  202. };
  203. ElegantOtaClass ElegantOTA;
  204. #endif