#include "XD0OTA.h" #include #include #include #include #include static const char* TAG = "OTA"; XD0OTA::XD0OTA(String deviceName) : deviceName{deviceName} {} // Set time via NTP, as required for x.509 validation void XD0OTA::setClock() { configTime(0, 0, "pool.ntp.org", "time.nist.gov"); // UTC Serial.print(F("Waiting for NTP time sync: ")); time_t now = time(nullptr); int tries = 0; while (now < 8 * 3600 * 2) { yield(); delay(500); Serial.print(F(".")); now = time(nullptr); tries++; if (tries>15) return; } Serial.println(F("")); struct tm timeinfo; gmtime_r(&now, &timeinfo); Serial.print(F("Current time: ")); Serial.print(asctime(&timeinfo)); } String XD0OTA::getMAC() { uint8_t mac[6]; char result[14]; WiFi.macAddress( mac ); snprintf( result, sizeof( result ), "%02x%02x%02x%02x%02x%02x", mac[ 0 ], mac[ 1 ], mac[ 2 ], mac[ 3 ], mac[ 4 ], mac[ 5 ] ); return String( result ); } String XD0OTA::getUpdateURL(String file, String extension) { String updateURL = String(fwUrlBase); updateURL.concat(file); updateURL.concat(extension); return updateURL; } void XD0OTA::update(void) { setClock(); // try device specific image first String fwURL = getUpdateURL(getMAC(), ".bin"); int newVersion = checkForUpdates(fwURL + ".version"); if (newVersion < 1) { ESP_LOGW(TAG, "[update] no device specific update found..\n"); fwURL = getUpdateURL(deviceName, ".bin"); newVersion = checkForUpdates(fwURL + ".version"); // try project specific image if (newVersion < 1) { ESP_LOGW(TAG, "[update] Error while looking for updates..\n"); return; } } if( newVersion > FW_VERSION ) { ESP_LOGW(TAG, "Preparing to update.\n" ); ESP_LOGW(TAG, "Firmware image URL: " ); ESP_LOGW(TAG, "%s\n", fwURL.c_str() ); WiFiClientSecure client; client.setCACert(rootCACertificate); client.setTimeout(12); // seconds httpUpdate.setLedPin(LED_BUILTIN, HIGH); t_httpUpdate_return ret = httpUpdate.update( client, fwURL ); switch(ret) { case HTTP_UPDATE_FAILED: ESP_LOGW(TAG, "HTTP_UPDATE_FAILED Error (%d): %s\n", httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str()); break; case HTTP_UPDATE_NO_UPDATES: ESP_LOGW(TAG, "HTTP_UPDATE_NO_UPDATES\n"); break; case HTTP_UPDATE_OK: ESP_LOGW(TAG, "[update] Update ok.\n"); // may not called we reboot the ESP break; } } else { ESP_LOGW(TAG, "[update] Already on latest version\n" ); } } int XD0OTA::checkForUpdates(String url) { int newVersion = -1; ESP_LOGW(TAG, "Checking for firmware updates.\n" ); ESP_LOGW(TAG, "Firmware version URL: " ); ESP_LOGW(TAG, "%s\n", url.c_str() ); WiFiClientSecure client; client.setCACert(rootCACertificate); client.setTimeout(5); // seconds HTTPClient httpClient; httpClient.begin( client, url ); int httpCode = httpClient.GET(); if( httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY ) { String newFWVersion = httpClient.getString(); ESP_LOGW(TAG, "Current firmware version: " ); ESP_LOGW(TAG, "%s\n", String(FW_VERSION).c_str() ); ESP_LOGW(TAG, "Available firmware version: " ); ESP_LOGW(TAG, "%s\n", newFWVersion.c_str() ); newVersion = newFWVersion.toInt(); } else { ESP_LOGW(TAG, "Firmware version check failed, got HTTP response code " ); ESP_LOGW(TAG, "%d\n", httpCode ); newVersion = -1; } httpClient.end(); client.stop(); return newVersion; }