faster response times
Some checks failed
Build Release / build (push) Failing after 1m18s

This commit is contained in:
2026-08-16 16:55:32 +02:00
parent 3648538cbc
commit fb884acc27
4 changed files with 109 additions and 105 deletions

View File

@@ -12,12 +12,10 @@
namespace OtaUpdate {
namespace {
constexpr const char* RELEASES_API_URL =
"https://git.rasmusbendtsen.dk/api/v1/repos/rasmus/flyradar/releases/latest";
// Gitea API uses Authorization: token header instead of
// User-Agent. The token is set in Config::GITEA_API_TOKEN.
// Gitea serves downloads directly (no redirect), so
// setFollowRedirects is not needed.
// Gitea API URL constructed from config constants at runtime
String releasesApiUrl() {
return String("https://") + Config::GITEA_API_HOST + Config::GITEA_API_PATH;
}
bool parseVersion(const char* s, int& major, int& minor, int& patch) {
major = minor = patch = 0;
@@ -26,10 +24,7 @@ namespace {
return sscanf(s, "%d.%d.%d", &major, &minor, &patch) == 3;
}
// > 0 if a is newer than b, 0 if equal, < 0 if a is older than b.
// Deliberately a real numeric version comparison instead of a simple
// string comparison (which would e.g. wrongly rank "3.10.0" as "less"
// than "3.9.0").
// Numeric version comparison (not string-based, so e.g. "3.10.0" > "3.9.0").
int compareVersions(const char* a, const char* b) {
int aMaj, aMin, aPat, bMaj, bMin, bPat;
if (!parseVersion(a, aMaj, aMin, aPat) || !parseVersion(b, bMaj, bMin, bPat)) return 0;
@@ -37,12 +32,22 @@ namespace {
if (aMin != bMin) return aMin - bMin;
return aPat - bPat;
}
void addAuthHeader(HTTPClient& http) {
http.addHeader("User-Agent", "EiswolfsFlightradarCYD-OTA/1.0");
if (Config::GITEA_API_TOKEN[0]) {
String auth = "token ";
auth += Config::GITEA_API_TOKEN;
http.addHeader("Authorization", auth);
}
}
}
CheckInfo checkForUpdate() {
CheckInfo info;
String url = releasesApiUrl();
Serial.printf("[OTA] Checking for update: url=%s freeHeap=%u RSSI=%ddBm\n", RELEASES_API_URL,
Serial.printf("[OTA] Checking for update: url=%s freeHeap=%u RSSI=%ddBm\n", url.c_str(),
(unsigned)ESP.getFreeHeap(), WiFi.RSSI());
WiFiClientSecure client;
@@ -51,16 +56,11 @@ CheckInfo checkForUpdate() {
HTTPClient http;
http.setTimeout(8000);
if (!http.begin(client, RELEASES_API_URL)) {
if (!http.begin(client, url)) {
Serial.println("[OTA] Check failed: http.begin() returned false.");
return info;
}
http.addHeader("User-Agent", "EiswolfsFlightradarCYD-OTA/1.0");
if (Config::GITEA_API_TOKEN[0]) {
String auth = "token ";
auth += Config::GITEA_API_TOKEN;
http.addHeader("Authorization", auth);
}
addAuthHeader(http);
int code = http.GET();
if (code != HTTP_CODE_OK) {
@@ -92,12 +92,15 @@ CheckInfo checkForUpdate() {
strncpy(info.latestVersion, (tag[0] == 'v' || tag[0] == 'V') ? tag + 1 : tag,
sizeof(info.latestVersion) - 1);
// Use browser_download_url from the API response — this contains the
// external proxy URL (https://git.rasmusbendtsen.dk/...) which the
// ESP32 can reach through the proxy.
JsonArray assets = doc["assets"];
for (JsonObject asset : assets) {
const char* name = asset["name"] | "";
if (strcmp(name, "firmware.bin") == 0) {
const char* url = asset["browser_download_url"] | "";
strncpy(info.downloadUrl, url, sizeof(info.downloadUrl) - 1);
const char* dlUrl = asset["browser_download_url"] | "";
strncpy(info.downloadUrl, dlUrl, sizeof(info.downloadUrl) - 1);
break;
}
}
@@ -105,54 +108,39 @@ CheckInfo checkForUpdate() {
if (!info.downloadUrl[0]) {
Serial.printf("[OTA] Check failed: Release v%s has no firmware.bin attachment.\n",
info.latestVersion);
return info; // Release without firmware.bin attachment
return info;
}
int cmp = compareVersions(info.latestVersion, Config::APP_VERSION);
info.result = (cmp > 0) ? CheckResult::UpdateAvailable : CheckResult::UpToDate;
Serial.printf("[OTA] Check successful: installed=v%s latest=v%s -> %s\n", Config::APP_VERSION,
Serial.printf("[OTA] Check successful: installed=v%s latest=v%s -> %s\n", Config::APP_VERSION,
info.latestVersion,
info.result == CheckResult::UpdateAvailable ? "Update available" : "already up-to-date");
return info;
}
bool performUpdate(const char* url, void (*onProgress)(uint8_t percent)) {
// Diagnostic logging (only visible over USB serial, no impact on
// the UI) - previously a failed update only returned a simple "true/
// false" externally, without recording the actual reason (timeout,
// TLS error, HTTP status code...). This allows tracing a failed
// OTA attempt on the serial monitor instead of having to guess again.
Serial.printf("[OTA] Starting: url=%s freeHeap=%u RSSI=%ddBm\n", url,
(unsigned)ESP.getFreeHeap(), WiFi.RSSI());
WiFiClientSecure client;
WiFiClientSecure client;
client.setInsecure();
client.setTimeout(15000);
// Gitea serves downloads directly (no redirect like GitHub's S3),
// but private repos still need the Authorization header. Use the
// HTTPClient overload of httpUpdate.update() so we can set it.
// Use HTTPClient overload so we can add the Authorization header
// (required for private repos even during download).
HTTPClient http;
if (!http.begin(client, url)) {
Serial.println("[OTA] Failed: http.begin() returned false for download URL.");
return false;
}
if (Config::GITEA_API_TOKEN[0]) {
String auth = "token ";
auth += Config::GITEA_API_TOKEN;
http.addHeader("Authorization", auth);
}
addAuthHeader(http);
// We show a brief success message ourselves after successful installation,
// before the device reboots - see
// menu_screen.cpp::runOtaUpdateScreen().
httpUpdate.rebootOnUpdate(false);
httpUpdate.onProgress([onProgress](int cur, int total) {
if (onProgress && total > 0) {
onProgress((uint8_t)((cur * 100) / total));
}
// Only log occasionally (every ~10%), otherwise the serial
// monitor overflows with hundreds of lines for large files.
static int8_t lastLoggedPercent = -1;
if (total > 0) {
int8_t pct = (int8_t)((cur * 100) / total);
@@ -165,11 +153,10 @@ WiFiClientSecure client;
});
t_httpUpdate_return result = httpUpdate.update(http);
http.end();
if (result != HTTP_UPDATE_OK) {
Serial.printf("[OTA] Failed: result=%d error=%d (%s) freeHeap=%u\n", (int)result,
Serial.printf("[OTA] Failed: result=%d error=%d (%s) freeHeap=%u\n", (int)result,
httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str(),
(unsigned)ESP.getFreeHeap());
} else {
@@ -179,4 +166,4 @@ Serial.printf("[OTA] Failed: result=%d error=%d (%s) freeHeap=%u\n", (int)result
return result == HTTP_UPDATE_OK;
}
}
}