├── .gitattributes ├── 0TA_Template_Sketch ├── 0TA_Template_Sketch.ino └── OTA.h ├── 0TA_Template_Sketch_TelnetStream ├── 0TA_Template_Sketch_TelnetStream.ino └── OTA.h └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /0TA_Template_Sketch/0TA_Template_Sketch.ino: -------------------------------------------------------------------------------- 1 | #define ESP32_RTOS // Uncomment this line if you want to use the code with freertos only on the ESP32 2 | // Has to be done before including "OTA.h" 3 | 4 | #include "OTA.h" 5 | #include 6 | 7 | void setup() { 8 | Serial.begin(115200); 9 | Serial.println("Booting"); 10 | 11 | setupOTA("TemplateSketch", mySSID, myPASSWORD); 12 | 13 | // Your setup code 14 | } 15 | 16 | void loop() { 17 | #ifdef defined(ESP32_RTOS) && defined(ESP32) 18 | #else // If you do not use FreeRTOS, you have to regulary call the handle method. 19 | ArduinoOTA.handle(); 20 | #endif 21 | 22 | // Your code here 23 | } -------------------------------------------------------------------------------- /0TA_Template_Sketch_TelnetStream/0TA_Template_Sketch_TelnetStream.ino: -------------------------------------------------------------------------------- 1 | #define ESP32_RTOS // Uncomment this line if you want to use the code with freertos only on the ESP32 2 | // Has to be done before including "OTA.h" 3 | 4 | #include "OTA.h" 5 | #include 6 | 7 | uint32_t entry; 8 | 9 | void setup() { 10 | Serial.begin(115200); 11 | Serial.println("Booting"); 12 | 13 | setupOTA("TemplateSketch", mySSID, myPASSWORD); 14 | 15 | // Your setup code 16 | } 17 | 18 | void loop() { 19 | entry = micros(); 20 | #ifdef defined(ESP32_RTOS) && defined(ESP32) 21 | #else // If you do not use FreeRTOS, you have to regulary call the handle method. 22 | ArduinoOTA.handle(); 23 | #endif 24 | TelnetStream.println(micros()-entry); 25 | TelnetStream.println("Loop"); 26 | delay(1000); 27 | // Your code here 28 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP32 OTA 2 | 3 | [![MIT License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 4 | [![GitHub stars](https://img.shields.io/github/stars/SensorsIot/ESP32-OTA)](https://github.com/SensorsIot/ESP32-OTA/stargazers) 5 | [![YouTube](https://img.shields.io/badge/YouTube-Video-red?logo=youtube)](https://www.youtube.com/watch?v=1pwqS_NUG7Q) 6 | 7 | ![ESP32](https://img.shields.io/badge/ESP32-Supported-green?logo=espressif) 8 | ![Arduino](https://img.shields.io/badge/Arduino-Compatible-00979D?logo=arduino) 9 | ![OTA](https://img.shields.io/badge/OTA-Over--The--Air-blue) 10 | 11 | Over-The-Air (OTA) update template for ESP32. 12 | 13 | 📺 **Video Tutorial:** https://www.youtube.com/watch?v=1pwqS_NUG7Q 14 | 15 | ## ⚠️ Important 16 | 17 | The `setupOTA()` function **replaces** `WiFi.begin()` - do not call both! The `setupOTA()` function handles WiFi connection internally. 18 | 19 | ```cpp 20 | // ❌ Wrong - don't do this 21 | WiFi.begin(ssid, password); 22 | setupOTA("DeviceName", ssid, password); 23 | 24 | // ✅ Correct - setupOTA handles WiFi 25 | setupOTA("DeviceName", ssid, password); 26 | ``` 27 | 28 | ## ⚙️ Configuration 29 | 30 | ### 📶 WiFi Credentials 31 | 32 | Create a `credentials.h` file in the sketch folder: 33 | 34 | ```cpp 35 | #pragma once 36 | const char* mySSID = "your-wifi-name"; 37 | const char* myPASSWORD = "your-wifi-password"; 38 | ``` 39 | 40 | Or comment out `#include ` and define credentials directly in the sketch. 41 | 42 | ## 📁 Examples 43 | 44 | | Folder | Description | 45 | |--------|-------------| 46 | | `0TA_Template_Sketch/` | Basic OTA template | 47 | | `0TA_Template_Sketch_TelnetStream/` | OTA with Telnet debugging | 48 | -------------------------------------------------------------------------------- /0TA_Template_Sketch/OTA.h: -------------------------------------------------------------------------------- 1 | #ifdef ESP32 2 | #include 3 | #include 4 | #else 5 | #include 6 | #include 7 | #endif 8 | 9 | #include 10 | #include 11 | 12 | #if defined(ESP32_RTOS) && defined(ESP32) 13 | void ota_handle( void * parameter ) { 14 | for (;;) { 15 | ArduinoOTA.handle(); 16 | delay(3500); 17 | } 18 | } 19 | #endif 20 | 21 | void setupOTA(const char* nameprefix, const char* ssid, const char* password) { 22 | // Configure the hostname 23 | uint16_t maxlen = strlen(nameprefix) + 7; 24 | char *fullhostname = new char[maxlen]; 25 | uint8_t mac[6]; 26 | WiFi.macAddress(mac); 27 | snprintf(fullhostname, maxlen, "%s-%02x%02x%02x", nameprefix, mac[3], mac[4], mac[5]); 28 | ArduinoOTA.setHostname(fullhostname); 29 | delete[] fullhostname; 30 | 31 | // Configure and start the WiFi station 32 | WiFi.mode(WIFI_STA); 33 | WiFi.begin(ssid, password); 34 | 35 | // Wait for connection 36 | while (WiFi.waitForConnectResult() != WL_CONNECTED) { 37 | Serial.println("Connection Failed! Rebooting..."); 38 | delay(5000); 39 | ESP.restart(); 40 | } 41 | 42 | // Port defaults to 3232 43 | // ArduinoOTA.setPort(3232); // Use 8266 port if you are working in Sloeber IDE, it is fixed there and not adjustable 44 | 45 | // No authentication by default 46 | // ArduinoOTA.setPassword("admin"); 47 | 48 | // Password can be set with it's md5 value as well 49 | // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3 50 | // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3"); 51 | 52 | ArduinoOTA.onStart([]() { 53 | //NOTE: make .detach() here for all functions called by Ticker.h library - not to interrupt transfer process in any way. 54 | String type; 55 | if (ArduinoOTA.getCommand() == U_FLASH) 56 | type = "sketch"; 57 | else // U_SPIFFS 58 | type = "filesystem"; 59 | 60 | // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end() 61 | Serial.println("Start updating " + type); 62 | }); 63 | 64 | ArduinoOTA.onEnd([]() { 65 | Serial.println("\nEnd"); 66 | }); 67 | 68 | ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { 69 | Serial.printf("Progress: %u%%\r", (progress / (total / 100))); 70 | }); 71 | 72 | ArduinoOTA.onError([](ota_error_t error) { 73 | Serial.printf("Error[%u]: ", error); 74 | if (error == OTA_AUTH_ERROR) Serial.println("\nAuth Failed"); 75 | else if (error == OTA_BEGIN_ERROR) Serial.println("\nBegin Failed"); 76 | else if (error == OTA_CONNECT_ERROR) Serial.println("\nConnect Failed"); 77 | else if (error == OTA_RECEIVE_ERROR) Serial.println("\nReceive Failed"); 78 | else if (error == OTA_END_ERROR) Serial.println("\nEnd Failed"); 79 | }); 80 | 81 | ArduinoOTA.begin(); 82 | 83 | Serial.println("OTA Initialized"); 84 | Serial.print("IP address: "); 85 | Serial.println(WiFi.localIP()); 86 | 87 | #if defined(ESP32_RTOS) && defined(ESP32) 88 | xTaskCreate( 89 | ota_handle, /* Task function. */ 90 | "OTA_HANDLE", /* String with name of task. */ 91 | 10000, /* Stack size in bytes. */ 92 | NULL, /* Parameter passed as input of the task */ 93 | 1, /* Priority of the task. */ 94 | NULL); /* Task handle. */ 95 | #endif 96 | } -------------------------------------------------------------------------------- /0TA_Template_Sketch_TelnetStream/OTA.h: -------------------------------------------------------------------------------- 1 | #ifdef ESP32 2 | #include 3 | #include 4 | #else 5 | #include 6 | #include 7 | #endif 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #if defined(ESP32_RTOS) && defined(ESP32) 14 | void ota_handle( void * parameter ) { 15 | for (;;) { 16 | ArduinoOTA.handle(); 17 | delay(3500); 18 | } 19 | } 20 | #endif 21 | 22 | void setupOTA(const char* nameprefix, const char* ssid, const char* password) { 23 | // Configure the hostname 24 | uint16_t maxlen = strlen(nameprefix) + 7; 25 | char *fullhostname = new char[maxlen]; 26 | uint8_t mac[6]; 27 | WiFi.macAddress(mac); 28 | snprintf(fullhostname, maxlen, "%s-%02x%02x%02x", nameprefix, mac[3], mac[4], mac[5]); 29 | ArduinoOTA.setHostname(fullhostname); 30 | delete[] fullhostname; 31 | 32 | // Configure and start the WiFi station 33 | WiFi.mode(WIFI_STA); 34 | WiFi.begin(ssid, password); 35 | 36 | // Wait for connection 37 | while (WiFi.waitForConnectResult() != WL_CONNECTED) { 38 | Serial.println("Connection Failed! Rebooting..."); 39 | delay(5000); 40 | ESP.restart(); 41 | } 42 | 43 | // Port defaults to 3232 44 | // ArduinoOTA.setPort(3232); // Use 8266 port if you are working in Sloeber IDE, it is fixed there and not adjustable 45 | 46 | 47 | // No authentication by default 48 | // ArduinoOTA.setPassword("admin"); 49 | 50 | // Password can be set with it's md5 value as well 51 | // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3 52 | // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3"); 53 | 54 | ArduinoOTA.onStart([]() { 55 | //NOTE: make .detach() here for all functions called by Ticker.h library - not to interrupt transfer process in any way. 56 | 57 | String type; 58 | if (ArduinoOTA.getCommand() == U_FLASH) 59 | type = "sketch"; 60 | else // U_SPIFFS 61 | type = "filesystem"; 62 | 63 | // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end() 64 | Serial.println("Start updating " + type); 65 | }); 66 | 67 | ArduinoOTA.onEnd([]() { 68 | Serial.println("\nEnd"); 69 | }); 70 | 71 | ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { 72 | Serial.printf("Progress: %u%%\r", (progress / (total / 100))); 73 | }); 74 | 75 | ArduinoOTA.onError([](ota_error_t error) { 76 | Serial.printf("Error[%u]: ", error); 77 | if (error == OTA_AUTH_ERROR) Serial.println("\nAuth Failed"); 78 | else if (error == OTA_BEGIN_ERROR) Serial.println("\nBegin Failed"); 79 | else if (error == OTA_CONNECT_ERROR) Serial.println("\nConnect Failed"); 80 | else if (error == OTA_RECEIVE_ERROR) Serial.println("\nReceive Failed"); 81 | else if (error == OTA_END_ERROR) Serial.println("\nEnd Failed"); 82 | }); 83 | 84 | ArduinoOTA.begin(); 85 | TelnetStream.begin(); 86 | 87 | Serial.println("OTA Initialized"); 88 | Serial.print("IP address: "); 89 | Serial.println(WiFi.localIP()); 90 | 91 | #if defined(ESP32_RTOS) && defined(ESP32) 92 | xTaskCreate( 93 | ota_handle, /* Task function. */ 94 | "OTA_HANDLE", /* String with name of task. */ 95 | 10000, /* Stack size in bytes. */ 96 | NULL, /* Parameter passed as input of the task */ 97 | 1, /* Priority of the task. */ 98 | NULL); /* Task handle. */ 99 | #endif 100 | } --------------------------------------------------------------------------------