├── esp32_ota ├── bin_version.txt ├── cert.h ├── esp32_ota.ino └── fw.bin ├── esp8266_ota └── esp8266_ota.ino └── readme.md /esp32_ota/bin_version.txt: -------------------------------------------------------------------------------- 1 | 2.2 2 | -------------------------------------------------------------------------------- /esp32_ota/cert.h: -------------------------------------------------------------------------------- 1 | #ifndef CERT_H 2 | 3 | #define CERT_H 4 | 5 | //DigiCert root certificate has expiry date of 10 Nov 2031 6 | const char * rootCACertificate = \ 7 | "-----BEGIN CERTIFICATE-----\n" \ 8 | "MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n" \ 9 | "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" \ 10 | "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n" \ 11 | "QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n" \ 12 | "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n" \ 13 | "b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n" \ 14 | "9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n" \ 15 | "CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n" \ 16 | "nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n" \ 17 | "43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n" \ 18 | "T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n" \ 19 | "gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n" \ 20 | "BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n" \ 21 | "TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n" \ 22 | "DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n" \ 23 | "hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n" \ 24 | "06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n" \ 25 | "PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n" \ 26 | "YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n" \ 27 | "CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n" \ 28 | "-----END CERTIFICATE-----\n"; 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /esp32_ota/esp32_ota.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "cert.h" 6 | 7 | const char * ssid = "home_wifi"; 8 | const char * password = "helloworld"; 9 | 10 | 11 | String FirmwareVer = { 12 | "2.2" 13 | }; 14 | #define URL_fw_Version "https://raw.githubusercontent.com/programmer131/ESP8266_ESP32_SelfUpdate/master/esp32_ota/bin_version.txt" 15 | #define URL_fw_Bin "https://raw.githubusercontent.com/programmer131/ESP8266_ESP32_SelfUpdate/master/esp32_ota/fw.bin" 16 | 17 | //#define URL_fw_Version "http://cade-make.000webhostapp.com/version.txt" 18 | //#define URL_fw_Bin "http://cade-make.000webhostapp.com/firmware.bin" 19 | 20 | void connect_wifi(); 21 | void firmwareUpdate(); 22 | int FirmwareVersionCheck(); 23 | 24 | unsigned long previousMillis = 0; // will store last time LED was updated 25 | unsigned long previousMillis_2 = 0; 26 | const long interval = 60000; 27 | const long mini_interval = 1000; 28 | void repeatedCall() { 29 | static int num=0; 30 | unsigned long currentMillis = millis(); 31 | if ((currentMillis - previousMillis) >= interval) { 32 | // save the last time you blinked the LED 33 | previousMillis = currentMillis; 34 | if (FirmwareVersionCheck()) { 35 | firmwareUpdate(); 36 | } 37 | } 38 | if ((currentMillis - previousMillis_2) >= mini_interval) { 39 | previousMillis_2 = currentMillis; 40 | Serial.print("idle loop..."); 41 | Serial.print(num++); 42 | Serial.print(" Active fw version:"); 43 | Serial.println(FirmwareVer); 44 | if(WiFi.status() == WL_CONNECTED) 45 | { 46 | Serial.println("wifi connected"); 47 | } 48 | else 49 | { 50 | connect_wifi(); 51 | } 52 | } 53 | } 54 | 55 | struct Button { 56 | const uint8_t PIN; 57 | uint32_t numberKeyPresses; 58 | bool pressed; 59 | }; 60 | 61 | Button button_boot = { 62 | 0, 63 | 0, 64 | false 65 | }; 66 | /*void IRAM_ATTR isr(void* arg) { 67 | Button* s = static_cast(arg); 68 | s->numberKeyPresses += 1; 69 | s->pressed = true; 70 | }*/ 71 | 72 | void IRAM_ATTR isr() { 73 | button_boot.numberKeyPresses += 1; 74 | button_boot.pressed = true; 75 | } 76 | 77 | 78 | void setup() { 79 | pinMode(button_boot.PIN, INPUT); 80 | attachInterrupt(button_boot.PIN, isr, RISING); 81 | Serial.begin(115200); 82 | Serial.print("Active firmware version:"); 83 | Serial.println(FirmwareVer); 84 | pinMode(LED_BUILTIN, OUTPUT); 85 | connect_wifi(); 86 | } 87 | void loop() { 88 | if (button_boot.pressed) { //to connect wifi via Android esp touch app 89 | Serial.println("Firmware update Starting.."); 90 | firmwareUpdate(); 91 | button_boot.pressed = false; 92 | } 93 | repeatedCall(); 94 | } 95 | 96 | void connect_wifi() { 97 | Serial.println("Waiting for WiFi"); 98 | WiFi.begin(ssid, password); 99 | while (WiFi.status() != WL_CONNECTED) { 100 | delay(500); 101 | Serial.print("."); 102 | } 103 | 104 | Serial.println(""); 105 | Serial.println("WiFi connected"); 106 | Serial.println("IP address: "); 107 | Serial.println(WiFi.localIP()); 108 | } 109 | 110 | 111 | void firmwareUpdate(void) { 112 | WiFiClientSecure client; 113 | client.setCACert(rootCACertificate); 114 | httpUpdate.setLedPin(LED_BUILTIN, LOW); 115 | t_httpUpdate_return ret = httpUpdate.update(client, URL_fw_Bin); 116 | 117 | switch (ret) { 118 | case HTTP_UPDATE_FAILED: 119 | Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s\n", httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str()); 120 | break; 121 | 122 | case HTTP_UPDATE_NO_UPDATES: 123 | Serial.println("HTTP_UPDATE_NO_UPDATES"); 124 | break; 125 | 126 | case HTTP_UPDATE_OK: 127 | Serial.println("HTTP_UPDATE_OK"); 128 | break; 129 | } 130 | } 131 | int FirmwareVersionCheck(void) { 132 | String payload; 133 | int httpCode; 134 | String fwurl = ""; 135 | fwurl += URL_fw_Version; 136 | fwurl += "?"; 137 | fwurl += String(rand()); 138 | Serial.println(fwurl); 139 | WiFiClientSecure * client = new WiFiClientSecure; 140 | 141 | if (client) 142 | { 143 | client -> setCACert(rootCACertificate); 144 | 145 | // Add a scoping block for HTTPClient https to make sure it is destroyed before WiFiClientSecure *client is 146 | HTTPClient https; 147 | 148 | if (https.begin( * client, fwurl)) 149 | { // HTTPS 150 | Serial.print("[HTTPS] GET...\n"); 151 | // start connection and send HTTP header 152 | delay(100); 153 | httpCode = https.GET(); 154 | delay(100); 155 | if (httpCode == HTTP_CODE_OK) // if version received 156 | { 157 | payload = https.getString(); // save received version 158 | } else { 159 | Serial.print("error in downloading version file:"); 160 | Serial.println(httpCode); 161 | } 162 | https.end(); 163 | } 164 | delete client; 165 | } 166 | 167 | if (httpCode == HTTP_CODE_OK) // if version received 168 | { 169 | payload.trim(); 170 | if (payload.equals(FirmwareVer)) { 171 | Serial.printf("\nDevice already on latest firmware version:%s\n", FirmwareVer); 172 | return 0; 173 | } 174 | else 175 | { 176 | Serial.println(payload); 177 | Serial.println("New firmware detected"); 178 | return 1; 179 | } 180 | } 181 | return 0; 182 | } -------------------------------------------------------------------------------- /esp32_ota/fw.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmer131/ESP8266_ESP32_SelfUpdate/4c5d592ffbabde5236641e1378087b95c924ca80/esp32_ota/fw.bin -------------------------------------------------------------------------------- /esp8266_ota/esp8266_ota.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | BearSSL::CertStore certStore; 7 | #include 8 | 9 | const String FirmwareVer={"1.8"}; 10 | #define URL_fw_Version "/programmer131/otaFiles/master/version.txt" 11 | #define URL_fw_Bin "https://raw.githubusercontent.com/programmer131/otaFiles/master/firmware.bin" 12 | const char* host = "raw.githubusercontent.com"; 13 | const int httpsPort = 443; 14 | 15 | // DigiCert High Assurance EV Root CA 16 | const char trustRoot[] PROGMEM = R"EOF( 17 | -----BEGIN CERTIFICATE----- 18 | MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh 19 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 20 | d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD 21 | QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT 22 | MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j 23 | b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG 24 | 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB 25 | CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 26 | nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt 27 | 43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P 28 | T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 29 | gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO 30 | BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR 31 | TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw 32 | DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr 33 | hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg 34 | 06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF 35 | PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls 36 | YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk 37 | CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= 38 | -----END CERTIFICATE----- 39 | )EOF"; 40 | X509List cert(trustRoot); 41 | 42 | 43 | extern const unsigned char caCert[] PROGMEM; 44 | extern const unsigned int caCertLen; 45 | 46 | const char* ssid = "home_wifi"; 47 | const char* password = "helloworld"; 48 | 49 | void setClock() { 50 | // Set time via NTP, as required for x.509 validation 51 | configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov"); 52 | Serial.print("Waiting for NTP time sync: "); 53 | time_t now = time(nullptr); 54 | while (now < 8 * 3600 * 2) { 55 | delay(500); 56 | Serial.print("."); 57 | now = time(nullptr); 58 | } 59 | /* 60 | Serial.println(""); 61 | struct tm timeinfo; 62 | gmtime_r(&now, &timeinfo); 63 | Serial.print("Current time: "); 64 | Serial.print(asctime(&timeinfo)); 65 | */ 66 | } 67 | 68 | void FirmwareUpdate() 69 | { 70 | WiFiClientSecure client; 71 | client.setTrustAnchors(&cert); 72 | if (!client.connect(host, httpsPort)) { 73 | Serial.println("Connection failed"); 74 | return; 75 | } 76 | client.print(String("GET ") + URL_fw_Version + " HTTP/1.1\r\n" + 77 | "Host: " + host + "\r\n" + 78 | "User-Agent: BuildFailureDetectorESP8266\r\n" + 79 | "Connection: close\r\n\r\n"); 80 | while (client.connected()) { 81 | String line = client.readStringUntil('\n'); 82 | if (line == "\r") { 83 | //Serial.println("Headers received"); 84 | break; 85 | } 86 | } 87 | String payload = client.readStringUntil('\n'); 88 | 89 | payload.trim(); 90 | if(payload.equals(FirmwareVer) ) 91 | { 92 | Serial.println("Device already on latest firmware version"); 93 | } 94 | else 95 | { 96 | Serial.println("New firmware detected"); 97 | ESPhttpUpdate.setLedPin(LED_BUILTIN, LOW); 98 | t_httpUpdate_return ret = ESPhttpUpdate.update(client, URL_fw_Bin); 99 | 100 | switch (ret) { 101 | case HTTP_UPDATE_FAILED: 102 | Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str()); 103 | break; 104 | 105 | case HTTP_UPDATE_NO_UPDATES: 106 | Serial.println("HTTP_UPDATE_NO_UPDATES"); 107 | break; 108 | 109 | case HTTP_UPDATE_OK: 110 | Serial.println("HTTP_UPDATE_OK"); 111 | break; 112 | } 113 | } 114 | } 115 | void connect_wifi(); 116 | unsigned long previousMillis_2 = 0; 117 | unsigned long previousMillis = 0; // will store last time LED was updated 118 | const long interval = 60000; 119 | const long mini_interval = 1000; 120 | void repeatedCall(){ 121 | unsigned long currentMillis = millis(); 122 | if ((currentMillis - previousMillis) >= interval) 123 | { 124 | // save the last time you blinked the LED 125 | previousMillis = currentMillis; 126 | setClock(); 127 | FirmwareUpdate(); 128 | } 129 | 130 | if ((currentMillis - previousMillis_2) >= mini_interval) { 131 | static int idle_counter=0; 132 | previousMillis_2 = currentMillis; 133 | Serial.print(" Active fw version:"); 134 | Serial.println(FirmwareVer); 135 | Serial.print("Idle Loop...."); 136 | Serial.println(idle_counter++); 137 | if(idle_counter%2==0) 138 | digitalWrite(LED_BUILTIN, HIGH); 139 | else 140 | digitalWrite(LED_BUILTIN, LOW); 141 | if(WiFi.status() == !WL_CONNECTED) 142 | connect_wifi(); 143 | } 144 | } 145 | 146 | 147 | void setup() 148 | { 149 | Serial.begin(115200); 150 | Serial.println(""); 151 | Serial.println("Start"); 152 | WiFi.mode(WIFI_STA); 153 | connect_wifi(); 154 | setClock(); 155 | pinMode(LED_BUILTIN, OUTPUT); 156 | 157 | } 158 | void loop() 159 | { 160 | repeatedCall(); 161 | } 162 | 163 | void connect_wifi() 164 | { 165 | WiFi.begin(ssid, password); 166 | while (WiFi.status() != WL_CONNECTED) 167 | { 168 | delay(500); 169 | Serial.print("O"); 170 | } 171 | Serial.println("Connected to WiFi"); 172 | } 173 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | repo contains Arduino sketch that include self OTA support. 2 | 3 | ESP32 OTA Demo: https://youtu.be/qCmdUtguwPw 4 | 5 | demonstration and code explanation https://youtu.be/FuY6BobS-1k 6 | 7 | Just another small demo: https://youtu.be/2J8KK5Cxf6g 8 | 9 | Update: removed fingerprint and added rootca certificate for esp8266 but bin file downloading 10 | is quite slow now. 11 | 12 | June 2022 update: Instead of using static url in your firmware, just send it in mqtt message, this way you can avoid scenarios where url/domain goes offline. This project utilize this technique, https://github.com/programmer131/cam-flood-light 13 | --------------------------------------------------------------------------------